pommedoro/Sources/Pommedoro/Settings.swift

98 lines
3.3 KiB
Swift

import AppKit
// MARK: - Settings Keys
private enum SettingsKey {
static let intensityScale = "pommedoro.intensityScale"
static let blinkDurationScale = "pommedoro.blinkDurationScale"
static let gradientColorRed = "pommedoro.gradientColor.red"
static let gradientColorGreen = "pommedoro.gradientColor.green"
static let gradientColorBlue = "pommedoro.gradientColor.blue"
}
// MARK: - Settings Manager
class Settings {
static let shared = Settings()
/// Notification posted when any setting changes
static let didChangeNotification = Notification.Name("PommedoroSettingsDidChange")
private let defaults = UserDefaults.standard
private init() {
registerDefaults()
}
private func registerDefaults() {
// Extract default teal components for consistent defaults
let teal = NSColor.systemTeal.usingColorSpace(.sRGB) ?? NSColor.systemTeal
defaults.register(defaults: [
SettingsKey.intensityScale: 1.0,
SettingsKey.blinkDurationScale: 1.0,
SettingsKey.gradientColorRed: Double(teal.redComponent),
SettingsKey.gradientColorGreen: Double(teal.greenComponent),
SettingsKey.gradientColorBlue: Double(teal.blueComponent),
])
}
/// Intensity multiplier (0.25 to 2.0, default 1.0)
var intensityScale: Double {
get { defaults.double(forKey: SettingsKey.intensityScale) }
set {
defaults.set(newValue.clamped(to: 0.25...2.0), forKey: SettingsKey.intensityScale)
notifyChange()
}
}
/// Blink duration multiplier (0.25 to 3.0, default 1.0)
var blinkDurationScale: Double {
get { defaults.double(forKey: SettingsKey.blinkDurationScale) }
set {
defaults.set(newValue.clamped(to: 0.25...3.0), forKey: SettingsKey.blinkDurationScale)
notifyChange()
}
}
/// Gradient color as NSColor
var gradientColor: NSColor {
get {
NSColor(
srgbRed: CGFloat(defaults.double(forKey: SettingsKey.gradientColorRed)),
green: CGFloat(defaults.double(forKey: SettingsKey.gradientColorGreen)),
blue: CGFloat(defaults.double(forKey: SettingsKey.gradientColorBlue)),
alpha: 1.0
)
}
set {
let c = newValue.usingColorSpace(.sRGB) ?? newValue
defaults.set(Double(c.redComponent), forKey: SettingsKey.gradientColorRed)
defaults.set(Double(c.greenComponent), forKey: SettingsKey.gradientColorGreen)
defaults.set(Double(c.blueComponent), forKey: SettingsKey.gradientColorBlue)
notifyChange()
}
}
func resetToDefaults() {
for key in [
SettingsKey.intensityScale,
SettingsKey.blinkDurationScale,
SettingsKey.gradientColorRed,
SettingsKey.gradientColorGreen,
SettingsKey.gradientColorBlue,
] {
defaults.removeObject(forKey: key)
}
notifyChange()
}
private func notifyChange() {
NotificationCenter.default.post(name: Settings.didChangeNotification, object: nil)
}
}
// MARK: - Comparable Clamping
private extension Comparable {
func clamped(to range: ClosedRange<Self>) -> Self {
min(max(self, range.lowerBound), range.upperBound)
}
}