70ba3a4359
- Add FlowKeepAliveMode (Dynamic Island vs PiP) with iCloud sync - Settings: keep-alive picker; inactivity timeout only for Live Activity - PiP: waveform sample-buffer controller, mic released between utterances - PiP sessions have no idle expiry; user closing PiP ends the session - FlowSessionManager branches hostReady, session start, and utterance paths - UIBackgroundModes picture-in-picture; bilingual strings and tests Co-authored-by: Rocky <hkgood@users.noreply.github.com>
52 lines
1.9 KiB
Swift
52 lines
1.9 KiB
Swift
// FlowSessionPolicy.swift
|
|
// OSGKeyboard · Shared
|
|
//
|
|
// Reads Flow session behaviour preferences from the App Group.
|
|
|
|
import Foundation
|
|
|
|
public enum FlowSessionPolicy {
|
|
public static func skipAppSwitch(defaults: UserDefaults? = nil) -> Bool {
|
|
let store = resolvedDefaults(defaults)
|
|
if store.object(forKey: AppGroupConfiguration.Keys.flowSkipAppSwitch) == nil {
|
|
return true
|
|
}
|
|
return store.bool(forKey: AppGroupConfiguration.Keys.flowSkipAppSwitch)
|
|
}
|
|
|
|
public static func inactivityDuration(defaults: UserDefaults? = nil) -> FlowInactivityDuration {
|
|
let store = resolvedDefaults(defaults)
|
|
return FlowInactivityDuration.fromStored(
|
|
store.string(forKey: AppGroupConfiguration.Keys.flowInactivityDuration)
|
|
)
|
|
}
|
|
|
|
public static func sessionDuration(defaults: UserDefaults? = nil) -> TimeInterval {
|
|
inactivityDuration(defaults: defaults).timeInterval
|
|
}
|
|
|
|
public static func keepAliveMode(defaults: UserDefaults? = nil) -> FlowKeepAliveMode {
|
|
let store = resolvedDefaults(defaults)
|
|
return FlowKeepAliveMode.fromStored(
|
|
store.string(forKey: AppGroupConfiguration.Keys.flowKeepAliveMode)
|
|
)
|
|
}
|
|
|
|
/// PiP sessions have no inactivity expiry; only the Live Activity path times out.
|
|
public static func usesInactivityExpiry(defaults: UserDefaults? = nil) -> Bool {
|
|
keepAliveMode(defaults: defaults) == .liveActivity
|
|
}
|
|
|
|
private static func resolvedDefaults(_ defaults: UserDefaults?) -> UserDefaults {
|
|
if let defaults { return defaults }
|
|
guard let available = AppGroup.defaultsIfAvailable else {
|
|
#if DEBUG
|
|
fatalError("App Group unavailable — inject UserDefaults in tests.")
|
|
#else
|
|
fatalError("App Group unavailable.")
|
|
#endif
|
|
}
|
|
return available
|
|
}
|
|
}
|