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