@glassly/engine 0.1.0-dev.1 → 0.1.0-dev.100
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 +492 -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 +516 -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,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Effective device capabilities — the static model profile plus what the
|
|
3
|
-
* connected firmware reports at runtime.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* connected firmware reports at runtime. The runtime override is the scene
|
|
4
|
+
* canvas: Glassly CFW on the G2 rasterizes scenes phone-side straight into
|
|
5
|
+
* the 640×480 panel, so the drawable canvas grows past stock's 576×288.
|
|
6
|
+
* Native publishes the canvas into the glasses status (0 = none). Because
|
|
7
|
+
* that path is phone-side rasterization, the stock firmware's container
|
|
8
|
+
* pools (6 text / 4 image) don't bound a CFW frame either — element caps are
|
|
9
|
+
* lifted alongside the canvas, bounded only to keep frames sane.
|
|
7
10
|
*/
|
|
8
11
|
import {useGlassesStore} from "../stores/glasses"
|
|
9
|
-
import {getModelCapabilities, type Capabilities
|
|
12
|
+
import {DeviceTypes, getModelCapabilities, type Capabilities} from "../types"
|
|
13
|
+
import {isGlasslyCfwFirmwareVersion} from "./CustomDashboardModel"
|
|
14
|
+
|
|
15
|
+
const CFW_MAX_TEXT_ELEMENTS = 24
|
|
16
|
+
const CFW_MAX_IMAGE_ELEMENTS = 16
|
|
10
17
|
|
|
11
18
|
export interface SceneCanvasSize {
|
|
12
19
|
width: number
|
|
@@ -22,6 +29,19 @@ export function runtimeSceneCanvas(): SceneCanvasSize | null {
|
|
|
22
29
|
export function getEffectiveCapabilities(model: DeviceTypes): Capabilities {
|
|
23
30
|
const base = getModelCapabilities(model)
|
|
24
31
|
const canvas = runtimeSceneCanvas()
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
// The firmware marker lifts the caps even when no canvas has been published:
|
|
33
|
+
// CFW classification rides the version string, and a G2 running Glassly CFW
|
|
34
|
+
// always rasterizes phone-side regardless of whether native reported dims.
|
|
35
|
+
const cfw = model === DeviceTypes.G2 && isGlasslyCfwFirmwareVersion(useGlassesStore.getState().firmwareVersion)
|
|
36
|
+
if (!base.display || (!canvas && !cfw)) return base
|
|
37
|
+
return {
|
|
38
|
+
...base,
|
|
39
|
+
display: {
|
|
40
|
+
...base.display,
|
|
41
|
+
width: canvas?.width ?? base.display.width,
|
|
42
|
+
height: canvas?.height ?? base.display.height,
|
|
43
|
+
maxTextElements: Math.max(base.display.maxTextElements ?? 0, CFW_MAX_TEXT_ELEMENTS),
|
|
44
|
+
maxImageElements: Math.max(base.display.maxImageElements ?? 0, CFW_MAX_IMAGE_ELEMENTS),
|
|
45
|
+
},
|
|
46
|
+
}
|
|
27
47
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gesture-claim arbitration (CLAIM_GESTURES), split out of
|
|
3
|
+
* LocalMiniappRuntime so it is unit-testable — the runtime module itself
|
|
4
|
+
* pulls a native import surface bun can't parse.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* True iff the miniapp in front of the user has claimed `gesture`.
|
|
9
|
+
*
|
|
10
|
+
* "In front" spans both screens. Most claiming apps are glasses-side: the
|
|
11
|
+
* terminal runs as a background miniapp with the phone pocketed, so gating on
|
|
12
|
+
* the phone's Compositor foreground alone left its double_tap claim inert and
|
|
13
|
+
* the system dashboard kept opening mid-session. Glasses ownership is the
|
|
14
|
+
* primary signal; the phone foreground is still honored for apps driven from
|
|
15
|
+
* the handset. A claimer that owns neither screen is background and never
|
|
16
|
+
* hijacks a system gesture.
|
|
17
|
+
*/
|
|
18
|
+
export function claimsGesture(
|
|
19
|
+
claims: ReadonlyMap<string, ReadonlySet<string>>,
|
|
20
|
+
gesture: string,
|
|
21
|
+
glassesOwner: string | null,
|
|
22
|
+
phoneForeground: string | null,
|
|
23
|
+
): boolean {
|
|
24
|
+
for (const pkg of [glassesOwner, phoneForeground]) {
|
|
25
|
+
if (pkg && claims.get(pkg)?.has(gesture) === true) return true
|
|
26
|
+
}
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/gen-gesture-dot-glyphs.mjs — do not edit by hand.
|
|
3
|
+
* 24×24 8-bit grayscale PNGs (white on black) for the gesture-dots indicator.
|
|
4
|
+
*/
|
|
5
|
+
export const GESTURE_DOT_GLYPH_SIZE = 24
|
|
6
|
+
|
|
7
|
+
export type GestureDotGlyph = "dot" | "up" | "down" | "hold" | "blank"
|
|
8
|
+
|
|
9
|
+
export const GESTURE_DOT_GLYPHS: Record<GestureDotGlyph, string> = {
|
|
10
|
+
dot: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAALklEQVR4nM2QsQ0AAAjC/P/pmrhqZ+xIF6DqBQyWbwO3gduAmKjQuj7QL/ETEzQmMptl7Q9NBAAAAABJRU5ErkJggg==",
|
|
11
|
+
up: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAMElEQVR4nGNgoCv4////f1zi2GT+/4ciTHE4RhdHIlDFUUhkcTQKQx9WBw8PCVoBAIcbOcf3xeeBAAAAAElFTkSuQmCC",
|
|
12
|
+
down: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAALUlEQVR4nGNgoC/4/3+4SkBFUCkkNjKJIoMg0GRgGEMGgrC4CQSwuxanR2gEAO1/Ocfgp8uvAAAAAElFTkSuQmCC",
|
|
13
|
+
hold: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAR0lEQVR4nGNgIAj+gwF2UUy5//+xyyDzcLGRedjMhTEwXAKl0Z0Lof7DKbgMhBpQCZzOxedBHEGCMxAJBTXhKGRAA9hFMQEANr7jHQU9fO0AAAAASUVORK5CYII=",
|
|
14
|
+
blank: "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAD0lEQVR4nGNgGAWjgPoAAAJYAAGgxYwDAAAAAElFTkSuQmCC",
|
|
15
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Push phone time to glasses only when clock skew is detected (gallery sync, OTA, etc.).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import BluetoothSdk from "@glassly/bluetooth-sdk
|
|
5
|
+
import BluetoothSdk from "@glassly/bluetooth-sdk"
|
|
6
6
|
import {BgTimer} from "../utils/timers"
|
|
7
7
|
import {useGlassesStore} from "../stores/glasses"
|
|
8
8
|
|
|
@@ -87,6 +87,10 @@ export async function handleOtaClockSkewFromGlasses(
|
|
|
87
87
|
lastOtaClockFixAt = Date.now()
|
|
88
88
|
const {buildNumber, otaVersionUrl} = useGlassesStore.getState()
|
|
89
89
|
const manifestUrl = resolveOtaManifestUrl(otaVersionUrl, buildNumber)
|
|
90
|
+
if (!manifestUrl) {
|
|
91
|
+
console.warn("[GlassesClockSync] OTA restart skipped because this build has no manifest pin")
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
90
94
|
console.log("[GlassesClockSync] ⏰ Restarting OTA with ota_start after clock fix")
|
|
91
95
|
await BluetoothSdk.startOtaUpdate(manifestUrl)
|
|
92
96
|
return true
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeded catalog of common iOS apps that post notifications, keyed by bundle
|
|
3
|
+
* id. iOS has no installed-apps enumeration — the filter UI shows this catalog
|
|
4
|
+
* plus apps the glasses have actually observed via ANCS — and the on-glass
|
|
5
|
+
* allowlist push needs known ids so a blocked app doesn't take every
|
|
6
|
+
* not-yet-seen app down with it (the firmware filter is allow-based).
|
|
7
|
+
*/
|
|
8
|
+
export interface IosNotificationApp {
|
|
9
|
+
appId: string
|
|
10
|
+
displayName: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const IOS_NOTIFICATION_APP_CATALOG: IosNotificationApp[] = [
|
|
14
|
+
{appId: "com.apple.MobileSMS", displayName: "Messages"},
|
|
15
|
+
{appId: "com.apple.mobilephone", displayName: "Phone"},
|
|
16
|
+
{appId: "com.apple.mobilemail", displayName: "Mail"},
|
|
17
|
+
{appId: "com.apple.mobilecal", displayName: "Calendar"},
|
|
18
|
+
{appId: "com.apple.reminders", displayName: "Reminders"},
|
|
19
|
+
{appId: "com.apple.facetime", displayName: "FaceTime"},
|
|
20
|
+
{appId: "net.whatsapp.WhatsApp", displayName: "WhatsApp"},
|
|
21
|
+
{appId: "ph.telegra.Telegraph", displayName: "Telegram"},
|
|
22
|
+
{appId: "org.whispersystems.signal", displayName: "Signal"},
|
|
23
|
+
{appId: "com.google.Gmail", displayName: "Gmail"},
|
|
24
|
+
{appId: "com.microsoft.Office.Outlook", displayName: "Outlook"},
|
|
25
|
+
{appId: "com.tinyspeck.chatlyio", displayName: "Slack"},
|
|
26
|
+
{appId: "com.hammerandchisel.discord", displayName: "Discord"},
|
|
27
|
+
{appId: "com.microsoft.skype.teams", displayName: "Teams"},
|
|
28
|
+
{appId: "com.facebook.Messenger", displayName: "Messenger"},
|
|
29
|
+
{appId: "com.facebook.Facebook", displayName: "Facebook"},
|
|
30
|
+
{appId: "com.burbn.instagram", displayName: "Instagram"},
|
|
31
|
+
{appId: "com.atebits.Tweetie2", displayName: "X"},
|
|
32
|
+
{appId: "com.zhiliaoapp.musically", displayName: "TikTok"},
|
|
33
|
+
{appId: "com.toyopagroup.picaboo", displayName: "Snapchat"},
|
|
34
|
+
{appId: "com.linkedin.LinkedIn", displayName: "LinkedIn"},
|
|
35
|
+
{appId: "com.google.ios.youtube", displayName: "YouTube"},
|
|
36
|
+
{appId: "com.spotify.client", displayName: "Spotify"},
|
|
37
|
+
{appId: "com.ubercab.UberClient", displayName: "Uber"},
|
|
38
|
+
{appId: "com.venmo.TouchFree", displayName: "Venmo"},
|
|
39
|
+
]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Shared OTA progress watchdog timings (see progress-legacy.tsx / progress.tsx). */
|
|
2
|
-
import type {OtaProgress, OtaStatus} from "@glassly/bluetooth-sdk
|
|
2
|
+
import type {OtaProgress, OtaStatus} from "@glassly/bluetooth-sdk"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* First glasses `build_number` (ASG `versionCode`) that uses `progress.tsx` with unified
|
|
@@ -32,6 +32,8 @@ export const PING_INTERVAL_MS = 10_000
|
|
|
32
32
|
export const QUERY_REPLY_TIMEOUT_MS = 6000
|
|
33
33
|
/** 15s lockout on the Continue button after a BES restart, to prevent an accidental tap. */
|
|
34
34
|
export const BES_CONTINUE_LOCKOUT_MS = 15_000
|
|
35
|
+
/** Fail closed if a BES reboot never reconnects; normal restarts complete in a fraction of this window. */
|
|
36
|
+
export const BES_RESTART_TIMEOUT_MS = 120_000
|
|
35
37
|
|
|
36
38
|
// --- Legacy old-build (< MINIMUM_OTA_STATUS_BUILD) OTA policy (WP 8C) ---
|
|
37
39
|
//
|
|
@@ -51,6 +53,7 @@ export const LEGACY_MTK_INSTALL_TIMEOUT_MS = MTK_INSTALL_TIMEOUT_MS + LEGACY_EXT
|
|
|
51
53
|
export const LEGACY_GLOBAL_OTA_TIMEOUT_MS = GLOBAL_OTA_TIMEOUT_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
52
54
|
export const LEGACY_PING_INTERVAL_MS = PING_INTERVAL_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
53
55
|
export const LEGACY_BES_CONTINUE_LOCKOUT_MS = BES_CONTINUE_LOCKOUT_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
56
|
+
export const LEGACY_BES_RESTART_TIMEOUT_MS = BES_RESTART_TIMEOUT_MS + LEGACY_EXTRA_TIMEOUT_MS
|
|
54
57
|
/**
|
|
55
58
|
* After a legacy apk `install FINISHED` observed in-flight, the legacy screen held the
|
|
56
59
|
* completed state for 12s (+20s pad) so the ASG process restart settles (and fresh
|
|
@@ -122,6 +125,7 @@ export function selectOtaProtocolProfile(
|
|
|
122
125
|
export const OtaProgressMessages = {
|
|
123
126
|
stalledOrStuck: "Update may have failed. Ensure glasses have internet access and try again.",
|
|
124
127
|
globalTimeout: "Update took too long. Please try again.",
|
|
128
|
+
restartTimeout: "Glasses did not finish restarting. Restart them before trying the update again.",
|
|
125
129
|
sendOtaStartFailed: "Failed to communicate with glasses.",
|
|
126
130
|
hotspotArtifactDownloadFailed: "Could not download the update to your phone. Check phone internet and try again.",
|
|
127
131
|
hotspotArtifactVerifyFailed: "The update package could not be verified. Please try again later.",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {OtaProgress, OtaProgressStatus, OtaStatus} from "@glassly/bluetooth-sdk
|
|
1
|
+
import type {OtaProgress, OtaProgressStatus, OtaStatus} from "@glassly/bluetooth-sdk"
|
|
2
2
|
|
|
3
3
|
/** Normalized ota_status fields (snake_case) after bridging Core/expo (snake or camel). */
|
|
4
4
|
export type NormalizedOtaStatusEvent = {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Legacy production manifest — pre-39 glasses install from this (they ignore ota_start's URL).
|
|
2
|
+
const OTA_VERSION_URL_LEGACY_PROD = "https://ota.glassly.ai/prod_live_version.json"
|
|
3
|
+
|
|
4
|
+
function trimmed(value?: string | null): string | null {
|
|
5
|
+
const result = value?.trim()
|
|
6
|
+
return result || null
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isLegacyAsgOtaStartBuild(glassesBuildNumber?: string | null): boolean {
|
|
10
|
+
const buildNumber = Number.parseInt(glassesBuildNumber ?? "", 10)
|
|
11
|
+
return Number.isFinite(buildNumber) && buildNumber < 39
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function selectModernOtaManifestPin({
|
|
15
|
+
developerOverride,
|
|
16
|
+
hostReleasePin,
|
|
17
|
+
engineReleasePin,
|
|
18
|
+
}: {
|
|
19
|
+
developerOverride?: string | null
|
|
20
|
+
hostReleasePin?: string | null
|
|
21
|
+
engineReleasePin?: string | null
|
|
22
|
+
}): string | null {
|
|
23
|
+
return trimmed(developerOverride) || trimmed(hostReleasePin) || trimmed(engineReleasePin)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function resolveOtaManifestPolicy({
|
|
27
|
+
glassesUrl,
|
|
28
|
+
glassesBuildNumber,
|
|
29
|
+
developerOverride,
|
|
30
|
+
hostReleasePin,
|
|
31
|
+
engineReleasePin,
|
|
32
|
+
}: {
|
|
33
|
+
glassesUrl?: string | null
|
|
34
|
+
glassesBuildNumber?: string | null
|
|
35
|
+
developerOverride?: string | null
|
|
36
|
+
hostReleasePin?: string | null
|
|
37
|
+
engineReleasePin?: string | null
|
|
38
|
+
}): string | null {
|
|
39
|
+
if (isLegacyAsgOtaStartBuild(glassesBuildNumber)) {
|
|
40
|
+
return trimmed(glassesUrl) || OTA_VERSION_URL_LEGACY_PROD
|
|
41
|
+
}
|
|
42
|
+
return selectModernOtaManifestPin({developerOverride, hostReleasePin, engineReleasePin})
|
|
43
|
+
}
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {ENGINE_RELEASE_METADATA} from "../generated/releaseMetadata"
|
|
3
2
|
import {SETTINGS, useSettingsStore} from "../stores/settings"
|
|
4
|
-
|
|
5
|
-
// Legacy production manifest — pre-39 glasses install from this (they ignore ota_start's URL).
|
|
6
|
-
const OTA_VERSION_URL_LEGACY_PROD = "https://ota.glassly.ai/prod_live_version.json"
|
|
7
|
-
// Modern production fleet manifest (v2). Only a last-resort fallback when the SDK-derived pin
|
|
8
|
-
// URL is somehow unavailable; modern glasses honor ota_start's URL, so this must be the v2
|
|
9
|
-
// artifact, not the legacy v1 rescue manifest.
|
|
10
|
-
const OTA_VERSION_URL_PROD = "https://ota.glassly.ai/prod_live_version_v2.json"
|
|
11
|
-
|
|
12
|
-
function isLegacyAsgOtaStartBuild(glassesBuildNumber?: string | null): boolean {
|
|
13
|
-
const buildNumber = Number.parseInt(glassesBuildNumber ?? "", 10)
|
|
14
|
-
// ASG builds before 39 ignore ota_start.ota_version_url, so compare against
|
|
15
|
-
// the URL they will actually use.
|
|
16
|
-
return Number.isFinite(buildNumber) && buildNumber < 39
|
|
17
|
-
}
|
|
3
|
+
import {resolveOtaManifestPolicy, selectModernOtaManifestPin} from "./otaManifestPolicy"
|
|
18
4
|
|
|
19
5
|
function getOtaVersionUrlDevOverride(): string | null {
|
|
20
6
|
// Super mode only: a wrong OTA manifest can brick glasses, so a saved
|
|
@@ -27,27 +13,32 @@ function getOtaVersionUrlDevOverride(): string | null {
|
|
|
27
13
|
return trimmed || null
|
|
28
14
|
}
|
|
29
15
|
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// compiled default, so the developer override does not apply to them either.
|
|
35
|
-
return deviceUrl || OTA_VERSION_URL_LEGACY_PROD
|
|
36
|
-
}
|
|
16
|
+
function getHostReleasePin(): string | null {
|
|
17
|
+
const value = process.env.EXPO_PUBLIC_ASG_OTA_VERSION_URL?.trim()
|
|
18
|
+
return value || null
|
|
19
|
+
}
|
|
37
20
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
21
|
+
function getEmbeddedEngineReleasePin(): string | null {
|
|
22
|
+
const value = ENGINE_RELEASE_METADATA.otaManifestUrl?.trim()
|
|
23
|
+
return value || null
|
|
24
|
+
}
|
|
42
25
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
export function hasConfiguredModernOtaManifestPin(): boolean {
|
|
27
|
+
return Boolean(
|
|
28
|
+
selectModernOtaManifestPin({
|
|
29
|
+
developerOverride: getOtaVersionUrlDevOverride(),
|
|
30
|
+
hostReleasePin: getHostReleasePin(),
|
|
31
|
+
engineReleasePin: getEmbeddedEngineReleasePin(),
|
|
32
|
+
}),
|
|
33
|
+
)
|
|
34
|
+
}
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
export function resolveOtaManifestUrl(glassesUrl?: string | null, glassesBuildNumber?: string | null): string | null {
|
|
37
|
+
return resolveOtaManifestPolicy({
|
|
38
|
+
glassesUrl,
|
|
39
|
+
glassesBuildNumber,
|
|
40
|
+
developerOverride: getOtaVersionUrlDevOverride(),
|
|
41
|
+
hostReleasePin: getHostReleasePin(),
|
|
42
|
+
engineReleasePin: getEmbeddedEngineReleasePin(),
|
|
43
|
+
})
|
|
53
44
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const COORDINATED_RELEASE_VERSION = /^\d+\.\d+\.\d+(?:-(?:dev|beta)\.[1-9]\d*)?$/
|
|
2
|
+
|
|
3
|
+
type OtaReleaseVersionInput = {
|
|
4
|
+
manifestReleaseVersion?: string | null
|
|
5
|
+
manifestUrl: string
|
|
6
|
+
packagedManifestUrl?: string | null
|
|
7
|
+
packagedReleaseIdentity?: string | null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function validReleaseVersion(version: string | null | undefined): string | null {
|
|
11
|
+
const trimmed = version?.trim()
|
|
12
|
+
return trimmed && COORDINATED_RELEASE_VERSION.test(trimmed) ? trimmed : null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Resolve the label for the selected OTA pin, including stable promotion of exact beta OTA bytes. */
|
|
16
|
+
export function resolveOtaReleaseVersion(input: OtaReleaseVersionInput): string | null {
|
|
17
|
+
const packagedRelease = validReleaseVersion(input.packagedReleaseIdentity)
|
|
18
|
+
if (packagedRelease && input.packagedManifestUrl?.trim() === input.manifestUrl.trim()) {
|
|
19
|
+
return packagedRelease
|
|
20
|
+
}
|
|
21
|
+
return validReleaseVersion(input.manifestReleaseVersion)
|
|
22
|
+
}
|
package/src/stores/apps.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {islandNotifications} from "../services/NotificationsEmitter"
|
|
|
25
25
|
import sttModelManager from "../services/STTModelManager"
|
|
26
26
|
import {miniappLauncher} from "../services/MiniappLauncher"
|
|
27
27
|
import {miniappRunningRegistry} from "../services/MiniappRunningRegistry"
|
|
28
|
+
import {resolveHiddenStatus} from "./appVisibility"
|
|
28
29
|
import {SETTINGS, useSettingsStore} from "./settings"
|
|
29
30
|
import BluetoothSdk from "@glassly/bluetooth-sdk"
|
|
30
31
|
|
|
@@ -221,7 +222,12 @@ function projectApps(previousState: AppStatusState, localApps: ClientApp[]): Cli
|
|
|
221
222
|
...app,
|
|
222
223
|
screenshot: previousByPackage.get(app.packageName)?.screenshot ?? app.screenshot,
|
|
223
224
|
compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),
|
|
224
|
-
|
|
225
|
+
// A registry source can force an app off the primary home screen (for
|
|
226
|
+
// example, Miniapp Developer while its home-screen setting is disabled).
|
|
227
|
+
// Compose that gate with the user's persisted home-screen layout instead
|
|
228
|
+
// of replacing it, otherwise a default-false persisted value makes a
|
|
229
|
+
// source-hidden app visible again during projection.
|
|
230
|
+
hidden: resolveHiddenStatus(app.hidden, previousState.getHiddenStatus(app.packageName)),
|
|
225
231
|
// Derive the foreground flag from the store's single source of truth
|
|
226
232
|
// (`foregroundedPackage`), NOT from the previous snapshot. Carrying it over
|
|
227
233
|
// per-app meant a refresh that momentarily omitted an app (e.g. the
|
package/src/stores/core.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {create} from "zustand"
|
|
2
2
|
import {subscribeWithSelector} from "zustand/middleware"
|
|
3
|
-
import type {
|
|
3
|
+
import type {PublicBluetoothStatus} from "@glassly/bluetooth-sdk"
|
|
4
4
|
|
|
5
|
-
export interface CoreState extends
|
|
6
|
-
setCoreInfo: (info: Partial<
|
|
5
|
+
export interface CoreState extends PublicBluetoothStatus {
|
|
6
|
+
setCoreInfo: (info: Partial<PublicBluetoothStatus>) => void
|
|
7
7
|
reset: () => void
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const initialState:
|
|
10
|
+
const initialState: PublicBluetoothStatus = {
|
|
11
11
|
// state:
|
|
12
12
|
searching: false,
|
|
13
13
|
searchingController: false,
|
package/src/stores/display.ts
CHANGED
|
@@ -29,54 +29,34 @@ const DISPLAY_COALESCE_MS = 150
|
|
|
29
29
|
|
|
30
30
|
type DisplayEvent = Record<string, unknown> & {view?: string}
|
|
31
31
|
|
|
32
|
-
function applyDisplayEvent(
|
|
33
|
-
|
|
34
|
-
get: () => DisplayStore,
|
|
35
|
-
event: DisplayEvent,
|
|
36
|
-
) {
|
|
37
|
-
const currentView = get().view
|
|
38
|
-
const targetBucket = event.view === "dashboard" ? "dashboardEvent" : "mainEvent"
|
|
39
|
-
|
|
40
|
-
const updates: Partial<DisplayStore> = {
|
|
41
|
-
[targetBucket]: event,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// also update the current event if the view is the same:
|
|
45
|
-
if (event.view === currentView) {
|
|
46
|
-
updates.currentEvent = event
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const visibleEvent = (updates.currentEvent ?? event) as DisplayEvent
|
|
50
|
-
const textLines = extractDisplayText(visibleEvent)
|
|
32
|
+
function applyDisplayEvent(set: (partial: Partial<DisplayStore>) => void, event: DisplayEvent) {
|
|
33
|
+
const textLines = extractDisplayText(event)
|
|
51
34
|
if (textLines.some((line) => line.trim() !== "")) {
|
|
52
35
|
logE2EMetric("display_store_update", {
|
|
53
|
-
view:
|
|
54
|
-
layout_type: (
|
|
36
|
+
view: event.view ?? "main",
|
|
37
|
+
layout_type: (event.layout as {layoutType?: string} | undefined)?.layoutType ?? "",
|
|
55
38
|
text_lines: textLines,
|
|
56
39
|
})
|
|
57
40
|
}
|
|
58
|
-
|
|
59
|
-
set(updates)
|
|
41
|
+
set({currentEvent: event})
|
|
60
42
|
}
|
|
61
43
|
|
|
62
44
|
export interface DisplayStore {
|
|
45
|
+
/** The frame currently on the glasses — the mirror renders this. */
|
|
63
46
|
currentEvent: any
|
|
64
|
-
|
|
65
|
-
|
|
47
|
+
/** True while the dashboard covers the main content (see DashboardCoordinator). */
|
|
48
|
+
dashboardActive: boolean
|
|
66
49
|
setDisplayEvent: (event: DisplayEvent | string) => void
|
|
67
|
-
|
|
68
|
-
setView: (view: string) => void
|
|
50
|
+
setDashboardActive: (active: boolean) => void
|
|
69
51
|
}
|
|
70
52
|
|
|
71
53
|
let pendingDisplayEvent: DisplayEvent | null = null
|
|
72
54
|
let displayCoalesceTimer: ReturnType<typeof BgTimer.setTimeout> | null = null
|
|
73
55
|
|
|
74
56
|
export const useDisplayStore = create<DisplayStore>()(
|
|
75
|
-
subscribeWithSelector((set
|
|
57
|
+
subscribeWithSelector((set) => ({
|
|
76
58
|
currentEvent: {} as any,
|
|
77
|
-
|
|
78
|
-
mainEvent: {} as any,
|
|
79
|
-
view: "main",
|
|
59
|
+
dashboardActive: false,
|
|
80
60
|
setDisplayEvent: (event: DisplayEvent | string) => {
|
|
81
61
|
const parsed: DisplayEvent = typeof event === "string" ? JSON.parse(event) : event
|
|
82
62
|
pendingDisplayEvent = parsed
|
|
@@ -85,24 +65,12 @@ export const useDisplayStore = create<DisplayStore>()(
|
|
|
85
65
|
displayCoalesceTimer = null
|
|
86
66
|
const next = pendingDisplayEvent
|
|
87
67
|
pendingDisplayEvent = null
|
|
88
|
-
if (next) applyDisplayEvent(set,
|
|
68
|
+
if (next) applyDisplayEvent(set, next)
|
|
89
69
|
}, DISPLAY_COALESCE_MS)
|
|
90
70
|
},
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// update the view and the currentEvent with the corresponding event:
|
|
98
|
-
let newEvent
|
|
99
|
-
if (view === "dashboard") {
|
|
100
|
-
newEvent = get().dashboardEvent
|
|
101
|
-
} else {
|
|
102
|
-
newEvent = get().mainEvent
|
|
103
|
-
}
|
|
104
|
-
logE2EMetric("display_view_changed", {view})
|
|
105
|
-
set({view, currentEvent: newEvent})
|
|
71
|
+
setDashboardActive: (active: boolean) => {
|
|
72
|
+
logE2EMetric("display_view_changed", {view: active ? "dashboard" : "main"})
|
|
73
|
+
set({dashboardActive: active})
|
|
106
74
|
},
|
|
107
75
|
})),
|
|
108
76
|
)
|
|
@@ -116,6 +84,6 @@ export function flushDisplayCoalesceForTests(): void {
|
|
|
116
84
|
if (pendingDisplayEvent) {
|
|
117
85
|
const event = pendingDisplayEvent
|
|
118
86
|
pendingDisplayEvent = null
|
|
119
|
-
applyDisplayEvent(useDisplayStore.setState,
|
|
87
|
+
applyDisplayEvent(useDisplayStore.setState, event)
|
|
120
88
|
}
|
|
121
89
|
}
|
package/src/stores/glasses.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
GlassesConnectionStatus,
|
|
3
|
-
GlassesStatus,
|
|
4
3
|
HotspotStatus,
|
|
5
4
|
OtaProgress,
|
|
6
5
|
OtaStatus,
|
|
7
6
|
OtaUpdateInfo,
|
|
7
|
+
PublicGlassesStatus,
|
|
8
8
|
WifiStatus,
|
|
9
|
-
} from "@glassly/bluetooth-sdk
|
|
9
|
+
} from "@glassly/bluetooth-sdk"
|
|
10
10
|
import {isGlassesConnected, isGlassesLinkLayerBusy, isGlassesReady} from "../services/GlassesReadiness"
|
|
11
11
|
import {create} from "zustand"
|
|
12
12
|
import {subscribeWithSelector} from "zustand/middleware"
|
|
@@ -20,7 +20,14 @@ export const selectGlassesConnected = (state: {connection: GlassesConnectionStat
|
|
|
20
20
|
|
|
21
21
|
export const selectGlassesReady = (state: {connection: GlassesConnectionStatus}) => isGlassesReady(state.connection)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
type EngineGlassesStatus = PublicGlassesStatus & {
|
|
24
|
+
otaUpdateAvailable: OtaUpdateInfo | null
|
|
25
|
+
otaProgress: OtaProgress | null
|
|
26
|
+
otaInProgress: boolean
|
|
27
|
+
otaVersionUrl: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface GlassesState extends EngineGlassesStatus {
|
|
24
31
|
systemTimeMs: number
|
|
25
32
|
wifiStatusKnown: boolean
|
|
26
33
|
setGlassesInfo: (info: GlassesInfoUpdate) => void
|
|
@@ -53,7 +60,7 @@ type LegacyHotspotFields = {
|
|
|
53
60
|
hotspotLocalIp?: string
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
type GlassesInfoUpdate = Partial<
|
|
63
|
+
type GlassesInfoUpdate = Partial<EngineGlassesStatus> & LegacyWifiFields & LegacyHotspotFields
|
|
57
64
|
|
|
58
65
|
function wifiFromLegacyFields(info: LegacyWifiFields): WifiStatus | null {
|
|
59
66
|
if (info.wifiConnected === true) {
|
|
@@ -80,7 +87,7 @@ function hotspotFromLegacyFields(info: LegacyHotspotFields): HotspotStatus | nul
|
|
|
80
87
|
return null
|
|
81
88
|
}
|
|
82
89
|
|
|
83
|
-
export const getGlasesInfoPartial = (state:
|
|
90
|
+
export const getGlasesInfoPartial = (state: EngineGlassesStatus) => {
|
|
84
91
|
const wifi = state.wifi
|
|
85
92
|
const connected = isGlassesConnected(state.connection)
|
|
86
93
|
return {
|
|
@@ -98,7 +105,7 @@ export const getGlasesInfoPartial = (state: GlassesStatus) => {
|
|
|
98
105
|
}
|
|
99
106
|
}
|
|
100
107
|
|
|
101
|
-
interface GlassesStore extends
|
|
108
|
+
interface GlassesStore extends EngineGlassesStatus {
|
|
102
109
|
systemTimeMs: number
|
|
103
110
|
mtkUpdatedThisSession: boolean
|
|
104
111
|
wifiStatusKnown: boolean
|
|
@@ -158,6 +165,8 @@ const initialState: GlassesStore = {
|
|
|
158
165
|
controllerMacAddress: "",
|
|
159
166
|
controllerBatteryLevel: -1,
|
|
160
167
|
controllerSignalStrength: -1,
|
|
168
|
+
// iOS ANCS consent (G2 consumes notifications on-firmware):
|
|
169
|
+
ancsAuthorized: false,
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
export const useGlassesStore = create<GlassesState>()(
|