diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-11 15:13:58 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-11 15:13:58 +0200 |
| commit | ee5f1ff07ebf275becb47d5a9159130b2190c485 (patch) | |
| tree | df5996ecc1e446e8aa6185e04b2995238b58a2af | |
| parent | 49766f0c78015831f8be57349317f0d1c8228327 (diff) | |
More control over theme
| -rw-r--r-- | Map/Assets.xcassets/Colors/Secondary.colorset/Contents.json | 38 | ||||
| -rw-r--r-- | Map/Data/UserPreferences.swift | 38 | ||||
| -rw-r--r-- | Map/Localizable.xcstrings | 44 | ||||
| -rw-r--r-- | Map/MapApp.swift | 26 | ||||
| -rw-r--r-- | Map/Presentation/Preferences/GeneralPreferencesView.swift | 23 | ||||
| -rw-r--r-- | Map/Presentation/Theme/Color+theme.swift | 1 |
6 files changed, 169 insertions, 1 deletions
diff --git a/Map/Assets.xcassets/Colors/Secondary.colorset/Contents.json b/Map/Assets.xcassets/Colors/Secondary.colorset/Contents.json new file mode 100644 index 0000000..02a3b46 --- /dev/null +++ b/Map/Assets.xcassets/Colors/Secondary.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.488", + "green" : "0.500", + "red" : "0.434" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xE3", + "green" : "0xE6", + "red" : "0xDA" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Map/Data/UserPreferences.swift b/Map/Data/UserPreferences.swift index 01c4f37..761c5a8 100644 --- a/Map/Data/UserPreferences.swift +++ b/Map/Data/UserPreferences.swift @@ -16,6 +16,23 @@ import Foundation // MARK: - Enums +enum AppearanceStyle: String, CaseIterable, Codable { + case system = "system" + case light = "light" + case dark = "dark" + + var localizedName: String { + switch self { + case .system: + return String(localized: "preferences.appearance.style.system") + case .light: + return String(localized: "preferences.appearance.style.light") + case .dark: + return String(localized: "preferences.appearance.style.dark") + } + } +} + enum QuickLookPreviewStyle: String, CaseIterable, Codable { case map = "map" case highlightedText = "highlighted_text" @@ -35,6 +52,9 @@ enum QuickLookPreviewStyle: String, CaseIterable, Codable { // MARK: - JSON Export/Import Structures struct UserPreferencesJSON: Codable { + // MARK: - Appearance Preferences + var appearanceStyle: String? + // MARK: - Map Preferences var showMapBackground: Bool? var useCustomFont: Bool? @@ -66,6 +86,9 @@ struct UserPreferencesJSON: Codable { struct UserPreferences: Codable { + // MARK: - Appearance Preferences + var appearanceStyle: String + // MARK: - Map Preferences var showMapBackground: Bool var useCustomFont: Bool @@ -96,6 +119,8 @@ struct UserPreferences: Codable { // MARK: - Default Values struct Defaults { + static let appearanceStyle = AppearanceStyle.system.rawValue + static let showMapBackground = true static let useCustomFont = false static let customFontName = "Helvetica" @@ -141,6 +166,8 @@ struct UserPreferences: Codable { // MARK: - Initialization init() { + self.appearanceStyle = Defaults.appearanceStyle + self.showMapBackground = Defaults.showMapBackground self.useCustomFont = Defaults.useCustomFont self.customFontName = Defaults.customFontName @@ -171,6 +198,7 @@ struct UserPreferences: Codable { do { // Convert to JSON-friendly format let jsonPrefs = UserPreferencesJSON( + appearanceStyle: appearanceStyle, showMapBackground: showMapBackground, useCustomFont: useCustomFont, customFontName: customFontName, @@ -204,6 +232,9 @@ struct UserPreferences: Codable { // Convert from JSON format back to UserPreferences // Only update values that are present in the JSON (partial updates) + if let value = jsonPrefs.appearanceStyle { + self.appearanceStyle = value + } if let value = jsonPrefs.showMapBackground { self.showMapBackground = value } @@ -301,6 +332,9 @@ struct UserPreferences: Codable { let defaults = UserDefaults.standard let sharedDefaults = UserDefaults(suiteName: "group.systems.tranquil.Map") + // Appearance Preferences + defaults.set(appearanceStyle, forKey: "appearanceStyle") + // Map Preferences defaults.set(showMapBackground, forKey: "showMapBackground") defaults.set(useCustomFont, forKey: "useCustomFont") @@ -337,6 +371,10 @@ struct UserPreferences: Codable { var preferences = UserPreferences() + // Appearance Preferences + preferences.appearanceStyle = + defaults.object(forKey: "appearanceStyle") as? String ?? Defaults.appearanceStyle + // Map Preferences preferences.showMapBackground = defaults.object(forKey: "showMapBackground") as? Bool ?? Defaults.showMapBackground diff --git a/Map/Localizable.xcstrings b/Map/Localizable.xcstrings index dda0deb..ffede54 100644 --- a/Map/Localizable.xcstrings +++ b/Map/Localizable.xcstrings @@ -548,6 +548,50 @@ } } }, + "preferences.appearance.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appearance:" + } + } + } + }, + "preferences.appearance.style.system" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Match system" + } + } + } + }, + "preferences.appearance.style.light" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Light" + } + } + } + }, + "preferences.appearance.style.dark" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dark" + } + } + } + }, "preferences.general.preferences.title" : { "extractionState" : "manual", "localizations" : { diff --git a/Map/MapApp.swift b/Map/MapApp.swift index 78b0423..b66d715 100644 --- a/Map/MapApp.swift +++ b/Map/MapApp.swift @@ -22,6 +22,14 @@ struct MapApp: App { private let updaterController: SPUStandardUpdaterController = SPUStandardUpdaterController( startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil) + @AppStorage("appearanceStyle") private var appearanceStyle: String = UserPreferences.Defaults + .appearanceStyle + + init() { + // Apply appearance setting at app launch + applyAppearanceStyle() + } + var body: some Scene { DocumentGroup(newDocument: MapDocument(text: nil)) { file in MapEditor(document: file.$document, url: file.fileURL) @@ -37,6 +45,24 @@ struct MapApp: App { Settings { PreferencesWindow() } + .onChange(of: appearanceStyle) { _, newValue in + applyAppearanceStyle() + } + } + + private func applyAppearanceStyle() { + guard let style = AppearanceStyle(rawValue: appearanceStyle) else { return } + + DispatchQueue.main.async { + switch style { + case .system: + NSApp.appearance = nil + case .light: + NSApp.appearance = NSAppearance(named: .aqua) + case .dark: + NSApp.appearance = NSAppearance(named: .darkAqua) + } + } } } diff --git a/Map/Presentation/Preferences/GeneralPreferencesView.swift b/Map/Presentation/Preferences/GeneralPreferencesView.swift index b5b781d..31e54c2 100644 --- a/Map/Presentation/Preferences/GeneralPreferencesView.swift +++ b/Map/Presentation/Preferences/GeneralPreferencesView.swift @@ -25,11 +25,32 @@ struct GeneralPreferencesView: View { @State private var showingExportFailedAlert = false @State private var exportShouldReset = false + @AppStorage("appearanceStyle") private var appearanceStyle: String = UserPreferences.Defaults + .appearanceStyle @AppStorage("quickLookPreviewStyle", store: UserDefaults(suiteName: "group.systems.tranquil.Map")) private var quickLookPreviewStyle: String = UserPreferences.Defaults.quickLookPreviewStyle var body: some View { VStack(alignment: .center, spacing: Dimensions.Spacing.loose) { + // Appearance section + HStack(alignment: .firstTextBaseline, spacing: Dimensions.Spacing.regular) { + Text("preferences.appearance.title") + .font(.Theme.Body.emphasized) + .frame(maxWidth: 250, alignment: .trailing) + + Picker("", selection: $appearanceStyle) { + ForEach(AppearanceStyle.allCases, id: \.rawValue) { style in + Text(style.localizedName) + .tag(style.rawValue) + } + } + .pickerStyle(.radioGroup) + .frame(maxWidth: 250, alignment: .leading) + .frame(maxWidth: .infinity, alignment: .leading) + } + + Divider() + // QuickLook section HStack(alignment: .firstTextBaseline, spacing: Dimensions.Spacing.regular) { Text("preferences.quick_look.title") @@ -95,7 +116,7 @@ struct GeneralPreferencesView: View { label: { Text("preferences.general.preferences.reset") .font(.Theme.Body.regular) - .foregroundColor(Color.Theme.jasperRed) + .foregroundColor(Color.Theme.UI.secondary) } ) .buttonStyle(.borderless) diff --git a/Map/Presentation/Theme/Color+theme.swift b/Map/Presentation/Theme/Color+theme.swift index 4433dc1..7f6995d 100644 --- a/Map/Presentation/Theme/Color+theme.swift +++ b/Map/Presentation/Theme/Color+theme.swift @@ -35,6 +35,7 @@ extension Color { struct UI { static let foreground = Color("Foreground") static let background = Color("Background") + static let secondary = Color("Secondary") static let accent = Color.Theme.jasperRed } |