|
|
@@ -0,0 +1,80 @@
|
|
|
+import Foundation
|
|
|
+import SwiftUI
|
|
|
+
|
|
|
+@MainActor
|
|
|
+@Observable
|
|
|
+final class AppearanceManager {
|
|
|
+ static let shared = AppearanceManager()
|
|
|
+
|
|
|
+ private static let storageKey = "isDarkMode"
|
|
|
+
|
|
|
+ var isDarkMode: Bool {
|
|
|
+ didSet {
|
|
|
+ guard isDarkMode != oldValue else { return }
|
|
|
+ UserDefaults.standard.set(isDarkMode, forKey: Self.storageKey)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var palette: ThemePalette {
|
|
|
+ isDarkMode ? .dark : .light
|
|
|
+ }
|
|
|
+
|
|
|
+ init() {
|
|
|
+ if UserDefaults.standard.object(forKey: Self.storageKey) != nil {
|
|
|
+ isDarkMode = UserDefaults.standard.bool(forKey: Self.storageKey)
|
|
|
+ } else {
|
|
|
+ isDarkMode = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct ThemePalette {
|
|
|
+ let background: Color
|
|
|
+ let sidebarBackground: Color
|
|
|
+ let panelBackground: Color
|
|
|
+ let cardBackground: Color
|
|
|
+ let quickAccessBackground: Color
|
|
|
+ let border: Color
|
|
|
+ let cardBorder: Color
|
|
|
+ let textPrimary: Color
|
|
|
+ let textSecondary: Color
|
|
|
+ let textTertiary: Color
|
|
|
+ let hoverFill: Color
|
|
|
+ let hoverBorder: Color
|
|
|
+ let selectedRowFill: Color
|
|
|
+ let scrim: Color
|
|
|
+
|
|
|
+ static let dark = ThemePalette(
|
|
|
+ background: Color(hex: 0x0B0E14),
|
|
|
+ sidebarBackground: Color(hex: 0x0B0E14),
|
|
|
+ panelBackground: Color(hex: 0x11141C),
|
|
|
+ cardBackground: Color(hex: 0x151922),
|
|
|
+ quickAccessBackground: Color(hex: 0x151922),
|
|
|
+ border: Color.white.opacity(0.06),
|
|
|
+ cardBorder: Color.white.opacity(0.08),
|
|
|
+ textPrimary: Color.white,
|
|
|
+ textSecondary: Color(hex: 0x8E9297),
|
|
|
+ textTertiary: Color(hex: 0x6B7280),
|
|
|
+ hoverFill: Color.white.opacity(0.06),
|
|
|
+ hoverBorder: Color.white.opacity(0.14),
|
|
|
+ selectedRowFill: Color.white.opacity(0.05),
|
|
|
+ scrim: Color.black.opacity(0.35)
|
|
|
+ )
|
|
|
+
|
|
|
+ static let light = ThemePalette(
|
|
|
+ background: Color(hex: 0xF5F6F8),
|
|
|
+ sidebarBackground: Color(hex: 0xFFFFFF),
|
|
|
+ panelBackground: Color(hex: 0xF9FAFB),
|
|
|
+ cardBackground: Color(hex: 0xFFFFFF),
|
|
|
+ quickAccessBackground: Color(hex: 0xF0F2F5),
|
|
|
+ border: Color(hex: 0xE5E7EB),
|
|
|
+ cardBorder: Color(hex: 0xD1D5DB),
|
|
|
+ textPrimary: Color(hex: 0x111827),
|
|
|
+ textSecondary: Color(hex: 0x6B7280),
|
|
|
+ textTertiary: Color(hex: 0x9CA3AF),
|
|
|
+ hoverFill: Color.black.opacity(0.05),
|
|
|
+ hoverBorder: Color(hex: 0x9CA3AF),
|
|
|
+ selectedRowFill: Color.black.opacity(0.06),
|
|
|
+ scrim: Color.black.opacity(0.25)
|
|
|
+ )
|
|
|
+}
|