@glassly/engine 0.1.0-dev.1 → 0.1.0-dev.101
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 +57 -19
- package/build/bluetooth-sdk/debug.d.ts +2 -0
- package/build/bluetooth-sdk/debug.d.ts.map +1 -0
- package/build/bluetooth-sdk/debug.js +2 -0
- package/build/bluetooth-sdk/debug.js.map +1 -0
- package/build/bluetooth-sdk/index.d.ts +3 -0
- package/build/bluetooth-sdk/index.d.ts.map +1 -0
- package/build/bluetooth-sdk/index.js +3 -0
- package/build/bluetooth-sdk/index.js.map +1 -0
- package/build/bluetooth-sdk/ota-transport.d.ts +2 -0
- package/build/bluetooth-sdk/ota-transport.d.ts.map +1 -0
- package/build/bluetooth-sdk/ota-transport.js +2 -0
- package/build/bluetooth-sdk/ota-transport.js.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.js +3 -0
- package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
- package/build/bluetooth-sdk/react.d.ts +2 -0
- package/build/bluetooth-sdk/react.d.ts.map +1 -0
- package/build/bluetooth-sdk/react.js +2 -0
- package/build/bluetooth-sdk/react.js.map +1 -0
- package/build/bluetooth-sdk/types.d.ts +2 -0
- package/build/bluetooth-sdk/types.d.ts.map +1 -0
- package/build/bluetooth-sdk/types.js +2 -0
- package/build/bluetooth-sdk/types.js.map +1 -0
- package/build/engine.d.ts +30 -18
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +12 -3
- package/build/engine.js.map +1 -1
- package/build/facades/dev.d.ts +1 -1
- package/build/facades/display.d.ts +11 -4
- package/build/facades/display.d.ts.map +1 -1
- package/build/facades/display.js +12 -2
- package/build/facades/display.js.map +1 -1
- package/build/facades/displayMirror.d.ts +2 -6
- package/build/facades/displayMirror.d.ts.map +1 -1
- package/build/facades/displayMirror.js +7 -14
- package/build/facades/displayMirror.js.map +1 -1
- package/build/facades/glasses.d.ts +6 -13
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +7 -3
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/ota.d.ts +21 -21
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +26 -10
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +11 -5
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +93 -17
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/phoneNotifications.d.ts +12 -2
- package/build/facades/phoneNotifications.d.ts.map +1 -1
- package/build/facades/phoneNotifications.js +30 -10
- package/build/facades/phoneNotifications.js.map +1 -1
- package/build/facades/speakers.d.ts +1 -1
- package/build/facades/speakers.d.ts.map +1 -1
- package/build/facades/speakers.js.map +1 -1
- package/build/facades/speech.d.ts +7 -6
- package/build/facades/speech.d.ts.map +1 -1
- package/build/facades/speech.js +1 -1
- package/build/facades/speech.js.map +1 -1
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +9 -6
- package/build/index.d.ts.map +1 -1
- package/build/index.js +7 -5
- package/build/index.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.d.ts +44 -0
- package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
- package/build/react/MentraLiveOtaFlow.js +322 -0
- package/build/react/MentraLiveOtaFlow.js.map +1 -0
- package/build/react/index.d.ts +3 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +3 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useEngineSnapshot.d.ts +2 -0
- package/build/react/useEngineSnapshot.d.ts.map +1 -0
- package/build/react/useEngineSnapshot.js +14 -0
- package/build/react/useEngineSnapshot.js.map +1 -0
- package/build/react/useMentraLiveOta.d.ts +84 -0
- package/build/react/useMentraLiveOta.d.ts.map +1 -0
- package/build/react/useMentraLiveOta.js +627 -0
- package/build/react/useMentraLiveOta.js.map +1 -0
- package/build/services/AppRegistry.d.ts +8 -0
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +15 -0
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/BlobStore.d.ts +2 -0
- package/build/services/BlobStore.d.ts.map +1 -1
- package/build/services/BlobStore.js +63 -10
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/CustomDashboardModel.d.ts +48 -0
- package/build/services/CustomDashboardModel.d.ts.map +1 -0
- package/build/services/CustomDashboardModel.js +73 -0
- package/build/services/CustomDashboardModel.js.map +1 -0
- package/build/services/CustomDashboardService.d.ts +55 -0
- package/build/services/CustomDashboardService.d.ts.map +1 -0
- package/build/services/CustomDashboardService.js +520 -0
- package/build/services/CustomDashboardService.js.map +1 -0
- package/build/services/DashboardCoordinator.d.ts +26 -0
- package/build/services/DashboardCoordinator.d.ts.map +1 -0
- package/build/services/DashboardCoordinator.js +125 -0
- package/build/services/DashboardCoordinator.js.map +1 -0
- package/build/services/DeviceEventRouter.d.ts.map +1 -1
- package/build/services/DeviceEventRouter.js +45 -6
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/DisplayProcessor.d.ts +3 -3
- package/build/services/DisplayProcessor.js +3 -3
- package/build/services/DisplayProcessor.js.map +1 -1
- package/build/services/GestureDotsService.d.ts +40 -0
- package/build/services/GestureDotsService.d.ts.map +1 -0
- package/build/services/GestureDotsService.js +167 -0
- package/build/services/GestureDotsService.js.map +1 -0
- package/build/services/GlassesStatusProjection.d.ts +15 -1
- package/build/services/GlassesStatusProjection.d.ts.map +1 -1
- package/build/services/GlassesStatusProjection.js +18 -11
- package/build/services/GlassesStatusProjection.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts.map +1 -1
- package/build/services/HotspotOtaTransport.js +8 -7
- package/build/services/HotspotOtaTransport.js.map +1 -1
- package/build/services/LocalDisplayManager.d.ts +55 -3
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +196 -16
- 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 +32 -0
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/MiniappExitGesture.d.ts +33 -0
- package/build/services/MiniappExitGesture.d.ts.map +1 -0
- package/build/services/MiniappExitGesture.js +54 -0
- package/build/services/MiniappExitGesture.js.map +1 -0
- package/build/services/OtaAutoChain.d.ts +41 -0
- package/build/services/OtaAutoChain.d.ts.map +1 -0
- package/build/services/OtaAutoChain.js +91 -0
- package/build/services/OtaAutoChain.js.map +1 -0
- package/build/services/OtaErrorMapping.d.ts +18 -0
- package/build/services/OtaErrorMapping.d.ts.map +1 -0
- package/build/services/OtaErrorMapping.js +63 -0
- package/build/services/OtaErrorMapping.js.map +1 -0
- package/build/services/OtaInstallCoordinator.d.ts +26 -3
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +38 -13
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/OtaService.d.ts.map +1 -1
- package/build/services/OtaService.js +1 -1
- package/build/services/OtaService.js.map +1 -1
- package/build/services/OtaUpdateCheckService.d.ts +4 -1
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +28 -16
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts +13 -0
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +101 -9
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +1 -1
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js +9 -6
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +5 -0
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/StreamLifecycleController.d.ts +4 -0
- package/build/services/StreamLifecycleController.d.ts.map +1 -1
- package/build/services/StreamLifecycleController.js +4 -0
- package/build/services/StreamLifecycleController.js.map +1 -1
- package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
- package/build/services/asg/localNetworkTransport.js +13 -12
- package/build/services/asg/localNetworkTransport.js.map +1 -1
- package/build/services/effectiveCapabilities.d.ts +1 -1
- package/build/services/effectiveCapabilities.d.ts.map +1 -1
- package/build/services/effectiveCapabilities.js +26 -7
- package/build/services/effectiveCapabilities.js.map +1 -1
- package/build/services/gestureClaims.d.ts +18 -0
- package/build/services/gestureClaims.d.ts.map +1 -0
- package/build/services/gestureClaims.js +24 -0
- package/build/services/gestureClaims.js.map +1 -0
- package/build/services/gestureDotGlyphs.d.ts +8 -0
- package/build/services/gestureDotGlyphs.d.ts.map +1 -0
- package/build/services/gestureDotGlyphs.js +13 -0
- package/build/services/gestureDotGlyphs.js.map +1 -0
- package/build/services/glassesClockSync.d.ts.map +1 -1
- package/build/services/glassesClockSync.js +5 -1
- package/build/services/glassesClockSync.js.map +1 -1
- package/build/services/iosNotificationAppCatalog.d.ts +13 -0
- package/build/services/iosNotificationAppCatalog.d.ts.map +1 -0
- package/build/services/iosNotificationAppCatalog.js +28 -0
- package/build/services/iosNotificationAppCatalog.js.map +1 -0
- package/build/services/otaDisplayState.d.ts +1 -1
- package/build/services/otaDisplayState.d.ts.map +1 -1
- package/build/services/otaDisplayState.js.map +1 -1
- package/build/services/otaInstallPolicy.d.ts +5 -1
- package/build/services/otaInstallPolicy.d.ts.map +1 -1
- package/build/services/otaInstallPolicy.js +4 -0
- package/build/services/otaInstallPolicy.js.map +1 -1
- package/build/services/otaLegacyMapping.d.ts +1 -1
- package/build/services/otaLegacyMapping.d.ts.map +1 -1
- package/build/services/otaLegacyMapping.js.map +1 -1
- package/build/services/otaManifestPolicy.d.ts +14 -0
- package/build/services/otaManifestPolicy.d.ts.map +1 -0
- package/build/services/otaManifestPolicy.js +20 -0
- package/build/services/otaManifestPolicy.js.map +1 -0
- package/build/services/otaManifestUrl.d.ts +2 -1
- package/build/services/otaManifestUrl.d.ts.map +1 -1
- package/build/services/otaManifestUrl.js +24 -32
- package/build/services/otaManifestUrl.js.map +1 -1
- package/build/services/otaReleaseVersion.d.ts +10 -0
- package/build/services/otaReleaseVersion.d.ts.map +1 -0
- package/build/services/otaReleaseVersion.js +14 -0
- package/build/services/otaReleaseVersion.js.map +1 -0
- package/build/stores/appVisibility.d.ts +3 -0
- package/build/stores/appVisibility.d.ts.map +1 -0
- package/build/stores/appVisibility.js +3 -0
- package/build/stores/appVisibility.js.map +1 -0
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +7 -1
- package/build/stores/apps.js.map +1 -1
- package/build/stores/core.d.ts +3 -3
- package/build/stores/core.d.ts.map +1 -1
- package/build/stores/core.js.map +1 -1
- package/build/stores/display.d.ts +4 -4
- package/build/stores/display.d.ts.map +1 -1
- package/build/stores/display.js +12 -36
- package/build/stores/display.js.map +1 -1
- package/build/stores/glasses.d.ts +10 -4
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js +2 -0
- package/build/stores/glasses.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +140 -5
- package/build/stores/settings.js.map +1 -1
- package/build/types/applet.d.ts +3 -1
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js +0 -3
- package/build/types/applet.js.map +1 -1
- package/build/types/capabilities/even-realities-g2.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g2.js +2 -2
- package/build/types/capabilities/even-realities-g2.js.map +1 -1
- package/build/types/enums.d.ts +1 -5
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -8
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +1 -1
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +1 -0
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +3 -7
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +3 -7
- package/build/types/index.js.map +1 -1
- package/build/utils/display/composer/ColumnComposer.d.ts +1 -1
- package/build/utils/display/composer/ColumnComposer.js +1 -1
- package/build/utils/display/composer/ColumnComposer.js.map +1 -1
- package/build/utils/display/scene/process.d.ts.map +1 -1
- package/build/utils/display/scene/process.js +4 -3
- package/build/utils/display/scene/process.js.map +1 -1
- package/build/utils/display/scene/types.d.ts +6 -2
- package/build/utils/display/scene/types.d.ts.map +1 -1
- package/build/utils/display/scene/types.js.map +1 -1
- package/package.json +69 -35
- package/src/bluetooth-sdk/debug.ts +1 -0
- package/src/bluetooth-sdk/index.ts +2 -0
- package/src/bluetooth-sdk/ota-transport.ts +1 -0
- package/src/bluetooth-sdk/photo-receiver.ts +2 -0
- package/src/bluetooth-sdk/react.ts +1 -0
- package/src/bluetooth-sdk/types.ts +1 -0
- package/src/engine.ts +12 -3
- package/src/facades/display.ts +12 -2
- package/src/facades/displayMirror.ts +7 -15
- package/src/facades/glasses.ts +8 -4
- package/src/facades/ota.ts +36 -11
- package/src/facades/pairing.ts +103 -23
- package/src/facades/phoneNotifications.ts +32 -10
- package/src/facades/speakers.ts +1 -1
- package/src/facades/speech.ts +21 -7
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +31 -5
- package/src/react/MentraLiveOtaFlow.tsx +754 -0
- package/src/react/index.ts +21 -0
- package/src/react/useEngineSnapshot.ts +16 -0
- package/src/react/useMentraLiveOta.ts +793 -0
- package/src/services/AppRegistry.ts +16 -0
- package/src/services/BlobStore.ts +57 -10
- package/src/services/CustomDashboardModel.ts +83 -0
- package/src/services/CustomDashboardService.ts +544 -0
- package/src/services/DashboardCoordinator.ts +121 -0
- package/src/services/DeviceEventRouter.ts +48 -8
- package/src/services/DisplayProcessor.ts +3 -3
- package/src/services/GestureDotsService.ts +164 -0
- package/src/services/GlassesStatusProjection.ts +20 -11
- package/src/services/HotspotOtaTransport.ts +8 -7
- package/src/services/LocalDisplayManager.ts +198 -18
- package/src/services/LocalMiniappRuntime.ts +37 -0
- package/src/services/MiniappExitGesture.ts +76 -0
- package/src/services/OtaAutoChain.ts +130 -0
- package/src/services/OtaErrorMapping.ts +80 -0
- package/src/services/OtaInstallCoordinator.ts +40 -13
- package/src/services/OtaService.ts +1 -2
- package/src/services/OtaUpdateCheckService.ts +33 -19
- package/src/services/PhoneNotificationsSync.ts +125 -9
- package/src/services/PhonePhotoCoordinator.ts +1 -1
- package/src/services/PhoneStreamCoordinator.ts +10 -6
- package/src/services/SceneRenderer.ts +4 -0
- package/src/services/StreamLifecycleController.ts +4 -0
- package/src/services/asg/localNetworkTransport.ts +20 -19
- package/src/services/effectiveCapabilities.ts +27 -7
- package/src/services/gestureClaims.ts +28 -0
- package/src/services/gestureDotGlyphs.ts +15 -0
- package/src/services/glassesClockSync.ts +5 -1
- package/src/services/iosNotificationAppCatalog.ts +39 -0
- package/src/services/otaDisplayState.ts +1 -1
- package/src/services/otaInstallPolicy.ts +5 -1
- package/src/services/otaLegacyMapping.ts +1 -1
- package/src/services/otaManifestPolicy.ts +43 -0
- package/src/services/otaManifestUrl.ts +27 -36
- package/src/services/otaReleaseVersion.ts +22 -0
- package/src/stores/appVisibility.ts +3 -0
- package/src/stores/apps.ts +7 -1
- package/src/stores/core.ts +4 -4
- package/src/stores/display.ts +16 -48
- package/src/stores/glasses.ts +15 -6
- package/src/stores/settings.ts +140 -5
- package/src/types/applet.ts +3 -1
- package/src/types/capabilities/even-realities-g2.ts +3 -2
- package/src/types/enums.ts +1 -9
- package/src/types/hardware.ts +2 -1
- package/src/types/index.ts +3 -7
- package/src/utils/display/composer/ColumnComposer.ts +1 -1
- package/src/utils/display/scene/process.ts +4 -3
- package/src/utils/display/scene/types.ts +0 -0
- package/build/devtools.d.ts +0 -11
- package/build/devtools.d.ts.map +0 -1
- package/build/devtools.js +0 -13
- package/build/devtools.js.map +0 -1
- package/build/internal.d.ts +0 -67
- package/build/internal.d.ts.map +0 -1
- package/build/internal.js +0 -90
- package/build/internal.js.map +0 -1
- package/src/devtools.ts +0 -13
- package/src/internal.ts +0 -155
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HotspotOtaTransport.js","sourceRoot":"","sources":["../../src/services/HotspotOtaTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk, {isEnabledHotspotStatus, OtaServer} from \"@glassly/bluetooth-sdk/internal\"\n// One coordinator selects the native Android or iOS staging implementation at runtime.\n// eslint-disable-next-line react-native/split-platform-components\nimport {PermissionsAndroid, Platform} from \"react-native\"\nimport type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\nimport {\n cleanupArtifacts,\n OtaArtifactError,\n planArtifacts,\n prepareArtifacts,\n rewriteManifestForLocalServer,\n type OtaArtifactDownloadProgress,\n type PreparedOtaArtifact,\n} from \"./OtaArtifactDownloader\"\nimport {disableHotspotWithRetry} from \"./HotspotShutdown\"\nimport {localNetworkTransport} from \"./asg/localNetworkTransport\"\n\nexport type HotspotOtaPhase = \"idle\" | \"downloading\" | \"starting_hotspot\" | \"joining_hotspot\" | \"serving\"\n\nexport type HotspotOtaProgress = {\n phase: HotspotOtaPhase\n artifact?: OtaArtifactDownloadProgress\n}\n\nexport type HotspotOtaErrorCode =\n | \"hotspot_wifi_permission_denied\"\n | \"hotspot_start_failed\"\n | \"hotspot_join_failed\"\n | \"hotspot_server_failed\"\n\nexport class HotspotOtaTransportError extends Error {\n constructor(\n public readonly code: HotspotOtaErrorCode,\n message: string,\n ) {\n super(message)\n this.name = \"HotspotOtaTransportError\"\n }\n}\n\n/** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */\nclass HotspotOtaTransport {\n private active = false\n private prepared: PreparedOtaArtifact[] = []\n private hotspotRequested = false\n private localNetworkConnected = false\n private serverStarted = false\n private teardownPromise: Promise<void> | null = null\n\n async prepare(\n checkResult: OtaCheckCurrentGlassesResult,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n if (this.teardownPromise) await this.teardownPromise\n if (this.active) {\n throw new Error(\"A hotspot OTA transport is already active\")\n }\n if (!checkResult.manifestBody) {\n throw new Error(\"The selected OTA check has no manifest body\")\n }\n\n let phase: HotspotOtaPhase = \"downloading\"\n try {\n await this.ensureAndroidWifiPermission()\n onProgress?.({phase: \"downloading\"})\n this.prepared = await prepareArtifacts(\n planArtifacts(checkResult),\n (artifact) => onProgress?.({phase: \"downloading\", artifact}),\n Platform.OS === \"ios\" ? this.downloadIosArtifact : undefined,\n )\n\n phase = \"starting_hotspot\"\n onProgress?.({phase: \"starting_hotspot\"})\n this.hotspotRequested = true\n const hotspot = await BluetoothSdk.setHotspotState(true)\n if (!isEnabledHotspotStatus(hotspot)) {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", \"Mentra Live did not return hotspot credentials\")\n }\n phase = \"joining_hotspot\"\n onProgress?.({phase: \"joining_hotspot\"})\n const scopedAddress = await localNetworkTransport.connect(hotspot.ssid, hotspot.password)\n this.localNetworkConnected = true\n let localAddress = scopedAddress\n if (Platform.OS === \"ios\") {\n try {\n localAddress = await OtaServer.waitForWifiAddress(hotspot.localIp, 15_000)\n } catch (error) {\n throw new HotspotOtaTransportError(\n \"hotspot_join_failed\",\n error instanceof Error ? error.message : String(error),\n )\n }\n }\n const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))\n // Start exactly one native listener to learn its selected port, then atomically replace\n // the placeholder with the immutable rewritten manifest before ota_start is sent.\n const server = await OtaServer.startOtaServer(\"{}\", artifactPaths, localAddress)\n this.serverStarted = true\n const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl)\n const published = await OtaServer.startOtaServer(manifest, artifactPaths, server.host)\n if (published.manifestUrl !== server.manifestUrl) {\n throw new Error(\"Local OTA server endpoint changed while publishing the manifest\")\n }\n this.active = true\n onProgress?.({phase: \"serving\"})\n return published.manifestUrl\n } catch (error) {\n const joined = this.localNetworkConnected\n await this.teardown()\n if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {\n throw error\n }\n const message = error instanceof Error ? error.message : String(error)\n if (phase === \"starting_hotspot\") {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", message)\n }\n if (phase === \"joining_hotspot\" && !joined) {\n throw new HotspotOtaTransportError(\"hotspot_join_failed\", message)\n }\n throw new HotspotOtaTransportError(\"hotspot_server_failed\", message)\n }\n }\n\n /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */\n private async ensureAndroidWifiPermission(): Promise<void> {\n if (Platform.OS !== \"android\") return\n\n const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES\n if (await PermissionsAndroid.check(permission)) return\n const result = await PermissionsAndroid.request(permission)\n if (result !== PermissionsAndroid.RESULTS.GRANTED) {\n throw new HotspotOtaTransportError(\n \"hotspot_wifi_permission_denied\",\n \"Nearby devices permission is required to connect to the glasses hotspot\",\n )\n }\n }\n\n private downloadIosArtifact = async (\n entry: {url: string},\n destination: string,\n onProgress?: (bytesWritten: number, contentLength: number) => void,\n ): Promise<{statusCode: number}> => {\n const subscription = OtaServer.addListener(\"artifactDownloadProgress\", (event) => {\n if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)\n })\n try {\n return await OtaServer.downloadArtifact(entry.url, destination)\n } finally {\n subscription.remove()\n }\n }\n\n async teardown(): Promise<void> {\n if (this.teardownPromise) return this.teardownPromise\n this.teardownPromise = (async () => {\n if (this.hotspotRequested) {\n const hotspotStopped = await disableHotspotWithRetry(() => BluetoothSdk.setHotspotState(false), {\n // A completed APK step has just replaced ASG. Let the new command path\n // settle before asking it to tear down the SystemUI-owned access point.\n initialDelayMs: this.serverStarted ? 750 : 0,\n })\n if (!hotspotStopped) {\n console.warn(\"[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries\")\n }\n }\n if (this.serverStarted) await OtaServer.stopOtaServer().catch(() => {})\n if (this.localNetworkConnected) await localNetworkTransport.disconnect().catch(() => {})\n await cleanupArtifacts().catch(() => {})\n this.prepared = []\n this.active = false\n this.serverStarted = false\n this.localNetworkConnected = false\n this.hotspotRequested = false\n })()\n try {\n await this.teardownPromise\n } finally {\n this.teardownPromise = null\n }\n }\n}\n\nexport const hotspotOtaTransport = new HotspotOtaTransport()\n"]}
|
|
1
|
+
{"version":3,"file":"HotspotOtaTransport.js","sourceRoot":"","sources":["../../src/services/HotspotOtaTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk, {isEnabledHotspotStatus} from \"@glassly/bluetooth-sdk\"\nimport {otaServer} from \"@glassly/bluetooth-sdk/ota-transport\"\n// One coordinator selects the native Android or iOS staging implementation at runtime.\n// eslint-disable-next-line react-native/split-platform-components\nimport {PermissionsAndroid, Platform} from \"react-native\"\nimport type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\nimport {\n cleanupArtifacts,\n OtaArtifactError,\n planArtifacts,\n prepareArtifacts,\n rewriteManifestForLocalServer,\n type OtaArtifactDownloadProgress,\n type PreparedOtaArtifact,\n} from \"./OtaArtifactDownloader\"\nimport {disableHotspotWithRetry} from \"./HotspotShutdown\"\nimport {localNetworkTransport} from \"./asg/localNetworkTransport\"\n\nexport type HotspotOtaPhase = \"idle\" | \"downloading\" | \"starting_hotspot\" | \"joining_hotspot\" | \"serving\"\n\nexport type HotspotOtaProgress = {\n phase: HotspotOtaPhase\n artifact?: OtaArtifactDownloadProgress\n}\n\nexport type HotspotOtaErrorCode =\n | \"hotspot_wifi_permission_denied\"\n | \"hotspot_start_failed\"\n | \"hotspot_join_failed\"\n | \"hotspot_server_failed\"\n\nexport class HotspotOtaTransportError extends Error {\n constructor(\n public readonly code: HotspotOtaErrorCode,\n message: string,\n ) {\n super(message)\n this.name = \"HotspotOtaTransportError\"\n }\n}\n\n/** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */\nclass HotspotOtaTransport {\n private active = false\n private prepared: PreparedOtaArtifact[] = []\n private hotspotRequested = false\n private localNetworkConnected = false\n private serverStarted = false\n private teardownPromise: Promise<void> | null = null\n\n async prepare(\n checkResult: OtaCheckCurrentGlassesResult,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n if (this.teardownPromise) await this.teardownPromise\n if (this.active) {\n throw new Error(\"A hotspot OTA transport is already active\")\n }\n if (!checkResult.manifestBody) {\n throw new Error(\"The selected OTA check has no manifest body\")\n }\n\n let phase: HotspotOtaPhase = \"downloading\"\n try {\n await this.ensureAndroidWifiPermission()\n onProgress?.({phase: \"downloading\"})\n this.prepared = await prepareArtifacts(\n planArtifacts(checkResult),\n (artifact) => onProgress?.({phase: \"downloading\", artifact}),\n Platform.OS === \"ios\" ? this.downloadIosArtifact : undefined,\n )\n\n phase = \"starting_hotspot\"\n onProgress?.({phase: \"starting_hotspot\"})\n this.hotspotRequested = true\n const hotspot = await BluetoothSdk.setHotspotState(true)\n if (!isEnabledHotspotStatus(hotspot)) {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", \"Mentra Live did not return hotspot credentials\")\n }\n phase = \"joining_hotspot\"\n onProgress?.({phase: \"joining_hotspot\"})\n const scopedAddress = await localNetworkTransport.connect(hotspot.ssid, hotspot.password)\n this.localNetworkConnected = true\n let localAddress = scopedAddress\n if (Platform.OS === \"ios\") {\n try {\n localAddress = await otaServer.waitForWifiAddress(hotspot.localIp, 15_000)\n } catch (error) {\n throw new HotspotOtaTransportError(\n \"hotspot_join_failed\",\n error instanceof Error ? error.message : String(error),\n )\n }\n }\n const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))\n // Start exactly one native listener to learn its selected port, then atomically replace\n // the placeholder with the immutable rewritten manifest before ota_start is sent.\n const server = await otaServer.start(\"{}\", artifactPaths, localAddress)\n this.serverStarted = true\n const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl)\n const published = await otaServer.start(manifest, artifactPaths, server.host)\n if (published.manifestUrl !== server.manifestUrl) {\n throw new Error(\"Local OTA server endpoint changed while publishing the manifest\")\n }\n this.active = true\n onProgress?.({phase: \"serving\"})\n return published.manifestUrl\n } catch (error) {\n const joined = this.localNetworkConnected\n await this.teardown()\n if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {\n throw error\n }\n const message = error instanceof Error ? error.message : String(error)\n if (phase === \"starting_hotspot\") {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", message)\n }\n if (phase === \"joining_hotspot\" && !joined) {\n throw new HotspotOtaTransportError(\"hotspot_join_failed\", message)\n }\n throw new HotspotOtaTransportError(\"hotspot_server_failed\", message)\n }\n }\n\n /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */\n private async ensureAndroidWifiPermission(): Promise<void> {\n if (Platform.OS !== \"android\") return\n\n const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES\n if (await PermissionsAndroid.check(permission)) return\n const result = await PermissionsAndroid.request(permission)\n if (result !== PermissionsAndroid.RESULTS.GRANTED) {\n throw new HotspotOtaTransportError(\n \"hotspot_wifi_permission_denied\",\n \"Nearby devices permission is required to connect to the glasses hotspot\",\n )\n }\n }\n\n private downloadIosArtifact = async (\n entry: {url: string},\n destination: string,\n onProgress?: (bytesWritten: number, contentLength: number) => void,\n ): Promise<{statusCode: number}> => {\n const subscription = otaServer.onArtifactDownloadProgress((event) => {\n if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)\n })\n try {\n return await otaServer.downloadArtifact(entry.url, destination)\n } finally {\n subscription.remove()\n }\n }\n\n async teardown(): Promise<void> {\n if (this.teardownPromise) return this.teardownPromise\n this.teardownPromise = (async () => {\n if (this.hotspotRequested) {\n const hotspotStopped = await disableHotspotWithRetry(() => BluetoothSdk.setHotspotState(false), {\n // A completed APK step has just replaced ASG. Let the new command path\n // settle before asking it to tear down the SystemUI-owned access point.\n initialDelayMs: this.serverStarted ? 750 : 0,\n })\n if (!hotspotStopped) {\n console.warn(\"[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries\")\n }\n }\n if (this.serverStarted) await otaServer.stop().catch(() => {})\n if (this.localNetworkConnected) await localNetworkTransport.disconnect().catch(() => {})\n await cleanupArtifacts().catch(() => {})\n this.prepared = []\n this.active = false\n this.serverStarted = false\n this.localNetworkConnected = false\n this.hotspotRequested = false\n })()\n try {\n await this.teardownPromise\n } finally {\n this.teardownPromise = null\n }\n }\n}\n\nexport const hotspotOtaTransport = new HotspotOtaTransport()\n"]}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* LocalDisplayManager
|
|
3
3
|
*
|
|
4
4
|
* Phone-side arbiter for display requests originating from LOCAL miniapps
|
|
5
|
-
* (the @glassly/miniapp SDK).
|
|
6
|
-
*
|
|
5
|
+
* (the @glassly/miniapp SDK). Preserves the retired cloud display manager's
|
|
6
|
+
* user-facing behavior for the features that matter on the phone:
|
|
7
7
|
*
|
|
8
8
|
* - boot message ("Starting <AppName>…") with a bounded window
|
|
9
9
|
* - durationMs auto-clear
|
|
@@ -49,10 +49,22 @@ declare class LocalDisplayManager {
|
|
|
49
49
|
private static instance;
|
|
50
50
|
private coreApp;
|
|
51
51
|
private coreAppDisplay;
|
|
52
|
-
private
|
|
52
|
+
private _currentDisplay;
|
|
53
53
|
private backgroundLock;
|
|
54
|
+
/** Fired when the display transitions between empty and occupied (any package, system screens included). */
|
|
55
|
+
private activeDisplayListeners;
|
|
56
|
+
private get currentDisplay();
|
|
57
|
+
private set currentDisplay(value);
|
|
58
|
+
/** True while anything (miniapp or system screen) is on the glasses display. */
|
|
59
|
+
hasActiveDisplay(): boolean;
|
|
60
|
+
/** Subscribe to empty↔occupied display transitions. Returns an unsubscribe. */
|
|
61
|
+
onActiveDisplayChange(listener: (active: boolean) => void): () => void;
|
|
54
62
|
private bootingApp;
|
|
55
63
|
private bootQueue;
|
|
64
|
+
/** While true the dashboard owns the glasses: main frames are retained but not sent. */
|
|
65
|
+
private dashboardActive;
|
|
66
|
+
/** Miniapp whose visible frame is temporarily covered by an OS exit notice. */
|
|
67
|
+
private exitingApp;
|
|
56
68
|
private expiryTimerId;
|
|
57
69
|
/** Reconnect-replay subscription state (attachToRuntime). */
|
|
58
70
|
private runtimeAttached;
|
|
@@ -82,12 +94,51 @@ declare class LocalDisplayManager {
|
|
|
82
94
|
* miniapp is foreground.
|
|
83
95
|
*/
|
|
84
96
|
onCoreAppChange(packageName: string | null): void;
|
|
97
|
+
/**
|
|
98
|
+
* The package that currently owns the glasses screen, for gesture-claim
|
|
99
|
+
* arbitration (see LocalMiniappRuntime.foregroundClaimsGesture). This is
|
|
100
|
+
* glasses ownership, not the phone's Compositor foreground: a background
|
|
101
|
+
* miniapp rendering to the glasses with the phone pocketed is the owner.
|
|
102
|
+
*
|
|
103
|
+
* The live frame's owner wins; a background app that holds the display lock
|
|
104
|
+
* but has no frame up right now (between renders) still counts. System
|
|
105
|
+
* frames (boot, notices) own nothing claimable. Returns null when the
|
|
106
|
+
* glasses are idle.
|
|
107
|
+
*/
|
|
108
|
+
getGestureOwner(): string | null;
|
|
109
|
+
/**
|
|
110
|
+
* The miniapp whose frame is visibly on the glasses right now.
|
|
111
|
+
*
|
|
112
|
+
* Unlike getGestureOwner(), this deliberately does not fall back to a
|
|
113
|
+
* background display lock: a lock holder with no live frame is not visible
|
|
114
|
+
* and therefore must not be closed by the system double-tap gesture.
|
|
115
|
+
*/
|
|
116
|
+
getVisibleMiniappPackageName(): string | null;
|
|
117
|
+
/**
|
|
118
|
+
* Cover the currently visible miniapp with a persistent system exit notice.
|
|
119
|
+
* While it is up, miniapp display traffic is held off so a streaming app
|
|
120
|
+
* cannot immediately overwrite the notice. The caller completes the normal
|
|
121
|
+
* stop flow and then calls finishMiniappExit(); onUnmount does the same as a
|
|
122
|
+
* safety net.
|
|
123
|
+
*/
|
|
124
|
+
beginMiniappExit(packageName: string, text: string): boolean;
|
|
125
|
+
/** Remove an exit notice and resume the display state normal app teardown leaves behind. */
|
|
126
|
+
finishMiniappExit(packageName: string): void;
|
|
127
|
+
/** Cancel the handoff and put back the frame the exit notice covered. */
|
|
128
|
+
cancelMiniappExit(packageName: string): void;
|
|
85
129
|
/** Report-safe ownership snapshot for incident diagnostics. */
|
|
86
130
|
getDiagnosticSnapshot(): Record<string, unknown>;
|
|
87
131
|
/**
|
|
88
132
|
* A local miniapp is going away. Clean up all state associated with it.
|
|
89
133
|
*/
|
|
90
134
|
onUnmount(packageName: string): void;
|
|
135
|
+
/**
|
|
136
|
+
* Dashboard cover state. On deactivate the retained main frame repaints
|
|
137
|
+
* (scenes replay create-based; legacy re-sends), or the glasses clear.
|
|
138
|
+
*/
|
|
139
|
+
setDashboardActive(active: boolean): void;
|
|
140
|
+
/** Dashboard renderers only; bypasses arbitration and main ownership state. */
|
|
141
|
+
renderDashboard(packageName: string, payload: DisplayPayload): void;
|
|
91
142
|
/**
|
|
92
143
|
* A miniapp requested a display. Routes through boot queue, arbitration,
|
|
93
144
|
* and throttle. This is the only public entry point for miniapp display
|
|
@@ -120,6 +171,7 @@ declare class LocalDisplayManager {
|
|
|
120
171
|
*/
|
|
121
172
|
private sendScene;
|
|
122
173
|
private sendToNative;
|
|
174
|
+
private pushToNative;
|
|
123
175
|
private handleExpiry;
|
|
124
176
|
private tryRestoreCoreDisplay;
|
|
125
177
|
private sendClear;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalDisplayManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalDisplayManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAQH,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAA;AAO7D,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAA;IACpC,kFAAkF;IAClF,MAAM,CAAC,EAAE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAC,CAAA;IACrD,qEAAqE;IACrE,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,+EAA+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAA;AAsD3E,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmC;IAE1D,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"LocalDisplayManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalDisplayManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* LocalDisplayManager
|
|
3
3
|
*
|
|
4
4
|
* Phone-side arbiter for display requests originating from LOCAL miniapps
|
|
5
|
-
* (the @glassly/miniapp SDK).
|
|
6
|
-
*
|
|
5
|
+
* (the @glassly/miniapp SDK). Preserves the retired cloud display manager's
|
|
6
|
+
* user-facing behavior for the features that matter on the phone:
|
|
7
7
|
*
|
|
8
8
|
* - boot message ("Starting <AppName>…") with a bounded window
|
|
9
9
|
* - durationMs auto-clear
|
|
@@ -59,10 +59,43 @@ class LocalDisplayManager {
|
|
|
59
59
|
static instance = null;
|
|
60
60
|
coreApp = null;
|
|
61
61
|
coreAppDisplay = null;
|
|
62
|
-
|
|
62
|
+
_currentDisplay = null;
|
|
63
63
|
backgroundLock = null;
|
|
64
|
+
/** Fired when the display transitions between empty and occupied (any package, system screens included). */
|
|
65
|
+
activeDisplayListeners = new Set();
|
|
66
|
+
get currentDisplay() {
|
|
67
|
+
return this._currentDisplay;
|
|
68
|
+
}
|
|
69
|
+
set currentDisplay(value) {
|
|
70
|
+
const wasActive = this._currentDisplay !== null;
|
|
71
|
+
this._currentDisplay = value;
|
|
72
|
+
const isActive = value !== null;
|
|
73
|
+
if (wasActive === isActive)
|
|
74
|
+
return;
|
|
75
|
+
for (const listener of this.activeDisplayListeners) {
|
|
76
|
+
try {
|
|
77
|
+
listener(isActive);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(`${LOG_TAG}: onActiveDisplayChange listener failed:`, error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** True while anything (miniapp or system screen) is on the glasses display. */
|
|
85
|
+
hasActiveDisplay() {
|
|
86
|
+
return this._currentDisplay !== null;
|
|
87
|
+
}
|
|
88
|
+
/** Subscribe to empty↔occupied display transitions. Returns an unsubscribe. */
|
|
89
|
+
onActiveDisplayChange(listener) {
|
|
90
|
+
this.activeDisplayListeners.add(listener);
|
|
91
|
+
return () => this.activeDisplayListeners.delete(listener);
|
|
92
|
+
}
|
|
64
93
|
bootingApp = null;
|
|
65
94
|
bootQueue = new Map();
|
|
95
|
+
/** While true the dashboard owns the glasses: main frames are retained but not sent. */
|
|
96
|
+
dashboardActive = false;
|
|
97
|
+
/** Miniapp whose visible frame is temporarily covered by an OS exit notice. */
|
|
98
|
+
exitingApp = null;
|
|
66
99
|
expiryTimerId = null;
|
|
67
100
|
/** Reconnect-replay subscription state (attachToRuntime). */
|
|
68
101
|
runtimeAttached = false;
|
|
@@ -131,7 +164,7 @@ class LocalDisplayManager {
|
|
|
131
164
|
showSystemNotice(text, durationMs = SYSTEM_NOTICE_DURATION_MS) {
|
|
132
165
|
if (!isGlassesConnected(useGlassesStore.getState().connection))
|
|
133
166
|
return;
|
|
134
|
-
if (this.bootingApp)
|
|
167
|
+
if (this.bootingApp || this.exitingApp)
|
|
135
168
|
return;
|
|
136
169
|
console.log(`${LOG_TAG}: showSystemNotice("${text}")`);
|
|
137
170
|
this.sendNow(SYSTEM_NOTICE_PKG, {
|
|
@@ -157,6 +190,92 @@ class LocalDisplayManager {
|
|
|
157
190
|
this.coreAppDisplay = null;
|
|
158
191
|
}
|
|
159
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* The package that currently owns the glasses screen, for gesture-claim
|
|
195
|
+
* arbitration (see LocalMiniappRuntime.foregroundClaimsGesture). This is
|
|
196
|
+
* glasses ownership, not the phone's Compositor foreground: a background
|
|
197
|
+
* miniapp rendering to the glasses with the phone pocketed is the owner.
|
|
198
|
+
*
|
|
199
|
+
* The live frame's owner wins; a background app that holds the display lock
|
|
200
|
+
* but has no frame up right now (between renders) still counts. System
|
|
201
|
+
* frames (boot, notices) own nothing claimable. Returns null when the
|
|
202
|
+
* glasses are idle.
|
|
203
|
+
*/
|
|
204
|
+
getGestureOwner() {
|
|
205
|
+
const current = this.currentDisplay?.packageName ?? null;
|
|
206
|
+
if (current && current !== SYSTEM_BOOT_PKG && current !== SYSTEM_NOTICE_PKG)
|
|
207
|
+
return current;
|
|
208
|
+
const lock = this.backgroundLock;
|
|
209
|
+
if (lock && this.now() <= lock.expiresAt)
|
|
210
|
+
return lock.packageName;
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The miniapp whose frame is visibly on the glasses right now.
|
|
215
|
+
*
|
|
216
|
+
* Unlike getGestureOwner(), this deliberately does not fall back to a
|
|
217
|
+
* background display lock: a lock holder with no live frame is not visible
|
|
218
|
+
* and therefore must not be closed by the system double-tap gesture.
|
|
219
|
+
*/
|
|
220
|
+
getVisibleMiniappPackageName() {
|
|
221
|
+
const current = this.currentDisplay?.packageName ?? null;
|
|
222
|
+
if (!current || current === SYSTEM_BOOT_PKG || current === SYSTEM_NOTICE_PKG)
|
|
223
|
+
return null;
|
|
224
|
+
return current;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Cover the currently visible miniapp with a persistent system exit notice.
|
|
228
|
+
* While it is up, miniapp display traffic is held off so a streaming app
|
|
229
|
+
* cannot immediately overwrite the notice. The caller completes the normal
|
|
230
|
+
* stop flow and then calls finishMiniappExit(); onUnmount does the same as a
|
|
231
|
+
* safety net.
|
|
232
|
+
*/
|
|
233
|
+
beginMiniappExit(packageName, text) {
|
|
234
|
+
if (this.exitingApp !== null)
|
|
235
|
+
return this.exitingApp.packageName === packageName;
|
|
236
|
+
const coveredDisplay = this.currentDisplay;
|
|
237
|
+
if (!coveredDisplay || this.getVisibleMiniappPackageName() !== packageName)
|
|
238
|
+
return false;
|
|
239
|
+
console.log(`${LOG_TAG}: beginMiniappExit(${packageName})`);
|
|
240
|
+
this.exitingApp = { packageName, coveredDisplay };
|
|
241
|
+
this.clearExpiryTimer();
|
|
242
|
+
this.sendNow(SYSTEM_NOTICE_PKG, {
|
|
243
|
+
view: "main",
|
|
244
|
+
layout: { layoutType: "text_wall", text },
|
|
245
|
+
});
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
/** Remove an exit notice and resume the display state normal app teardown leaves behind. */
|
|
249
|
+
finishMiniappExit(packageName) {
|
|
250
|
+
if (this.exitingApp?.packageName !== packageName)
|
|
251
|
+
return;
|
|
252
|
+
console.log(`${LOG_TAG}: finishMiniappExit(${packageName})`);
|
|
253
|
+
this.exitingApp = null;
|
|
254
|
+
if (this.currentDisplay?.packageName !== SYSTEM_NOTICE_PKG)
|
|
255
|
+
return;
|
|
256
|
+
this.currentDisplay = null;
|
|
257
|
+
this.tryRestoreCoreDisplay();
|
|
258
|
+
if (!this.currentDisplay)
|
|
259
|
+
this.sendClear();
|
|
260
|
+
}
|
|
261
|
+
/** Cancel the handoff and put back the frame the exit notice covered. */
|
|
262
|
+
cancelMiniappExit(packageName) {
|
|
263
|
+
if (this.exitingApp?.packageName !== packageName)
|
|
264
|
+
return;
|
|
265
|
+
const covered = this.exitingApp.coveredDisplay;
|
|
266
|
+
this.exitingApp = null;
|
|
267
|
+
if (this.currentDisplay?.packageName !== SYSTEM_NOTICE_PKG)
|
|
268
|
+
return;
|
|
269
|
+
if (covered.expiresAt === null || covered.expiresAt > this.now()) {
|
|
270
|
+
this.restoreDisplay(covered);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
this.currentDisplay = null;
|
|
274
|
+
this.tryRestoreCoreDisplay();
|
|
275
|
+
if (!this.currentDisplay)
|
|
276
|
+
this.sendClear();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
160
279
|
/** Report-safe ownership snapshot for incident diagnostics. */
|
|
161
280
|
getDiagnosticSnapshot() {
|
|
162
281
|
return {
|
|
@@ -164,6 +283,7 @@ class LocalDisplayManager {
|
|
|
164
283
|
currentDisplayPackageName: this.currentDisplay?.packageName ?? null,
|
|
165
284
|
backgroundLockPackageName: this.backgroundLock?.packageName ?? null,
|
|
166
285
|
bootingPackageName: this.bootingApp?.packageName ?? null,
|
|
286
|
+
exitingPackageName: this.exitingApp?.packageName ?? null,
|
|
167
287
|
};
|
|
168
288
|
}
|
|
169
289
|
/**
|
|
@@ -221,6 +341,51 @@ class LocalDisplayManager {
|
|
|
221
341
|
this.sendClear();
|
|
222
342
|
}
|
|
223
343
|
}
|
|
344
|
+
this.finishMiniappExit(packageName);
|
|
345
|
+
}
|
|
346
|
+
// ===========================================================================
|
|
347
|
+
// Dashboard switching (called from DashboardCoordinator)
|
|
348
|
+
// ===========================================================================
|
|
349
|
+
/**
|
|
350
|
+
* Dashboard cover state. On deactivate the retained main frame repaints
|
|
351
|
+
* (scenes replay create-based; legacy re-sends), or the glasses clear.
|
|
352
|
+
*/
|
|
353
|
+
setDashboardActive(active) {
|
|
354
|
+
if (this.dashboardActive === active)
|
|
355
|
+
return;
|
|
356
|
+
this.dashboardActive = active;
|
|
357
|
+
useDisplayStore.getState().setDashboardActive(active);
|
|
358
|
+
if (active)
|
|
359
|
+
return;
|
|
360
|
+
sceneRenderer.markViewStale("dashboard");
|
|
361
|
+
const current = this.currentDisplay;
|
|
362
|
+
if (current && (current.expiresAt === null || this.now() < current.expiresAt)) {
|
|
363
|
+
this.replayCurrent();
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
this.sendClear();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/** Dashboard renderers only; bypasses arbitration and main ownership state. */
|
|
370
|
+
renderDashboard(packageName, payload) {
|
|
371
|
+
if (!this.dashboardActive)
|
|
372
|
+
return;
|
|
373
|
+
if (payload.scene) {
|
|
374
|
+
sceneRenderer.emitScene(packageName, "dashboard", payload.scene);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (!payload.layout)
|
|
378
|
+
return;
|
|
379
|
+
const rawEvent = { view: "dashboard", layout: payload.layout };
|
|
380
|
+
let processedEvent;
|
|
381
|
+
try {
|
|
382
|
+
processedEvent = displayProcessor.processDisplayEvent(rawEvent);
|
|
383
|
+
}
|
|
384
|
+
catch (err) {
|
|
385
|
+
console.error(`${LOG_TAG}: DisplayProcessor error, using raw event:`, err);
|
|
386
|
+
processedEvent = rawEvent;
|
|
387
|
+
}
|
|
388
|
+
this.pushToNative(processedEvent);
|
|
224
389
|
}
|
|
225
390
|
// ===========================================================================
|
|
226
391
|
// Display request API (called from LocalMiniappRuntime.handleDisplay)
|
|
@@ -235,10 +400,17 @@ class LocalDisplayManager {
|
|
|
235
400
|
* the boot queue (resolved when drained or superseded).
|
|
236
401
|
*/
|
|
237
402
|
request(packageName, payload, resolve) {
|
|
238
|
-
//
|
|
239
|
-
//
|
|
403
|
+
// Keep the OS exit notice visible for its short handoff window. Without
|
|
404
|
+
// this, streaming captions/terminal frames can replace it immediately.
|
|
405
|
+
if (this.exitingApp !== null) {
|
|
406
|
+
resolve?.({ status: "blocked", reason: "a miniapp exit notice is active" });
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
// Dashboard view: only visible while the dashboard covers the glasses.
|
|
410
|
+
// Local miniapp dashboard content remains a stub.
|
|
240
411
|
if (payload.view === "dashboard") {
|
|
241
|
-
this.
|
|
412
|
+
this.renderDashboard(packageName, payload);
|
|
413
|
+
resolve?.({ status: "displayed" });
|
|
242
414
|
return;
|
|
243
415
|
}
|
|
244
416
|
// During boot, any app's requests go into the queue. If the booting app
|
|
@@ -448,6 +620,21 @@ class LocalDisplayManager {
|
|
|
448
620
|
console.error(`${LOG_TAG}: DisplayProcessor error, using raw event:`, err);
|
|
449
621
|
processedEvent = rawEvent;
|
|
450
622
|
}
|
|
623
|
+
// While the dashboard covers the glasses, main frames only update the
|
|
624
|
+
// retained state; setDashboardActive(false) replays the latest.
|
|
625
|
+
if (!this.dashboardActive)
|
|
626
|
+
this.pushToNative(processedEvent);
|
|
627
|
+
this.currentDisplay = { packageName, processedEvent, expiresAt };
|
|
628
|
+
this.clearExpiryTimer();
|
|
629
|
+
if (expiresAt !== null) {
|
|
630
|
+
const delay = Math.max(0, expiresAt - this.now());
|
|
631
|
+
this.expiryTimerId = BgTimer.setTimeout(() => {
|
|
632
|
+
this.expiryTimerId = null;
|
|
633
|
+
this.handleExpiry(packageName);
|
|
634
|
+
}, delay);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
pushToNative(processedEvent) {
|
|
451
638
|
try {
|
|
452
639
|
// The display output path is a direct btsdk call now (was a host sendDisplayEvent
|
|
453
640
|
// hook) so a bare OEM renders to the glasses without wiring it.
|
|
@@ -461,15 +648,6 @@ class LocalDisplayManager {
|
|
|
461
648
|
catch (err) {
|
|
462
649
|
console.error(`${LOG_TAG}: native display failed:`, err);
|
|
463
650
|
}
|
|
464
|
-
this.currentDisplay = { packageName, processedEvent, expiresAt };
|
|
465
|
-
this.clearExpiryTimer();
|
|
466
|
-
if (expiresAt !== null) {
|
|
467
|
-
const delay = Math.max(0, expiresAt - this.now());
|
|
468
|
-
this.expiryTimerId = BgTimer.setTimeout(() => {
|
|
469
|
-
this.expiryTimerId = null;
|
|
470
|
-
this.handleExpiry(packageName);
|
|
471
|
-
}, delay);
|
|
472
|
-
}
|
|
473
651
|
}
|
|
474
652
|
handleExpiry(packageName) {
|
|
475
653
|
// Someone else is on the glasses now — ignore.
|
|
@@ -663,6 +841,8 @@ class LocalDisplayManager {
|
|
|
663
841
|
this.coreAppDisplay = null;
|
|
664
842
|
this.currentDisplay = null;
|
|
665
843
|
this.backgroundLock = null;
|
|
844
|
+
this.exitingApp = null;
|
|
845
|
+
this.dashboardActive = false;
|
|
666
846
|
this.bootQueue.clear();
|
|
667
847
|
this.now = () => Date.now();
|
|
668
848
|
this.unsubscribeGlassesStatus?.();
|