AppearanceManager.swift 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import AppKit
  2. import Foundation
  3. import SwiftUI
  4. @MainActor
  5. @Observable
  6. final class AppearanceManager {
  7. static let shared = AppearanceManager()
  8. private static let storageKey = "isDarkMode"
  9. var isDarkMode: Bool {
  10. didSet {
  11. guard isDarkMode != oldValue else { return }
  12. UserDefaults.standard.set(isDarkMode, forKey: Self.storageKey)
  13. }
  14. }
  15. var palette: ThemePalette {
  16. isDarkMode ? .dark : .light
  17. }
  18. var webUnderPageBackgroundColor: NSColor {
  19. Self.webUnderPageBackgroundColor(isDarkMode: isDarkMode)
  20. }
  21. static func webUnderPageBackgroundColor(isDarkMode: Bool) -> NSColor {
  22. NSColor(hex: (isDarkMode ? ThemePalette.dark : ThemePalette.light).webUnderPageBackgroundHex)
  23. }
  24. init() {
  25. if UserDefaults.standard.object(forKey: Self.storageKey) != nil {
  26. isDarkMode = UserDefaults.standard.bool(forKey: Self.storageKey)
  27. } else {
  28. isDarkMode = true
  29. }
  30. }
  31. }
  32. struct ThemePalette {
  33. let webUnderPageBackgroundHex: UInt
  34. let background: Color
  35. let sidebarBackground: Color
  36. let panelBackground: Color
  37. let cardBackground: Color
  38. let quickAccessBackground: Color
  39. let border: Color
  40. let cardBorder: Color
  41. let textPrimary: Color
  42. let textSecondary: Color
  43. let textTertiary: Color
  44. let hoverFill: Color
  45. let hoverBorder: Color
  46. let selectedRowFill: Color
  47. let scrim: Color
  48. static let dark = ThemePalette(
  49. webUnderPageBackgroundHex: 0x0B0E14,
  50. background: Color(hex: 0x0B0E14),
  51. sidebarBackground: Color(hex: 0x0B0E14),
  52. panelBackground: Color(hex: 0x11141C),
  53. cardBackground: Color(hex: 0x151922),
  54. quickAccessBackground: Color(hex: 0x151922),
  55. border: Color.white.opacity(0.06),
  56. cardBorder: Color.white.opacity(0.08),
  57. textPrimary: Color.white,
  58. textSecondary: Color(hex: 0x8E9297),
  59. textTertiary: Color(hex: 0x6B7280),
  60. hoverFill: Color.white.opacity(0.06),
  61. hoverBorder: Color.white.opacity(0.14),
  62. selectedRowFill: Color.white.opacity(0.05),
  63. scrim: Color.black.opacity(0.35)
  64. )
  65. static let light = ThemePalette(
  66. webUnderPageBackgroundHex: 0xFFFFFF,
  67. background: Color(hex: 0xF5F6F8),
  68. sidebarBackground: Color(hex: 0xFFFFFF),
  69. panelBackground: Color(hex: 0xF9FAFB),
  70. cardBackground: Color(hex: 0xFFFFFF),
  71. quickAccessBackground: Color(hex: 0xF0F2F5),
  72. border: Color(hex: 0xE5E7EB),
  73. cardBorder: Color(hex: 0xD1D5DB),
  74. textPrimary: Color(hex: 0x111827),
  75. textSecondary: Color(hex: 0x6B7280),
  76. textTertiary: Color(hex: 0x9CA3AF),
  77. hoverFill: Color.black.opacity(0.05),
  78. hoverBorder: Color(hex: 0x9CA3AF),
  79. selectedRowFill: Color.black.opacity(0.06),
  80. scrim: Color.black.opacity(0.25)
  81. )
  82. }
  83. private extension NSColor {
  84. convenience init(hex: UInt, alpha: CGFloat = 1.0) {
  85. self.init(
  86. red: CGFloat((hex >> 16) & 0xFF) / 255,
  87. green: CGFloat((hex >> 8) & 0xFF) / 255,
  88. blue: CGFloat(hex & 0xFF) / 255,
  89. alpha: alpha
  90. )
  91. }
  92. }