@glassly/engine 0.3.7 → 0.3.8-beta.1013
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/build/engine.d.ts +18 -2
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +7 -4
- package/build/engine.js.map +1 -1
- package/build/facades/ai.d.ts +3 -0
- package/build/facades/ai.d.ts.map +1 -1
- package/build/facades/ai.js +3 -0
- package/build/facades/ai.js.map +1 -1
- package/build/facades/backup.d.ts +14 -0
- package/build/facades/backup.d.ts.map +1 -0
- package/build/facades/backup.js +22 -0
- package/build/facades/backup.js.map +1 -0
- package/build/facades/glasses.d.ts +13 -5
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +17 -4
- package/build/facades/glasses.js.map +1 -1
- package/build/generated/releaseMetadata.js +4 -4
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/services/AppRegistry.d.ts +2 -1
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +38 -8
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/AppStateBackup.d.ts +98 -0
- package/build/services/AppStateBackup.d.ts.map +1 -0
- package/build/services/AppStateBackup.js +224 -0
- package/build/services/AppStateBackup.js.map +1 -0
- package/build/services/BlobStore.d.ts.map +1 -1
- package/build/services/BlobStore.js +5 -12
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/CloudClientService.d.ts +3 -1
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +42 -2
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DeviceEventRouter.d.ts.map +1 -1
- package/build/services/DeviceEventRouter.js +1 -0
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/DisplayDiagnostics.d.ts.map +1 -1
- package/build/services/DisplayDiagnostics.js +4 -2
- package/build/services/DisplayDiagnostics.js.map +1 -1
- package/build/services/DisplayProcessor.d.ts +2 -0
- package/build/services/DisplayProcessor.d.ts.map +1 -1
- package/build/services/DisplayProcessor.js +15 -1
- package/build/services/DisplayProcessor.js.map +1 -1
- package/build/services/GlassesTouchInput.d.ts.map +1 -1
- package/build/services/GlassesTouchInput.js +4 -2
- package/build/services/GlassesTouchInput.js.map +1 -1
- package/build/services/JSCrashloopReportService.d.ts.map +1 -1
- package/build/services/JSCrashloopReportService.js +5 -0
- package/build/services/JSCrashloopReportService.js.map +1 -1
- package/build/services/JSRouter.d.ts +11 -3
- package/build/services/JSRouter.d.ts.map +1 -1
- package/build/services/JSRouter.js +36 -6
- package/build/services/JSRouter.js.map +1 -1
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +5 -2
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +13 -0
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +61 -22
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js +2 -0
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/LocalTranslationService.d.ts +2 -0
- package/build/services/LocalTranslationService.d.ts.map +1 -1
- package/build/services/LocalTranslationService.js +22 -0
- package/build/services/LocalTranslationService.js.map +1 -1
- package/build/services/MiniappEngine.d.ts +9 -0
- package/build/services/MiniappEngine.d.ts.map +1 -1
- package/build/services/MiniappEngine.js +60 -27
- package/build/services/MiniappEngine.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts +2 -0
- package/build/services/MiniappLauncher.d.ts.map +1 -1
- package/build/services/MiniappLauncher.js +6 -0
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/NavigationService.d.ts +1 -0
- package/build/services/NavigationService.d.ts.map +1 -1
- package/build/services/NavigationService.js +20 -6
- package/build/services/NavigationService.js.map +1 -1
- package/build/services/OfflineActivity.d.ts +54 -0
- package/build/services/OfflineActivity.d.ts.map +1 -0
- package/build/services/OfflineActivity.js +86 -0
- package/build/services/OfflineActivity.js.map +1 -0
- package/build/services/PhoneCalendarService.d.ts.map +1 -1
- package/build/services/PhoneCalendarService.js +8 -0
- package/build/services/PhoneCalendarService.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +7 -3
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/STTModelManager.d.ts +1 -0
- package/build/services/STTModelManager.d.ts.map +1 -1
- package/build/services/STTModelManager.js +6 -0
- package/build/services/STTModelManager.js.map +1 -1
- package/build/services/SceneRenderer.js +1 -1
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/appStateBackupFile.d.ts +32 -0
- package/build/services/appStateBackupFile.d.ts.map +1 -0
- package/build/services/appStateBackupFile.js +135 -0
- package/build/services/appStateBackupFile.js.map +1 -0
- package/build/services/controllers.d.ts.map +1 -1
- package/build/services/controllers.js +13 -3
- package/build/services/controllers.js.map +1 -1
- package/build/services/effectiveCapabilities.js +6 -1
- package/build/services/effectiveCapabilities.js.map +1 -1
- package/build/services/neuralBand/NeuralBandInput.d.ts +12 -1
- package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -1
- package/build/services/neuralBand/NeuralBandInput.js +27 -0
- package/build/services/neuralBand/NeuralBandInput.js.map +1 -1
- package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -1
- package/build/services/neuralBand/NeuralBandSettingsSync.js +6 -0
- package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -1
- package/build/services/pages/pageEligibility.d.ts.map +1 -1
- package/build/services/pages/pageEligibility.js +8 -1
- package/build/services/pages/pageEligibility.js.map +1 -1
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js +1 -0
- package/build/services/settingsBridge.js.map +1 -1
- package/build/services/{appleWatch/AppleWatchLink.d.ts → watch/WatchLink.d.ts} +8 -7
- package/build/services/watch/WatchLink.d.ts.map +1 -0
- package/build/services/{appleWatch/AppleWatchLink.js → watch/WatchLink.js} +14 -15
- package/build/services/watch/WatchLink.js.map +1 -0
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js +0 -1
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +22 -10
- package/build/stores/apps.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +71 -6
- package/build/stores/settings.js.map +1 -1
- package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g1.js +3 -0
- package/build/types/capabilities/even-realities-g1.js.map +1 -1
- package/build/types/capabilities/memomind-one.d.ts +3 -0
- package/build/types/capabilities/memomind-one.d.ts.map +1 -0
- package/build/types/capabilities/memomind-one.js +42 -0
- package/build/types/capabilities/memomind-one.js.map +1 -0
- package/build/types/capabilities/rayneo-io.d.ts.map +1 -1
- package/build/types/capabilities/rayneo-io.js +3 -2
- package/build/types/capabilities/rayneo-io.js.map +1 -1
- package/build/types/enums.d.ts +8 -2
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +6 -0
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +3 -1
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +3 -1
- package/build/types/hardware.js.map +1 -1
- package/build/utils/display/index.d.ts +2 -1
- package/build/utils/display/index.d.ts.map +1 -1
- package/build/utils/display/index.js +3 -2
- package/build/utils/display/index.js.map +1 -1
- package/build/utils/display/profiles/index.d.ts +2 -1
- package/build/utils/display/profiles/index.d.ts.map +1 -1
- package/build/utils/display/profiles/index.js +3 -2
- package/build/utils/display/profiles/index.js.map +1 -1
- package/build/utils/display/profiles/rayneo-io.d.ts +1 -1
- package/build/utils/display/profiles/rayneo-io.d.ts.map +1 -1
- package/build/utils/display/profiles/rayneo-io.js +1 -1
- package/build/utils/display/profiles/rayneo-io.js.map +1 -1
- package/build/utils/display/scene/index.d.ts +1 -1
- package/build/utils/display/scene/index.d.ts.map +1 -1
- package/build/utils/display/scene/index.js +1 -1
- package/build/utils/display/scene/index.js.map +1 -1
- package/build/utils/display/scene/process.d.ts +6 -0
- package/build/utils/display/scene/process.d.ts.map +1 -1
- package/build/utils/display/scene/process.js +22 -7
- package/build/utils/display/scene/process.js.map +1 -1
- package/build/utils/miniappGlobals.d.ts +13 -17
- package/build/utils/miniappGlobals.d.ts.map +1 -1
- package/build/utils/miniappGlobals.js +24 -56
- package/build/utils/miniappGlobals.js.map +1 -1
- package/package.json +7 -7
- package/src/engine.ts +7 -4
- package/src/facades/ai.ts +4 -0
- package/src/facades/backup.ts +28 -0
- package/src/facades/glasses.ts +22 -5
- package/src/generated/releaseMetadata.ts +4 -4
- package/src/index.ts +10 -0
- package/src/services/AppRegistry.ts +36 -9
- package/src/services/AppStateBackup.ts +283 -0
- package/src/services/BlobStore.ts +5 -11
- package/src/services/CloudClientService.ts +43 -4
- package/src/services/DeviceEventRouter.ts +1 -0
- package/src/services/DisplayDiagnostics.ts +4 -2
- package/src/services/DisplayProcessor.ts +20 -8
- package/src/services/GlassesTouchInput.ts +6 -2
- package/src/services/JSCrashloopReportService.ts +5 -0
- package/src/services/JSRouter.ts +37 -6
- package/src/services/LocalDisplayManager.ts +5 -2
- package/src/services/LocalMiniappRuntime.ts +61 -22
- package/src/services/LocalSttFallbackCoordinator.ts +4 -0
- package/src/services/LocalTranslationService.ts +20 -0
- package/src/services/MiniappEngine.ts +62 -27
- package/src/services/MiniappLauncher.ts +7 -0
- package/src/services/NavigationService.ts +28 -8
- package/src/services/OfflineActivity.ts +131 -0
- package/src/services/PhoneCalendarService.ts +7 -0
- package/src/services/PhoneNotificationsSync.ts +8 -3
- package/src/services/STTModelManager.ts +6 -0
- package/src/services/SceneRenderer.ts +1 -1
- package/src/services/appStateBackupFile.ts +171 -0
- package/src/services/controllers.ts +14 -3
- package/src/services/effectiveCapabilities.ts +6 -1
- package/src/services/neuralBand/NeuralBandInput.ts +37 -1
- package/src/services/neuralBand/NeuralBandSettingsSync.ts +12 -0
- package/src/services/pages/pageEligibility.ts +9 -1
- package/src/services/settingsBridge.ts +1 -0
- package/src/services/{appleWatch/AppleWatchLink.ts → watch/WatchLink.ts} +20 -20
- package/src/stores/appVisibility.ts +0 -1
- package/src/stores/apps.ts +22 -11
- package/src/stores/settings.ts +78 -10
- package/src/types/capabilities/even-realities-g1.ts +4 -0
- package/src/types/capabilities/memomind-one.ts +43 -0
- package/src/types/capabilities/rayneo-io.ts +3 -2
- package/src/types/enums.ts +6 -0
- package/src/types/hardware.ts +14 -1
- package/src/utils/display/index.ts +4 -2
- package/src/utils/display/profiles/index.ts +9 -2
- package/src/utils/display/profiles/rayneo-io.ts +6 -1
- package/src/utils/display/scene/index.ts +1 -1
- package/src/utils/display/scene/process.ts +22 -7
- package/src/utils/miniappGlobals.ts +32 -64
- package/build/services/appleWatch/AppleWatchLink.d.ts.map +0 -1
- package/build/services/appleWatch/AppleWatchLink.js.map +0 -1
|
@@ -67,6 +67,10 @@ export function nativeNotificationsSupported() {
|
|
|
67
67
|
const model = useGlassesStore.getState().deviceModel;
|
|
68
68
|
return getModelCapabilities(model).hasNativeNotifications === true;
|
|
69
69
|
}
|
|
70
|
+
function notificationRelaySupported() {
|
|
71
|
+
const model = useGlassesStore.getState().deviceModel;
|
|
72
|
+
return Platform.OS === "ios" && getModelCapabilities(model).hasNotificationRelay === true;
|
|
73
|
+
}
|
|
70
74
|
/** Popup durations the firmware accepts, or an empty list when it takes any. */
|
|
71
75
|
export function nativeNotificationPopupSeconds() {
|
|
72
76
|
const model = useGlassesStore.getState().deviceModel;
|
|
@@ -114,12 +118,12 @@ export function currentPresentationOwner(hostActive) {
|
|
|
114
118
|
export function captureAuthorization() {
|
|
115
119
|
if (Platform.OS !== "ios")
|
|
116
120
|
return "not_needed";
|
|
117
|
-
if (!nativeNotificationsSupported())
|
|
121
|
+
if (!nativeNotificationsSupported() && !notificationRelaySupported())
|
|
118
122
|
return "not_needed";
|
|
119
123
|
const glasses = useGlassesStore.getState();
|
|
120
124
|
if (!isGlassesConnected(glasses.connection))
|
|
121
125
|
return "unknown";
|
|
122
|
-
return glasses.ancsAuthorized ? "granted" : "denied";
|
|
126
|
+
return glasses.ancsAuthorized ? "granted" : notificationRelaySupported() ? "unknown" : "denied";
|
|
123
127
|
}
|
|
124
128
|
/**
|
|
125
129
|
* Hand one captured notification to glasses whose firmware presents it from
|
|
@@ -148,7 +152,7 @@ function pushListenerConfig() {
|
|
|
148
152
|
CrustModule.setNotificationConfig(listenerEnabled, Array.isArray(blocklist) ? blocklist : []).catch((err) => console.warn(`PhoneNotificationsSync: setNotificationConfig failed: ${err?.message ?? err}`));
|
|
149
153
|
}
|
|
150
154
|
function pushGlassesConfig() {
|
|
151
|
-
if (!nativeNotificationsSupported())
|
|
155
|
+
if (!nativeNotificationsSupported() && !notificationRelaySupported())
|
|
152
156
|
return;
|
|
153
157
|
if (!isGlassesConnected(useGlassesStore.getState().connection))
|
|
154
158
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhoneNotificationsSync.js","sourceRoot":"","sources":["../../src/services/PhoneNotificationsSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Phone-notifications sync — engine-owned, started by `engine.start()`. Keeps\n * three things in step with settings and the connected glasses, for any host:\n *\n * - Android: the notification listener's kill switch + per-app blocklist\n * (`CrustModule.setNotificationConfig`). The listener runs in its own\n * guarded process and is desired by default; the debug setting stays a\n * hidden emergency switch. Notify's running state gates presentation, not\n * capture.\n * - Glasses whose firmware presents notifications (`hasNativeNotifications`):\n * one `GlassesNotificationConfig` pushed through the Bluetooth SDK whenever\n * a setting, the phone's activity, the seen-apps list or the connected\n * glasses change. Drivers re-apply their last config on reconnect; the push\n * repeats on connection so a fresh driver gets it too.\n * - The seen-apps list (`notification_seen_apps`) from `notification_app_seen`:\n * glasses that read the phone's stream report each source app, which is\n * the only app enumeration iOS offers.\n *\n * Presentation is one question with one answer (`presentationOwner`); hosts\n * ask it per event instead of reasoning about models or platforms.\n */\nimport {Platform} from \"react-native\"\nimport {shallow} from \"zustand/shallow\"\nimport CrustModule from \"@glassly/crust\"\nimport type {PhoneNotificationEvent} from \"@glassly/crust\"\nimport type {GlassesNotificationConfig} from \"@glassly/bluetooth-sdk\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {NotificationAppSeenEvent} from \"@glassly/bluetooth-sdk/internal\"\n\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {DeviceTypes} from \"../types/enums\"\nimport {getModelCapabilities} from \"../types/hardware\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport {notificationAppCatalog} from \"./notificationAppCatalog\"\nimport {\n glassesNotificationConfig,\n presentationOwner,\n type NotificationApp,\n type PresentationOwner,\n} from \"./notifications/notificationPolicy\"\nimport {overlayViewerRunning} from \"./pages/overlayApps\"\nimport {pagesEligible} from \"./pages/pageEligibility\"\nimport {isPhoneActive, onPhoneActivityChange} from \"./PhoneActivity\"\n\nexport type {PresentationOwner}\n\nexport interface SeenNotificationApp {\n appId: string\n displayName: string\n lastSeen: number\n}\n\nlet unsubscribers: Array<() => void> = []\n\nexport function getSeenNotificationApps(): SeenNotificationApp[] {\n const seen = useSettingsStore.getState().getSetting(SETTINGS.notification_seen_apps.key)\n return Array.isArray(seen) ? (seen as SeenNotificationApp[]) : []\n}\n\n/** Catalog ∪ seen apps, seen display names winning. Sorted by name. */\nexport function getKnownNotificationApps(): NotificationApp[] {\n const merged = new Map<string, string>()\n for (const app of notificationAppCatalog()) merged.set(app.appId, app.displayName)\n for (const app of getSeenNotificationApps()) {\n if (app.appId) merged.set(app.appId, app.displayName || app.appId)\n }\n return [...merged.entries()]\n .map(([appId, displayName]) => ({appId, displayName}))\n .sort((a, b) => a.displayName.localeCompare(b.displayName))\n}\n\n/**\n * Apps to show in a notification filter UI (package/bundle id, name, icon).\n * Android: installed apps. iOS: seeded catalog ∪ glasses-reported apps\n * (icons unavailable — iOS offers no cross-app icon lookup).\n */\nexport function installedNotificationApps(): Promise<\n Array<{packageName: string; appName: string; icon: string | null}>\n> {\n if (Platform.OS === \"android\") return CrustModule.getInstalledApps()\n if (Platform.OS !== \"ios\") return Promise.resolve([])\n return Promise.resolve(\n getKnownNotificationApps().map((app) => ({packageName: app.appId, appName: app.displayName, icon: null})),\n )\n}\n\n/** The connected (or remembered) model presents notifications in firmware. */\nexport function nativeNotificationsSupported(): boolean {\n const model = useGlassesStore.getState().deviceModel as DeviceTypes\n return getModelCapabilities(model).hasNativeNotifications === true\n}\n\n/** Popup durations the firmware accepts, or an empty list when it takes any. */\nexport function nativeNotificationPopupSeconds(): number[] {\n const model = useGlassesStore.getState().deviceModel as DeviceTypes\n return getModelCapabilities(model).nativeNotificationPopupSeconds ?? []\n}\n\nexport function notificationsEnabled(): boolean {\n return useSettingsStore.getState().getSetting(SETTINGS.notifications_enabled.key) !== false\n}\n\nexport function desiredGlassesNotificationConfig(): GlassesNotificationConfig {\n const s = useSettingsStore.getState()\n const blocklist = s.getSetting(SETTINGS.notifications_blocklist.key)\n return glassesNotificationConfig({\n enabled: notificationsEnabled(),\n popups: s.getSetting(SETTINGS.notifications_popups.key) !== false,\n popupSeconds: Number(s.getSetting(SETTINGS.notifications_popup_seconds.key)),\n holdDuringApps: s.getSetting(SETTINGS.notifications_hold_during_apps.key) !== false,\n ignoreWhileActive: s.getSetting(SETTINGS.notifications_ignore_while_active.key) === true,\n phoneActive: isPhoneActive(),\n blockedApps: Array.isArray(blocklist) ? (blocklist as string[]) : [],\n knownApps: getKnownNotificationApps(),\n })\n}\n\n/**\n * Who presents the next phone notification. `hostActive` is the host's own\n * presentation surface (Notify in the Glassly App); the engine has no view of\n * it.\n */\nexport function currentPresentationOwner(hostActive: boolean): PresentationOwner {\n return presentationOwner({\n enabled: notificationsEnabled(),\n pagesEligible: pagesEligible(),\n // The viewer is an overlay miniapp listening to phone notifications\n // (ADR-0006): with none running, nothing draws one on eligible glasses.\n viewerRunning: overlayViewerRunning(),\n nativeNotifications: nativeNotificationsSupported() && isGlassesConnected(useGlassesStore.getState().connection),\n hostActive,\n })\n}\n\n/**\n * Whether the glasses may read the phone's notifications. iOS glasses read\n * the stream themselves under the Bluetooth notification-sharing consent the\n * driver reports as `ancsAuthorized`; Android glasses get content from the\n * phone's listener, whose grant the permission flow owns.\n */\nexport function captureAuthorization(): \"granted\" | \"denied\" | \"unknown\" | \"not_needed\" {\n if (Platform.OS !== \"ios\") return \"not_needed\"\n if (!nativeNotificationsSupported()) return \"not_needed\"\n const glasses = useGlassesStore.getState()\n if (!isGlassesConnected(glasses.connection)) return \"unknown\"\n return glasses.ancsAuthorized ? \"granted\" : \"denied\"\n}\n\n/**\n * Hand one captured notification to glasses whose firmware presents it from\n * uploaded content (Android). Glasses that read the phone's stream reject it;\n * callers only reach here when the owner is `firmware`.\n */\nexport function uploadPhoneNotification(event: PhoneNotificationEvent): Promise<void> {\n if (Platform.OS !== \"android\") return Promise.resolve()\n return Promise.resolve(\n BluetoothSdk.uploadPhoneNotification({\n notificationId: String(event.notificationId ?? \"\"),\n packageName: String(event.packageName ?? \"\"),\n appName: String(event.app ?? \"\"),\n title: String(event.title ?? \"\"),\n subtitle: \"\",\n body: String(event.content ?? \"\"),\n timestampMs: Number(event.timestamp) || Date.now(),\n }),\n )\n}\n\nfunction pushListenerConfig(): void {\n if (Platform.OS !== \"android\") return\n const s = useSettingsStore.getState()\n const listenerEnabled = Boolean(s.getSetting(SETTINGS.android_notification_listener_enabled.key))\n const blocklist = s.getSetting(SETTINGS.notifications_blocklist.key)\n CrustModule.setNotificationConfig(listenerEnabled, Array.isArray(blocklist) ? blocklist : []).catch((err: unknown) =>\n console.warn(`PhoneNotificationsSync: setNotificationConfig failed: ${(err as Error)?.message ?? err}`),\n )\n}\n\nfunction pushGlassesConfig(): void {\n if (!nativeNotificationsSupported()) return\n if (!isGlassesConnected(useGlassesStore.getState().connection)) return\n void Promise.resolve(BluetoothSdk.setGlassesNotificationConfig(desiredGlassesNotificationConfig())).catch(\n (err: unknown) =>\n console.warn(`PhoneNotificationsSync: glasses notification config failed: ${(err as Error)?.message ?? err}`),\n )\n}\n\nfunction pushAll(): void {\n pushListenerConfig()\n pushGlassesConfig()\n}\n\n/** Record a glasses-reported source app. Writes only on new app / renamed app. */\nfunction recordSeenApp(event: NotificationAppSeenEvent): void {\n if (!event.appId) return\n const seen = getSeenNotificationApps()\n const existing = seen.find((app) => app.appId === event.appId)\n const displayName = event.displayName || existing?.displayName || event.appId\n if (existing && existing.displayName === displayName) return\n const next = seen\n .filter((app) => app.appId !== event.appId)\n .concat([{appId: event.appId, displayName, lastSeen: event.timestamp || Date.now()}])\n useSettingsStore.getState().setSetting(SETTINGS.notification_seen_apps.key, next)\n}\n\nexport function startPhoneNotificationsSync(): void {\n if (unsubscribers.length) return\n pushAll()\n const seenApps = BluetoothSdk.addListener(\"notification_app_seen\", recordSeenApp)\n unsubscribers = [\n useSettingsStore.subscribe(\n (state) =>\n [\n SETTINGS.android_notification_listener_enabled,\n SETTINGS.notifications_blocklist,\n SETTINGS.notification_seen_apps,\n SETTINGS.notifications_enabled,\n SETTINGS.notifications_popups,\n SETTINGS.notifications_popup_seconds,\n SETTINGS.notifications_hold_during_apps,\n SETTINGS.notifications_ignore_while_active,\n ].map((setting) => state.getSetting(setting.key)),\n pushAll,\n {equalityFn: shallow},\n ),\n // A (re)connected driver gets the current config; the SDK dedupes nothing\n // here, so only connection state and model are watched, not every field.\n useGlassesStore.subscribe(\n (state) => ({model: state.deviceModel, connected: isGlassesConnected(state.connection)}),\n pushGlassesConfig,\n {equalityFn: shallow},\n ),\n // Lock / foreground changes flip the effective popups flag for firmware\n // that pops notifications up by itself.\n onPhoneActivityChange(pushGlassesConfig),\n () => seenApps.remove(),\n ]\n}\n\nexport function stopPhoneNotificationsSync(): void {\n for (const unsubscribe of unsubscribers) unsubscribe()\n unsubscribers = []\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PhoneNotificationsSync.js","sourceRoot":"","sources":["../../src/services/PhoneNotificationsSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Phone-notifications sync — engine-owned, started by `engine.start()`. Keeps\n * three things in step with settings and the connected glasses, for any host:\n *\n * - Android: the notification listener's kill switch + per-app blocklist\n * (`CrustModule.setNotificationConfig`). The listener runs in its own\n * guarded process and is desired by default; the debug setting stays a\n * hidden emergency switch. Notify's running state gates presentation, not\n * capture.\n * - Glasses whose firmware presents notifications (`hasNativeNotifications`):\n * one `GlassesNotificationConfig` pushed through the Bluetooth SDK whenever\n * a setting, the phone's activity, the seen-apps list or the connected\n * glasses change. Drivers re-apply their last config on reconnect; the push\n * repeats on connection so a fresh driver gets it too.\n * - The seen-apps list (`notification_seen_apps`) from `notification_app_seen`:\n * glasses that read the phone's stream report each source app, which is\n * the only app enumeration iOS offers.\n *\n * Presentation is one question with one answer (`presentationOwner`); hosts\n * ask it per event instead of reasoning about models or platforms.\n */\nimport {Platform} from \"react-native\"\nimport {shallow} from \"zustand/shallow\"\nimport CrustModule from \"@glassly/crust\"\nimport type {PhoneNotificationEvent} from \"@glassly/crust\"\nimport type {GlassesNotificationConfig} from \"@glassly/bluetooth-sdk\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {NotificationAppSeenEvent} from \"@glassly/bluetooth-sdk/internal\"\n\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {DeviceTypes} from \"../types/enums\"\nimport {getModelCapabilities} from \"../types/hardware\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport {notificationAppCatalog} from \"./notificationAppCatalog\"\nimport {\n glassesNotificationConfig,\n presentationOwner,\n type NotificationApp,\n type PresentationOwner,\n} from \"./notifications/notificationPolicy\"\nimport {overlayViewerRunning} from \"./pages/overlayApps\"\nimport {pagesEligible} from \"./pages/pageEligibility\"\nimport {isPhoneActive, onPhoneActivityChange} from \"./PhoneActivity\"\n\nexport type {PresentationOwner}\n\nexport interface SeenNotificationApp {\n appId: string\n displayName: string\n lastSeen: number\n}\n\nlet unsubscribers: Array<() => void> = []\n\nexport function getSeenNotificationApps(): SeenNotificationApp[] {\n const seen = useSettingsStore.getState().getSetting(SETTINGS.notification_seen_apps.key)\n return Array.isArray(seen) ? (seen as SeenNotificationApp[]) : []\n}\n\n/** Catalog ∪ seen apps, seen display names winning. Sorted by name. */\nexport function getKnownNotificationApps(): NotificationApp[] {\n const merged = new Map<string, string>()\n for (const app of notificationAppCatalog()) merged.set(app.appId, app.displayName)\n for (const app of getSeenNotificationApps()) {\n if (app.appId) merged.set(app.appId, app.displayName || app.appId)\n }\n return [...merged.entries()]\n .map(([appId, displayName]) => ({appId, displayName}))\n .sort((a, b) => a.displayName.localeCompare(b.displayName))\n}\n\n/**\n * Apps to show in a notification filter UI (package/bundle id, name, icon).\n * Android: installed apps. iOS: seeded catalog ∪ glasses-reported apps\n * (icons unavailable — iOS offers no cross-app icon lookup).\n */\nexport function installedNotificationApps(): Promise<\n Array<{packageName: string; appName: string; icon: string | null}>\n> {\n if (Platform.OS === \"android\") return CrustModule.getInstalledApps()\n if (Platform.OS !== \"ios\") return Promise.resolve([])\n return Promise.resolve(\n getKnownNotificationApps().map((app) => ({packageName: app.appId, appName: app.displayName, icon: null})),\n )\n}\n\n/** The connected (or remembered) model presents notifications in firmware. */\nexport function nativeNotificationsSupported(): boolean {\n const model = useGlassesStore.getState().deviceModel as DeviceTypes\n return getModelCapabilities(model).hasNativeNotifications === true\n}\n\nfunction notificationRelaySupported(): boolean {\n const model = useGlassesStore.getState().deviceModel as DeviceTypes\n return Platform.OS === \"ios\" && getModelCapabilities(model).hasNotificationRelay === true\n}\n\n/** Popup durations the firmware accepts, or an empty list when it takes any. */\nexport function nativeNotificationPopupSeconds(): number[] {\n const model = useGlassesStore.getState().deviceModel as DeviceTypes\n return getModelCapabilities(model).nativeNotificationPopupSeconds ?? []\n}\n\nexport function notificationsEnabled(): boolean {\n return useSettingsStore.getState().getSetting(SETTINGS.notifications_enabled.key) !== false\n}\n\nexport function desiredGlassesNotificationConfig(): GlassesNotificationConfig {\n const s = useSettingsStore.getState()\n const blocklist = s.getSetting(SETTINGS.notifications_blocklist.key)\n return glassesNotificationConfig({\n enabled: notificationsEnabled(),\n popups: s.getSetting(SETTINGS.notifications_popups.key) !== false,\n popupSeconds: Number(s.getSetting(SETTINGS.notifications_popup_seconds.key)),\n holdDuringApps: s.getSetting(SETTINGS.notifications_hold_during_apps.key) !== false,\n ignoreWhileActive: s.getSetting(SETTINGS.notifications_ignore_while_active.key) === true,\n phoneActive: isPhoneActive(),\n blockedApps: Array.isArray(blocklist) ? (blocklist as string[]) : [],\n knownApps: getKnownNotificationApps(),\n })\n}\n\n/**\n * Who presents the next phone notification. `hostActive` is the host's own\n * presentation surface (Notify in the Glassly App); the engine has no view of\n * it.\n */\nexport function currentPresentationOwner(hostActive: boolean): PresentationOwner {\n return presentationOwner({\n enabled: notificationsEnabled(),\n pagesEligible: pagesEligible(),\n // The viewer is an overlay miniapp listening to phone notifications\n // (ADR-0006): with none running, nothing draws one on eligible glasses.\n viewerRunning: overlayViewerRunning(),\n nativeNotifications: nativeNotificationsSupported() && isGlassesConnected(useGlassesStore.getState().connection),\n hostActive,\n })\n}\n\n/**\n * Whether the glasses may read the phone's notifications. iOS glasses read\n * the stream themselves under the Bluetooth notification-sharing consent the\n * driver reports as `ancsAuthorized`; Android glasses get content from the\n * phone's listener, whose grant the permission flow owns.\n */\nexport function captureAuthorization(): \"granted\" | \"denied\" | \"unknown\" | \"not_needed\" {\n if (Platform.OS !== \"ios\") return \"not_needed\"\n if (!nativeNotificationsSupported() && !notificationRelaySupported()) return \"not_needed\"\n const glasses = useGlassesStore.getState()\n if (!isGlassesConnected(glasses.connection)) return \"unknown\"\n return glasses.ancsAuthorized ? \"granted\" : notificationRelaySupported() ? \"unknown\" : \"denied\"\n}\n\n/**\n * Hand one captured notification to glasses whose firmware presents it from\n * uploaded content (Android). Glasses that read the phone's stream reject it;\n * callers only reach here when the owner is `firmware`.\n */\nexport function uploadPhoneNotification(event: PhoneNotificationEvent): Promise<void> {\n if (Platform.OS !== \"android\") return Promise.resolve()\n return Promise.resolve(\n BluetoothSdk.uploadPhoneNotification({\n notificationId: String(event.notificationId ?? \"\"),\n packageName: String(event.packageName ?? \"\"),\n appName: String(event.app ?? \"\"),\n title: String(event.title ?? \"\"),\n subtitle: \"\",\n body: String(event.content ?? \"\"),\n timestampMs: Number(event.timestamp) || Date.now(),\n }),\n )\n}\n\nfunction pushListenerConfig(): void {\n if (Platform.OS !== \"android\") return\n const s = useSettingsStore.getState()\n const listenerEnabled = Boolean(s.getSetting(SETTINGS.android_notification_listener_enabled.key))\n const blocklist = s.getSetting(SETTINGS.notifications_blocklist.key)\n CrustModule.setNotificationConfig(listenerEnabled, Array.isArray(blocklist) ? blocklist : []).catch((err: unknown) =>\n console.warn(`PhoneNotificationsSync: setNotificationConfig failed: ${(err as Error)?.message ?? err}`),\n )\n}\n\nfunction pushGlassesConfig(): void {\n if (!nativeNotificationsSupported() && !notificationRelaySupported()) return\n if (!isGlassesConnected(useGlassesStore.getState().connection)) return\n void Promise.resolve(BluetoothSdk.setGlassesNotificationConfig(desiredGlassesNotificationConfig())).catch(\n (err: unknown) =>\n console.warn(`PhoneNotificationsSync: glasses notification config failed: ${(err as Error)?.message ?? err}`),\n )\n}\n\nfunction pushAll(): void {\n pushListenerConfig()\n pushGlassesConfig()\n}\n\n/** Record a glasses-reported source app. Writes only on new app / renamed app. */\nfunction recordSeenApp(event: NotificationAppSeenEvent): void {\n if (!event.appId) return\n const seen = getSeenNotificationApps()\n const existing = seen.find((app) => app.appId === event.appId)\n const displayName = event.displayName || existing?.displayName || event.appId\n if (existing && existing.displayName === displayName) return\n const next = seen\n .filter((app) => app.appId !== event.appId)\n .concat([{appId: event.appId, displayName, lastSeen: event.timestamp || Date.now()}])\n useSettingsStore.getState().setSetting(SETTINGS.notification_seen_apps.key, next)\n}\n\nexport function startPhoneNotificationsSync(): void {\n if (unsubscribers.length) return\n pushAll()\n const seenApps = BluetoothSdk.addListener(\"notification_app_seen\", recordSeenApp)\n unsubscribers = [\n useSettingsStore.subscribe(\n (state) =>\n [\n SETTINGS.android_notification_listener_enabled,\n SETTINGS.notifications_blocklist,\n SETTINGS.notification_seen_apps,\n SETTINGS.notifications_enabled,\n SETTINGS.notifications_popups,\n SETTINGS.notifications_popup_seconds,\n SETTINGS.notifications_hold_during_apps,\n SETTINGS.notifications_ignore_while_active,\n ].map((setting) => state.getSetting(setting.key)),\n pushAll,\n {equalityFn: shallow},\n ),\n // A (re)connected driver gets the current config; the SDK dedupes nothing\n // here, so only connection state and model are watched, not every field.\n useGlassesStore.subscribe(\n (state) => ({model: state.deviceModel, connected: isGlassesConnected(state.connection)}),\n pushGlassesConfig,\n {equalityFn: shallow},\n ),\n // Lock / foreground changes flip the effective popups flag for firmware\n // that pops notifications up by itself.\n onPhoneActivityChange(pushGlassesConfig),\n () => seenApps.remove(),\n ]\n}\n\nexport function stopPhoneNotificationsSync(): void {\n for (const unsubscribe of unsubscribers) unsubscribe()\n unsubscribers = []\n}\n"]}
|
|
@@ -52,6 +52,7 @@ declare class STTModelManager {
|
|
|
52
52
|
static getInstance(): STTModelManager;
|
|
53
53
|
getCurrentLanguageFromPreferences(): Promise<string>;
|
|
54
54
|
getCurrentLanguage(): string;
|
|
55
|
+
currentModelLabel(): string;
|
|
55
56
|
setCurrentLanguage(code: string): void;
|
|
56
57
|
getBcp47ForLanguage(code?: string): string;
|
|
57
58
|
/** Sherpa models first, then whatever Apple locales the last refresh reported. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"STTModelManager.d.ts","sourceRoot":"","sources":["../../src/services/STTModelManager.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAA;AAEtE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,YAAY,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,YAAY,CAAA;IAClB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;CACrB;AAID;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAExC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,cAAM,eAAe;IACnB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAiB;IACxC,OAAO,CAAC,aAAa,CAAC,CAAQ;IAC9B,OAAO,CAAC,eAAe,CAAmB;IAC1C,OAAO,CAAC,mBAAmB,CAAwB;IACnD,OAAO,CAAC,YAAY,CAAwE;IAC5F,qEAAqE;IACrE,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,cAAc,CAAoB;IAC1C,OAAO,CAAC,YAAY,CAA6B;IAEjD,OAAO,CAAC,SAAS,CAiIhB;IAED,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,eAAe;IAO/B,iCAAiC,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB1D,kBAAkB,IAAI,MAAM;IAI5B,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMtC,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAK1C,kFAAkF;IAClF,qBAAqB,IAAI,cAAc,EAAE;IAIzC,OAAO,CAAC,MAAM;IAId;;;OAGG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC5C,iBAAiB,IAAI,MAAM;IAK3B,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAMnC,wEAAwE;IACxE,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAInC,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA+BjD,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAqBrD,kBAAkB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAsBnD,gGAAgG;YAClF,iBAAiB;IA4BzB,aAAa,CACjB,IAAI,CAAC,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,EACjD,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,GAC5D,OAAO,CAAC,IAAI,CAAC;IAwFV,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/B,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBzC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBrC,kBAAkB;IAWhC,yEAAyE;IACzE,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKxC,cAAc,IAAI,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;IAQ9D,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIlC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAO1C;AAED,QAAA,MAAM,QAAQ,iBAAgC,CAAA;AAC9C,OAAO,EAAC,eAAe,EAAC,CAAA;AACxB,eAAe,QAAQ,CAAA"}
|
|
1
|
+
{"version":3,"file":"STTModelManager.d.ts","sourceRoot":"","sources":["../../src/services/STTModelManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -183,6 +183,12 @@ class STTModelManager {
|
|
|
183
183
|
getCurrentLanguage() {
|
|
184
184
|
return this.currentLanguage;
|
|
185
185
|
}
|
|
186
|
+
currentModelLabel() {
|
|
187
|
+
const language = this.config(this.currentLanguage);
|
|
188
|
+
if (!language)
|
|
189
|
+
return this.currentLanguage;
|
|
190
|
+
return language.type === "apple" ? `Apple · ${language.displayName}` : language.displayName;
|
|
191
|
+
}
|
|
186
192
|
setCurrentLanguage(code) {
|
|
187
193
|
if (this.config(code)) {
|
|
188
194
|
this.currentLanguage = code;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"STTModelManager.js","sourceRoot":"","sources":["../../src/services/STTModelManager.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk from \"@glassly/bluetooth-sdk\"\nimport {Platform} from \"react-native\"\nimport * as RNFS from \"@dr.pogodin/react-native-fs\"\n\nexport type SttModelType = \"transducer\" | \"ctc\" | \"nemotron\" | \"apple\"\n\nexport interface LanguageInfo {\n code: string\n displayName: string\n size: number\n language: string\n downloaded: boolean\n path?: string\n type: SttModelType\n}\n\nexport interface DownloadProgress {\n jobId: number\n bytesWritten: number\n contentLength: number\n percentage: number\n}\n\nexport interface ExtractionProgress {\n percentage: number\n currentFile?: string\n}\n\nexport interface LanguageConfig {\n code: string\n displayName: string\n fileName: string\n downloadUrl?: string\n size: number\n type: SttModelType\n requiredFiles: string[]\n languageCode: string\n}\n\nconst DEFAULT_LANGUAGE = \"en\"\n\n/**\n * Apple SpeechTranscriber entries are keyed `apple:<bcp47>`; the same string is\n * what native stores as the model path, since the OS owns the assets and there\n * is no directory to point at.\n */\nexport const APPLE_STT_PREFIX = \"apple:\"\n\nexport function isAppleSttCode(code: string): boolean {\n return code.startsWith(APPLE_STT_PREFIX)\n}\n\n/** SpeechTranscriber ships with iOS 26. */\nexport function appleSttSupported(): boolean {\n return Platform.OS === \"ios\" && parseInt(String(Platform.Version), 10) >= 26\n}\n\nclass STTModelManager {\n private static instance: STTModelManager\n private downloadJobId?: number\n private currentLanguage = DEFAULT_LANGUAGE\n private modelReadyListeners = new Set<() => void>()\n private modelBaseUrl = \"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/\"\n /** Apple locales reported by the OS, refreshed on each list load. */\n private appleLanguages: Record<string, LanguageConfig> = {}\n private appleInstalled = new Set<string>()\n private appleRefresh: Promise<void> | null = null\n\n private languages: Record<string, LanguageConfig> = {\n \"en\": {\n code: \"en\",\n displayName: \"English\",\n fileName: \"sherpa-onnx-streaming-zipformer-en-2023-06-21-mobile\",\n size: 349 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n \"fr\": {\n code: \"fr\",\n displayName: \"Français\",\n fileName: \"sherpa-onnx-streaming-zipformer-fr-kroko-2025-08-06\",\n size: 57 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"fr-FR\",\n },\n \"de\": {\n code: \"de\",\n displayName: \"Deutsch\",\n fileName: \"sherpa-onnx-streaming-zipformer-de-kroko-2025-08-06\",\n size: 58 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"de-DE\",\n },\n \"es\": {\n code: \"es\",\n displayName: \"Español\",\n fileName: \"sherpa-onnx-streaming-zipformer-es-kroko-2025-08-06\",\n size: 124 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"es-ES\",\n },\n \"zh\": {\n code: \"zh\",\n displayName: \"中文\",\n fileName: \"sherpa-onnx-streaming-zipformer-zh-2025-06-30\",\n size: 150 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"zh-CN\",\n },\n \"ko\": {\n code: \"ko\",\n displayName: \"한국어\",\n fileName: \"sherpa-onnx-streaming-zipformer-korean-2024-06-16\",\n size: 200 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"ko-KR\",\n },\n // Alternative English streaming models, kept alongside \"en\" so the three can\n // be compared on-device. Both are newer than the 2023 Zipformer used for\n // \"en\" and are a fraction of its 349 MB.\n //\n // Kroko: same family as the fr/de/es entries above, and the smallest English\n // option here. Ships bare encoder/decoder/joiner .onnx (no int8 variants).\n \"en-kroko\": {\n code: \"en-kroko\",\n displayName: \"English (Kroko, 55 MB)\",\n fileName: \"sherpa-onnx-streaming-zipformer-en-kroko-2025-08-06\",\n size: 55 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n // NeMo streaming fast-conformer, 480 ms chunk. Upstream publishes 80/480/1040 ms;\n // 480 ms is the middle latency/accuracy point. Unlike Kroko this ships only\n // int8 weights, so requiredFiles uses the .int8.onnx names — the archive has\n // no bare .onnx files at all.\n //\n // sherpa-onnx loads it through the plain transducer config (type \"transducer\",\n // not \"nemotron\"): the nemotron branch in SherpaOnnxTranscriber exists for the\n // Nemotron models below, which need a different modelType string to decode\n // correctly. This one is a stock NeMo transducer.\n \"en-nemo-fast-conformer\": {\n code: \"en-nemo-fast-conformer\",\n displayName: \"English (NeMo Fast-Conformer 480ms, 101 MB)\",\n fileName: \"sherpa-onnx-nemo-streaming-fast-conformer-transducer-en-480ms-int8\",\n size: 101 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\n \"encoder.int8.onnx\",\n \"decoder.int8.onnx\",\n \"joiner.int8.onnx\",\n \"tokens.txt\",\n ],\n languageCode: \"en-US\",\n },\n // NVIDIA Nemotron streaming ASR. These are model choices rather than plain\n // languages, so they get their own codes and sort after the per-language\n // Zipformers above.\n //\n // Both ship int8 encoder/decoder/joiner — the same file shape as a Zipformer\n // transducer — and are loaded through the identical transducer config;\n // sherpa-onnx dispatches to its NeMo implementation from the ONNX metadata.\n // Requires sherpa-onnx >= 1.13.4 (see the pins in the Android build.gradle\n // and scripts/setup-sherpa-onnx-optional.sh).\n //\n // The 560ms chunk variant is chosen for both: upstream publishes\n // 80/160/320/560/1120ms, trading latency against accuracy, and 560ms is the\n // middle ground that stays usable for live captions. These are ~450 MB\n // downloads — substantially larger than every other model here.\n \"nemotron-en\": {\n code: \"nemotron-en\",\n displayName: \"Nemotron English (high accuracy)\",\n fileName: \"sherpa-onnx-nemotron-speech-streaming-en-0.6b-560ms-int8-2026-04-25\",\n size: 442 * 1024 * 1024,\n type: \"nemotron\",\n requiredFiles: [\"encoder.int8.onnx\", \"decoder.int8.onnx\", \"joiner.int8.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n // Nemotron-3.5 covers 40 language-locales with automatic language detection,\n // so there is no single BCP-47 tag for it. We report en-US as the nominal\n // tag because downstream consumers require one; the model itself is not\n // restricted to English.\n \"nemotron-3.5\": {\n code: \"nemotron-3.5\",\n displayName: \"Nemotron 3.5 Multilingual (40 languages)\",\n fileName: \"sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11\",\n size: 453 * 1024 * 1024,\n type: \"nemotron\",\n requiredFiles: [\"encoder.int8.onnx\", \"decoder.int8.onnx\", \"joiner.int8.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n }\n\n private constructor() {}\n\n static getInstance(): STTModelManager {\n if (!STTModelManager.instance) {\n STTModelManager.instance = new STTModelManager()\n }\n return STTModelManager.instance\n }\n\n async getCurrentLanguageFromPreferences(): Promise<string> {\n try {\n const path = await BluetoothSdk.getSttModelPath()\n const code = path && path.length > 0 ? this.getLanguageFromPath(path) : \"\"\n if (code && isAppleSttCode(code)) {\n await this.refreshAppleLanguages()\n }\n if (code && this.config(code)) {\n this.currentLanguage = code\n return code\n }\n return \"\"\n } catch (error) {\n console.error(\"Error getting current STT language from preferences:\", error)\n return \"\"\n }\n }\n\n getCurrentLanguage(): string {\n return this.currentLanguage\n }\n\n setCurrentLanguage(code: string): void {\n if (this.config(code)) {\n this.currentLanguage = code\n }\n }\n\n getBcp47ForLanguage(code?: string): string {\n const id = code || this.currentLanguage\n return this.config(id)?.languageCode ?? \"en-US\"\n }\n\n /** Sherpa models first, then whatever Apple locales the last refresh reported. */\n getAvailableLanguages(): LanguageConfig[] {\n return [...Object.values(this.languages), ...Object.values(this.appleLanguages)]\n }\n\n private config(code: string): LanguageConfig | undefined {\n return this.languages[code] ?? this.appleLanguages[code]\n }\n\n /**\n * Re-read the Apple locale list and install states from the OS. A no-op below\n * iOS 26 and on Android, where the Apple section simply never appears.\n */\n async refreshAppleLanguages(): Promise<void> {\n if (!appleSttSupported()) return\n if (this.appleRefresh) return this.appleRefresh\n this.appleRefresh = (async () => {\n try {\n const rows = await BluetoothSdk.getAppleSpeechLocales()\n const next: Record<string, LanguageConfig> = {}\n const installed = new Set<string>()\n for (const row of rows) {\n const code = APPLE_STT_PREFIX + row.code\n next[code] = {\n code,\n displayName: row.name,\n fileName: \"\",\n size: 0,\n type: \"apple\",\n requiredFiles: [],\n languageCode: row.code,\n }\n if (row.status === \"installed\") installed.add(code)\n }\n this.appleLanguages = next\n this.appleInstalled = installed\n } catch (error) {\n console.warn(\"STTModelManager: Apple locale refresh failed:\", error)\n } finally {\n this.appleRefresh = null\n }\n })()\n return this.appleRefresh\n }\n\n getModelDirectory(): string {\n const baseDir = Platform.OS === \"ios\" ? RNFS.DocumentDirectoryPath : RNFS.DocumentDirectoryPath\n return `${baseDir}/stt_models`\n }\n\n getModelPath(code?: string): string {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) return id\n return `${this.getModelDirectory()}/${id}`\n }\n\n /** Last path segment is the language code (the on-disk folder name). */\n getLanguageFromPath(path: string): string {\n return path.split(\"/\").pop() || \"\"\n }\n\n async isModelAvailable(code?: string): Promise<boolean> {\n try {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) {\n if (!appleSttSupported()) return false\n const status = await BluetoothSdk.getAppleSpeechLocaleStatus(id.slice(APPLE_STT_PREFIX.length))\n const installed = status === \"installed\"\n if (installed) this.appleInstalled.add(id)\n else this.appleInstalled.delete(id)\n return installed\n }\n const language = this.languages[id]\n if (!language) return false\n\n const modelPath = this.getModelPath(id)\n for (const file of language.requiredFiles) {\n const filePath = `${modelPath}/${file}`\n const exists = await RNFS.exists(filePath)\n if (!exists) {\n console.log(`Missing required STT file: ${file} at ${filePath}`)\n return false\n }\n }\n\n return await BluetoothSdk.validateSttModel(modelPath)\n } catch (error) {\n console.error(\"Error checking STT model availability:\", error)\n return false\n }\n }\n\n async getLanguageInfo(code?: string): Promise<LanguageInfo> {\n const id = code || this.currentLanguage\n const language = this.config(id)\n if (!language) {\n throw new Error(`Language ${id} not found`)\n }\n\n const downloaded = await this.isModelAvailable(id)\n const path = downloaded ? this.getModelPath(id) : undefined\n\n return {\n code: id,\n displayName: language.displayName,\n size: language.size,\n language: language.languageCode,\n downloaded,\n path,\n type: language.type,\n }\n }\n\n async getAllLanguageInfo(): Promise<LanguageInfo[]> {\n const infos: LanguageInfo[] = []\n for (const code of Object.keys(this.languages)) {\n infos.push(await this.getLanguageInfo(code))\n }\n // One OS round-trip covers every Apple row's install state.\n await this.refreshAppleLanguages()\n for (const language of Object.values(this.appleLanguages)) {\n const downloaded = this.appleInstalled.has(language.code)\n infos.push({\n code: language.code,\n displayName: language.displayName,\n size: 0,\n language: language.languageCode,\n downloaded,\n path: downloaded ? language.code : undefined,\n type: \"apple\",\n })\n }\n return infos\n }\n\n /** Downloads the Apple locale's assets through the OS, surfacing its progress as a download. */\n private async installAppleModel(\n code: string,\n onProgress?: (progress: DownloadProgress) => void,\n onExtractionProgress?: (progress: ExtractionProgress) => void,\n ): Promise<void> {\n if (!appleSttSupported()) {\n throw new Error(\"Apple on-device speech requires iOS 26\")\n }\n const locale = code.slice(APPLE_STT_PREFIX.length)\n const subscription = BluetoothSdk.addListener(\"apple_speech_install_progress\", (event) => {\n if (event.locale !== locale) return\n onProgress?.({jobId: 0, bytesWritten: 0, contentLength: 0, percentage: event.percentage})\n })\n try {\n const status = await BluetoothSdk.installAppleSpeechLocale(locale)\n if (status !== \"installed\") {\n throw new Error(`Apple speech assets for ${locale} are ${status}`)\n }\n } finally {\n subscription.remove()\n }\n onExtractionProgress?.({percentage: 100})\n this.appleInstalled.add(code)\n if (code === this.currentLanguage) {\n await this.setNativeModelPath(code, locale)\n }\n }\n\n async downloadModel(\n code?: string,\n onProgress?: (progress: DownloadProgress) => void,\n onExtractionProgress?: (progress: ExtractionProgress) => void,\n ): Promise<void> {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) {\n return this.installAppleModel(id, onProgress, onExtractionProgress)\n }\n const language = this.languages[id]\n if (!language) {\n throw new Error(`Language ${id} not found`)\n }\n\n const modelUrl = language.downloadUrl ?? `${this.modelBaseUrl}${language.fileName}.tar.bz2`\n const tempPath = `${RNFS.TemporaryDirectoryPath}/${language.fileName}.tar.bz2`\n const modelDir = this.getModelDirectory()\n const finalPath = this.getModelPath(id)\n\n try {\n await RNFS.mkdir(modelDir, {NSURLIsExcludedFromBackupKey: true})\n\n const downloadOptions = {\n fromUrl: modelUrl,\n toFile: tempPath,\n progress: (res: RNFS.DownloadProgressCallbackResultT) => {\n const percentage = Math.round((res.bytesWritten / res.contentLength) * 100)\n onProgress?.({\n jobId: res.jobId,\n bytesWritten: res.bytesWritten,\n contentLength: res.contentLength,\n percentage,\n })\n },\n progressDivider: 10,\n begin: (res: RNFS.DownloadBeginCallbackResultT) => {\n console.log(\"Download started:\", res)\n },\n connectionTimeout: 30000,\n readTimeout: 30000,\n }\n\n const result = await RNFS.downloadFile(downloadOptions)\n this.downloadJobId = result.jobId\n\n const downloadResult = await result.promise\n\n if (downloadResult.statusCode !== 200) {\n throw new Error(`Download failed with status code: ${downloadResult.statusCode}`)\n }\n\n onExtractionProgress?.({percentage: 0})\n\n const subscription = BluetoothSdk.addListener(\"extraction_progress\", (event) => {\n onExtractionProgress?.({percentage: event.percentage})\n })\n\n try {\n const extractionResult = await BluetoothSdk.extractTarBz2(tempPath, finalPath)\n if (!extractionResult) {\n throw new Error(\"Native extraction returned failure status\")\n }\n } catch (extractError) {\n console.error(\"Native extraction failed:\", extractError)\n throw extractError\n } finally {\n subscription.remove()\n }\n\n onExtractionProgress?.({percentage: 100})\n\n await RNFS.unlink(tempPath)\n\n if (id === this.currentLanguage) {\n await this.setNativeModelPath(finalPath, language.languageCode)\n }\n } catch (error) {\n // Best-effort cleanup; never let it mask the original error.\n try {\n if (await RNFS.exists(tempPath)) await RNFS.unlink(tempPath)\n } catch (cleanupError) {\n console.warn(\"STTModelManager: temp cleanup failed:\", cleanupError)\n }\n try {\n if (await RNFS.exists(finalPath)) await RNFS.unlink(finalPath)\n } catch (cleanupError) {\n console.warn(\"STTModelManager: final cleanup failed:\", cleanupError)\n }\n throw error\n }\n }\n\n async cancelDownload(): Promise<void> {\n if (this.downloadJobId !== undefined) {\n await RNFS.stopDownload(this.downloadJobId)\n this.downloadJobId = undefined\n }\n }\n\n async deleteModel(code?: string): Promise<void> {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) {\n // The OS owns the assets; only the app's reservation can be dropped.\n this.appleInstalled.delete(id)\n if (appleSttSupported()) {\n await BluetoothSdk.releaseAppleSpeechLocale(id.slice(APPLE_STT_PREFIX.length))\n }\n return\n }\n const modelPath = this.getModelPath(id)\n if (await RNFS.exists(modelPath)) {\n await RNFS.unlink(modelPath)\n }\n }\n\n async activateLanguage(code: string): Promise<void> {\n if (isAppleSttCode(code) && !this.appleLanguages[code]) {\n await this.refreshAppleLanguages()\n }\n const language = this.config(code)\n if (!language) {\n throw new Error(`Language ${code} not found`)\n }\n\n const isAvailable = await this.isModelAvailable(code)\n if (!isAvailable) {\n throw new Error(`Language ${code} model is not downloaded`)\n }\n\n this.currentLanguage = code\n const modelPath = this.getModelPath(code)\n await this.setNativeModelPath(modelPath, language.languageCode)\n }\n\n private async setNativeModelPath(path: string, languageCode: string): Promise<void> {\n await BluetoothSdk.setSttModelDetails(path, languageCode)\n for (const listener of this.modelReadyListeners) {\n try {\n listener()\n } catch (error) {\n console.warn(\"STTModelManager: model-ready listener failed:\", error)\n }\n }\n }\n\n /** Fired after a downloaded/selected model's path has reached native. */\n onModelReady(listener: () => void): () => void {\n this.modelReadyListeners.add(listener)\n return () => this.modelReadyListeners.delete(listener)\n }\n\n async getStorageInfo(): Promise<{free: number; total: number}> {\n const fsInfo = await RNFS.getFSInfo()\n return {\n free: fsInfo.freeSpace,\n total: fsInfo.totalSpace,\n }\n }\n\n formatBytes(bytes: number): string {\n return STTModelManager.formatBytes(bytes)\n }\n\n static formatBytes(bytes: number): string {\n if (bytes === 0) return \"0 Bytes\"\n const k = 1024\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"]\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + \" \" + sizes[i]\n }\n}\n\nconst instance = STTModelManager.getInstance()\nexport {STTModelManager}\nexport default instance\n"]}
|
|
1
|
+
{"version":3,"file":"STTModelManager.js","sourceRoot":"","sources":["../../src/services/STTModelManager.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk from \"@glassly/bluetooth-sdk\"\nimport {Platform} from \"react-native\"\nimport * as RNFS from \"@dr.pogodin/react-native-fs\"\n\nexport type SttModelType = \"transducer\" | \"ctc\" | \"nemotron\" | \"apple\"\n\nexport interface LanguageInfo {\n code: string\n displayName: string\n size: number\n language: string\n downloaded: boolean\n path?: string\n type: SttModelType\n}\n\nexport interface DownloadProgress {\n jobId: number\n bytesWritten: number\n contentLength: number\n percentage: number\n}\n\nexport interface ExtractionProgress {\n percentage: number\n currentFile?: string\n}\n\nexport interface LanguageConfig {\n code: string\n displayName: string\n fileName: string\n downloadUrl?: string\n size: number\n type: SttModelType\n requiredFiles: string[]\n languageCode: string\n}\n\nconst DEFAULT_LANGUAGE = \"en\"\n\n/**\n * Apple SpeechTranscriber entries are keyed `apple:<bcp47>`; the same string is\n * what native stores as the model path, since the OS owns the assets and there\n * is no directory to point at.\n */\nexport const APPLE_STT_PREFIX = \"apple:\"\n\nexport function isAppleSttCode(code: string): boolean {\n return code.startsWith(APPLE_STT_PREFIX)\n}\n\n/** SpeechTranscriber ships with iOS 26. */\nexport function appleSttSupported(): boolean {\n return Platform.OS === \"ios\" && parseInt(String(Platform.Version), 10) >= 26\n}\n\nclass STTModelManager {\n private static instance: STTModelManager\n private downloadJobId?: number\n private currentLanguage = DEFAULT_LANGUAGE\n private modelReadyListeners = new Set<() => void>()\n private modelBaseUrl = \"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/\"\n /** Apple locales reported by the OS, refreshed on each list load. */\n private appleLanguages: Record<string, LanguageConfig> = {}\n private appleInstalled = new Set<string>()\n private appleRefresh: Promise<void> | null = null\n\n private languages: Record<string, LanguageConfig> = {\n \"en\": {\n code: \"en\",\n displayName: \"English\",\n fileName: \"sherpa-onnx-streaming-zipformer-en-2023-06-21-mobile\",\n size: 349 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n \"fr\": {\n code: \"fr\",\n displayName: \"Français\",\n fileName: \"sherpa-onnx-streaming-zipformer-fr-kroko-2025-08-06\",\n size: 57 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"fr-FR\",\n },\n \"de\": {\n code: \"de\",\n displayName: \"Deutsch\",\n fileName: \"sherpa-onnx-streaming-zipformer-de-kroko-2025-08-06\",\n size: 58 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"de-DE\",\n },\n \"es\": {\n code: \"es\",\n displayName: \"Español\",\n fileName: \"sherpa-onnx-streaming-zipformer-es-kroko-2025-08-06\",\n size: 124 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"es-ES\",\n },\n \"zh\": {\n code: \"zh\",\n displayName: \"中文\",\n fileName: \"sherpa-onnx-streaming-zipformer-zh-2025-06-30\",\n size: 150 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"zh-CN\",\n },\n \"ko\": {\n code: \"ko\",\n displayName: \"한국어\",\n fileName: \"sherpa-onnx-streaming-zipformer-korean-2024-06-16\",\n size: 200 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"ko-KR\",\n },\n // Alternative English streaming models, kept alongside \"en\" so the three can\n // be compared on-device. Both are newer than the 2023 Zipformer used for\n // \"en\" and are a fraction of its 349 MB.\n //\n // Kroko: same family as the fr/de/es entries above, and the smallest English\n // option here. Ships bare encoder/decoder/joiner .onnx (no int8 variants).\n \"en-kroko\": {\n code: \"en-kroko\",\n displayName: \"English (Kroko, 55 MB)\",\n fileName: \"sherpa-onnx-streaming-zipformer-en-kroko-2025-08-06\",\n size: 55 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\"encoder.onnx\", \"decoder.onnx\", \"joiner.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n // NeMo streaming fast-conformer, 480 ms chunk. Upstream publishes 80/480/1040 ms;\n // 480 ms is the middle latency/accuracy point. Unlike Kroko this ships only\n // int8 weights, so requiredFiles uses the .int8.onnx names — the archive has\n // no bare .onnx files at all.\n //\n // sherpa-onnx loads it through the plain transducer config (type \"transducer\",\n // not \"nemotron\"): the nemotron branch in SherpaOnnxTranscriber exists for the\n // Nemotron models below, which need a different modelType string to decode\n // correctly. This one is a stock NeMo transducer.\n \"en-nemo-fast-conformer\": {\n code: \"en-nemo-fast-conformer\",\n displayName: \"English (NeMo Fast-Conformer 480ms, 101 MB)\",\n fileName: \"sherpa-onnx-nemo-streaming-fast-conformer-transducer-en-480ms-int8\",\n size: 101 * 1024 * 1024,\n type: \"transducer\",\n requiredFiles: [\n \"encoder.int8.onnx\",\n \"decoder.int8.onnx\",\n \"joiner.int8.onnx\",\n \"tokens.txt\",\n ],\n languageCode: \"en-US\",\n },\n // NVIDIA Nemotron streaming ASR. These are model choices rather than plain\n // languages, so they get their own codes and sort after the per-language\n // Zipformers above.\n //\n // Both ship int8 encoder/decoder/joiner — the same file shape as a Zipformer\n // transducer — and are loaded through the identical transducer config;\n // sherpa-onnx dispatches to its NeMo implementation from the ONNX metadata.\n // Requires sherpa-onnx >= 1.13.4 (see the pins in the Android build.gradle\n // and scripts/setup-sherpa-onnx-optional.sh).\n //\n // The 560ms chunk variant is chosen for both: upstream publishes\n // 80/160/320/560/1120ms, trading latency against accuracy, and 560ms is the\n // middle ground that stays usable for live captions. These are ~450 MB\n // downloads — substantially larger than every other model here.\n \"nemotron-en\": {\n code: \"nemotron-en\",\n displayName: \"Nemotron English (high accuracy)\",\n fileName: \"sherpa-onnx-nemotron-speech-streaming-en-0.6b-560ms-int8-2026-04-25\",\n size: 442 * 1024 * 1024,\n type: \"nemotron\",\n requiredFiles: [\"encoder.int8.onnx\", \"decoder.int8.onnx\", \"joiner.int8.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n // Nemotron-3.5 covers 40 language-locales with automatic language detection,\n // so there is no single BCP-47 tag for it. We report en-US as the nominal\n // tag because downstream consumers require one; the model itself is not\n // restricted to English.\n \"nemotron-3.5\": {\n code: \"nemotron-3.5\",\n displayName: \"Nemotron 3.5 Multilingual (40 languages)\",\n fileName: \"sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11\",\n size: 453 * 1024 * 1024,\n type: \"nemotron\",\n requiredFiles: [\"encoder.int8.onnx\", \"decoder.int8.onnx\", \"joiner.int8.onnx\", \"tokens.txt\"],\n languageCode: \"en-US\",\n },\n }\n\n private constructor() {}\n\n static getInstance(): STTModelManager {\n if (!STTModelManager.instance) {\n STTModelManager.instance = new STTModelManager()\n }\n return STTModelManager.instance\n }\n\n async getCurrentLanguageFromPreferences(): Promise<string> {\n try {\n const path = await BluetoothSdk.getSttModelPath()\n const code = path && path.length > 0 ? this.getLanguageFromPath(path) : \"\"\n if (code && isAppleSttCode(code)) {\n await this.refreshAppleLanguages()\n }\n if (code && this.config(code)) {\n this.currentLanguage = code\n return code\n }\n return \"\"\n } catch (error) {\n console.error(\"Error getting current STT language from preferences:\", error)\n return \"\"\n }\n }\n\n getCurrentLanguage(): string {\n return this.currentLanguage\n }\n\n currentModelLabel(): string {\n const language = this.config(this.currentLanguage)\n if (!language) return this.currentLanguage\n return language.type === \"apple\" ? `Apple · ${language.displayName}` : language.displayName\n }\n\n setCurrentLanguage(code: string): void {\n if (this.config(code)) {\n this.currentLanguage = code\n }\n }\n\n getBcp47ForLanguage(code?: string): string {\n const id = code || this.currentLanguage\n return this.config(id)?.languageCode ?? \"en-US\"\n }\n\n /** Sherpa models first, then whatever Apple locales the last refresh reported. */\n getAvailableLanguages(): LanguageConfig[] {\n return [...Object.values(this.languages), ...Object.values(this.appleLanguages)]\n }\n\n private config(code: string): LanguageConfig | undefined {\n return this.languages[code] ?? this.appleLanguages[code]\n }\n\n /**\n * Re-read the Apple locale list and install states from the OS. A no-op below\n * iOS 26 and on Android, where the Apple section simply never appears.\n */\n async refreshAppleLanguages(): Promise<void> {\n if (!appleSttSupported()) return\n if (this.appleRefresh) return this.appleRefresh\n this.appleRefresh = (async () => {\n try {\n const rows = await BluetoothSdk.getAppleSpeechLocales()\n const next: Record<string, LanguageConfig> = {}\n const installed = new Set<string>()\n for (const row of rows) {\n const code = APPLE_STT_PREFIX + row.code\n next[code] = {\n code,\n displayName: row.name,\n fileName: \"\",\n size: 0,\n type: \"apple\",\n requiredFiles: [],\n languageCode: row.code,\n }\n if (row.status === \"installed\") installed.add(code)\n }\n this.appleLanguages = next\n this.appleInstalled = installed\n } catch (error) {\n console.warn(\"STTModelManager: Apple locale refresh failed:\", error)\n } finally {\n this.appleRefresh = null\n }\n })()\n return this.appleRefresh\n }\n\n getModelDirectory(): string {\n const baseDir = Platform.OS === \"ios\" ? RNFS.DocumentDirectoryPath : RNFS.DocumentDirectoryPath\n return `${baseDir}/stt_models`\n }\n\n getModelPath(code?: string): string {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) return id\n return `${this.getModelDirectory()}/${id}`\n }\n\n /** Last path segment is the language code (the on-disk folder name). */\n getLanguageFromPath(path: string): string {\n return path.split(\"/\").pop() || \"\"\n }\n\n async isModelAvailable(code?: string): Promise<boolean> {\n try {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) {\n if (!appleSttSupported()) return false\n const status = await BluetoothSdk.getAppleSpeechLocaleStatus(id.slice(APPLE_STT_PREFIX.length))\n const installed = status === \"installed\"\n if (installed) this.appleInstalled.add(id)\n else this.appleInstalled.delete(id)\n return installed\n }\n const language = this.languages[id]\n if (!language) return false\n\n const modelPath = this.getModelPath(id)\n for (const file of language.requiredFiles) {\n const filePath = `${modelPath}/${file}`\n const exists = await RNFS.exists(filePath)\n if (!exists) {\n console.log(`Missing required STT file: ${file} at ${filePath}`)\n return false\n }\n }\n\n return await BluetoothSdk.validateSttModel(modelPath)\n } catch (error) {\n console.error(\"Error checking STT model availability:\", error)\n return false\n }\n }\n\n async getLanguageInfo(code?: string): Promise<LanguageInfo> {\n const id = code || this.currentLanguage\n const language = this.config(id)\n if (!language) {\n throw new Error(`Language ${id} not found`)\n }\n\n const downloaded = await this.isModelAvailable(id)\n const path = downloaded ? this.getModelPath(id) : undefined\n\n return {\n code: id,\n displayName: language.displayName,\n size: language.size,\n language: language.languageCode,\n downloaded,\n path,\n type: language.type,\n }\n }\n\n async getAllLanguageInfo(): Promise<LanguageInfo[]> {\n const infos: LanguageInfo[] = []\n for (const code of Object.keys(this.languages)) {\n infos.push(await this.getLanguageInfo(code))\n }\n // One OS round-trip covers every Apple row's install state.\n await this.refreshAppleLanguages()\n for (const language of Object.values(this.appleLanguages)) {\n const downloaded = this.appleInstalled.has(language.code)\n infos.push({\n code: language.code,\n displayName: language.displayName,\n size: 0,\n language: language.languageCode,\n downloaded,\n path: downloaded ? language.code : undefined,\n type: \"apple\",\n })\n }\n return infos\n }\n\n /** Downloads the Apple locale's assets through the OS, surfacing its progress as a download. */\n private async installAppleModel(\n code: string,\n onProgress?: (progress: DownloadProgress) => void,\n onExtractionProgress?: (progress: ExtractionProgress) => void,\n ): Promise<void> {\n if (!appleSttSupported()) {\n throw new Error(\"Apple on-device speech requires iOS 26\")\n }\n const locale = code.slice(APPLE_STT_PREFIX.length)\n const subscription = BluetoothSdk.addListener(\"apple_speech_install_progress\", (event) => {\n if (event.locale !== locale) return\n onProgress?.({jobId: 0, bytesWritten: 0, contentLength: 0, percentage: event.percentage})\n })\n try {\n const status = await BluetoothSdk.installAppleSpeechLocale(locale)\n if (status !== \"installed\") {\n throw new Error(`Apple speech assets for ${locale} are ${status}`)\n }\n } finally {\n subscription.remove()\n }\n onExtractionProgress?.({percentage: 100})\n this.appleInstalled.add(code)\n if (code === this.currentLanguage) {\n await this.setNativeModelPath(code, locale)\n }\n }\n\n async downloadModel(\n code?: string,\n onProgress?: (progress: DownloadProgress) => void,\n onExtractionProgress?: (progress: ExtractionProgress) => void,\n ): Promise<void> {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) {\n return this.installAppleModel(id, onProgress, onExtractionProgress)\n }\n const language = this.languages[id]\n if (!language) {\n throw new Error(`Language ${id} not found`)\n }\n\n const modelUrl = language.downloadUrl ?? `${this.modelBaseUrl}${language.fileName}.tar.bz2`\n const tempPath = `${RNFS.TemporaryDirectoryPath}/${language.fileName}.tar.bz2`\n const modelDir = this.getModelDirectory()\n const finalPath = this.getModelPath(id)\n\n try {\n await RNFS.mkdir(modelDir, {NSURLIsExcludedFromBackupKey: true})\n\n const downloadOptions = {\n fromUrl: modelUrl,\n toFile: tempPath,\n progress: (res: RNFS.DownloadProgressCallbackResultT) => {\n const percentage = Math.round((res.bytesWritten / res.contentLength) * 100)\n onProgress?.({\n jobId: res.jobId,\n bytesWritten: res.bytesWritten,\n contentLength: res.contentLength,\n percentage,\n })\n },\n progressDivider: 10,\n begin: (res: RNFS.DownloadBeginCallbackResultT) => {\n console.log(\"Download started:\", res)\n },\n connectionTimeout: 30000,\n readTimeout: 30000,\n }\n\n const result = await RNFS.downloadFile(downloadOptions)\n this.downloadJobId = result.jobId\n\n const downloadResult = await result.promise\n\n if (downloadResult.statusCode !== 200) {\n throw new Error(`Download failed with status code: ${downloadResult.statusCode}`)\n }\n\n onExtractionProgress?.({percentage: 0})\n\n const subscription = BluetoothSdk.addListener(\"extraction_progress\", (event) => {\n onExtractionProgress?.({percentage: event.percentage})\n })\n\n try {\n const extractionResult = await BluetoothSdk.extractTarBz2(tempPath, finalPath)\n if (!extractionResult) {\n throw new Error(\"Native extraction returned failure status\")\n }\n } catch (extractError) {\n console.error(\"Native extraction failed:\", extractError)\n throw extractError\n } finally {\n subscription.remove()\n }\n\n onExtractionProgress?.({percentage: 100})\n\n await RNFS.unlink(tempPath)\n\n if (id === this.currentLanguage) {\n await this.setNativeModelPath(finalPath, language.languageCode)\n }\n } catch (error) {\n // Best-effort cleanup; never let it mask the original error.\n try {\n if (await RNFS.exists(tempPath)) await RNFS.unlink(tempPath)\n } catch (cleanupError) {\n console.warn(\"STTModelManager: temp cleanup failed:\", cleanupError)\n }\n try {\n if (await RNFS.exists(finalPath)) await RNFS.unlink(finalPath)\n } catch (cleanupError) {\n console.warn(\"STTModelManager: final cleanup failed:\", cleanupError)\n }\n throw error\n }\n }\n\n async cancelDownload(): Promise<void> {\n if (this.downloadJobId !== undefined) {\n await RNFS.stopDownload(this.downloadJobId)\n this.downloadJobId = undefined\n }\n }\n\n async deleteModel(code?: string): Promise<void> {\n const id = code || this.currentLanguage\n if (isAppleSttCode(id)) {\n // The OS owns the assets; only the app's reservation can be dropped.\n this.appleInstalled.delete(id)\n if (appleSttSupported()) {\n await BluetoothSdk.releaseAppleSpeechLocale(id.slice(APPLE_STT_PREFIX.length))\n }\n return\n }\n const modelPath = this.getModelPath(id)\n if (await RNFS.exists(modelPath)) {\n await RNFS.unlink(modelPath)\n }\n }\n\n async activateLanguage(code: string): Promise<void> {\n if (isAppleSttCode(code) && !this.appleLanguages[code]) {\n await this.refreshAppleLanguages()\n }\n const language = this.config(code)\n if (!language) {\n throw new Error(`Language ${code} not found`)\n }\n\n const isAvailable = await this.isModelAvailable(code)\n if (!isAvailable) {\n throw new Error(`Language ${code} model is not downloaded`)\n }\n\n this.currentLanguage = code\n const modelPath = this.getModelPath(code)\n await this.setNativeModelPath(modelPath, language.languageCode)\n }\n\n private async setNativeModelPath(path: string, languageCode: string): Promise<void> {\n await BluetoothSdk.setSttModelDetails(path, languageCode)\n for (const listener of this.modelReadyListeners) {\n try {\n listener()\n } catch (error) {\n console.warn(\"STTModelManager: model-ready listener failed:\", error)\n }\n }\n }\n\n /** Fired after a downloaded/selected model's path has reached native. */\n onModelReady(listener: () => void): () => void {\n this.modelReadyListeners.add(listener)\n return () => this.modelReadyListeners.delete(listener)\n }\n\n async getStorageInfo(): Promise<{free: number; total: number}> {\n const fsInfo = await RNFS.getFSInfo()\n return {\n free: fsInfo.freeSpace,\n total: fsInfo.totalSpace,\n }\n }\n\n formatBytes(bytes: number): string {\n return STTModelManager.formatBytes(bytes)\n }\n\n static formatBytes(bytes: number): string {\n if (bytes === 0) return \"0 Bytes\"\n const k = 1024\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"]\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + \" \" + sizes[i]\n }\n}\n\nconst instance = STTModelManager.getInstance()\nexport {STTModelManager}\nexport default instance\n"]}
|
|
@@ -200,7 +200,7 @@ class SceneRenderer {
|
|
|
200
200
|
const { layout, degraded, dropped } = degradeScene(elements);
|
|
201
201
|
return { kind: "legacy", layout, degraded, dropped };
|
|
202
202
|
}
|
|
203
|
-
const processed = processScene(elements, caps, displayProcessor.
|
|
203
|
+
const processed = processScene(elements, caps, displayProcessor.getSceneProfile());
|
|
204
204
|
// A stale baseline means the glasses were cleared since the last commit —
|
|
205
205
|
// diff from empty so everything repaints (the retained frame stays valid
|
|
206
206
|
// as the replay source only).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneRenderer.js","sourceRoot":"","sources":["../../src/services/SceneRenderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SceneRenderer — the device-aware boundary of the scene display pipeline.\n *\n * LocalDisplayManager owns WHO may draw (arbitration/boot/expiry); this service\n * owns WHAT gets sent for a scene: capabilities lookup, legacy-layout→scene\n * conversion (sugar and old bundles ride the same pipeline), process → diff →\n * SceneFrame emission, retained-scene replay, and the degrade branch for\n * devices that can't position elements.\n *\n * Everything device-specific here is DATA (capability fields, display profile);\n * the code paths are generic. Spec: notes/miniapp-display-render-implementation-spec.md\n */\n\nimport displayProcessor from \"./DisplayProcessor\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport {useDisplayStore} from \"../stores/display\"\nimport {SETTINGS, useSettingsStore} from \"../stores/settings\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {DeviceTypes} from \"../types\"\nimport {getEffectiveCapabilities} from \"./effectiveCapabilities\"\nimport {BgTimer} from \"../utils/timers\"\nimport {\n degradeScene,\n diffScene,\n processScene,\n resolveAnchors,\n SceneStore,\n type FrameElement,\n type SceneBreakMode,\n type SceneDisplayCapabilities,\n type SceneElementInput,\n type SceneFrame,\n} from \"../utils/display/scene\"\n\nconst LOG_TAG = \"SCENE_RENDERER\"\n\n/** Legacy layout shape (matches DisplayPayload.layout). */\nexport type LegacyLayout = {layoutType: string; [key: string]: unknown}\n\nexport type SceneEmitResult =\n /**\n * A SceneFrame was committed. `sent` is false when the frame stayed\n * phone-side (dashboard covering main). `settleMs` is how long the device\n * keeps animating after it has the frame: the longest transition among the\n * elements this frame changed, 0 on devices that jump.\n */\n | {kind: \"scene\"; degraded: boolean; dropped: string[]; seq: number; sent: boolean; settleMs: number}\n /** Degrade path: caller routes this legacy layout through the existing pipeline (null layout ⇒ clear). */\n | {kind: \"legacy\"; layout: LegacyLayout | null; degraded: boolean; dropped: string[]}\n /** No display capabilities on the connected device. */\n | {kind: \"no-display\"}\n\n/** How a frame ended up, as reported by native (or inferred from a later frame's report). */\nexport interface ScenePresentation {\n /** The device had the frame's content (this frame or a later one that folded it in). */\n presented: boolean\n /** A later frame's report settled this one. */\n superseded: boolean\n reason?: string\n}\n\n/** Longest geometry tween (255 frames at ~30 fps); rotation uses a separate millisecond clock. */\nconst MAX_SETTLE_MS = 255 * 33\n\n/** Longest transition among the elements that actually change on the device this frame. */\nfunction settleTimeOf(elements: FrameElement[]): number {\n let ms = 0\n for (const el of elements) {\n // Entering and leaving elements tween too, from or to their offset.\n const edge = el.transition?.exit !== undefined || (el.change === \"created\" && el.transition?.enter !== undefined)\n if (el.change !== \"updated\" && el.change !== \"moved\" && !edge) continue\n const t = el.transition?.durationMs ?? 0\n // Rotation has its own millisecond clock, beyond the geometry frame limit.\n const duration = Math.min(t, el.rotation !== undefined ? 65535 : MAX_SETTLE_MS)\n if (duration > ms) ms = duration\n }\n return ms\n}\n\nclass SceneRenderer {\n private static instance: SceneRenderer | null = null\n private store = new SceneStore()\n private seqCounter = 0\n private pending = new Map<number, {appId: string; resolve: (p: ScenePresentation) => void}>()\n private presentedSub: {remove: () => void} | null = null\n private settledSub: {remove: () => void} | null = null\n private settledListeners = new Set<(seq: number) => void>()\n\n public static getInstance(): SceneRenderer {\n if (!SceneRenderer.instance) {\n SceneRenderer.instance = new SceneRenderer()\n }\n return SceneRenderer.instance\n }\n\n // ===========================================================================\n // Capabilities\n // ===========================================================================\n\n /**\n * Scene capabilities of the currently-selected device, or null when it has no\n * display block. Read on demand — same model source the CONNECT_ACK uses.\n */\n public currentCapabilities(): SceneDisplayCapabilities | null {\n // dev read these via the (since-removed) settings/glassesStatus runtime\n // hooks; engine reads its own stores directly.\n const model =\n (useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key) as string | undefined) ??\n (useGlassesStore.getState().deviceModel as string | undefined)\n const display = getEffectiveCapabilities((model ?? DeviceTypes.NONE) as DeviceTypes)?.display\n if (!display) return null\n return {\n width: display.width ?? display.resolution?.width ?? displayProcessor.getProfile().displayWidthPx,\n height: display.height ?? display.resolution?.height ?? displayProcessor.getProfile().displayHeightPx ?? 288,\n canPosition: display.canPosition === true,\n maxTextElements: display.maxTextElements ?? 6,\n maxImageElements: display.maxImageElements ?? 0,\n maxImagePx: display.maxImagePx,\n shapes: display.shapes ?? [],\n animation: display.animation ?? false,\n rotation: display.rotation ?? false,\n depth: display.depth ?? false,\n intensityLevels: display.intensityLevels ?? 2,\n\n partialUpdate: display.partialUpdate ?? false,\n }\n }\n\n // ===========================================================================\n // Legacy layout → scene conversion (sugar + old bundles on the scene path)\n // ===========================================================================\n\n /**\n * Convert a legacy layout into scene elements for a positioning device.\n * Returns null for layouts that must stay on the legacy path (dashboard_card,\n * clear_view, unknown types). Sugar semantics: full-canvas / split boxes.\n */\n public convertLegacyLayout(layout: LegacyLayout, caps: SceneDisplayCapabilities): SceneElementInput[] | null {\n const W = caps.width\n const H = caps.height\n const breakMode = layout.breakMode as SceneBreakMode | undefined\n\n switch (layout.layoutType) {\n case \"text_wall\":\n return [\n {\n type: \"text\",\n id: \"sugar:wall\",\n box: {x: 0, y: 0, w: W, h: H},\n text: String(layout.text ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n ]\n case \"double_text_wall\": {\n const half = Math.floor(W / 2)\n return [\n {\n type: \"text\",\n id: \"sugar:left\",\n box: {x: 0, y: 0, w: half, h: H},\n text: String(layout.topText ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n {\n type: \"text\",\n id: \"sugar:right\",\n box: {x: half, y: 0, w: W - half, h: H},\n text: String(layout.bottomText ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n ]\n }\n case \"reference_card\": {\n const titleH = Math.max(24, Math.floor(H / 5))\n return [\n {type: \"text\", id: \"sugar:title\", box: {x: 0, y: 0, w: W, h: titleH}, text: String(layout.title ?? \"\")},\n {\n type: \"text\",\n id: \"sugar:body\",\n box: {x: 0, y: titleH, w: W, h: H - titleH},\n text: String(layout.text ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n ]\n }\n case \"bitmap_view\": {\n // Dimensionless legacy bitmaps historically landed in the device's\n // default ~200×100 container (G2 seeded 200×100 at 188,44) — NOT the\n // full canvas, which would tile a small image across the whole frame.\n const w = (layout.width as number | undefined) ?? Math.min(200, W)\n const h = (layout.height as number | undefined) ?? Math.min(100, H)\n return [\n {\n type: \"image\",\n id: \"sugar:bmp\",\n box: {\n x: (layout.x as number | undefined) ?? Math.max(0, Math.round((W - w) / 2)),\n y: (layout.y as number | undefined) ?? Math.max(0, Math.round((H - h) / 4)),\n w,\n h,\n },\n data: String(layout.data ?? \"\"),\n },\n ]\n }\n case \"positioned_text\": {\n const border = (layout.borderWidth as number | undefined) ?? 0\n const radius = (layout.borderRadius as number | undefined) ?? 0\n return [\n {\n type: \"text\",\n id: \"sugar:pos\",\n box: {\n x: (layout.x as number | undefined) ?? 0,\n y: (layout.y as number | undefined) ?? 0,\n w: (layout.width as number | undefined) ?? W,\n h: (layout.height as number | undefined) ?? H,\n },\n text: String(layout.text ?? \"\"),\n ...(border || radius ? {style: {border, radius}} : {}),\n },\n ]\n }\n default:\n return null\n }\n }\n\n // ===========================================================================\n // Emit\n // ===========================================================================\n\n /**\n * Process + diff + send a scene for (app, view). On non-positioning devices\n * this returns the degraded legacy layout instead — the caller routes it\n * through the existing DisplayProcessor path (which wraps it, keeping G1/Z100\n * output byte-identical to today).\n */\n public emitScene(appId: string, view: \"main\" | \"dashboard\", elements: SceneElementInput[]): SceneEmitResult {\n const caps = this.currentCapabilities()\n if (!caps) return {kind: \"no-display\"}\n\n // Corner-anchored boxes resolve against the REAL canvas before either\n // branch: processScene clamps concrete coords, and degradeScene's reading\n // order sorts by resolved y (a bottom-anchored y:0 must not sort first).\n elements = resolveAnchors(elements, caps.width, caps.height)\n\n if (!caps.canPosition) {\n const {layout, degraded, dropped} = degradeScene(elements)\n return {kind: \"legacy\", layout, degraded, dropped}\n }\n\n const processed = processScene(elements, caps, displayProcessor.getProfile())\n // A stale baseline means the glasses were cleared since the last commit —\n // diff from empty so everything repaints (the retained frame stays valid\n // as the replay source only).\n const prevFrame = this.store.isBaselineStale(appId, view) ? [] : this.store.lastFrame(appId, view)\n const {elements: diffed, removed} = diffScene(\n prevFrame,\n processed.elements,\n this.store.nextSyntheticId(appId, view),\n )\n const canvas = {width: caps.width, height: caps.height}\n this.store.commit(appId, view, diffed, canvas)\n\n const frame: SceneFrame = {\n appId,\n view,\n sceneEpoch: this.store.currentEpoch(appId, view),\n seq: ++this.seqCounter,\n elements: diffed,\n removed,\n canvas,\n }\n const sent = this.sendFrame(frame)\n return {\n kind: \"scene\",\n degraded: processed.degraded,\n dropped: processed.dropped,\n seq: frame.seq,\n sent,\n settleMs: caps.animation ? settleTimeOf(diffed) : 0,\n }\n }\n\n /**\n * Re-emit an app's retained scene (reconnect / arbitration restore). Replay\n * is always create-based — the device rebuilds from scratch (spec §4).\n * Returns false when nothing is retained.\n */\n public replayApp(appId: string, view: \"main\" | \"dashboard\"): boolean {\n const frame = this.store.buildReplayFrame(appId, view, ++this.seqCounter)\n if (!frame) return false\n this.sendFrame(frame)\n return true\n }\n\n /** Forget an app's retained scenes (app stop). Frames still in flight will never show. */\n public clearApp(appId: string): void {\n this.store.clear(appId)\n this.settlePending((p) => p.appId === appId, {presented: false, superseded: true, reason: \"cleared\"})\n }\n\n // ===========================================================================\n // Presentation — native reports when the device has a frame\n // ===========================================================================\n\n /**\n * Resolves once native reports frame `seq` on the device, or a later frame\n * that folded it in. Never rejects; `timeoutMs` bounds a frame the device\n * never acknowledges (link stalls, page rebuilding).\n */\n public whenPresented(seq: number, timeoutMs: number, appId: string): Promise<ScenePresentation> {\n this.ensurePresentedListener()\n return new Promise((resolve) => {\n const timer = BgTimer.setTimeout(() => {\n if (this.pending.delete(seq)) resolve({presented: false, superseded: false, reason: \"no presentation report\"})\n }, timeoutMs)\n this.pending.set(seq, {\n appId,\n resolve: (p) => {\n BgTimer.clearTimeout(timer)\n resolve(p)\n },\n })\n })\n }\n\n private ensurePresentedListener(): void {\n if (this.presentedSub) return\n this.presentedSub = BluetoothSdk.addListener(\"scene_frame_presented\", (event) => {\n this.onFramePresented(event.seq, event.appId, event.presented, event.reason)\n })\n }\n\n /**\n * Fires with the host frame number once the glasses report that every\n * animation the frame started has ended (Glassly CFW revision 27+). The\n * device echoes the low 16 bits of the seq; the full number is recovered\n * against the latest frame sent.\n */\n public onSettled(listener: (seq: number) => void): {remove: () => void} {\n this.settledListeners.add(listener)\n if (!this.settledSub) {\n this.settledSub = BluetoothSdk.addListener(\"scene_settled\", (event) => {\n const seq = this.seqCounter - ((this.seqCounter - event.tag) & 0xffff)\n if (seq <= 0) return\n for (const settled of [...this.settledListeners]) settled(seq)\n })\n }\n return {remove: () => this.settledListeners.delete(listener)}\n }\n\n /** A report for `seq` settles it and every earlier frame (folded in by the native pacer). */\n private onFramePresented(seq: number, appId: string, presented: boolean, reason?: string): void {\n this.settlePending(\n (p, s) => s <= seq,\n (p, s) =>\n s === seq\n ? {presented, superseded: false, reason}\n : p.appId === appId\n ? {presented, superseded: true, reason}\n : {presented: false, superseded: true, reason: `superseded by ${appId}`},\n )\n }\n\n private settlePending(\n match: (p: {appId: string}, seq: number) => boolean,\n outcome: ScenePresentation | ((p: {appId: string}, seq: number) => ScenePresentation),\n ): void {\n for (const [seq, p] of [...this.pending]) {\n if (!match(p, seq)) continue\n this.pending.delete(seq)\n p.resolve(typeof outcome === \"function\" ? outcome(p, seq) : outcome)\n }\n }\n\n /**\n * Reset the diff baseline for (app, view) without touching the device.\n * Used when a legacy layout bypasses the scene path (clear_view /\n * dashboard_card / unknown layoutTypes go to native raw): after that, the\n * retained frame no longer matches the glasses, so the next render() must\n * diff from empty — otherwise \"unchanged\" elements would be skipped and\n * never repainted.\n */\n public resetBaseline(appId: string, view: \"main\" | \"dashboard\"): void {\n this.store.commit(appId, view, [])\n }\n\n /**\n * A system-level clear wiped the view (durationMs expiry, unmount fallback,\n * boot-window expiry): mark every app's baseline for that view stale. Unlike\n * resetBaseline this KEEPS the retained frames — they remain the\n * restore-as-replay source; only incremental diffing restarts from empty.\n */\n public markViewStale(view: \"main\" | \"dashboard\"): void {\n this.store.markViewStale(view)\n // Whatever was in flight for the view got wiped with it.\n this.settlePending(() => true, {presented: false, superseded: true, reason: \"cleared\"})\n }\n\n /** Returns false when the frame stayed phone-side (no presentation report will follow). */\n private sendFrame(frame: SceneFrame): boolean {\n // Single native view: only the visible surface's frames go out. Suppressed\n // main frames stay committed; setOverlayOwner(null) replays them.\n const overlayHeld = useDisplayStore.getState().overlayOwner !== null\n if (overlayHeld !== (frame.view === \"dashboard\")) return false\n try {\n // Frames carry the canvas they were laid out against; only a frame from\n // a path that predates the tag falls back to the current capabilities.\n const caps = this.currentCapabilities()\n if (!frame.canvas && caps) frame = {...frame, canvas: {width: caps.width, height: caps.height}}\n // sendDisplayEvent hook -> direct BluetoothSdk.displayEvent (the exact\n // wiring the deleted MantleManager hook provided).\n void Promise.resolve(BluetoothSdk.displayEvent({view: frame.view, scene: frame})).catch((err) => {\n console.error(`${LOG_TAG}: native scene send failed:`, err)\n })\n\n // Keep the phone-side glasses mirror on the same frame as native. Legacy\n // layouts update this store in LocalDisplayManager.sendToNative; scene\n // frames bypass that method, so without an explicit write every\n // positioning device (including G2) leaves the mirror blank/stale.\n useDisplayStore.getState().setDisplayEvent({\n view: frame.view,\n layout: {\n layoutType: \"scene\",\n appId: frame.appId,\n view: frame.view,\n sceneEpoch: frame.sceneEpoch,\n width: frame.canvas?.width,\n height: frame.canvas?.height,\n elements: frame.elements,\n },\n })\n return true\n } catch (err) {\n console.error(`${LOG_TAG}: native scene send failed:`, err)\n return false\n }\n }\n\n // ===========================================================================\n // Test hooks\n // ===========================================================================\n\n public _resetForTest(): void {\n this.store.clearAll()\n this.settlePending(() => true, {presented: false, superseded: false, reason: \"reset\"})\n this.presentedSub?.remove()\n this.presentedSub = null\n this.settledSub?.remove()\n this.settledSub = null\n this.settledListeners.clear()\n this.seqCounter = 0\n }\n\n public _lastFrameForTest(appId: string, view: string): FrameElement[] {\n return this.store.lastFrame(appId, view)\n }\n}\n\nconst sceneRenderer = SceneRenderer.getInstance()\nexport default sceneRenderer\nexport {SceneRenderer}\n"]}
|
|
1
|
+
{"version":3,"file":"SceneRenderer.js","sourceRoot":"","sources":["../../src/services/SceneRenderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SceneRenderer — the device-aware boundary of the scene display pipeline.\n *\n * LocalDisplayManager owns WHO may draw (arbitration/boot/expiry); this service\n * owns WHAT gets sent for a scene: capabilities lookup, legacy-layout→scene\n * conversion (sugar and old bundles ride the same pipeline), process → diff →\n * SceneFrame emission, retained-scene replay, and the degrade branch for\n * devices that can't position elements.\n *\n * Everything device-specific here is DATA (capability fields, display profile);\n * the code paths are generic. Spec: notes/miniapp-display-render-implementation-spec.md\n */\n\nimport displayProcessor from \"./DisplayProcessor\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport {useDisplayStore} from \"../stores/display\"\nimport {SETTINGS, useSettingsStore} from \"../stores/settings\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {DeviceTypes} from \"../types\"\nimport {getEffectiveCapabilities} from \"./effectiveCapabilities\"\nimport {BgTimer} from \"../utils/timers\"\nimport {\n degradeScene,\n diffScene,\n processScene,\n resolveAnchors,\n SceneStore,\n type FrameElement,\n type SceneBreakMode,\n type SceneDisplayCapabilities,\n type SceneElementInput,\n type SceneFrame,\n} from \"../utils/display/scene\"\n\nconst LOG_TAG = \"SCENE_RENDERER\"\n\n/** Legacy layout shape (matches DisplayPayload.layout). */\nexport type LegacyLayout = {layoutType: string; [key: string]: unknown}\n\nexport type SceneEmitResult =\n /**\n * A SceneFrame was committed. `sent` is false when the frame stayed\n * phone-side (dashboard covering main). `settleMs` is how long the device\n * keeps animating after it has the frame: the longest transition among the\n * elements this frame changed, 0 on devices that jump.\n */\n | {kind: \"scene\"; degraded: boolean; dropped: string[]; seq: number; sent: boolean; settleMs: number}\n /** Degrade path: caller routes this legacy layout through the existing pipeline (null layout ⇒ clear). */\n | {kind: \"legacy\"; layout: LegacyLayout | null; degraded: boolean; dropped: string[]}\n /** No display capabilities on the connected device. */\n | {kind: \"no-display\"}\n\n/** How a frame ended up, as reported by native (or inferred from a later frame's report). */\nexport interface ScenePresentation {\n /** The device had the frame's content (this frame or a later one that folded it in). */\n presented: boolean\n /** A later frame's report settled this one. */\n superseded: boolean\n reason?: string\n}\n\n/** Longest geometry tween (255 frames at ~30 fps); rotation uses a separate millisecond clock. */\nconst MAX_SETTLE_MS = 255 * 33\n\n/** Longest transition among the elements that actually change on the device this frame. */\nfunction settleTimeOf(elements: FrameElement[]): number {\n let ms = 0\n for (const el of elements) {\n // Entering and leaving elements tween too, from or to their offset.\n const edge = el.transition?.exit !== undefined || (el.change === \"created\" && el.transition?.enter !== undefined)\n if (el.change !== \"updated\" && el.change !== \"moved\" && !edge) continue\n const t = el.transition?.durationMs ?? 0\n // Rotation has its own millisecond clock, beyond the geometry frame limit.\n const duration = Math.min(t, el.rotation !== undefined ? 65535 : MAX_SETTLE_MS)\n if (duration > ms) ms = duration\n }\n return ms\n}\n\nclass SceneRenderer {\n private static instance: SceneRenderer | null = null\n private store = new SceneStore()\n private seqCounter = 0\n private pending = new Map<number, {appId: string; resolve: (p: ScenePresentation) => void}>()\n private presentedSub: {remove: () => void} | null = null\n private settledSub: {remove: () => void} | null = null\n private settledListeners = new Set<(seq: number) => void>()\n\n public static getInstance(): SceneRenderer {\n if (!SceneRenderer.instance) {\n SceneRenderer.instance = new SceneRenderer()\n }\n return SceneRenderer.instance\n }\n\n // ===========================================================================\n // Capabilities\n // ===========================================================================\n\n /**\n * Scene capabilities of the currently-selected device, or null when it has no\n * display block. Read on demand — same model source the CONNECT_ACK uses.\n */\n public currentCapabilities(): SceneDisplayCapabilities | null {\n // dev read these via the (since-removed) settings/glassesStatus runtime\n // hooks; engine reads its own stores directly.\n const model =\n (useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key) as string | undefined) ??\n (useGlassesStore.getState().deviceModel as string | undefined)\n const display = getEffectiveCapabilities((model ?? DeviceTypes.NONE) as DeviceTypes)?.display\n if (!display) return null\n return {\n width: display.width ?? display.resolution?.width ?? displayProcessor.getProfile().displayWidthPx,\n height: display.height ?? display.resolution?.height ?? displayProcessor.getProfile().displayHeightPx ?? 288,\n canPosition: display.canPosition === true,\n maxTextElements: display.maxTextElements ?? 6,\n maxImageElements: display.maxImageElements ?? 0,\n maxImagePx: display.maxImagePx,\n shapes: display.shapes ?? [],\n animation: display.animation ?? false,\n rotation: display.rotation ?? false,\n depth: display.depth ?? false,\n intensityLevels: display.intensityLevels ?? 2,\n\n partialUpdate: display.partialUpdate ?? false,\n }\n }\n\n // ===========================================================================\n // Legacy layout → scene conversion (sugar + old bundles on the scene path)\n // ===========================================================================\n\n /**\n * Convert a legacy layout into scene elements for a positioning device.\n * Returns null for layouts that must stay on the legacy path (dashboard_card,\n * clear_view, unknown types). Sugar semantics: full-canvas / split boxes.\n */\n public convertLegacyLayout(layout: LegacyLayout, caps: SceneDisplayCapabilities): SceneElementInput[] | null {\n const W = caps.width\n const H = caps.height\n const breakMode = layout.breakMode as SceneBreakMode | undefined\n\n switch (layout.layoutType) {\n case \"text_wall\":\n return [\n {\n type: \"text\",\n id: \"sugar:wall\",\n box: {x: 0, y: 0, w: W, h: H},\n text: String(layout.text ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n ]\n case \"double_text_wall\": {\n const half = Math.floor(W / 2)\n return [\n {\n type: \"text\",\n id: \"sugar:left\",\n box: {x: 0, y: 0, w: half, h: H},\n text: String(layout.topText ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n {\n type: \"text\",\n id: \"sugar:right\",\n box: {x: half, y: 0, w: W - half, h: H},\n text: String(layout.bottomText ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n ]\n }\n case \"reference_card\": {\n const titleH = Math.max(24, Math.floor(H / 5))\n return [\n {type: \"text\", id: \"sugar:title\", box: {x: 0, y: 0, w: W, h: titleH}, text: String(layout.title ?? \"\")},\n {\n type: \"text\",\n id: \"sugar:body\",\n box: {x: 0, y: titleH, w: W, h: H - titleH},\n text: String(layout.text ?? \"\"),\n ...(breakMode ? {style: {breakMode}} : {}),\n },\n ]\n }\n case \"bitmap_view\": {\n // Dimensionless legacy bitmaps historically landed in the device's\n // default ~200×100 container (G2 seeded 200×100 at 188,44) — NOT the\n // full canvas, which would tile a small image across the whole frame.\n const w = (layout.width as number | undefined) ?? Math.min(200, W)\n const h = (layout.height as number | undefined) ?? Math.min(100, H)\n return [\n {\n type: \"image\",\n id: \"sugar:bmp\",\n box: {\n x: (layout.x as number | undefined) ?? Math.max(0, Math.round((W - w) / 2)),\n y: (layout.y as number | undefined) ?? Math.max(0, Math.round((H - h) / 4)),\n w,\n h,\n },\n data: String(layout.data ?? \"\"),\n },\n ]\n }\n case \"positioned_text\": {\n const border = (layout.borderWidth as number | undefined) ?? 0\n const radius = (layout.borderRadius as number | undefined) ?? 0\n return [\n {\n type: \"text\",\n id: \"sugar:pos\",\n box: {\n x: (layout.x as number | undefined) ?? 0,\n y: (layout.y as number | undefined) ?? 0,\n w: (layout.width as number | undefined) ?? W,\n h: (layout.height as number | undefined) ?? H,\n },\n text: String(layout.text ?? \"\"),\n ...(border || radius ? {style: {border, radius}} : {}),\n },\n ]\n }\n default:\n return null\n }\n }\n\n // ===========================================================================\n // Emit\n // ===========================================================================\n\n /**\n * Process + diff + send a scene for (app, view). On non-positioning devices\n * this returns the degraded legacy layout instead — the caller routes it\n * through the existing DisplayProcessor path (which wraps it, keeping G1/Z100\n * output byte-identical to today).\n */\n public emitScene(appId: string, view: \"main\" | \"dashboard\", elements: SceneElementInput[]): SceneEmitResult {\n const caps = this.currentCapabilities()\n if (!caps) return {kind: \"no-display\"}\n\n // Corner-anchored boxes resolve against the REAL canvas before either\n // branch: processScene clamps concrete coords, and degradeScene's reading\n // order sorts by resolved y (a bottom-anchored y:0 must not sort first).\n elements = resolveAnchors(elements, caps.width, caps.height)\n\n if (!caps.canPosition) {\n const {layout, degraded, dropped} = degradeScene(elements)\n return {kind: \"legacy\", layout, degraded, dropped}\n }\n\n const processed = processScene(elements, caps, displayProcessor.getSceneProfile())\n // A stale baseline means the glasses were cleared since the last commit —\n // diff from empty so everything repaints (the retained frame stays valid\n // as the replay source only).\n const prevFrame = this.store.isBaselineStale(appId, view) ? [] : this.store.lastFrame(appId, view)\n const {elements: diffed, removed} = diffScene(\n prevFrame,\n processed.elements,\n this.store.nextSyntheticId(appId, view),\n )\n const canvas = {width: caps.width, height: caps.height}\n this.store.commit(appId, view, diffed, canvas)\n\n const frame: SceneFrame = {\n appId,\n view,\n sceneEpoch: this.store.currentEpoch(appId, view),\n seq: ++this.seqCounter,\n elements: diffed,\n removed,\n canvas,\n }\n const sent = this.sendFrame(frame)\n return {\n kind: \"scene\",\n degraded: processed.degraded,\n dropped: processed.dropped,\n seq: frame.seq,\n sent,\n settleMs: caps.animation ? settleTimeOf(diffed) : 0,\n }\n }\n\n /**\n * Re-emit an app's retained scene (reconnect / arbitration restore). Replay\n * is always create-based — the device rebuilds from scratch (spec §4).\n * Returns false when nothing is retained.\n */\n public replayApp(appId: string, view: \"main\" | \"dashboard\"): boolean {\n const frame = this.store.buildReplayFrame(appId, view, ++this.seqCounter)\n if (!frame) return false\n this.sendFrame(frame)\n return true\n }\n\n /** Forget an app's retained scenes (app stop). Frames still in flight will never show. */\n public clearApp(appId: string): void {\n this.store.clear(appId)\n this.settlePending((p) => p.appId === appId, {presented: false, superseded: true, reason: \"cleared\"})\n }\n\n // ===========================================================================\n // Presentation — native reports when the device has a frame\n // ===========================================================================\n\n /**\n * Resolves once native reports frame `seq` on the device, or a later frame\n * that folded it in. Never rejects; `timeoutMs` bounds a frame the device\n * never acknowledges (link stalls, page rebuilding).\n */\n public whenPresented(seq: number, timeoutMs: number, appId: string): Promise<ScenePresentation> {\n this.ensurePresentedListener()\n return new Promise((resolve) => {\n const timer = BgTimer.setTimeout(() => {\n if (this.pending.delete(seq)) resolve({presented: false, superseded: false, reason: \"no presentation report\"})\n }, timeoutMs)\n this.pending.set(seq, {\n appId,\n resolve: (p) => {\n BgTimer.clearTimeout(timer)\n resolve(p)\n },\n })\n })\n }\n\n private ensurePresentedListener(): void {\n if (this.presentedSub) return\n this.presentedSub = BluetoothSdk.addListener(\"scene_frame_presented\", (event) => {\n this.onFramePresented(event.seq, event.appId, event.presented, event.reason)\n })\n }\n\n /**\n * Fires with the host frame number once the glasses report that every\n * animation the frame started has ended (Glassly CFW revision 27+). The\n * device echoes the low 16 bits of the seq; the full number is recovered\n * against the latest frame sent.\n */\n public onSettled(listener: (seq: number) => void): {remove: () => void} {\n this.settledListeners.add(listener)\n if (!this.settledSub) {\n this.settledSub = BluetoothSdk.addListener(\"scene_settled\", (event) => {\n const seq = this.seqCounter - ((this.seqCounter - event.tag) & 0xffff)\n if (seq <= 0) return\n for (const settled of [...this.settledListeners]) settled(seq)\n })\n }\n return {remove: () => this.settledListeners.delete(listener)}\n }\n\n /** A report for `seq` settles it and every earlier frame (folded in by the native pacer). */\n private onFramePresented(seq: number, appId: string, presented: boolean, reason?: string): void {\n this.settlePending(\n (p, s) => s <= seq,\n (p, s) =>\n s === seq\n ? {presented, superseded: false, reason}\n : p.appId === appId\n ? {presented, superseded: true, reason}\n : {presented: false, superseded: true, reason: `superseded by ${appId}`},\n )\n }\n\n private settlePending(\n match: (p: {appId: string}, seq: number) => boolean,\n outcome: ScenePresentation | ((p: {appId: string}, seq: number) => ScenePresentation),\n ): void {\n for (const [seq, p] of [...this.pending]) {\n if (!match(p, seq)) continue\n this.pending.delete(seq)\n p.resolve(typeof outcome === \"function\" ? outcome(p, seq) : outcome)\n }\n }\n\n /**\n * Reset the diff baseline for (app, view) without touching the device.\n * Used when a legacy layout bypasses the scene path (clear_view /\n * dashboard_card / unknown layoutTypes go to native raw): after that, the\n * retained frame no longer matches the glasses, so the next render() must\n * diff from empty — otherwise \"unchanged\" elements would be skipped and\n * never repainted.\n */\n public resetBaseline(appId: string, view: \"main\" | \"dashboard\"): void {\n this.store.commit(appId, view, [])\n }\n\n /**\n * A system-level clear wiped the view (durationMs expiry, unmount fallback,\n * boot-window expiry): mark every app's baseline for that view stale. Unlike\n * resetBaseline this KEEPS the retained frames — they remain the\n * restore-as-replay source; only incremental diffing restarts from empty.\n */\n public markViewStale(view: \"main\" | \"dashboard\"): void {\n this.store.markViewStale(view)\n // Whatever was in flight for the view got wiped with it.\n this.settlePending(() => true, {presented: false, superseded: true, reason: \"cleared\"})\n }\n\n /** Returns false when the frame stayed phone-side (no presentation report will follow). */\n private sendFrame(frame: SceneFrame): boolean {\n // Single native view: only the visible surface's frames go out. Suppressed\n // main frames stay committed; setOverlayOwner(null) replays them.\n const overlayHeld = useDisplayStore.getState().overlayOwner !== null\n if (overlayHeld !== (frame.view === \"dashboard\")) return false\n try {\n // Frames carry the canvas they were laid out against; only a frame from\n // a path that predates the tag falls back to the current capabilities.\n const caps = this.currentCapabilities()\n if (!frame.canvas && caps) frame = {...frame, canvas: {width: caps.width, height: caps.height}}\n // sendDisplayEvent hook -> direct BluetoothSdk.displayEvent (the exact\n // wiring the deleted MantleManager hook provided).\n void Promise.resolve(BluetoothSdk.displayEvent({view: frame.view, scene: frame})).catch((err) => {\n console.error(`${LOG_TAG}: native scene send failed:`, err)\n })\n\n // Keep the phone-side glasses mirror on the same frame as native. Legacy\n // layouts update this store in LocalDisplayManager.sendToNative; scene\n // frames bypass that method, so without an explicit write every\n // positioning device (including G2) leaves the mirror blank/stale.\n useDisplayStore.getState().setDisplayEvent({\n view: frame.view,\n layout: {\n layoutType: \"scene\",\n appId: frame.appId,\n view: frame.view,\n sceneEpoch: frame.sceneEpoch,\n width: frame.canvas?.width,\n height: frame.canvas?.height,\n elements: frame.elements,\n },\n })\n return true\n } catch (err) {\n console.error(`${LOG_TAG}: native scene send failed:`, err)\n return false\n }\n }\n\n // ===========================================================================\n // Test hooks\n // ===========================================================================\n\n public _resetForTest(): void {\n this.store.clearAll()\n this.settlePending(() => true, {presented: false, superseded: false, reason: \"reset\"})\n this.presentedSub?.remove()\n this.presentedSub = null\n this.settledSub?.remove()\n this.settledSub = null\n this.settledListeners.clear()\n this.seqCounter = 0\n }\n\n public _lastFrameForTest(appId: string, view: string): FrameElement[] {\n return this.store.lastFrame(appId, view)\n }\n}\n\nconst sceneRenderer = SceneRenderer.getInstance()\nexport default sceneRenderer\nexport {SceneRenderer}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App state backup files: the share-sheet export and file-picker restore
|
|
3
|
+
* behind Settings > Profile > Backup. What goes in the file is decided in
|
|
4
|
+
* AppStateBackup.ts; this side reads and writes the live stores.
|
|
5
|
+
*/
|
|
6
|
+
import type { MemoryImportResult } from "@glassly/miniapp";
|
|
7
|
+
export interface AppStateExportResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
cancelled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface AppStateRestoreResult {
|
|
12
|
+
/** Settings written. */
|
|
13
|
+
settings: number;
|
|
14
|
+
/** Miniapps whose storage was restored. */
|
|
15
|
+
miniapps: number;
|
|
16
|
+
memory: MemoryImportResult | null;
|
|
17
|
+
/** Installed when the backup was made but not on this phone now. */
|
|
18
|
+
missing: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface AppStateRestoreOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Install what the backup had installed and this phone lacks. Runs before
|
|
23
|
+
* the restored miniapps start again, so the dashboard comes back with every
|
|
24
|
+
* widget provider its saved layout names: it drops unknown widgets from the
|
|
25
|
+
* layout the next time it saves it.
|
|
26
|
+
*/
|
|
27
|
+
reinstall?: (packageNames: string[]) => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare function exportAppStateFile(): Promise<AppStateExportResult>;
|
|
30
|
+
/** Resolves null when the user cancels the picker. */
|
|
31
|
+
export declare function importAppStateFile(opts?: AppStateRestoreOptions): Promise<AppStateRestoreResult | null>;
|
|
32
|
+
//# sourceMappingURL=appStateBackupFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appStateBackupFile.d.ts","sourceRoot":"","sources":["../../src/services/appStateBackupFile.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,kBAAkB,CAAA;AAuBxD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjC,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtD;AAiBD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAgCxE;AAED,sDAAsD;AACtD,wBAAsB,kBAAkB,CAAC,IAAI,GAAE,sBAA2B,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA4DjH"}
|