feat: migrate on-device Qwen3 ASR to CoreML for background Flow dictation
Replace MLX GPU inference with CoreML bundles so transcription continues while the host app is backgrounded. Adds model download and warm-up, vendored Qwen3Speech, and updates onboarding, settings, and copy for the ~1.6 GB CoreML package (iOS 18+).
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
// FlowAppLifecycle.swift
|
||||
// OSGKeyboard · Shared
|
||||
//
|
||||
// Tracks whether the host app process is in the foreground.
|
||||
// Retained for any future GPU-backed paths; CoreML ASR does not require it.
|
||||
|
||||
import Foundation
|
||||
|
||||
public final class FlowAppLifecycle: @unchecked Sendable {
|
||||
|
||||
public static let shared = FlowAppLifecycle()
|
||||
|
||||
private let lock = NSLock()
|
||||
private var isForeground = true
|
||||
|
||||
private init() {}
|
||||
|
||||
/// `true` when the host app scene is active (`.active`).
|
||||
public var allowsGPUInference: Bool {
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
return isForeground
|
||||
}
|
||||
|
||||
public func setForeground(_ foreground: Bool) {
|
||||
lock.lock()
|
||||
isForeground = foreground
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
/// Blocks until foreground or cancellation.
|
||||
public func waitUntilForeground() async -> Bool {
|
||||
while !allowsGPUInference {
|
||||
if Task.isCancelled { return false }
|
||||
try? await Task.sleep(nanoseconds: 200_000_000)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user