download themes using url scheme

this build enables iOS functionality only.
This commit is contained in:
Stuart Breckenridge
2021-09-19 17:48:29 +08:00
parent b43d8b6b28
commit 4fab4ffa7c
4 changed files with 131 additions and 10 deletions

View File

@@ -9,15 +9,16 @@
import UIKit
import UserNotifications
import Account
import Zip
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
class SceneDelegate: UIResponder, UIWindowSceneDelegate, URLSessionDownloadDelegate {
var window: UIWindow?
var window: UIWindow?
var coordinator = SceneCoordinator()
// UIWindowScene delegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// UIWindowScene delegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
window = UIWindow(windowScene: scene as! UIWindowScene)
window!.tintColor = AppAssets.primaryAccentColor
@@ -46,12 +47,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
return
}
if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
coordinator.handle(userActivity)
}
window!.makeKeyAndVisible()
}
}
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
appDelegate.resumeDatabaseProcessingIfNecessary()
@@ -79,9 +80,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
coordinator.resetFocus()
}
func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? {
func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? {
return coordinator.stateRestorationActivity
}
}
// API
@@ -89,7 +90,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
appDelegate.resumeDatabaseProcessingIfNecessary()
coordinator.handle(response)
}
func suspend() {
coordinator.suspend()
}
@@ -165,8 +166,69 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
let filename = context.url.standardizedFileURL.path
if filename.hasSuffix(ArticleTheme.nnwThemeSuffix) {
self.coordinator.importTheme(filename: filename)
return
}
// Handle theme URLs: netnewswire://theme/add?url={url}
guard let comps = URLComponents(url: context.url, resolvingAgainstBaseURL: false),
"theme" == comps.host,
let queryItems = comps.queryItems else {
return
}
if let providedThemeURL = queryItems.first(where: { $0.name == "url" })?.value {
if let themeURL = URL(string: providedThemeURL) {
let request = URLRequest(url: themeURL)
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
let downloadTask = session.downloadTask(with: request)
downloadTask.resume()
} else {
print("No theme URL")
return
}
} else {
return
}
}
}
// MARK: - URLSessionDownloadDelegate
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
var downloadDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
try? FileManager.default.createDirectory(at: downloadDirectory, withIntermediateDirectories: true, attributes: nil)
let tmpFileName = UUID().uuidString + ".zip"
downloadDirectory.appendPathComponent("\(tmpFileName)")
do {
try FileManager.default.moveItem(at: location, to: downloadDirectory)
var unzippedDir = downloadDirectory
unzippedDir = unzippedDir.deletingLastPathComponent()
unzippedDir.appendPathComponent("newtheme.nnwtheme")
try Zip.unzipFile(downloadDirectory, destination: unzippedDir, overwrite: true, password: nil, progress: nil, fileOutputHandler: nil)
try FileManager.default.removeItem(at: downloadDirectory)
let decoder = PropertyListDecoder()
let plistURL = URL(fileURLWithPath: unzippedDir.appendingPathComponent("Info.plist").path)
let data = try Data(contentsOf: plistURL)
let plist = try decoder.decode(ArticleThemePlist.self, from: data)
// rename
var renamedUnzippedDir = unzippedDir.deletingLastPathComponent()
renamedUnzippedDir.appendPathComponent(plist.name + ".nnwtheme")
if FileManager.default.fileExists(atPath: renamedUnzippedDir.path) {
try FileManager.default.removeItem(at: renamedUnzippedDir)
}
try FileManager.default.moveItem(at: unzippedDir, to: renamedUnzippedDir)
DispatchQueue.main.async {
self.coordinator.importTheme(filename: renamedUnzippedDir.path)
}
} catch {
print(error)
}
}