@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
|
@@ -20,7 +20,9 @@ import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
|
|
|
20
20
|
import {shallow} from "zustand/shallow"
|
|
21
21
|
|
|
22
22
|
import localMiniappRuntime from "./LocalMiniappRuntime"
|
|
23
|
+
import localDisplayManager from "./LocalDisplayManager"
|
|
23
24
|
import localSttFallbackCoordinator from "./LocalSttFallbackCoordinator"
|
|
25
|
+
import {MiniappExitGesture} from "./MiniappExitGesture"
|
|
24
26
|
import nativeNavigationService from "./NativeNavigationService"
|
|
25
27
|
import speakerLabelResolver from "./SpeakerLabelResolver"
|
|
26
28
|
import {phonePhotoCoordinator} from "./PhonePhotoCoordinator"
|
|
@@ -31,10 +33,23 @@ import {SETTINGS, useSettingsStore} from "../stores/settings"
|
|
|
31
33
|
import {useAppStatusStore} from "../stores/apps"
|
|
32
34
|
import {retirePendingSelectionOnPromotion} from "./PairingIdentity"
|
|
33
35
|
import GlobalEventEmitter from "../utils/GlobalEventEmitter"
|
|
36
|
+
import {BgTimer} from "../utils/timers"
|
|
34
37
|
import {asgCameraApi} from "./asg/asgCameraApi"
|
|
38
|
+
import dashboardCoordinator from "./DashboardCoordinator"
|
|
39
|
+
import gestureDotsService from "./GestureDotsService"
|
|
35
40
|
|
|
36
41
|
let subs: Array<{remove: () => void}> = []
|
|
37
42
|
|
|
43
|
+
const miniappExitGesture = new MiniappExitGesture({
|
|
44
|
+
getState: () => useAppStatusStore.getState(),
|
|
45
|
+
getVisiblePackageName: () => localDisplayManager.getVisibleMiniappPackageName(),
|
|
46
|
+
beginExitNotice: (packageName, text) => localDisplayManager.beginMiniappExit(packageName, text),
|
|
47
|
+
finishExitNotice: (packageName) => localDisplayManager.finishMiniappExit(packageName),
|
|
48
|
+
cancelExitNotice: (packageName) => localDisplayManager.cancelMiniappExit(packageName),
|
|
49
|
+
setTimeout: (callback, delay) => BgTimer.setTimeout(callback, delay),
|
|
50
|
+
clearTimeout: (timerId) => BgTimer.clearTimeout(timerId),
|
|
51
|
+
})
|
|
52
|
+
|
|
38
53
|
export function startDeviceEventRouter(): void {
|
|
39
54
|
if (subs.length) return
|
|
40
55
|
|
|
@@ -183,13 +198,38 @@ export function startDeviceEventRouter(): void {
|
|
|
183
198
|
)
|
|
184
199
|
subs.push(
|
|
185
200
|
BluetoothSdk.addListener("touch_event", (event) => {
|
|
201
|
+
// While the custom dashboard is visible it owns its focus/navigation
|
|
202
|
+
// gestures; do not leak those into a miniapp running underneath it.
|
|
203
|
+
if (dashboardCoordinator.handleGesture(event.gestureName)) return
|
|
204
|
+
|
|
205
|
+
// Gesture-dots debug indicator (any device, gated by its setting). It
|
|
206
|
+
// only paints while the screen is otherwise empty; the gesture still
|
|
207
|
+
// flows to miniapps below.
|
|
208
|
+
gestureDotsService.noteGesture(event.gestureName)
|
|
209
|
+
|
|
186
210
|
localMiniappRuntime.forwardEvent("touch_event", event)
|
|
187
|
-
// Double-tap policy, moved out of the native G2 handlers:
|
|
188
|
-
//
|
|
189
|
-
// reports the gesture now.
|
|
211
|
+
// Double-tap policy, moved out of the native G2 handlers: exit a visible
|
|
212
|
+
// unclaimed miniapp; otherwise open the dashboard or toggle head-up.
|
|
213
|
+
// Native only reports the gesture now.
|
|
190
214
|
if (event.gestureName === "double_tap") {
|
|
191
|
-
|
|
192
|
-
|
|
215
|
+
// A foreground miniapp that claimed double_tap (CLAIM_GESTURES) is
|
|
216
|
+
// using it as an in-app gesture (e.g. the terminal's back-to-menu) —
|
|
217
|
+
// the event was already forwarded above; skip the system default.
|
|
218
|
+
if (localMiniappRuntime.foregroundClaimsGesture("double_tap")) return
|
|
219
|
+
|
|
220
|
+
// An unclaimed double tap exits only the miniapp whose frame is visibly
|
|
221
|
+
// on the glasses. The controller shows the bounded OS notice first,
|
|
222
|
+
// then uses the normal store stop path (and closes its phone overlay).
|
|
223
|
+
// Checked before the dashboard toggle: while an app owns the screen an
|
|
224
|
+
// unclaimed double-tap always means "leave the app" — the (custom or
|
|
225
|
+
// native) dashboard is for the empty screen, and head-up still opens
|
|
226
|
+
// the custom dashboard mid-app.
|
|
227
|
+
if (miniappExitGesture.tryExitVisibleMiniapp()) return
|
|
228
|
+
|
|
229
|
+
// Eligible G2 custom firmware replaces the native dashboard.
|
|
230
|
+
if (dashboardCoordinator.toggleCustom()) return
|
|
231
|
+
|
|
232
|
+
const useNativeDashboard = useSettingsStore.getState().getSetting(SETTINGS.use_native_dashboard.key) !== false
|
|
193
233
|
if (useNativeDashboard) {
|
|
194
234
|
// The modal nav UI owns the screen; showDashboard would fight it.
|
|
195
235
|
if (!nativeNavigationService.isActive) {
|
|
@@ -198,9 +238,7 @@ export function startDeviceEventRouter(): void {
|
|
|
198
238
|
})
|
|
199
239
|
}
|
|
200
240
|
} else {
|
|
201
|
-
|
|
202
|
-
console.error("DeviceEventRouter: toggleHeadUp failed:", err)
|
|
203
|
-
})
|
|
241
|
+
dashboardCoordinator.toggleLegacy()
|
|
204
242
|
}
|
|
205
243
|
}
|
|
206
244
|
}),
|
|
@@ -219,6 +257,7 @@ export function startDeviceEventRouter(): void {
|
|
|
219
257
|
// Head position — translate native {up:boolean} → SDK {position:"up"|"down"}.
|
|
220
258
|
subs.push(
|
|
221
259
|
BluetoothSdk.addListener("head_up", (event) => {
|
|
260
|
+
dashboardCoordinator.setHeadUp(event.up)
|
|
222
261
|
localMiniappRuntime.forwardEvent("head_up", {position: event.up ? "up" : "down", timestamp: Date.now()})
|
|
223
262
|
}),
|
|
224
263
|
)
|
|
@@ -263,4 +302,5 @@ export function startDeviceEventRouter(): void {
|
|
|
263
302
|
export function stopDeviceEventRouter(): void {
|
|
264
303
|
for (const sub of subs) sub.remove()
|
|
265
304
|
subs = []
|
|
305
|
+
miniappExitGesture.reset()
|
|
266
306
|
}
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* DisplayProcessor
|
|
3
3
|
*
|
|
4
4
|
* Processes display events with pixel-accurate text wrapping using the same
|
|
5
|
-
* display
|
|
6
|
-
*
|
|
5
|
+
* Engine display utilities. This ensures the mobile preview matches exactly
|
|
6
|
+
* what is shown on the glasses.
|
|
7
7
|
*
|
|
8
8
|
* Key responsibilities:
|
|
9
9
|
* 1. Intercept display events before sending to native SGC
|
|
10
10
|
* 2. Wrap text using the correct device profile (G1, etc.)
|
|
11
11
|
* 3. Ensure GlassesDisplayMirror shows exactly what glasses will show
|
|
12
12
|
*
|
|
13
|
-
* @see
|
|
13
|
+
* @see notes/miniapp-display-api-redesign.md for the current display design
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import {
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gesture dots — a debug indicator that flashes a small glyph top-right on the
|
|
3
|
+
* glasses when a touch gesture arrives, while nothing else is on the display:
|
|
4
|
+
* a filled circle for a single tap, an arrow for a swipe (cleared after a
|
|
5
|
+
* short pulse), a bullseye while a CFW tap-then-hold is held. Extracted from
|
|
6
|
+
* the CFW dashboard service; it renders through
|
|
7
|
+
* the ordinary scene pipeline, so it works on any positioning device (stock
|
|
8
|
+
* G2 included), and is gated by the gesture_dots debug setting.
|
|
9
|
+
*
|
|
10
|
+
* The glyphs are pre-baked images (not text): the stock firmware's builtin
|
|
11
|
+
* font has no ●/↑/↓, and a single image element with a stable id and box maps
|
|
12
|
+
* to ONE re-used firmware image container — flash and idle swap its bytes
|
|
13
|
+
* (data-only update, no page rebuild) instead of creating/removing containers.
|
|
14
|
+
*/
|
|
15
|
+
import {SETTINGS, useSettingsStore} from "../stores/settings"
|
|
16
|
+
import type {SceneElementInput} from "../utils/display/scene"
|
|
17
|
+
import {BgTimer} from "../utils/timers"
|
|
18
|
+
import {GESTURE_DOT_GLYPHS, GESTURE_DOT_GLYPH_SIZE, type GestureDotGlyph} from "./gestureDotGlyphs"
|
|
19
|
+
import localDisplayManager from "./LocalDisplayManager"
|
|
20
|
+
import sceneRenderer from "./SceneRenderer"
|
|
21
|
+
|
|
22
|
+
const DOTS_APP_ID = "system.gesture-dots"
|
|
23
|
+
/** How long a gesture stays on the indicator. */
|
|
24
|
+
const GESTURE_FLASH_MS = 700
|
|
25
|
+
const MARGIN_X = 16
|
|
26
|
+
const MARGIN_TOP = 10
|
|
27
|
+
|
|
28
|
+
class GestureDotsService {
|
|
29
|
+
private started = false
|
|
30
|
+
private flash: GestureDotGlyph | null = null
|
|
31
|
+
private flashTimer: number | null = null
|
|
32
|
+
/** Finger currently on the touch bar (tap_start..tap_end; the CFW forwards holds as these edges). */
|
|
33
|
+
private held = false
|
|
34
|
+
/**
|
|
35
|
+
* The CFW's tap_then_hold fired during this press (discrete recognition
|
|
36
|
+
* event; the tap_end that follows on release is what clears it).
|
|
37
|
+
*/
|
|
38
|
+
private holdRecognized = false
|
|
39
|
+
/** Whether the indicator scene currently has anything on it (needs a clear when the flash ends). */
|
|
40
|
+
private visible = false
|
|
41
|
+
private unsubs: Array<() => void> = []
|
|
42
|
+
|
|
43
|
+
start(): void {
|
|
44
|
+
if (this.started) return
|
|
45
|
+
this.started = true
|
|
46
|
+
this.unsubs.push(
|
|
47
|
+
// The indicator owns the screen only while it is empty: drop our
|
|
48
|
+
// retained state when something else takes over, and clear any
|
|
49
|
+
// leftover flash when the display empties again.
|
|
50
|
+
localDisplayManager.onActiveDisplayChange((active) => {
|
|
51
|
+
if (active) this.visible = false
|
|
52
|
+
else this.render()
|
|
53
|
+
}),
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
stop(): void {
|
|
58
|
+
for (const unsub of this.unsubs) unsub()
|
|
59
|
+
this.unsubs = []
|
|
60
|
+
if (this.flashTimer !== null) BgTimer.clearTimeout(this.flashTimer)
|
|
61
|
+
this.flashTimer = null
|
|
62
|
+
this.flash = null
|
|
63
|
+
this.held = false
|
|
64
|
+
this.holdRecognized = false
|
|
65
|
+
this.visible = false
|
|
66
|
+
this.started = false
|
|
67
|
+
sceneRenderer.clearApp(DOTS_APP_ID)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private enabled(): boolean {
|
|
71
|
+
return useSettingsStore.getState().getSetting(SETTINGS.gesture_dots.key) === true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Flash a gesture on the indicator. Other gesture names are ignored. The
|
|
76
|
+
* device-event router calls this after the CFW dashboard had its chance to
|
|
77
|
+
* consume the gesture, so dashboard navigation does not flash.
|
|
78
|
+
*/
|
|
79
|
+
noteGesture(gestureName: string): void {
|
|
80
|
+
if (!this.started || !this.enabled()) return
|
|
81
|
+
// Tap edges show a steady circle for as long as the finger is down (on
|
|
82
|
+
// CFW these arrive for holds: ET_LONG/ET_REL forwarded as
|
|
83
|
+
// tap_start/tap_end), with no timer — tap_end clears it.
|
|
84
|
+
if (gestureName === "tap_start" || gestureName === "tap_end") {
|
|
85
|
+
const held = gestureName === "tap_start"
|
|
86
|
+
if (this.held === held) return
|
|
87
|
+
this.held = held
|
|
88
|
+
if (!held) this.holdRecognized = false
|
|
89
|
+
this.render()
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
// CFW tap-then-hold (the stock Menu gesture): swap the steady dot for the
|
|
93
|
+
// bullseye until release. Recognition arrives mid-press, but set held too
|
|
94
|
+
// in case the tap_start edge was missed — the release edge still clears.
|
|
95
|
+
if (gestureName === "tap_then_hold") {
|
|
96
|
+
this.held = true
|
|
97
|
+
this.holdRecognized = true
|
|
98
|
+
this.render()
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
const flash: GestureDotGlyph | null =
|
|
102
|
+
gestureName === "single_tap"
|
|
103
|
+
? "dot"
|
|
104
|
+
: gestureName === "swipe_up"
|
|
105
|
+
? "up"
|
|
106
|
+
: gestureName === "swipe_down"
|
|
107
|
+
? "down"
|
|
108
|
+
: null
|
|
109
|
+
if (!flash) return
|
|
110
|
+
this.flash = flash
|
|
111
|
+
if (this.flashTimer !== null) BgTimer.clearTimeout(this.flashTimer)
|
|
112
|
+
this.flashTimer = BgTimer.setTimeout(() => {
|
|
113
|
+
this.flashTimer = null
|
|
114
|
+
this.flash = null
|
|
115
|
+
this.render()
|
|
116
|
+
}, GESTURE_FLASH_MS)
|
|
117
|
+
this.render()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Paint or clear the indicator. Nothing is drawn while anything else is on
|
|
122
|
+
* the glasses (miniapp frame or system screen) or when no gesture was just
|
|
123
|
+
* received. The top-right anchor resolves against the device's real canvas,
|
|
124
|
+
* so no size math here.
|
|
125
|
+
*
|
|
126
|
+
* Between flashes the element STAYS in the scene with the blank glyph:
|
|
127
|
+
* removing it would tear down the firmware image container and rebuild the
|
|
128
|
+
* page on every flash (a rebuild storm on stock firmware). Only disabling
|
|
129
|
+
* the setting removes the element outright.
|
|
130
|
+
*/
|
|
131
|
+
private render(): void {
|
|
132
|
+
if (!this.started) return
|
|
133
|
+
if (localDisplayManager.hasActiveDisplay()) return
|
|
134
|
+
const shown = this.flash ?? (this.held ? (this.holdRecognized ? "hold" : "dot") : null)
|
|
135
|
+
if (!this.enabled()) {
|
|
136
|
+
if (this.visible) {
|
|
137
|
+
this.visible = false
|
|
138
|
+
sceneRenderer.emitScene(DOTS_APP_ID, "main", [])
|
|
139
|
+
}
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
if (!shown && !this.visible) return
|
|
143
|
+
const elements: SceneElementInput[] = [
|
|
144
|
+
{
|
|
145
|
+
type: "image",
|
|
146
|
+
id: "gesture-dot",
|
|
147
|
+
box: {
|
|
148
|
+
x: MARGIN_X,
|
|
149
|
+
y: MARGIN_TOP,
|
|
150
|
+
w: GESTURE_DOT_GLYPH_SIZE,
|
|
151
|
+
h: GESTURE_DOT_GLYPH_SIZE,
|
|
152
|
+
anchor: "top-right",
|
|
153
|
+
},
|
|
154
|
+
data: GESTURE_DOT_GLYPHS[shown ?? "blank"],
|
|
155
|
+
},
|
|
156
|
+
]
|
|
157
|
+
this.visible = true
|
|
158
|
+
sceneRenderer.emitScene(DOTS_APP_ID, "main", elements)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const gestureDotsService = new GestureDotsService()
|
|
163
|
+
export default gestureDotsService
|
|
164
|
+
export {GestureDotsService}
|
|
@@ -11,22 +11,26 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Started by `engine.start()`. Idempotent.
|
|
13
13
|
*/
|
|
14
|
-
import BluetoothSdk from "@glassly/bluetooth-sdk
|
|
14
|
+
import BluetoothSdk, {type PublicGlassesStatus} from "@glassly/bluetooth-sdk"
|
|
15
15
|
import {useCoreStore} from "../stores/core"
|
|
16
16
|
import {useGlassesStore} from "../stores/glasses"
|
|
17
|
-
import localMiniappRuntime from "./LocalMiniappRuntime"
|
|
18
17
|
|
|
19
18
|
let unsubs: Array<() => void> = []
|
|
20
19
|
let projectionRunId = 0
|
|
20
|
+
let glassesStatusForwarder: ((status: Partial<PublicGlassesStatus>) => void) | null = null
|
|
21
|
+
let hydrationPromise: Promise<void> | null = null
|
|
21
22
|
|
|
22
|
-
export function startGlassesStatusProjection(
|
|
23
|
-
|
|
23
|
+
export function startGlassesStatusProjection(
|
|
24
|
+
forwarder?: (status: Partial<PublicGlassesStatus>) => void,
|
|
25
|
+
): Promise<void> {
|
|
26
|
+
if (forwarder) glassesStatusForwarder = forwarder
|
|
27
|
+
if (unsubs.length) return hydrationPromise ?? Promise.resolve()
|
|
24
28
|
|
|
25
29
|
const runId = ++projectionRunId
|
|
26
30
|
let bluetoothEventSeen = false
|
|
27
31
|
let glassesEventSeen = false
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
const bluetoothHydration = BluetoothSdk.getBluetoothStatus()
|
|
30
34
|
.then((status) => {
|
|
31
35
|
if (runId !== projectionRunId || bluetoothEventSeen) return
|
|
32
36
|
useCoreStore.getState().setCoreInfo(status)
|
|
@@ -35,7 +39,7 @@ export function startGlassesStatusProjection(): void {
|
|
|
35
39
|
console.warn("GlassesStatusProjection: getBluetoothStatus failed", error)
|
|
36
40
|
})
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
const glassesHydration = BluetoothSdk.getGlassesStatus()
|
|
39
43
|
.then((status) => {
|
|
40
44
|
if (runId !== projectionRunId || glassesEventSeen) return
|
|
41
45
|
useGlassesStore.getState().setGlassesInfo(status)
|
|
@@ -46,28 +50,33 @@ export function startGlassesStatusProjection(): void {
|
|
|
46
50
|
|
|
47
51
|
// Bluetooth-adapter status -> core store.
|
|
48
52
|
unsubs.push(
|
|
49
|
-
BluetoothSdk.
|
|
53
|
+
BluetoothSdk.subscribeBluetoothStatus((changed) => {
|
|
50
54
|
bluetoothEventSeen = true
|
|
51
55
|
useCoreStore.getState().setCoreInfo(changed)
|
|
52
56
|
}),
|
|
53
57
|
)
|
|
54
58
|
|
|
55
|
-
// Glasses status -> glasses store (+
|
|
56
|
-
// OTA-available flag on disconnect).
|
|
59
|
+
// Glasses status -> glasses store (+ optional full-runtime forwarding to local
|
|
60
|
+
// miniapps; clear any stale OTA-available flag on disconnect).
|
|
57
61
|
unsubs.push(
|
|
58
|
-
BluetoothSdk.
|
|
62
|
+
BluetoothSdk.subscribeGlassesStatus((changed) => {
|
|
59
63
|
glassesEventSeen = true
|
|
60
64
|
useGlassesStore.getState().setGlassesInfo(changed)
|
|
61
|
-
|
|
65
|
+
glassesStatusForwarder?.(changed)
|
|
62
66
|
if (changed.connection?.state === "disconnected") {
|
|
63
67
|
useGlassesStore.getState().setOtaUpdateAvailable(null)
|
|
64
68
|
}
|
|
65
69
|
}),
|
|
66
70
|
)
|
|
71
|
+
|
|
72
|
+
hydrationPromise = Promise.allSettled([bluetoothHydration, glassesHydration]).then(() => undefined)
|
|
73
|
+
return hydrationPromise
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
export function stopGlassesStatusProjection(): void {
|
|
70
77
|
projectionRunId++
|
|
71
78
|
unsubs.forEach((unsub) => unsub())
|
|
72
79
|
unsubs = []
|
|
80
|
+
glassesStatusForwarder = null
|
|
81
|
+
hydrationPromise = null
|
|
73
82
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import BluetoothSdk, {isEnabledHotspotStatus
|
|
1
|
+
import BluetoothSdk, {isEnabledHotspotStatus} from "@glassly/bluetooth-sdk"
|
|
2
|
+
import {otaServer} from "@glassly/bluetooth-sdk/ota-transport"
|
|
2
3
|
// One coordinator selects the native Android or iOS staging implementation at runtime.
|
|
3
4
|
// eslint-disable-next-line react-native/split-platform-components
|
|
4
5
|
import {PermissionsAndroid, Platform} from "react-native"
|
|
@@ -83,7 +84,7 @@ class HotspotOtaTransport {
|
|
|
83
84
|
let localAddress = scopedAddress
|
|
84
85
|
if (Platform.OS === "ios") {
|
|
85
86
|
try {
|
|
86
|
-
localAddress = await
|
|
87
|
+
localAddress = await otaServer.waitForWifiAddress(hotspot.localIp, 15_000)
|
|
87
88
|
} catch (error) {
|
|
88
89
|
throw new HotspotOtaTransportError(
|
|
89
90
|
"hotspot_join_failed",
|
|
@@ -94,10 +95,10 @@ class HotspotOtaTransport {
|
|
|
94
95
|
const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))
|
|
95
96
|
// Start exactly one native listener to learn its selected port, then atomically replace
|
|
96
97
|
// the placeholder with the immutable rewritten manifest before ota_start is sent.
|
|
97
|
-
const server = await
|
|
98
|
+
const server = await otaServer.start("{}", artifactPaths, localAddress)
|
|
98
99
|
this.serverStarted = true
|
|
99
100
|
const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl)
|
|
100
|
-
const published = await
|
|
101
|
+
const published = await otaServer.start(manifest, artifactPaths, server.host)
|
|
101
102
|
if (published.manifestUrl !== server.manifestUrl) {
|
|
102
103
|
throw new Error("Local OTA server endpoint changed while publishing the manifest")
|
|
103
104
|
}
|
|
@@ -141,11 +142,11 @@ class HotspotOtaTransport {
|
|
|
141
142
|
destination: string,
|
|
142
143
|
onProgress?: (bytesWritten: number, contentLength: number) => void,
|
|
143
144
|
): Promise<{statusCode: number}> => {
|
|
144
|
-
const subscription =
|
|
145
|
+
const subscription = otaServer.onArtifactDownloadProgress((event) => {
|
|
145
146
|
if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)
|
|
146
147
|
})
|
|
147
148
|
try {
|
|
148
|
-
return await
|
|
149
|
+
return await otaServer.downloadArtifact(entry.url, destination)
|
|
149
150
|
} finally {
|
|
150
151
|
subscription.remove()
|
|
151
152
|
}
|
|
@@ -164,7 +165,7 @@ class HotspotOtaTransport {
|
|
|
164
165
|
console.warn("[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries")
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
if (this.serverStarted) await
|
|
168
|
+
if (this.serverStarted) await otaServer.stop().catch(() => {})
|
|
168
169
|
if (this.localNetworkConnected) await localNetworkTransport.disconnect().catch(() => {})
|
|
169
170
|
await cleanupArtifacts().catch(() => {})
|
|
170
171
|
this.prepared = []
|