Moves theme separation code to ArticleThemeManager

This cherry picks a change that is in ArticleThemeManager for macOS so that the theme pickers are using the same code to separate themes.
This commit is contained in:
Stuart Breckenridge
2023-02-09 17:29:48 +08:00
parent 69e20479b6
commit 7fd85f5ead
2 changed files with 75 additions and 19 deletions

View File

@@ -9,6 +9,9 @@
import Foundation
import RSCore
import Combine
#if canImport(AppKit)
import AppKit
#endif
public extension Notification.Name {
static let ArticleThemeNamesDidChangeNotification = Notification.Name("ArticleThemeNamesDidChangeNotification")
@@ -141,6 +144,73 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging, Observable
}
}
func themesByDeveloper() -> ([ArticleTheme], [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
}
// MARK : Private

View File

@@ -16,29 +16,24 @@ struct ArticleThemeManagerView: View {
@State private var showImportConfirmationAlert: (ArticleTheme?, Bool) = (nil, false)
@State private var showImportErrorAlert: (Error?, Bool) = (nil, false)
@State private var showImportSuccessAlert: Bool = false
@State private var installedFirstPartyThemes: [ArticleTheme] = []
@State private var installedThirdPartyThemes: [ArticleTheme] = []
var body: some View {
Form {
Section(header: Text("Built-in Themes", comment: "Section header for installed themes"), footer: Text("These themes cannot be deleted.", comment: "Section footer for installed themes.")) {
articleThemeRow(try! themeManager.articleThemeWithThemeName("Default"))
ForEach(0..<installedFirstPartyThemes.count, id: \.self) { i in
articleThemeRow(installedFirstPartyThemes[i])
articleThemeRow(try! themeManager.articleThemeWithThemeName(AppDefaults.defaultThemeName))
ForEach(0..<themeManager.themesByDeveloper().0.count, id: \.self) { i in
articleThemeRow(themeManager.themesByDeveloper().0[i])
}
}
Section(header: Text("Other Themes", comment: "Section header for third party themes")) {
ForEach(0..<installedThirdPartyThemes.count, id: \.self) { i in
articleThemeRow(installedThirdPartyThemes[i])
ForEach(0..<themeManager.themesByDeveloper().1.count, id: \.self) { i in
articleThemeRow(themeManager.themesByDeveloper().1[i])
}
}
}
.navigationTitle(Text("Article Themes", comment: "Navigation bar title for Article Themes"))
.task {
updateThemesArrays()
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
@@ -142,9 +137,6 @@ struct ArticleThemeManagerView: View {
actions: { }, message: {
Text("\(showImportErrorAlert.0?.localizedDescription ?? "")")
})
.onReceive(themeManager.objectWillChange) { _ in
updateThemesArrays()
}
}
func articleThemeRow(_ theme: ArticleTheme) -> some View {
@@ -181,12 +173,6 @@ struct ArticleThemeManagerView: View {
}
}
}
private func updateThemesArrays() {
installedFirstPartyThemes = themeManager.themeNames.map({ try? themeManager.articleThemeWithThemeName($0) }).compactMap({ $0 }).filter({ $0.isAppTheme }).sorted(by: { $0.name < $1.name })
installedThirdPartyThemes = themeManager.themeNames.map({ try? themeManager.articleThemeWithThemeName($0) }).compactMap({ $0 }).filter({ !$0.isAppTheme }).sorted(by: { $0.name < $1.name })
}
}
struct ArticleThemeImporterView_Previews: PreviewProvider {