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 hostedEndpoint = "endpoint" static let hostedModel = "model" static let localEndpoint = "local_endpoint" static let localModel = "local_model" static let hostedFirst = "hosted_first" static let prompt = "prompt" static let destination = "destination" static let shortcut = "shortcut" } private let defaults: UserDefaults @Published var hostedEndpoint: String { didSet { defaults.set(hostedEndpoint, forKey: Key.hostedEndpoint) } } @Published var hostedModel: String { didSet { defaults.set(hostedModel, forKey: Key.hostedModel) } } @Published var localEndpoint: String { didSet { defaults.set(localEndpoint, forKey: Key.localEndpoint) } } @Published var localModel: String { didSet { defaults.set(localModel, forKey: Key.localModel) } } @Published var hostedFirst: Bool { didSet { defaults.set(hostedFirst, forKey: Key.hostedFirst) } } @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 hostedEndpoint = defaults.string(forKey: Key.hostedEndpoint) ?? "" hostedModel = defaults.string(forKey: Key.hostedModel) ?? "" localEndpoint = defaults.string(forKey: Key.localEndpoint) ?? "http://localhost:8080" localModel = defaults.string(forKey: Key.localModel) ?? "" hostedFirst = defaults.object(forKey: Key.hostedFirst) as? Bool ?? true 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 hostedKey: String { get { KeychainStore.read(.hosted) } set { KeychainStore.write(newValue, account: .hosted) } } var localKey: String { get { KeychainStore.read(.local) } set { KeychainStore.write(newValue, account: .local) } } }