mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2024-12-22 23:58:36 +01:00
refactors downloader code for macOS & iOS
More consistent code across platforms.
This commit is contained in:
parent
eb8f27b457
commit
a1b01384d3
@ -125,6 +125,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(inspectableObjectsDidChange(_:)), name: .InspectableObjectsDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(importDownloadedTheme(_:)), name: .didEndDownloadingTheme, object: nil)
|
||||
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(didWakeNotification(_:)), name: NSWorkspace.didWakeNotification, object: nil)
|
||||
|
||||
appDelegate = self
|
||||
@ -375,6 +376,16 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
|
||||
@objc func didWakeNotification(_ note: Notification) {
|
||||
fireOldTimers()
|
||||
}
|
||||
|
||||
@objc func importDownloadedTheme(_ note: Notification) {
|
||||
guard let userInfo = note.userInfo,
|
||||
let url = userInfo["url"] as? URL else {
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
self.importTheme(filename: url.path)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Main Window
|
||||
|
||||
|
@ -56,40 +56,12 @@ extension AppDelegate : AppDelegateAppleEvents {
|
||||
if let themeURL = URL(string: themeURLString) {
|
||||
let request = URLRequest(url: themeURL)
|
||||
let task = URLSession.shared.downloadTask(with: request) { location, response, error in
|
||||
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)")
|
||||
if location == nil {
|
||||
guard let location = location else {
|
||||
return
|
||||
}
|
||||
|
||||
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.importTheme(filename: renamedUnzippedDir.path)
|
||||
}
|
||||
try ArticleThemeDownloader.handleFile(at: location)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
|
@ -140,6 +140,8 @@
|
||||
17D5F17124B0BC6700375168 /* SidebarToolbarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D5F17024B0BC6700375168 /* SidebarToolbarModel.swift */; };
|
||||
17D5F17224B0BC6700375168 /* SidebarToolbarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D5F17024B0BC6700375168 /* SidebarToolbarModel.swift */; };
|
||||
17D5F19524B0C1DD00375168 /* SidebarToolbarModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172199F024AB716900A31D04 /* SidebarToolbarModifier.swift */; };
|
||||
17D643B126F8A436008D4C05 /* ArticleThemeDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */; };
|
||||
17D643B226F8A436008D4C05 /* ArticleThemeDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */; };
|
||||
17D7586F2679C21800B17787 /* OnePasswordExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D7586E2679C21800B17787 /* OnePasswordExtension.m */; };
|
||||
17E0084625941887000C23F0 /* SizeCategories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E0084525941887000C23F0 /* SizeCategories.swift */; };
|
||||
17E4DBD624BFC53E00FE462A /* AdvancedPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E4DBD524BFC53E00FE462A /* AdvancedPreferencesModel.swift */; };
|
||||
@ -1608,6 +1610,7 @@
|
||||
17D232A724AFF10A0005F075 /* AddWebFeedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddWebFeedModel.swift; sourceTree = "<group>"; };
|
||||
17D3CEE2257C4D2300E74939 /* AddAccountSignUp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountSignUp.swift; sourceTree = "<group>"; };
|
||||
17D5F17024B0BC6700375168 /* SidebarToolbarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarToolbarModel.swift; sourceTree = "<group>"; };
|
||||
17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleThemeDownloader.swift; sourceTree = "<group>"; };
|
||||
17D7586C2679C21700B17787 /* NetNewsWire-iOS-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-iOS-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
17D7586D2679C21800B17787 /* OnePasswordExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnePasswordExtension.h; sourceTree = "<group>"; };
|
||||
17D7586E2679C21800B17787 /* OnePasswordExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OnePasswordExtension.m; sourceTree = "<group>"; };
|
||||
@ -3461,6 +3464,7 @@
|
||||
children = (
|
||||
849A97871ED9ECEF007D329B /* ArticleTheme.swift */,
|
||||
849A97881ED9ECEF007D329B /* ArticleThemesManager.swift */,
|
||||
17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */,
|
||||
179D280C26F73D83003B2E0A /* ArticleThemePlist.swift */,
|
||||
17071EEF26F8137400F5E71D /* ArticleTheme+Notifications.swift */,
|
||||
);
|
||||
@ -5589,6 +5593,7 @@
|
||||
512392BE24E33A3C00F11704 /* RedditSelectAccountTableViewController.swift in Sources */,
|
||||
515A517B243E90260089E588 /* ExtensionPoint.swift in Sources */,
|
||||
51C4529C22650A1000C03939 /* SingleFaviconDownloader.swift in Sources */,
|
||||
17D643B226F8A436008D4C05 /* ArticleThemeDownloader.swift in Sources */,
|
||||
51E595A6228CC36500FCC42B /* ArticleStatusSyncTimer.swift in Sources */,
|
||||
51F9F3F723DF6DB200A314FD /* ArticleIconSchemeHandler.swift in Sources */,
|
||||
512392C524E3451400F11704 /* TwitterEnterDetailTableViewController.swift in Sources */,
|
||||
@ -5721,6 +5726,7 @@
|
||||
8426118A1FCB67AA0086A189 /* WebFeedIconDownloader.swift in Sources */,
|
||||
84C9FC7B22629E1200D921D6 /* PreferencesControlsBackgroundView.swift in Sources */,
|
||||
84162A152038C12C00035290 /* MarkCommandValidationStatus.swift in Sources */,
|
||||
17D643B126F8A436008D4C05 /* ArticleThemeDownloader.swift in Sources */,
|
||||
84E95D241FB1087500552D99 /* ArticlePasteboardWriter.swift in Sources */,
|
||||
849A975B1ED9EB0D007D329B /* ArticleUtilities.swift in Sources */,
|
||||
849ADEE8235981A0000E1B81 /* NNW3OpenPanelAccessoryViewController.swift in Sources */,
|
||||
|
70
Shared/ArticleStyles/ArticleThemeDownloader.swift
Normal file
70
Shared/ArticleStyles/ArticleThemeDownloader.swift
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// ArticleThemeDownloader.swift
|
||||
// ArticleThemeDownloader
|
||||
//
|
||||
// Created by Stuart Breckenridge on 20/09/2021.
|
||||
// Copyright © 2021 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Zip
|
||||
|
||||
public struct ArticleThemeDownloader {
|
||||
|
||||
static func handleFile(at location: URL) throws {
|
||||
#if os(iOS)
|
||||
createDownloadDirectoryIfRequired()
|
||||
#endif
|
||||
let movedFileLocation = try moveTheme(from: location)
|
||||
let unzippedFileLocation = try unzipFile(at: movedFileLocation)
|
||||
let renamedFile = try renameFileToThemeName(at: unzippedFileLocation)
|
||||
NotificationCenter.default.post(name: .didEndDownloadingTheme, object: nil, userInfo: ["url" : renamedFile])
|
||||
}
|
||||
|
||||
private static func createDownloadDirectoryIfRequired() {
|
||||
let downloadDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
|
||||
try? FileManager.default.createDirectory(at: downloadDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
|
||||
private static func moveTheme(from location: URL) throws -> URL {
|
||||
#if os(iOS)
|
||||
var downloadDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
|
||||
#else
|
||||
var downloadDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
|
||||
#endif
|
||||
let tmpFileName = UUID().uuidString + ".zip"
|
||||
downloadDirectory.appendPathComponent("\(tmpFileName)")
|
||||
try FileManager.default.moveItem(at: location, to: downloadDirectory)
|
||||
return downloadDirectory
|
||||
}
|
||||
|
||||
private static func unzipFile(at location: URL) throws -> URL {
|
||||
var unzippedDir = location.deletingLastPathComponent()
|
||||
unzippedDir.appendPathComponent("newtheme.nnwtheme")
|
||||
do {
|
||||
try Zip.unzipFile(location, destination: unzippedDir, overwrite: true, password: nil, progress: nil, fileOutputHandler: nil)
|
||||
try FileManager.default.removeItem(at: location)
|
||||
return unzippedDir
|
||||
} catch {
|
||||
try? FileManager.default.removeItem(at: location)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private static func renameFileToThemeName(at location: URL) throws -> URL {
|
||||
let decoder = PropertyListDecoder()
|
||||
let plistURL = URL(fileURLWithPath: location.appendingPathComponent("Info.plist").path)
|
||||
let data = try Data(contentsOf: plistURL)
|
||||
let plist = try decoder.decode(ArticleThemePlist.self, from: data)
|
||||
var renamedUnzippedDir = location.deletingLastPathComponent()
|
||||
renamedUnzippedDir.appendPathComponent(plist.name + ".nnwtheme")
|
||||
if FileManager.default.fileExists(atPath: renamedUnzippedDir.path) {
|
||||
try FileManager.default.removeItem(at: renamedUnzippedDir)
|
||||
}
|
||||
try FileManager.default.moveItem(at: location, to: renamedUnzippedDir)
|
||||
return renamedUnzippedDir
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -29,6 +29,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange), name: UserDefaults.didChangeNotification, object: nil)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(importDownloadedTheme(_:)), name: .didEndDownloadingTheme, object: nil)
|
||||
|
||||
if let _ = connectionOptions.urlContexts.first?.url {
|
||||
window?.makeKeyAndVisible()
|
||||
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
|
||||
@ -184,19 +186,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
NotificationCenter.default.post(name: .didBeginDownloadingTheme, object: nil)
|
||||
}
|
||||
let task = URLSession.shared.downloadTask(with: request) { [weak self] location, response, error in
|
||||
guard let self = self, let location = location else { return }
|
||||
self.createDownloadDirectoryIfRequired()
|
||||
guard let self = self,
|
||||
let location = location else { return }
|
||||
|
||||
do {
|
||||
let movedFileLocation = try self.moveTheme(from: location)
|
||||
let unzippedFileLocation = try self.unzipFile(at: movedFileLocation)
|
||||
let renamedFileLocation = try self.renameFileToThemeName(at: unzippedFileLocation)
|
||||
DispatchQueue.main.async {
|
||||
NotificationCenter.default.post(name: .didEndDownloadingTheme, object: nil)
|
||||
self.coordinator.importTheme(filename: renamedFileLocation.path)
|
||||
}
|
||||
try ArticleThemeDownloader.handleFile(at: location)
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
NotificationCenter.default.post(name: .didEndDownloadingThemeWithError, object: nil, userInfo: ["error" : error])
|
||||
self.showAlert(error)
|
||||
}
|
||||
}
|
||||
@ -213,46 +209,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Theme Downloader
|
||||
private func createDownloadDirectoryIfRequired() {
|
||||
let downloadDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
|
||||
try? FileManager.default.createDirectory(at: downloadDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
|
||||
private func moveTheme(from location: URL) throws -> URL {
|
||||
var downloadDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
|
||||
let tmpFileName = UUID().uuidString + ".zip"
|
||||
downloadDirectory.appendPathComponent("\(tmpFileName)")
|
||||
try FileManager.default.moveItem(at: location, to: downloadDirectory)
|
||||
return downloadDirectory
|
||||
}
|
||||
|
||||
private func unzipFile(at location: URL) throws -> URL {
|
||||
var unzippedDir = location.deletingLastPathComponent()
|
||||
unzippedDir.appendPathComponent("newtheme.nnwtheme")
|
||||
do {
|
||||
try Zip.unzipFile(location, destination: unzippedDir, overwrite: true, password: nil, progress: nil, fileOutputHandler: nil)
|
||||
try FileManager.default.removeItem(at: location)
|
||||
return unzippedDir
|
||||
} catch {
|
||||
try? FileManager.default.removeItem(at: location)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private func renameFileToThemeName(at location: URL) throws -> URL {
|
||||
let decoder = PropertyListDecoder()
|
||||
let plistURL = URL(fileURLWithPath: location.appendingPathComponent("Info.plist").path)
|
||||
let data = try Data(contentsOf: plistURL)
|
||||
let plist = try decoder.decode(ArticleThemePlist.self, from: data)
|
||||
var renamedUnzippedDir = location.deletingLastPathComponent()
|
||||
renamedUnzippedDir.appendPathComponent(plist.name + ".nnwtheme")
|
||||
if FileManager.default.fileExists(atPath: renamedUnzippedDir.path) {
|
||||
try FileManager.default.removeItem(at: renamedUnzippedDir)
|
||||
}
|
||||
try FileManager.default.moveItem(at: location, to: renamedUnzippedDir)
|
||||
return renamedUnzippedDir
|
||||
}
|
||||
|
||||
private func showAlert(_ error: Error) {
|
||||
let alert = UIAlertController(title: NSLocalizedString("Error", comment: "Error"),
|
||||
@ -295,4 +252,15 @@ private extension SceneDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func importDownloadedTheme(_ note: Notification) {
|
||||
guard let userInfo = note.userInfo,
|
||||
let url = userInfo["url"] as? URL else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.coordinator.importTheme(filename: url.path)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user