From 9ec7b9434526ce36b9913d54c2d301c6f355127f Mon Sep 17 00:00:00 2001 From: Carsten Abele Date: Tue, 7 Apr 2026 19:39:48 +0200 Subject: [PATCH] feat: add AppSettings with API key, shortcut, output mode, delay --- MyVoxtral/MyVoxtral/Models/AppSettings.swift | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 MyVoxtral/MyVoxtral/Models/AppSettings.swift diff --git a/MyVoxtral/MyVoxtral/Models/AppSettings.swift b/MyVoxtral/MyVoxtral/Models/AppSettings.swift new file mode 100644 index 0000000..43c4c8a --- /dev/null +++ b/MyVoxtral/MyVoxtral/Models/AppSettings.swift @@ -0,0 +1,45 @@ +import SwiftUI +import Carbon.HIToolbox + +enum OutputMode: String, CaseIterable { + case textBox = "Text Window" + case cursorInjection = "Type at Cursor" +} + +final class AppSettings: ObservableObject { + static let shared = AppSettings() + + @AppStorage("apiKey") var apiKey: String = "" + @AppStorage("outputMode") var outputMode: OutputMode = .textBox + @AppStorage("streamingDelayMs") var streamingDelayMs: Int = 480 + @AppStorage("shortcutKeyCode") private var shortcutKeyCodeStorage: Int = 0 + @AppStorage("shortcutModifiers") private var shortcutModifiersStorage: Int = 0 + + var shortcutKeyCode: UInt16 { + get { UInt16(shortcutKeyCodeStorage) } + set { shortcutKeyCodeStorage = Int(newValue) } + } + + var shortcutModifiers: UInt { + get { UInt(bitPattern: shortcutModifiersStorage) } + set { shortcutModifiersStorage = Int(bitPattern: newValue) } + } + + var hasAPIKey: Bool { !apiKey.isEmpty } + + var hasShortcut: Bool { shortcutKeyCode != 0 || shortcutModifiers != 0 } + + var shortcutDisplayString: String { + guard hasShortcut else { return "Not Set" } + var parts: [String] = [] + let mods = NSEvent.ModifierFlags(rawValue: shortcutModifiers) + if mods.contains(.control) { parts.append("⌃") } + if mods.contains(.option) { parts.append("⌥") } + if mods.contains(.shift) { parts.append("⇧") } + if mods.contains(.command) { parts.append("⌘") } + if let scalar = Unicode.Scalar(shortcutKeyCode) { + parts.append(String(Character(scalar)).uppercased()) + } + return parts.joined() + } +}