feat: TypeWhisper Flow sessions, Phase 4 UX, and GitHub Pages privacy site

Migrate keyboard dictation to continuous Flow sessions with auto-start,
tap-to-toggle recording, 60s countdown, five-step onboarding, and App Group
IPC. Add docs/ GitHub Pages site with en/zh privacy policy for App Store compliance.
This commit is contained in:
Rocky
2026-06-19 18:05:50 +08:00
parent 6148d05093
commit 7f059dbd45
48 changed files with 3815 additions and 1065 deletions
+8 -11
View File
@@ -12,18 +12,15 @@ public enum AppGroup {
/// Whether the App Group container is available on this device.
///
/// Cached at first read the underlying `UserDefaults(suiteName:)`
/// call is cheap, but main-app startup and every keyboard-extension
/// read hit it, so we memoize the result.
///
/// Production code paths MUST go through `isAvailable` first and
/// surface a friendly error view (e.g. `AppGroupErrorView`) on the
/// main app, or the keyboard extension's persisted-locale load.
/// Calling `defaults` directly when the group is missing will trip
/// the DEBUG `fatalError` below that path is reserved for
/// developer-only escape hatches and intentional debugging.
/// Checks both `UserDefaults(suiteName:)` *and* the on-disk container.
/// The suite alone can appear to open while the container is still `(null)`
/// when provisioning is misconfigured that case produces the
/// `CFPrefsPlistSource Container: (null)` console warning.
public static let isAvailable: Bool = {
UserDefaults(suiteName: identifier) != nil
guard UserDefaults(suiteName: identifier) != nil else { return false }
return FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: identifier
) != nil
}()
/// Shared UserDefaults instance for cross-process config.