fix: run voice wake permission callbacks off the main actor
parent
09ed3f37db
commit
84b44069c8
|
|
@ -1314,7 +1314,6 @@ enum VoiceWakeTestState: Equatable {
|
||||||
case failed(String)
|
case failed(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
|
||||||
final class VoiceWakeTester {
|
final class VoiceWakeTester {
|
||||||
private let recognizer: SFSpeechRecognizer?
|
private let recognizer: SFSpeechRecognizer?
|
||||||
private let audioEngine = AVAudioEngine()
|
private let audioEngine = AVAudioEngine()
|
||||||
|
|
@ -1325,6 +1324,7 @@ final class VoiceWakeTester {
|
||||||
self.recognizer = SFSpeechRecognizer(locale: locale)
|
self.recognizer = SFSpeechRecognizer(locale: locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
func start(triggers: [String], onUpdate: @MainActor @escaping @Sendable (VoiceWakeTestState) -> Void) async throws {
|
func start(triggers: [String], onUpdate: @MainActor @escaping @Sendable (VoiceWakeTestState) -> Void) async throws {
|
||||||
guard recognitionTask == nil else { return }
|
guard recognitionTask == nil else { return }
|
||||||
guard let recognizer, recognizer.isAvailable else {
|
guard let recognizer, recognizer.isAvailable else {
|
||||||
|
|
@ -1376,6 +1376,7 @@ final class VoiceWakeTester {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
func stop() {
|
func stop() {
|
||||||
audioEngine.stop()
|
audioEngine.stop()
|
||||||
recognitionRequest?.endAudio()
|
recognitionRequest?.endAudio()
|
||||||
|
|
@ -1390,16 +1391,14 @@ final class VoiceWakeTester {
|
||||||
return triggers.contains { lowered.contains($0.lowercased()) }
|
return triggers.contains { lowered.contains($0.lowercased()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func ensurePermissions() async throws -> Bool {
|
nonisolated private static func ensurePermissions() async throws -> Bool {
|
||||||
let speechStatus = SFSpeechRecognizer.authorizationStatus()
|
let speechStatus = SFSpeechRecognizer.authorizationStatus()
|
||||||
if speechStatus == .notDetermined {
|
if speechStatus == .notDetermined {
|
||||||
let granted = await withCheckedContinuation { continuation in
|
let granted = await withCheckedContinuation { continuation in
|
||||||
SFSpeechRecognizer.requestAuthorization { status in
|
SFSpeechRecognizer.requestAuthorization { status in
|
||||||
Task { @MainActor in
|
|
||||||
continuation.resume(returning: status == .authorized)
|
continuation.resume(returning: status == .authorized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
guard granted else { return false }
|
guard granted else { return false }
|
||||||
} else if speechStatus != .authorized {
|
} else if speechStatus != .authorized {
|
||||||
return false
|
return false
|
||||||
|
|
@ -1411,7 +1410,7 @@ final class VoiceWakeTester {
|
||||||
case .notDetermined:
|
case .notDetermined:
|
||||||
return await withCheckedContinuation { continuation in
|
return await withCheckedContinuation { continuation in
|
||||||
AVCaptureDevice.requestAccess(for: .audio) { granted in
|
AVCaptureDevice.requestAccess(for: .audio) { granted in
|
||||||
Task { @MainActor in continuation.resume(returning: granted) }
|
continuation.resume(returning: granted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue