diff --git a/Shared/ArticleStyles/ArticleThemesManager.swift b/Shared/ArticleStyles/ArticleThemesManager.swift index 33a95736a..71d24842d 100644 --- a/Shared/ArticleStyles/ArticleThemesManager.swift +++ b/Shared/ArticleStyles/ArticleThemesManager.swift @@ -144,6 +144,73 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging, Observable return try ArticleTheme(path: path, isAppTheme: isAppTheme) } + + func themesByDeveloper() -> (builtIn: [ArticleTheme], other: [ArticleTheme]) { + let installedProvidedThemes = themeNames.map({ try? articleThemeWithThemeName($0) }).compactMap({ $0 }).filter({ $0.isAppTheme }).sorted(by: { $0.name < $1.name }).filter({ $0.name != AppDefaults.defaultThemeName }) + + let installedOtherThemes = themeNames.map({ try? articleThemeWithThemeName($0) }).compactMap({ $0 }).filter({ !$0.isAppTheme }).sorted(by: { $0.name < $1.name }) + + return (installedProvidedThemes, installedOtherThemes) + } + + #if os(macOS) + func articleThemesMenu(for popUpButton: NSPopUpButton?) -> NSMenu { + let menu = NSMenu() + menu.autoenablesItems = false + menu.removeAllItems() + + let defaultMenuItem = NSMenuItem() + defaultMenuItem.title = ArticleTheme.defaultTheme.name + defaultMenuItem.action = #selector(updateThemeSelection(_:)) + defaultMenuItem.state = currentTheme.name == defaultMenuItem.title ? .on : .off + defaultMenuItem.target = self + menu.addItem(defaultMenuItem) + menu.addItem(NSMenuItem.separator()) + + let rancheroHeading = NSMenuItem(title: "Built-in Themes", action: nil, keyEquivalent: "") + rancheroHeading.attributedTitle = NSAttributedString(string: "Built-in Themes", attributes: [NSAttributedString.Key.foregroundColor : NSColor.secondaryLabelColor, NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)]) + rancheroHeading.isEnabled = false + menu.addItem(rancheroHeading) + + let installedThemes = ArticleThemesManager.shared.themesByDeveloper() + + for theme in installedThemes.0 { + let item = NSMenuItem() + item.title = theme.name + item.action = #selector(updateThemeSelection(_:)) + item.state = currentTheme.name == theme.name ? .on : .off + item.target = self + menu.addItem(item) + } + + menu.addItem(NSMenuItem.separator()) + + let thirdPartyHeading = NSMenuItem(title: "Other Themes", action: nil, keyEquivalent: "") + thirdPartyHeading.attributedTitle = NSAttributedString(string: "Other Themes", attributes: [NSAttributedString.Key.foregroundColor : NSColor.secondaryLabelColor, NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)]) + thirdPartyHeading.isEnabled = false + menu.addItem(thirdPartyHeading) + + for theme in installedThemes.1 { + let item = NSMenuItem() + item.title = theme.name + item.action = #selector(updateThemeSelection(_:)) + item.state = currentTheme.name == theme.name ? .on : .off + item.target = self + menu.addItem(item) + } + popUpButton?.selectItem(withTitle: ArticleThemesManager.shared.currentThemeName) + if popUpButton?.indexOfSelectedItem == -1 { + popUpButton?.selectItem(withTitle: ArticleTheme.defaultTheme.name) + } + return menu + } + + @objc + func updateThemeSelection(_ menuItem: NSMenuItem) { + currentThemeName = menuItem.title + } + + #endif func deleteTheme(themeName: String) { if let filename = pathForThemeName(themeName, folder: folderPath) {