@@ -99,95 +99,62 @@ struct GeneralSettings: Codable, Equatable {
9999
100100// MARK: - Appearance Settings
101101
102- /// App theme options
103- enum AppTheme : String , Codable , CaseIterable , Identifiable {
104- case system = " system "
105- case light = " light "
106- case dark = " dark "
107-
108- var id : String { rawValue }
102+ /// Controls NSApp.appearance independent of the active theme.
103+ enum AppAppearanceMode : String , Codable , CaseIterable {
104+ case light
105+ case dark
106+ case auto
109107
110108 var displayName : String {
111109 switch self {
112- case . system: return String ( localized: " System " )
113110 case . light: return String ( localized: " Light " )
114111 case . dark: return String ( localized: " Dark " )
115- }
116- }
117-
118- /// Apply this theme to the app
119- func apply( ) {
120- guard let app = NSApp else { return }
121- switch self {
122- case . system:
123- app. appearance = nil
124- case . light:
125- app. appearance = NSAppearance ( named: . aqua)
126- case . dark:
127- app. appearance = NSAppearance ( named: . darkAqua)
112+ case . auto: return String ( localized: " Auto " )
128113 }
129114 }
130115}
131116
132- /// Accent color options
133- enum AccentColorOption : String , Codable , CaseIterable , Identifiable {
134- case system = " system "
135- case blue = " blue "
136- case purple = " purple "
137- case pink = " pink "
138- case red = " red "
139- case orange = " orange "
140- case yellow = " yellow "
141- case green = " green "
142- case graphite = " graphite "
117+ /// Appearance settings
118+ struct AppearanceSettings : Codable , Equatable {
119+ var activeThemeId : String
120+ var appearanceMode : AppAppearanceMode
143121
144- var id : String { rawValue }
122+ static let `default` = AppearanceSettings (
123+ activeThemeId: " tablepro.default-light " ,
124+ appearanceMode: . auto
125+ )
145126
146- var displayName : String {
147- switch self {
148- case . system: return String ( localized: " System " )
149- case . blue: return String ( localized: " Blue " )
150- case . purple: return String ( localized: " Purple " )
151- case . pink: return String ( localized: " Pink " )
152- case . red: return String ( localized: " Red " )
153- case . orange: return String ( localized: " Orange " )
154- case . yellow: return String ( localized: " Yellow " )
155- case . green: return String ( localized: " Green " )
156- case . graphite: return String ( localized: " Graphite " )
157- }
127+ init ( activeThemeId: String = " tablepro.default-light " , appearanceMode: AppAppearanceMode = . auto) {
128+ self . activeThemeId = activeThemeId
129+ self . appearanceMode = appearanceMode
158130 }
159131
160- /// Color for display in settings picker (always returns a concrete color)
161- var color : Color {
162- switch self {
163- case . system: return . accentColor
164- case . blue: return . blue
165- case . purple: return . purple
166- case . pink: return . pink
167- case . red: return . red
168- case . orange: return . orange
169- case . yellow: return . yellow
170- case . green: return . green
171- case . graphite: return . gray
132+ init ( from decoder: Decoder ) throws {
133+ let container = try decoder. container ( keyedBy: CodingKeys . self)
134+ // Migration: try new field first, then fall back to old theme field
135+ if let themeId = try container. decodeIfPresent ( String . self, forKey: . activeThemeId) {
136+ activeThemeId = themeId
137+ } else if let oldTheme = try ? container. decodeIfPresent ( String . self, forKey: . theme) {
138+ // Migrate from old AppTheme enum
139+ switch oldTheme {
140+ case " dark " : activeThemeId = " tablepro.default-dark "
141+ default : activeThemeId = " tablepro.default-light "
142+ }
143+ } else {
144+ activeThemeId = " tablepro.default-light "
172145 }
146+ appearanceMode = try container. decodeIfPresent ( AppAppearanceMode . self, forKey: . appearanceMode) ?? . auto
173147 }
174148
175- /// Tint color for applying to views (nil means use system default)
176- /// Derived from `color` property for DRY - only .system returns nil
177- var tintColor : Color ? {
178- self == . system ? nil : color
149+ private enum CodingKeys : String , CodingKey {
150+ case activeThemeId, theme, appearanceMode
179151 }
180- }
181-
182- /// Appearance settings
183- struct AppearanceSettings : Codable , Equatable {
184- var theme : AppTheme
185- var accentColor : AccentColorOption
186152
187- static let `default` = AppearanceSettings (
188- theme: . system,
189- accentColor: . system
190- )
153+ func encode( to encoder: Encoder ) throws {
154+ var container = encoder. container ( keyedBy: CodingKeys . self)
155+ try container. encode ( activeThemeId, forKey: . activeThemeId)
156+ try container. encode ( appearanceMode, forKey: . appearanceMode)
157+ }
191158}
192159
193160// MARK: - Editor Settings
@@ -243,8 +210,6 @@ enum EditorFont: String, Codable, CaseIterable, Identifiable {
243210
244211/// Editor settings
245212struct EditorSettings : Codable , Equatable {
246- var fontFamily : EditorFont
247- var fontSize : Int // 11-18pt
248213 var showLineNumbers : Bool
249214 var highlightCurrentLine : Bool
250215 var tabWidth : Int // 2, 4, or 8 spaces
@@ -253,8 +218,6 @@ struct EditorSettings: Codable, Equatable {
253218 var vimModeEnabled : Bool
254219
255220 static let `default` = EditorSettings (
256- fontFamily: . systemMono,
257- fontSize: 13 ,
258221 showLineNumbers: true ,
259222 highlightCurrentLine: true ,
260223 tabWidth: 4 ,
@@ -264,17 +227,13 @@ struct EditorSettings: Codable, Equatable {
264227 )
265228
266229 init (
267- fontFamily: EditorFont = . systemMono,
268- fontSize: Int = 13 ,
269230 showLineNumbers: Bool = true ,
270231 highlightCurrentLine: Bool = true ,
271232 tabWidth: Int = 4 ,
272233 autoIndent: Bool = true ,
273234 wordWrap: Bool = false ,
274235 vimModeEnabled: Bool = false
275236 ) {
276- self . fontFamily = fontFamily
277- self . fontSize = fontSize
278237 self . showLineNumbers = showLineNumbers
279238 self . highlightCurrentLine = highlightCurrentLine
280239 self . tabWidth = tabWidth
@@ -285,21 +244,15 @@ struct EditorSettings: Codable, Equatable {
285244
286245 init ( from decoder: Decoder ) throws {
287246 let container = try decoder. container ( keyedBy: CodingKeys . self)
288- fontFamily = try container. decode ( EditorFont . self, forKey: . fontFamily)
289- fontSize = try container. decode ( Int . self, forKey: . fontSize)
290- showLineNumbers = try container. decode ( Bool . self, forKey: . showLineNumbers)
291- highlightCurrentLine = try container. decode ( Bool . self, forKey: . highlightCurrentLine)
292- tabWidth = try container. decode ( Int . self, forKey: . tabWidth)
293- autoIndent = try container. decode ( Bool . self, forKey: . autoIndent)
294- wordWrap = try container. decode ( Bool . self, forKey: . wordWrap)
247+ // Old fontFamily/fontSize keys are ignored (moved to ThemeFonts)
248+ showLineNumbers = try container. decodeIfPresent ( Bool . self, forKey: . showLineNumbers) ?? true
249+ highlightCurrentLine = try container. decodeIfPresent ( Bool . self, forKey: . highlightCurrentLine) ?? true
250+ tabWidth = try container. decodeIfPresent ( Int . self, forKey: . tabWidth) ?? 4
251+ autoIndent = try container. decodeIfPresent ( Bool . self, forKey: . autoIndent) ?? true
252+ wordWrap = try container. decodeIfPresent ( Bool . self, forKey: . wordWrap) ?? false
295253 vimModeEnabled = try container. decodeIfPresent ( Bool . self, forKey: . vimModeEnabled) ?? false
296254 }
297255
298- /// Clamped font size (11-18)
299- var clampedFontSize : Int {
300- min ( max ( fontSize, 11 ) , 18 )
301- }
302-
303256 /// Clamped tab width (1-16)
304257 var clampedTabWidth : Int {
305258 min ( max ( tabWidth, 1 ) , 16 )
@@ -354,29 +307,30 @@ enum DateFormatOption: String, Codable, CaseIterable, Identifiable {
354307
355308/// Data grid settings
356309struct DataGridSettings : Codable , Equatable {
357- var fontFamily : EditorFont
358- var fontSize : Int
359310 var rowHeight : DataGridRowHeight
360311 var dateFormat : DateFormatOption
361312 var nullDisplay : String
362313 var defaultPageSize : Int
363314 var showAlternateRows : Bool
364315 var autoShowInspector : Bool
365316
366- static let `default` = DataGridSettings ( )
317+ static let `default` = DataGridSettings (
318+ rowHeight: . normal,
319+ dateFormat: . iso8601,
320+ nullDisplay: " NULL " ,
321+ defaultPageSize: 1_000 ,
322+ showAlternateRows: true ,
323+ autoShowInspector: false
324+ )
367325
368326 init (
369- fontFamily: EditorFont = . systemMono,
370- fontSize: Int = 13 ,
371327 rowHeight: DataGridRowHeight = . normal,
372328 dateFormat: DateFormatOption = . iso8601,
373329 nullDisplay: String = " NULL " ,
374330 defaultPageSize: Int = 1_000 ,
375331 showAlternateRows: Bool = true ,
376332 autoShowInspector: Bool = false
377333 ) {
378- self . fontFamily = fontFamily
379- self . fontSize = fontSize
380334 self . rowHeight = rowHeight
381335 self . dateFormat = dateFormat
382336 self . nullDisplay = nullDisplay
@@ -387,21 +341,15 @@ struct DataGridSettings: Codable, Equatable {
387341
388342 init ( from decoder: Decoder ) throws {
389343 let container = try decoder. container ( keyedBy: CodingKeys . self)
390- fontFamily = try container. decodeIfPresent ( EditorFont . self, forKey: . fontFamily) ?? . systemMono
391- fontSize = try container. decodeIfPresent ( Int . self, forKey: . fontSize) ?? 13
392- rowHeight = try container. decode ( DataGridRowHeight . self, forKey: . rowHeight)
393- dateFormat = try container. decode ( DateFormatOption . self, forKey: . dateFormat)
394- nullDisplay = try container. decode ( String . self, forKey: . nullDisplay)
395- defaultPageSize = try container. decode ( Int . self, forKey: . defaultPageSize)
396- showAlternateRows = try container. decode ( Bool . self, forKey: . showAlternateRows)
344+ // Old fontFamily/fontSize keys are ignored (moved to ThemeFonts)
345+ rowHeight = try container. decodeIfPresent ( DataGridRowHeight . self, forKey: . rowHeight) ?? . normal
346+ dateFormat = try container. decodeIfPresent ( DateFormatOption . self, forKey: . dateFormat) ?? . iso8601
347+ nullDisplay = try container. decodeIfPresent ( String . self, forKey: . nullDisplay) ?? " NULL "
348+ defaultPageSize = try container. decodeIfPresent ( Int . self, forKey: . defaultPageSize) ?? 1_000
349+ showAlternateRows = try container. decodeIfPresent ( Bool . self, forKey: . showAlternateRows) ?? true
397350 autoShowInspector = try container. decodeIfPresent ( Bool . self, forKey: . autoShowInspector) ?? false
398351 }
399352
400- /// Clamped font size (10-18)
401- var clampedFontSize : Int {
402- min ( max ( fontSize, 10 ) , 18 )
403- }
404-
405353 // MARK: - Validated Properties
406354
407355 /// Validated and sanitized nullDisplay (max 20 chars, no newlines)
0 commit comments