diff --git a/Pocket Poster/Controllers/DownloadManager.swift b/Pocket Poster/Controllers/DownloadManager.swift new file mode 100644 index 0000000..9766a07 --- /dev/null +++ b/Pocket Poster/Controllers/DownloadManager.swift @@ -0,0 +1,31 @@ +// +// DownloadManager.swift +// Pocket Poster +// +// Created by lemin on 6/1/25. +// + +import Foundation + +class DownloadManager { + static func getWallpaperNameFromURL(string url: String) -> String { + return String(url.split(separator: "/").last ?? "Unknown") + } + + static func downloadFromURL(_ url: URL) async throws -> URL { + print("Downloading from \(url.absoluteString)") + + let request = URLRequest(url: url) + + 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)) + try data.write(to: newURL) + return newURL + } + + static func downloadFromURL(string path: String) async throws -> URL { + guard let url = URL(string: path) else { throw URLError(.unknown) } + return try await downloadFromURL(url) + } +} diff --git a/Pocket Poster/Extensions/Alert++.swift b/Pocket Poster/Extensions/Alert++.swift new file mode 100644 index 0000000..f20e60e --- /dev/null +++ b/Pocket Poster/Extensions/Alert++.swift @@ -0,0 +1,72 @@ +// +// Alert++.swift +// Cowabunga +// +// Created by sourcelocation on 30/01/2023. +// + +import UIKit + +// credit: sourcelocation & TrollTools +var currentUIAlertController: UIAlertController? + + +fileprivate let errorString = NSLocalizedString("Error", comment: "") +fileprivate let okString = NSLocalizedString("OK", comment: "") +fileprivate let cancelString = NSLocalizedString("Cancel", comment: "") + +extension UIApplication { + + func dismissAlert(animated: Bool) { + DispatchQueue.main.async { + currentUIAlertController?.dismiss(animated: animated) + } + } + func alert(title: String = errorString, body: String, animated: Bool = true, withButton: Bool = true) { + DispatchQueue.main.async { + var body = body + + if title == errorString { + // append debug info + let device = UIDevice.current + let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" + let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "" + let systemVersion = device.systemVersion + body += "\n\(device.systemName) \(systemVersion), version \(appVersion) build \(appBuild) escaped=\(FileManager.default.isReadableFile(atPath: "/var/mobile"))" + } + + currentUIAlertController = UIAlertController(title: title, message: body, preferredStyle: .alert) + if withButton { currentUIAlertController?.addAction(.init(title: okString, style: .cancel)) } + self.present(alert: currentUIAlertController!) + } + } + func confirmAlert(title: String = errorString, body: String, confirmTitle: String = okString, onOK: @escaping () -> (), noCancel: Bool) { + DispatchQueue.main.async { + currentUIAlertController = UIAlertController(title: title, message: body, preferredStyle: .alert) + if !noCancel { + currentUIAlertController?.addAction(.init(title: cancelString, style: .cancel)) + } + currentUIAlertController?.addAction(.init(title: confirmTitle, style: noCancel ? .cancel : .default, handler: { _ in + onOK() + })) + self.present(alert: currentUIAlertController!) + } + } + func change(title: String = errorString, body: String) { + DispatchQueue.main.async { + currentUIAlertController?.title = title + currentUIAlertController?.message = body + } + } + + func present(alert: UIAlertController) { + if var topController = self.windows[0].rootViewController { + while let presentedViewController = topController.presentedViewController { + topController = presentedViewController + } + + topController.present(alert, animated: true) + // topController should now be your topmost view controller + } + } +} diff --git a/Pocket Poster/Extensions/Haptic.swift b/Pocket Poster/Extensions/Haptic.swift new file mode 100644 index 0000000..42c448f --- /dev/null +++ b/Pocket Poster/Extensions/Haptic.swift @@ -0,0 +1,23 @@ + // + // Haptic++.swift + // PsychicPaper + // + // Created by Hariz Shirazi on 2023-02-04. + // + +import Foundation +import UIKit + +class Haptic { + static let shared = Haptic() + + private init() { } + + func play(_ feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle) { + UIImpactFeedbackGenerator(style: feedbackStyle).impactOccurred() + } + + func notify(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) { + UINotificationFeedbackGenerator().notificationOccurred(feedbackType) + } +} diff --git a/Pocket Poster/Views/ContentView.swift b/Pocket Poster/Views/ContentView.swift index 8d2863d..19b57db 100644 --- a/Pocket Poster/Views/ContentView.swift +++ b/Pocket Poster/Views/ContentView.swift @@ -27,6 +27,9 @@ struct ContentView: View { @State var showSuccessAlert = false @State var lastError: String? + @State var downloadURL: String? = nil + @State var showDownloadAlert = false + var body: some View { NavigationStack { ScrollView { @@ -120,8 +123,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 \(downloadURL ?? "UNKNOWN")?") + } .onOpenURL(perform: { url in - if url.pathExtension == "tendies" { + if url.absoluteString.starts(with: "pocketposter://download") { + downloadURL = url.absoluteString.replacingOccurrences(of: "pocketposter://download?url=", with: "") + } + else if url.pathExtension == "tendies" { if selectedTendies == nil { selectedTendies = [] } @@ -136,6 +150,27 @@ struct ContentView: View { } } + 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 = [] + } + 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() { // Fix file picker let fixMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.fix_init(forOpeningContentTypes:asCopy:)))! diff --git a/Pocket Poster/Views/SettingsView.swift b/Pocket Poster/Views/SettingsView.swift index f354051..285b715 100644 --- a/Pocket Poster/Views/SettingsView.swift +++ b/Pocket Poster/Views/SettingsView.swift @@ -24,7 +24,7 @@ struct SettingsView: View { .foregroundColor(.primary) Spacer() } - TextField("App Hash", text: $pbHash) + TextField("Enter App Hash", text: $pbHash) .textFieldStyle(RoundedBorderTextFieldStyle()) .font(.system(.body, design: .monospaced)) } diff --git a/Pocket-Poster-Info.plist b/Pocket-Poster-Info.plist index 010d20e..8073dc1 100644 --- a/Pocket-Poster-Info.plist +++ b/Pocket-Poster-Info.plist @@ -15,6 +15,19 @@ + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + com.leemin.pocketposter + CFBundleURLSchemes + + pocketposter + + + UIFileSharingEnabled UTExportedTypeDeclarations