aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-07-11 15:13:58 +0200
committerRuben Beltran del Rio <git@r.bdr.sh>2025-07-11 15:13:58 +0200
commitee5f1ff07ebf275becb47d5a9159130b2190c485 (patch)
treedf5996ecc1e446e8aa6185e04b2995238b58a2af
parent49766f0c78015831f8be57349317f0d1c8228327 (diff)
More control over theme
-rw-r--r--Map/Assets.xcassets/Colors/Secondary.colorset/Contents.json38
-rw-r--r--Map/Data/UserPreferences.swift38
-rw-r--r--Map/Localizable.xcstrings44
-rw-r--r--Map/MapApp.swift26
-rw-r--r--Map/Presentation/Preferences/GeneralPreferencesView.swift23
-rw-r--r--Map/Presentation/Theme/Color+theme.swift1
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
}