import Foundation // 🤖 The Mac's chat Text Size preference, in points — the same seven-stop // ladder as the web slider (TEXT_SIZES in ui.js). The default sits ONE FROM // THE TOP: 16 is the only workable bigger size (beyond that bubbles read as // shouting), so the room to taste lies below. One UserDefaults key that // @AppStorage views observe; the View-menu commands, the ⌘= key monitor and // the Settings slider all step through here so every entry point moves the // same ladder. enum ChatTextSize { static let stops: [Double] = [10, 11, 12, 13, 14, 15, 16] static let defaultSize: Double = 15 static let key = "chatTextSize" static var current: Double { let v = UserDefaults.standard.double(forKey: key) return v > 0 ? snap(v) : defaultSize } // Nearest stop, so a value stored by a future (or hand-edited) ladder // still lands somewhere sane. static func snap(_ v: Double) -> Double { stops.min(by: { abs($0 - v) < abs($1 - v) }) ?? defaultSize } // @MainActor on the two WRITERS (not the pure reads/constants): UserDefaults // is process-global and unsafe against concurrent writes from two threads, so // every writer must stay on the main actor. All callers already do (View-menu // commands, the ⌘= key monitor); this makes that a compiler-enforced guarantee // rather than call-site discipline. @MainActor static func bump(_ direction: Int) { guard let i = stops.firstIndex(of: current) else { return } let j = min(max(i + direction, 0), stops.count - 1) UserDefaults.standard.set(stops[j], forKey: key) } @MainActor static func reset() { UserDefaults.standard.set(defaultSize, forKey: key) } }