fix(node): prevent iOS VoiceWake crash
parent
952d924581
commit
e502ad13f9
|
|
@ -82,7 +82,7 @@ actor BridgeClient {
|
||||||
var line = Data()
|
var line = Data()
|
||||||
line.append(data)
|
line.append(data)
|
||||||
line.append(0x0A)
|
line.append(0x0A)
|
||||||
try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in
|
try await withCheckedThrowingContinuation(isolation: nil) { (cont: CheckedContinuation<Void, Error>) in
|
||||||
connection.send(content: line, completion: .contentProcessed { err in
|
connection.send(content: line, completion: .contentProcessed { err in
|
||||||
if let err { cont.resume(throwing: err) } else { cont.resume(returning: ()) }
|
if let err { cont.resume(throwing: err) } else { cont.resume(returning: ()) }
|
||||||
})
|
})
|
||||||
|
|
@ -104,7 +104,7 @@ actor BridgeClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func receiveChunk(over connection: NWConnection) async throws -> Data {
|
private func receiveChunk(over connection: NWConnection) async throws -> Data {
|
||||||
try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Data, Error>) in
|
try await withCheckedThrowingContinuation(isolation: nil) { (cont: CheckedContinuation<Data, Error>) in
|
||||||
connection.receive(minimumIncompleteLength: 1, maximumLength: 64 * 1024) { data, _, isComplete, error in
|
connection.receive(minimumIncompleteLength: 1, maximumLength: 64 * 1024) { data, _, isComplete, error in
|
||||||
if let error {
|
if let error {
|
||||||
cont.resume(throwing: error)
|
cont.resume(throwing: error)
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ final class BridgeDiscoveryModel: ObservableObject {
|
||||||
func start() {
|
func start() {
|
||||||
if self.browser != nil { return }
|
if self.browser != nil { return }
|
||||||
let params = NWParameters.tcp
|
let params = NWParameters.tcp
|
||||||
|
params.includePeerToPeer = true
|
||||||
let browser = NWBrowser(
|
let browser = NWBrowser(
|
||||||
for: .bonjour(type: ClawdisBonjour.bridgeServiceType, domain: nil),
|
for: .bonjour(type: ClawdisBonjour.bridgeServiceType, domain: ClawdisBonjour.bridgeServiceDomain),
|
||||||
using: params)
|
using: params)
|
||||||
|
|
||||||
browser.stateUpdateHandler = { [weak self] state in
|
browser.stateUpdateHandler = { [weak self] state in
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ actor BridgeSession {
|
||||||
var line = Data()
|
var line = Data()
|
||||||
line.append(data)
|
line.append(data)
|
||||||
line.append(0x0A)
|
line.append(0x0A)
|
||||||
try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in
|
try await withCheckedThrowingContinuation(isolation: nil) { (cont: CheckedContinuation<Void, Error>) in
|
||||||
connection.send(content: line, completion: .contentProcessed { err in
|
connection.send(content: line, completion: .contentProcessed { err in
|
||||||
if let err { cont.resume(throwing: err) } else { cont.resume(returning: ()) }
|
if let err { cont.resume(throwing: err) } else { cont.resume(returning: ()) }
|
||||||
})
|
})
|
||||||
|
|
@ -134,7 +134,7 @@ actor BridgeSession {
|
||||||
|
|
||||||
private func receiveChunk() async throws -> Data {
|
private func receiveChunk() async throws -> Data {
|
||||||
guard let connection = self.connection else { return Data() }
|
guard let connection = self.connection else { return Data() }
|
||||||
return try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Data, Error>) in
|
return try await withCheckedThrowingContinuation(isolation: nil) { (cont: CheckedContinuation<Data, Error>) in
|
||||||
connection.receive(minimumIncompleteLength: 1, maximumLength: 64 * 1024) { data, _, isComplete, error in
|
connection.receive(minimumIncompleteLength: 1, maximumLength: 64 * 1024) { data, _, isComplete, error in
|
||||||
if let error {
|
if let error {
|
||||||
cont.resume(throwing: error)
|
cont.resume(throwing: error)
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ final class ScreenController: ObservableObject {
|
||||||
if let maxWidth {
|
if let maxWidth {
|
||||||
config.snapshotWidth = NSNumber(value: Double(maxWidth))
|
config.snapshotWidth = NSNumber(value: Double(maxWidth))
|
||||||
}
|
}
|
||||||
let image: UIImage = try await withCheckedThrowingContinuation { (cont: CheckedContinuation<UIImage, Error>) in
|
let image: UIImage = try await withCheckedThrowingContinuation { cont in
|
||||||
self.webView.takeSnapshot(with: config) { image, error in
|
self.webView.takeSnapshot(with: config) { image, error in
|
||||||
if let error {
|
if let error {
|
||||||
cont.resume(throwing: error)
|
cont.resume(throwing: error)
|
||||||
|
|
|
||||||
|
|
@ -96,9 +96,8 @@ final class VoiceWakeManager: NSObject, ObservableObject {
|
||||||
inputNode.removeTap(onBus: 0)
|
inputNode.removeTap(onBus: 0)
|
||||||
|
|
||||||
let recordingFormat = inputNode.outputFormat(forBus: 0)
|
let recordingFormat = inputNode.outputFormat(forBus: 0)
|
||||||
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [weak self] buffer, _ in
|
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [request] buffer, _ in
|
||||||
guard let self else { return }
|
request.append(buffer)
|
||||||
self.recognitionRequest?.append(buffer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.audioEngine.prepare()
|
self.audioEngine.prepare()
|
||||||
|
|
@ -169,22 +168,18 @@ final class VoiceWakeManager: NSObject, ObservableObject {
|
||||||
try session.setActive(true, options: [])
|
try session.setActive(true, options: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func requestMicrophonePermission() async -> Bool {
|
private nonisolated static func requestMicrophonePermission() async -> Bool {
|
||||||
await withCheckedContinuation { cont in
|
await withCheckedContinuation(isolation: nil) { cont in
|
||||||
AVAudioApplication.requestRecordPermission { ok in
|
AVAudioApplication.requestRecordPermission { ok in
|
||||||
Task { @MainActor in
|
cont.resume(returning: ok)
|
||||||
cont.resume(returning: ok)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func requestSpeechPermission() async -> Bool {
|
private nonisolated static func requestSpeechPermission() async -> Bool {
|
||||||
await withCheckedContinuation { cont in
|
await withCheckedContinuation(isolation: nil) { cont in
|
||||||
SFSpeechRecognizer.requestAuthorization { status in
|
SFSpeechRecognizer.requestAuthorization { status in
|
||||||
Task { @MainActor in
|
cont.resume(returning: status == .authorized)
|
||||||
cont.resume(returning: status == .authorized)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ actor BridgeConnectionHandler {
|
||||||
var line = Data()
|
var line = Data()
|
||||||
line.append(data)
|
line.append(data)
|
||||||
line.append(0x0A) // \n
|
line.append(0x0A) // \n
|
||||||
let _: Void = try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in
|
let _: Void = try await withCheckedThrowingContinuation { cont in
|
||||||
self.connection.send(content: line, completion: .contentProcessed { err in
|
self.connection.send(content: line, completion: .contentProcessed { err in
|
||||||
if let err {
|
if let err {
|
||||||
cont.resume(throwing: err)
|
cont.resume(throwing: err)
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,14 @@ actor BridgeServer {
|
||||||
self.store = store
|
self.store = store
|
||||||
|
|
||||||
let params = NWParameters.tcp
|
let params = NWParameters.tcp
|
||||||
|
params.includePeerToPeer = true
|
||||||
let listener = try NWListener(using: params, on: .any)
|
let listener = try NWListener(using: params, on: .any)
|
||||||
|
|
||||||
let name = Host.current().localizedName ?? ProcessInfo.processInfo.hostName
|
let name = Host.current().localizedName ?? ProcessInfo.processInfo.hostName
|
||||||
listener.service = NWListener.Service(
|
listener.service = NWListener.Service(
|
||||||
name: "\(name) (Clawdis)",
|
name: "\(name) (Clawdis)",
|
||||||
type: ClawdisBonjour.bridgeServiceType,
|
type: ClawdisBonjour.bridgeServiceType,
|
||||||
domain: nil,
|
domain: ClawdisBonjour.bridgeServiceDomain,
|
||||||
txtRecord: nil)
|
txtRecord: nil)
|
||||||
|
|
||||||
listener.newConnectionHandler = { [weak self] connection in
|
listener.newConnectionHandler = { [weak self] connection in
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue