chore: gate Voice Wake on macOS 26
parent
45400a1758
commit
b5f65e3304
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue