chore: gate Voice Wake on macOS 26

main
Peter Steinberger 2025-12-06 03:03:53 +01:00
parent 45400a1758
commit b5f65e3304
1 changed files with 19 additions and 1 deletions

View File

@ -24,6 +24,7 @@ private let swabbleEnabledKey = "clawdis.swabbleEnabled"
private let swabbleTriggersKey = "clawdis.swabbleTriggers" private let swabbleTriggersKey = "clawdis.swabbleTriggers"
private let defaultVoiceWakeTriggers = ["clawd", "claude"] private let defaultVoiceWakeTriggers = ["clawd", "claude"]
private let voiceWakeMicKey = "clawdis.voiceWakeMicID" private let voiceWakeMicKey = "clawdis.voiceWakeMicID"
private let voiceWakeSupported: Bool = ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 26
// MARK: - App model // MARK: - App model
@ -67,7 +68,8 @@ final class AppState: ObservableObject {
self.launchAtLogin = SMAppService.mainApp.status == .enabled self.launchAtLogin = SMAppService.mainApp.status == .enabled
self.onboardingSeen = UserDefaults.standard.bool(forKey: "clawdis.onboardingSeen") self.onboardingSeen = UserDefaults.standard.bool(forKey: "clawdis.onboardingSeen")
self.debugPaneEnabled = UserDefaults.standard.bool(forKey: "clawdis.debugPaneEnabled") self.debugPaneEnabled = UserDefaults.standard.bool(forKey: "clawdis.debugPaneEnabled")
self.swabbleEnabled = UserDefaults.standard.bool(forKey: swabbleEnabledKey) let savedVoiceWake = UserDefaults.standard.bool(forKey: swabbleEnabledKey)
self.swabbleEnabled = voiceWakeSupported ? savedVoiceWake : false
self.swabbleTriggerWords = UserDefaults.standard.stringArray(forKey: swabbleTriggersKey) ?? defaultVoiceWakeTriggers self.swabbleTriggerWords = UserDefaults.standard.stringArray(forKey: swabbleTriggersKey) ?? defaultVoiceWakeTriggers
self.voiceWakeMicID = UserDefaults.standard.string(forKey: voiceWakeMicKey) ?? "" self.voiceWakeMicID = UserDefaults.standard.string(forKey: voiceWakeMicKey) ?? ""
} }
@ -440,6 +442,8 @@ private struct MenuContent: View {
var body: some View { var body: some View {
Toggle(isOn: activeBinding) { Text("Clawdis Active") } Toggle(isOn: activeBinding) { Text("Clawdis Active") }
Toggle(isOn: $state.swabbleEnabled) { Text("Voice Wake") } Toggle(isOn: $state.swabbleEnabled) { Text("Voice Wake") }
.disabled(!voiceWakeSupported)
.opacity(voiceWakeSupported ? 1 : 0.5)
Button("Settings…") { open(tab: .general) } Button("Settings…") { open(tab: .general) }
.keyboardShortcut(",", modifiers: [.command]) .keyboardShortcut(",", modifiers: [.command])
Button("About Clawdis") { open(tab: .about) } Button("About Clawdis") { open(tab: .about) }
@ -1662,6 +1666,16 @@ struct VoiceWakeSettings: View {
subtitle: "Listen for a wake phrase (e.g. \"Claude\") before running voice commands.", subtitle: "Listen for a wake phrase (e.g. \"Claude\") before running voice commands.",
binding: $state.swabbleEnabled binding: $state.swabbleEnabled
) )
.disabled(!voiceWakeSupported)
if !voiceWakeSupported {
Label("Voice Wake requires macOS 26 or newer.", systemImage: "exclamationmark.triangle.fill")
.font(.callout)
.foregroundStyle(.yellow)
.padding(8)
.background(Color.secondary.opacity(0.15))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
micPicker micPicker
levelMeter levelMeter
@ -1823,6 +1837,10 @@ struct VoiceWakeSettings: View {
} }
private func toggleTest() { private func toggleTest() {
guard voiceWakeSupported else {
testState = .failed("Voice Wake requires macOS 26 or newer.")
return
}
if isTesting { if isTesting {
tester.stop() tester.stop()
isTesting = false isTesting = false