// // AppAppearanceManager.swift // App for Indeed // import AppKit /// Persists and applies the user’s light / dark / system appearance preference. @MainActor final class AppAppearanceManager { static let shared = AppAppearanceManager() static let didChangeNotification = Notification.Name("AppAppearanceManager.didChange") enum Mode: String, CaseIterable { case light case dark case system var segmentIndex: Int { switch self { case .system: 0 case .light: 1 case .dark: 2 } } init?(segmentIndex: Int) { switch segmentIndex { case 0: self = .system case 1: self = .light case 2: self = .dark default: return nil } } } private enum UserDefaultsKey { static let appearanceMode = "com.appforindeed.appearanceMode" } private var systemThemeObserver: NSObjectProtocol? private init() { systemThemeObserver = DistributedNotificationCenter.default().addObserver( forName: Notification.Name("AppleInterfaceThemeChangedNotification"), object: nil, queue: .main ) { [weak self] _ in guard let self, self.mode == .system else { return } self.apply() NotificationCenter.default.post(name: Self.didChangeNotification, object: self) } } /// Whether the app is currently rendering with a dark appearance (respects System mode). var isDark: Bool { NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua } var mode: Mode { get { guard let raw = UserDefaults.standard.string(forKey: UserDefaultsKey.appearanceMode), let stored = Mode(rawValue: raw) else { return .system } return stored } set { guard newValue != mode else { return } UserDefaults.standard.set(newValue.rawValue, forKey: UserDefaultsKey.appearanceMode) apply() NotificationCenter.default.post(name: Self.didChangeNotification, object: self) } } /// Window backing color aligned with dashboard chrome for the active appearance. var windowChromeColor: NSColor { AppDashboardTheme.chromeBackground } func apply() { switch mode { case .light: NSApp.appearance = NSAppearance(named: .aqua) case .dark: NSApp.appearance = NSAppearance(named: .darkAqua) case .system: NSApp.appearance = nil } updateWindowChrome() } private func updateWindowChrome() { let color = windowChromeColor for window in NSApp.windows where window.isVisible || window.canBecomeKey { window.backgroundColor = color } } }