diff --git a/Pocket Poster/Controllers/DownloadManager.swift b/Pocket Poster/Controllers/DownloadManager.swift index 9766a07..dae2ac4 100644 --- a/Pocket Poster/Controllers/DownloadManager.swift +++ b/Pocket Poster/Controllers/DownloadManager.swift @@ -19,7 +19,7 @@ class DownloadManager { let (data, response) = try await URLSession.shared.data(for: request) as! (Data, HTTPURLResponse) guard response.statusCode == 200 else { throw URLError(.cannotConnectToHost) } - let newURL = SymHandler.getDocumentsDirectory().appendingPathComponent(getWallpaperNameFromURL(string: url.absoluteString)) + let newURL = PosterBoardManager.getTendiesStoreURL().appendingPathComponent(getWallpaperNameFromURL(string: url.absoluteString)) try data.write(to: newURL) return newURL } @@ -28,4 +28,17 @@ class DownloadManager { guard let url = URL(string: path) else { throw URLError(.unknown) } return try await downloadFromURL(url) } + + static func copyTendies(from url: URL) throws -> URL { + // scope the resource + let accessing = url.startAccessingSecurityScopedResource() + defer { + if accessing { + url.stopAccessingSecurityScopedResource() + } + } + let newURL = PosterBoardManager.getTendiesStoreURL().appendingPathComponent(url.lastPathComponent) + try FileManager.default.copyItem(at: url, to: newURL) + return newURL + } } diff --git a/Pocket Poster/Controllers/PosterBoardManager.swift b/Pocket Poster/Controllers/PosterBoardManager.swift index 3272058..22c2813 100644 --- a/Pocket Poster/Controllers/PosterBoardManager.swift +++ b/Pocket Poster/Controllers/PosterBoardManager.swift @@ -13,6 +13,15 @@ class PosterBoardManager { static let ShortcutURL = "https://www.icloud.com/shortcuts/a28d2c02ca11453cb5b8f91c12cfa692" static let WallpapersURL = "https://cowabun.ga/wallpapers" + static func getTendiesStoreURL() -> URL { + let tendiesStoreURL = SymHandler.getDocumentsDirectory().appendingPathComponent("KFC Bucket", conformingTo: .directory) + // create it if it doesn't exist + if !FileManager.default.fileExists(atPath: tendiesStoreURL.path()) { + try? FileManager.default.createDirectory(at: tendiesStoreURL, withIntermediateDirectories: true) + } + return tendiesStoreURL + } + private static func unzipFile(at url: URL) throws -> URL { let fileName = url.deletingPathExtension().lastPathComponent let fileData = try Data(contentsOf: url) @@ -51,9 +60,7 @@ class PosterBoardManager { } static func getDescriptorsFromTendie(_ url: URL) throws -> URL? { - let unzippedDir = try unzipFile(at: url) - - for dir in try FileManager.default.contentsOfDirectory(at: unzippedDir, includingPropertiesForKeys: nil, options: .skipsHiddenFiles) { + for dir in try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: .skipsHiddenFiles) { let fileName = dir.lastPathComponent if fileName.lowercased() == "descriptor" || fileName.lowercased() == "descriptors" { return dir @@ -126,15 +133,8 @@ class PosterBoardManager { SymHandler.cleanup() } for url in urls { - // scope the resource - let accessing = url.startAccessingSecurityScopedResource() - defer { - if accessing { - url.stopAccessingSecurityScopedResource() - } - } - - guard let descriptors = try getDescriptorsFromTendie(url) else { return } // TODO: Add error handling + let unzippedDir = try unzipFile(at: url) + guard let descriptors = try getDescriptorsFromTendie(unzippedDir) else { continue } // TODO: Add error handling // create the folder for descr in try FileManager.default.contentsOfDirectory(at: descriptors, includingPropertiesForKeys: nil, options: .skipsHiddenFiles) { if descr.lastPathComponent != "__MACOSX" { @@ -142,15 +142,11 @@ class PosterBoardManager { let newURL = SymHandler.getDocumentsDirectory().appendingPathComponent(UUID().uuidString, conformingTo: .directory) try FileManager.default.moveItem(at: descr, to: newURL) - do { - try FileManager.default.trashItem(at: newURL, resultingItemURL: nil) - } catch { - print(error.localizedDescription) - } + try FileManager.default.trashItem(at: newURL, resultingItemURL: nil) } } - try? FileManager.default.removeItem(at: descriptors) + try? FileManager.default.removeItem(at: unzippedDir) } } diff --git a/Pocket Poster/Pocket_PosterApp.swift b/Pocket Poster/Pocket_PosterApp.swift index 3b484bc..328cad6 100644 --- a/Pocket Poster/Pocket_PosterApp.swift +++ b/Pocket Poster/Pocket_PosterApp.swift @@ -9,19 +9,83 @@ import SwiftUI @main struct Pocket_PosterApp: App { + // Prefs @AppStorage("finishedTutorial") var finishedTutorial: Bool = false + @AppStorage("pbHash") var pbHash: String = "" + + @State var selectedTendies: [URL]? = nil + + @State var downloadURL: String? = nil + @State var showDownloadAlert = false var body: some Scene { WindowGroup { Group { if finishedTutorial { - ContentView() + ContentView(selectedTendies: $selectedTendies) } else { OnBoardingView() } } .transition(.opacity) .animation(.easeOut(duration: 0.5), value: finishedTutorial) + .alert("Download Tendies File", isPresented: $showDownloadAlert) { + Button("OK") { + downloadWallpaper() + } + Button("Cancel", role: .cancel) {} + } message: { + Text("Would you like to download the file \(DownloadManager.getWallpaperNameFromURL(string: downloadURL ?? "/Unknown"))?") + } + .onOpenURL(perform: { url in + // Download URL + if url.absoluteString.starts(with: "pocketposter://download") { + downloadURL = url.absoluteString.replacingOccurrences(of: "pocketposter://download?url=", with: "") + showDownloadAlert = true + } + // App Hash URL + else if url.absoluteString.starts(with: "pocketposter://app-hash?uuid=") { + pbHash = url.absoluteString.replacingOccurrences(of: "pocketposter://app-hash?uuid=", with: "") + } + else if url.pathExtension == "tendies" { + // copy it over to the KFC bucket + do { + let newURL = try DownloadManager.copyTendies(from: url) + if selectedTendies == nil { + selectedTendies = [newURL] + } else { + selectedTendies?.append(newURL) + } + Haptic.shared.notify(.success) + UIApplication.shared.alert(title: "Successfully imported \(url.lastPathComponent)", body: "") + } catch { + Haptic.shared.notify(.error) + UIApplication.shared.alert(title: "Failed to import tendies", body: error.localizedDescription) + } + } + }) + } + } + + func downloadWallpaper() { + UIImpactFeedbackGenerator(style: .soft).impactOccurred() + UIApplication.shared.alert(title: NSLocalizedString("Downloading", comment: "") + " \(DownloadManager.getWallpaperNameFromURL(string: downloadURL ?? "/Unknown"))...", body: NSLocalizedString("Please wait", comment: ""), animated: false, withButton: false) + + Task { + do { + let newURL = try await DownloadManager.downloadFromURL(string: downloadURL!) + if selectedTendies == nil { + selectedTendies = [newURL] + } else { + selectedTendies?.append(newURL) + } + Haptic.shared.notify(.success) + UIApplication.shared.dismissAlert(animated: true) + } catch { + Haptic.shared.notify(.error) + UIApplication.shared.dismissAlert(animated: true) + UIApplication.shared.alert(title: NSLocalizedString("Could not download wallpaper!", comment: ""), body: error.localizedDescription) + } } } } diff --git a/Pocket Poster/Views/ContentView.swift b/Pocket Poster/Views/ContentView.swift index 1cab930..9ae3b90 100644 --- a/Pocket Poster/Views/ContentView.swift +++ b/Pocket Poster/Views/ContentView.swift @@ -21,15 +21,12 @@ struct ContentView: View { private let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "" @State var showTendiesImporter: Bool = false - @State var selectedTendies: [URL]? = nil + var selectedTendies: Binding<[URL]?> @State var showErrorAlert = false @State var showSuccessAlert = false @State var lastError: String? - @State var downloadURL: String? = nil - @State var showDownloadAlert = false - var body: some View { NavigationStack { ScrollView { @@ -50,7 +47,7 @@ struct ContentView: View { .buttonStyle(TintedButton(color: .green, fullwidth: true)) .padding(10) - if let selectedTendies = selectedTendies, !selectedTendies.isEmpty { + if let selectedTendies = selectedTendies.wrappedValue, !selectedTendies.isEmpty { HStack { Text("Selected Tendies") .font(.headline) @@ -67,7 +64,7 @@ struct ContentView: View { } Section { - if selectedTendies != nil && !selectedTendies!.isEmpty { + if selectedTendies.wrappedValue != nil && !selectedTendies.wrappedValue!.isEmpty { if pbHash == "" { Text("Enter your PosterBoard app hash in Settings.") } else { @@ -77,8 +74,9 @@ struct ContentView: View { // DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { do { - try PosterBoardManager.applyTendies(selectedTendies!, appHash: pbHash) - selectedTendies = nil + try PosterBoardManager.applyTendies(selectedTendies.wrappedValue!, appHash: pbHash) + selectedTendies.wrappedValue = nil + try? FileManager.default.removeItem(at: PosterBoardManager.getTendiesStoreURL()) Haptic.shared.notify(.success) // UIApplication.shared.dismissAlert(animated: true) // TODO: Clear downloaded tendies @@ -114,10 +112,10 @@ struct ContentView: View { .fileImporter(isPresented: $showTendiesImporter, allowedContentTypes: [UTType(filenameExtension: "tendies", conformingTo: .data)!], allowsMultipleSelection: true, onCompletion: { result in switch result { case .success(let url): - if selectedTendies == nil { - selectedTendies = url + if selectedTendies.wrappedValue == nil { + selectedTendies.wrappedValue = url } else { - selectedTendies?.append(contentsOf: url) + selectedTendies.wrappedValue?.append(contentsOf: url) } case .failure(let error): lastError = error.localizedDescription @@ -136,70 +134,19 @@ struct ContentView: View { } message: { Text(lastError ?? "???") } - .alert("Download Tendies File", isPresented: $showDownloadAlert) { - Button("OK") { - downloadWallpaper() - } - Button("Cancel", role: .cancel) {} - } message: { - Text("Would you like to download the file \(DownloadManager.getWallpaperNameFromURL(string: downloadURL ?? "/Unknown"))?") - } - .onOpenURL(perform: { url in - // Download URL - if url.absoluteString.starts(with: "pocketposter://download") { - downloadURL = url.absoluteString.replacingOccurrences(of: "pocketposter://download?url=", with: "") - showDownloadAlert = true - } - // App Hash URL - else if url.absoluteString.starts(with: "pocketposter://app-hash?uuid=") { - pbHash = url.absoluteString.replacingOccurrences(of: "pocketposter://app-hash?uuid=", with: "") - } - else if url.pathExtension == "tendies" { - if selectedTendies == nil { - selectedTendies = [url] - } else { - selectedTendies?.append(url) - } - } - }) } func delete(at offsets: IndexSet) { - if selectedTendies != nil { - selectedTendies?.remove(atOffsets: offsets) + if selectedTendies.wrappedValue != nil { + selectedTendies.wrappedValue?.remove(atOffsets: offsets) } } - func downloadWallpaper() { - UIImpactFeedbackGenerator(style: .soft).impactOccurred() - UIApplication.shared.alert(title: NSLocalizedString("Downloading", comment: "") + " \(DownloadManager.getWallpaperNameFromURL(string: downloadURL ?? "/Unknown"))...", body: NSLocalizedString("Please wait", comment: ""), animated: false, withButton: false) - - Task { - do { - let newURL = try await DownloadManager.downloadFromURL(string: downloadURL!) - if selectedTendies == nil { - selectedTendies = [newURL] - } else { - selectedTendies?.append(newURL) - } - Haptic.shared.notify(.success) - UIApplication.shared.dismissAlert(animated: true) - } catch { - Haptic.shared.notify(.error) - UIApplication.shared.dismissAlert(animated: true) - UIApplication.shared.alert(title: NSLocalizedString("Could not download wallpaper!", comment: ""), body: error.localizedDescription) - } - } - } - - init() { + init(selectedTendies: Binding<[URL]?>) { + self.selectedTendies = selectedTendies // Fix file picker let fixMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.fix_init(forOpeningContentTypes:asCopy:)))! let origMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.init(forOpeningContentTypes:asCopy:)))! method_exchangeImplementations(origMethod, fixMethod) } } - -#Preview { - ContentView() -}