@@ -14,33 +14,54 @@ private extension Color {
1414 blue: Double ( n & 0xFF ) / 255
1515 )
1616 }
17+ init ( light: String , dark: String ) {
18+ self . init ( nsColor: NSColor ( name: nil , dynamicProvider: { appearance in
19+ if appearance. bestMatch ( from: [ . darkAqua, . aqua] ) == . darkAqua {
20+ return NSColor ( Color ( hex: dark) )
21+ } else {
22+ return NSColor ( Color ( hex: light) )
23+ }
24+ } ) )
25+ }
26+ }
27+
28+ // MARK: - AppAppearance Extension
29+
30+ public extension AppAppearance {
31+ var colorScheme : ColorScheme ? {
32+ switch self {
33+ case . system: return nil
34+ case . light: return . light
35+ case . dark: return . dark
36+ }
37+ }
1738}
1839
1940// MARK: - Theme
2041
2142enum HeardTheme {
2243 enum Paper {
23- static let bg = Color ( hex : " F5EFE4 " )
24- static let surface = Color ( hex : " FBF7EF " )
25- static let surfaceAlt = Color ( hex : " EFE7D7 " )
26- static let sidebar = Color ( hex : " EBE2CE " )
27- static let border = Color ( hex : " D9CFB9 " )
28- static let borderSoft = Color ( hex : " E5DCC8 " )
29- static let ink = Color ( hex : " 1C2024 " )
30- static let ink2 = Color ( hex : " 3A3F47 " )
31- static let mute = Color ( hex : " 7B7264 " )
32- static let muteSoft = Color ( hex : " C9BBA5 " )
33- static let accent = Color ( hex : " 3F5C8C " )
34- static let accentInk = Color ( hex : " 2F4570 " )
35- static let accentSoft = Color ( hex : " E5EAF3 " )
36- static let good = Color ( hex : " 3D7A4F " )
37- static let goodSoft = Color ( hex : " E1EEDF " )
38- static let warn = Color ( hex : " A66A1F " )
39- static let warnSoft = Color ( hex : " F4E6CE " )
40- static let bad = Color ( hex : " A6452B " )
41- static let badSoft = Color ( hex : " F2DCD2 " )
42- static let recordingBg = Color ( hex : " 2E3338 " )
43- static let recordingInk = Color ( hex : " F5EFE4 " )
44+ static let bg = Color ( light : " F5EFE4 " , dark : " 1C2024 " )
45+ static let surface = Color ( light : " FBF7EF " , dark : " 252A30 " )
46+ static let surfaceAlt = Color ( light : " EFE7D7 " , dark : " 2E3338 " )
47+ static let sidebar = Color ( light : " EBE2CE " , dark : " 22272D " )
48+ static let border = Color ( light : " D9CFB9 " , dark : " 4A515A " )
49+ static let borderSoft = Color ( light : " E5DCC8 " , dark : " 3A3F47 " )
50+ static let ink = Color ( light : " 1C2024 " , dark : " F5EFE4 " )
51+ static let ink2 = Color ( light : " 3A3F47 " , dark : " D9CFB9 " )
52+ static let mute = Color ( light : " 7B7264 " , dark : " 9A9184 " )
53+ static let muteSoft = Color ( light : " C9BBA5 " , dark : " 4A515A " )
54+ static let accent = Color ( light : " 3F5C8C " , dark : " 658BC9 " )
55+ static let accentInk = Color ( light : " 2F4570 " , dark : " 8BB2F2 " )
56+ static let accentSoft = Color ( light : " E5EAF3 " , dark : " 26334A " )
57+ static let good = Color ( light : " 3D7A4F " , dark : " 53A66B " )
58+ static let goodSoft = Color ( light : " E1EEDF " , dark : " 243D2D " )
59+ static let warn = Color ( light : " A66A1F " , dark : " D98A29 " )
60+ static let warnSoft = Color ( light : " F4E6CE " , dark : " 4D351A " )
61+ static let bad = Color ( light : " A6452B " , dark : " D65738 " )
62+ static let badSoft = Color ( light : " F2DCD2 " , dark : " 4A251C " )
63+ static let recordingBg = Color ( light : " 2E3338 " , dark : " A6452B " )
64+ static let recordingInk = Color ( light : " F5EFE4 " , dark : " 1C2024 " )
4465 }
4566
4667 static var accent : Color { Paper . accent }
@@ -387,7 +408,6 @@ public struct MenuBarView: View {
387408 }
388409 . frame ( width: 268 )
389410 . background ( HeardTheme . Paper. bg)
390- . preferredColorScheme ( . light)
391411 . onChange ( of: model. showNamingPrompt) { _, show in
392412 NSLog ( " Heard: MenuBarView observed showNamingPrompt= \( show) " )
393413 if show {
@@ -778,7 +798,6 @@ public struct SettingsView: View {
778798 detailPane
779799 }
780800 . frame ( minWidth: 580 , minHeight: 440 )
781- . preferredColorScheme ( . light)
782801 . sheet ( item: $hotkeyTarget) { target in
783802 switch target {
784803 case . dictation:
@@ -790,7 +809,6 @@ public struct SettingsView: View {
790809 onCancel: { hotkeyTarget = nil } ,
791810 conflictingHotkey: model. settingsStore. settings. meetingNoteHotkey
792811 )
793- . preferredColorScheme ( . light)
794812 case . meetingNote:
795813 HotkeyRecorderView (
796814 onCommit: { combo in
@@ -800,7 +818,6 @@ public struct SettingsView: View {
800818 onCancel: { hotkeyTarget = nil } ,
801819 conflictingHotkey: model. settingsStore. settings. dictationHotkey
802820 )
803- . preferredColorScheme ( . light)
804821 }
805822 }
806823 }
@@ -914,6 +931,27 @@ public struct SettingsView: View {
914931 }
915932 }
916933
934+ sectionGroup ( " Appearance " ) {
935+ SettingsCard {
936+ CardRow ( isLast: true ) {
937+ HStack {
938+ Text ( " Theme " )
939+ . font ( . system( size: 12 , weight: . medium) )
940+ . foregroundStyle ( HeardTheme . Paper. ink)
941+ Spacer ( )
942+ Picker ( " " , selection: settingsBinding ( \. appearance) ) {
943+ ForEach ( AppAppearance . allCases) { appearance in
944+ Text ( appearance. displayName) . tag ( appearance)
945+ }
946+ }
947+ . labelsHidden ( )
948+ . controlSize ( . small)
949+ . frame ( maxWidth: 160 )
950+ }
951+ }
952+ }
953+ }
954+
917955 sectionGroup ( " Behavior " ) {
918956 SettingsCard {
919957 ToggleRow (
@@ -1527,9 +1565,8 @@ public struct SettingsView: View {
15271565
15281566 Spacer ( ) . frame ( height: 40 )
15291567 }
1530- . frame ( maxWidth: . infinity)
1531- }
1532- . background ( HeardTheme . Paper. bg)
1568+ . frame ( minWidth: 500 , minHeight: 500 )
1569+ . background ( HeardTheme . Paper. bg)
15331570 }
15341571 . frame ( maxWidth: . infinity, maxHeight: . infinity)
15351572 . background ( HeardTheme . Paper. bg)
0 commit comments