feat(flow): implement ABCD session policy and host return whitelist

- Scheme A: on-demand session start, inactivity-based expiry, handoff auto-recording
- Scheme B: cold-start overlay with swipe guidance and return alert
- Scheme C+D: HostAppURLRegistry (20 apps) and sourceApplication capture
- Settings: skip app switch toggle and inactivity duration picker
- Add LSApplicationQueriesSchemes for canOpenURL checks

Co-authored-by: Rocky <hkgood@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-07-06 07:38:26 +00:00
parent 6489340b2e
commit 13cd7b30f9
25 changed files with 936 additions and 77 deletions
@@ -0,0 +1,39 @@
// 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
}
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
}
}