import Combine import Foundation enum TranscriptDestination: String, CaseIterable, Identifiable { case cursor case clipboard var id: Self { self } var label: String { switch self { case .cursor: "Type at cursor" case .clipboard: "Copy to clipboard" } } } @MainActor final class AppSettings: ObservableObject { private enum Key { static let endpoint = "endpoint" static let model = "model" static let prompt = "prompt" static let destination = "destination" static let shortcut = "shortcut" } private let defaults: UserDefaults @Published var endpoint: String { didSet { defaults.set(endpoint, forKey: Key.endpoint) } } @Published var model: String { didSet { defaults.set(model, forKey: Key.model) } } @Published var prompt: String { didSet { defaults.set(prompt, forKey: Key.prompt) } } @Published var destination: TranscriptDestination { didSet { defaults.set(destination.rawValue, forKey: Key.destination) } } @Published var shortcut: HotkeyShortcut { didSet { if let data = try? JSONEncoder().encode(shortcut) { defaults.set(data, forKey: Key.shortcut) } } } init(defaults: UserDefaults = .standard) { self.defaults = defaults endpoint = defaults.string(forKey: Key.endpoint) ?? "" model = defaults.string(forKey: Key.model) ?? "" prompt = defaults.string(forKey: Key.prompt) ?? "" destination = TranscriptDestination( rawValue: defaults.string(forKey: Key.destination) ?? "" ) ?? .cursor if let data = defaults.data(forKey: Key.shortcut), let saved = try? JSONDecoder().decode(HotkeyShortcut.self, from: data) { shortcut = saved } else { shortcut = .defaultShortcut } } var apiKey: String { get { KeychainStore.read() } set { KeychainStore.write(newValue) } } }