diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index ad024b046..52fc0cbf9 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -817,7 +817,7 @@ internal extension AppDelegate { guard let window = mainWindowController?.window else { return } do { - let theme = try ArticleTheme(path: filename) + let theme = try ArticleTheme(path: filename, isAppTheme: false) let alert = NSAlert() alert.alertStyle = .informational diff --git a/Shared/ArticleStyles/ArticleTheme.swift b/Shared/ArticleStyles/ArticleTheme.swift index e40bde46f..302c45a53 100644 --- a/Shared/ArticleStyles/ArticleTheme.swift +++ b/Shared/ArticleStyles/ArticleTheme.swift @@ -19,6 +19,7 @@ struct ArticleTheme: Equatable { let path: String? let template: String? let css: String? + let isAppTheme: Bool var name: String { guard let path = path else { return Self.defaultThemeName } @@ -49,9 +50,11 @@ struct ArticleTheme: Equatable { let templatePath = Bundle.main.path(forResource: "template", ofType: "html")! template = Self.stringAtPath(templatePath)! + + isAppTheme = true } - init(path: String) throws { + init(path: String, isAppTheme: Bool) throws { self.path = path let infoPath = (path as NSString).appendingPathComponent("Info.plist") @@ -68,6 +71,8 @@ struct ArticleTheme: Equatable { let templatePath = (path as NSString).appendingPathComponent("template.html") self.template = Self.stringAtPath(templatePath) + + self.isAppTheme = isAppTheme } static func stringAtPath(_ f: String) -> String? { diff --git a/Shared/ArticleStyles/ArticleThemesManager.swift b/Shared/ArticleStyles/ArticleThemesManager.swift index e2205240a..c23f1d7ae 100644 --- a/Shared/ArticleStyles/ArticleThemesManager.swift +++ b/Shared/ArticleStyles/ArticleThemesManager.swift @@ -48,6 +48,10 @@ final class ArticleThemesManager: NSObject, NSFilePresenter { } } + var themes: [ArticleTheme] { + return themeNames.compactMap { articleThemeWithThemeName($0) } + } + init(folderPath: String) { self.folderPath = folderPath self.currentTheme = ArticleTheme.defaultTheme @@ -61,15 +65,6 @@ final class ArticleThemesManager: NSObject, NSFilePresenter { abort() } - let themeFilenames = Bundle.main.paths(forResourcesOfType: ArticleTheme.nnwThemeSuffix, inDirectory: nil) - let installedThemes = readInstalledThemes() ?? [String: Date]() - for themeFilename in themeFilenames { - let themeName = ArticleTheme.themeNameForPath(themeFilename) - if !installedThemes.keys.contains(themeName) { - try? importTheme(filename: themeFilename) - } - } - updateThemeNames() updateCurrentTheme() @@ -98,11 +93,6 @@ final class ArticleThemesManager: NSObject, NSFilePresenter { } try FileManager.default.copyItem(atPath: filename, toPath: toFilename) - - let themeName = ArticleTheme.themeNameForPath(filename) - var installedThemes = readInstalledThemes() ?? [String: Date]() - installedThemes[themeName] = Date() - writeInstalledThemes(installedThemes) } func deleteTheme(themeName: String) { @@ -118,8 +108,14 @@ final class ArticleThemesManager: NSObject, NSFilePresenter { private extension ArticleThemesManager { func updateThemeNames() { - let updatedThemeNames = allThemePaths(folderPath).map { ArticleTheme.themeNameForPath($0) } - let sortedThemeNames = updatedThemeNames.sorted(by: { $0.compare($1, options: .caseInsensitive) == .orderedAscending }) + let appThemeFilenames = Bundle.main.paths(forResourcesOfType: ArticleTheme.nnwThemeSuffix, inDirectory: nil) + let appThemeNames = Set(appThemeFilenames.map { ArticleTheme.themeNameForPath($0) }) + + let installedThemeNames = Set(allThemePaths(folderPath).map { ArticleTheme.themeNameForPath($0) }) + + let allThemeNames = appThemeNames.union(installedThemeNames) + + let sortedThemeNames = allThemeNames.sorted(by: { $0.compare($1, options: .caseInsensitive) == .orderedAscending }) if sortedThemeNames != themeNames { themeNames = sortedThemeNames } @@ -130,11 +126,20 @@ private extension ArticleThemesManager { return ArticleTheme.defaultTheme } - guard let path = pathForThemeName(themeName, folder: folderPath) else { + let path: String + let isAppTheme: Bool + if let appThemePath = Bundle.main.url(forResource: themeName, withExtension: ArticleTheme.nnwThemeSuffix)?.path { + path = appThemePath + isAppTheme = true + } else if let installedPath = pathForThemeName(themeName, folder: folderPath) { + path = installedPath + isAppTheme = false + } else { return nil } + do { - return try ArticleTheme(path: path) + return try ArticleTheme(path: path, isAppTheme: isAppTheme) } catch { NotificationCenter.default.post(name: .didFailToImportThemeWithError, object: nil, userInfo: ["error": error]) return nil @@ -178,14 +183,4 @@ private extension ArticleThemesManager { return nil } - func readInstalledThemes() -> [String: Date]? { - let filePath = (folderPath as NSString).appendingPathComponent("InstalledThemes.plist") - return NSDictionary(contentsOfFile: filePath) as? [String: Date] - } - - func writeInstalledThemes(_ dict: [String: Date]) { - let filePath = (folderPath as NSString).appendingPathComponent("InstalledThemes.plist") - (dict as NSDictionary).write(toFile: filePath, atomically: true) - } - } diff --git a/iOS/Settings/ArticleThemeImporter.swift b/iOS/Settings/ArticleThemeImporter.swift index 5eb8c8a6f..bfc8ff23a 100644 --- a/iOS/Settings/ArticleThemeImporter.swift +++ b/iOS/Settings/ArticleThemeImporter.swift @@ -11,7 +11,7 @@ import UIKit struct ArticleThemeImporter { static func importTheme(controller: UIViewController, filename: String) throws { - let theme = try ArticleTheme(path: filename) + let theme = try ArticleTheme(path: filename, isAppTheme: false) let localizedTitleText = NSLocalizedString("Install theme “%@” by %@?", comment: "Theme message text") let title = NSString.localizedStringWithFormat(localizedTitleText as NSString, theme.name, theme.creatorName) as String