@mentra/engine 3.1.0-dev.94 → 3.1.0-dev.96
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 +1 -1
- package/build/facades/ota.d.ts +1 -1
- package/build/facades/ota.js +1 -1
- package/build/facades/ota.js.map +1 -1
- package/build/generated/releaseMetadata.js +5 -5
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.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/LocalDisplayManager.d.ts +2 -3
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +2 -3
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +1 -1
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/StreamLifecycleController.d.ts +3 -3
- package/build/services/StreamLifecycleController.js +3 -3
- package/build/services/StreamLifecycleController.js.map +1 -1
- package/build/types/applet.d.ts +1 -1
- package/build/types/applet.js +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g1.js +2 -0
- package/build/types/capabilities/even-realities-g1.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 -0
- package/build/types/capabilities/even-realities-g2.js.map +1 -1
- package/build/types/capabilities/mentra-display.d.ts.map +1 -1
- package/build/types/capabilities/mentra-display.js +2 -0
- package/build/types/capabilities/mentra-display.js.map +1 -1
- package/build/types/capabilities/mentra-live.d.ts.map +1 -1
- package/build/types/capabilities/mentra-live.js +2 -0
- package/build/types/capabilities/mentra-live.js.map +1 -1
- package/build/types/capabilities/nimo.d.ts +9 -0
- package/build/types/capabilities/nimo.d.ts.map +1 -0
- package/build/types/capabilities/nimo.js +57 -0
- package/build/types/capabilities/nimo.js.map +1 -0
- package/build/types/capabilities/none.d.ts.map +1 -1
- package/build/types/capabilities/none.js +2 -0
- package/build/types/capabilities/none.js.map +1 -1
- package/build/types/capabilities/simulated-glasses.d.ts.map +1 -1
- package/build/types/capabilities/simulated-glasses.js +2 -0
- package/build/types/capabilities/simulated-glasses.js.map +1 -1
- package/build/types/capabilities/vuzix-z100.d.ts.map +1 -1
- package/build/types/capabilities/vuzix-z100.js +2 -0
- package/build/types/capabilities/vuzix-z100.js.map +1 -1
- package/build/types/enums.d.ts +2 -1
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +3 -2
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +3 -1
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +1 -1
- 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/package.json +6 -6
- package/src/facades/ota.ts +1 -1
- package/src/generated/releaseMetadata.ts +5 -5
- package/src/index.ts +1 -0
- package/src/services/DisplayProcessor.ts +3 -3
- package/src/services/LocalDisplayManager.ts +2 -3
- package/src/services/PhonePhotoCoordinator.ts +1 -1
- package/src/services/StreamLifecycleController.ts +3 -3
- package/src/types/applet.ts +1 -1
- package/src/types/capabilities/even-realities-g1.ts +3 -0
- package/src/types/capabilities/even-realities-g2.ts +3 -0
- package/src/types/capabilities/mentra-display.ts +3 -0
- package/src/types/capabilities/mentra-live.ts +3 -0
- package/src/types/capabilities/nimo.ts +59 -0
- package/src/types/capabilities/none.ts +3 -0
- package/src/types/capabilities/simulated-glasses.ts +3 -0
- package/src/types/capabilities/vuzix-z100.ts +3 -0
- package/src/types/enums.ts +1 -0
- package/src/types/hardware.ts +4 -2
- package/src/types/index.ts +1 -0
- package/src/utils/display/composer/ColumnComposer.ts +1 -1
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ import BluetoothSdk from "@mentra/engine/bluetooth-sdk"
|
|
|
69
69
|
### Mentra Live OTA flow
|
|
70
70
|
|
|
71
71
|
Bluetooth-only hosts can render the OTA flow without configuring or starting
|
|
72
|
-
the authenticated cloud
|
|
72
|
+
the authenticated cloud connection or miniapp runtime:
|
|
73
73
|
|
|
74
74
|
```tsx
|
|
75
75
|
import {MentraLiveOtaFlow} from "@mentra/engine/ota"
|
package/build/facades/ota.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type { OtaProgress, OtaProgressStatus, OtaStatus, OtaUpdateInfo, ReleaseC
|
|
|
24
24
|
export declare const ota: {
|
|
25
25
|
/**
|
|
26
26
|
* Start the device-status and OTA projections without starting the authenticated
|
|
27
|
-
* cloud
|
|
27
|
+
* cloud connection or miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.
|
|
28
28
|
* Idempotent and safe when the full engine runtime is already running.
|
|
29
29
|
*/
|
|
30
30
|
initialize: () => Promise<void>;
|
package/build/facades/ota.js
CHANGED
|
@@ -40,7 +40,7 @@ export const ota = {
|
|
|
40
40
|
// --- actions ---
|
|
41
41
|
/**
|
|
42
42
|
* Start the device-status and OTA projections without starting the authenticated
|
|
43
|
-
* cloud
|
|
43
|
+
* cloud connection or miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.
|
|
44
44
|
* Idempotent and safe when the full engine runtime is already running.
|
|
45
45
|
*/
|
|
46
46
|
initialize: async () => {
|
package/build/facades/ota.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ota.js","sourceRoot":"","sources":["../../src/facades/ota.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ota facade — `engine.ota`: the OEM-facing OTA read/observe surface. Engine's\n * OtaService projects the glasses' OTA BLE events into the engine store; this facade\n * exposes the snapshot + change subscriptions behind the shared OTA flow exported by\n * `@mentra/engine/ota`. Hosts retain only their surrounding navigation and theme/i18n adapters.\n *\n * Availability checks live in engine. Install orchestration lives in engine too:\n * `installSession` fronts the OtaInstallCoordinator state machine (WP 8B) — the host\n * progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk\"\nimport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStartAckEvent,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n} from \"@mentra/bluetooth-sdk\"\nimport {isGlassesConnected, isGlassesReady, useGlassesStore} from \"../stores/glasses\"\nimport {resolveOtaManifestUrl} from \"../services/otaManifestUrl\"\nimport {otaInstallCoordinator, type OtaInstallSnapshot} from \"../services/OtaInstallCoordinator\"\nimport {startGlassesStatusProjection} from \"../services/GlassesStatusProjection\"\nimport {startOtaService} from \"../services/OtaService\"\nimport {\n checkCurrentGlassesForUpdate,\n type OtaCheckCurrentGlassesOptions,\n type OtaCheckCurrentGlassesResult,\n} from \"../services/OtaUpdateCheckService\"\n\nfunction projectSnapshot() {\n const s = useGlassesStore.getState()\n return {\n connected: isGlassesConnected(s.connection),\n ready: isGlassesReady(s.connection),\n buildNumber: s.buildNumber || null,\n appVersion: s.appVersion || null,\n mtkFirmwareVersion: s.mtkFirmwareVersion || null,\n besFirmwareVersion: s.besFirmwareVersion || null,\n batteryLevel: s.batteryLevel >= 0 ? s.batteryLevel : null,\n hotspotOtaVersion: s.hotspotOtaVersion ?? 0,\n wifiConnected: s.wifi.state === \"connected\",\n wifiStatusKnown: s.wifiStatusKnown,\n manifestUrl: resolveOtaManifestUrl(s.otaVersionUrl, s.buildNumber),\n updateAvailable: s.otaUpdateAvailable,\n status: s.otaStatus,\n legacyProgress: s.otaProgress,\n inProgress: s.otaInProgress,\n mtkUpdatedThisSession: s.mtkUpdatedThisSession,\n }\n}\n\nexport type OtaSnapshot = ReturnType<typeof projectSnapshot>\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n OtaInstallSnapshot,\n OtaCheckCurrentGlassesOptions,\n OtaCheckCurrentGlassesResult,\n}\n\nexport const ota = {\n // --- actions ---\n /**\n * Start the device-status and OTA projections without starting the authenticated\n * cloud/miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.\n * Idempotent and safe when the full engine runtime is already running.\n */\n initialize: async () => {\n const hydrated = startGlassesStatusProjection()\n startOtaService()\n await hydrated\n },\n /**\n * Start the firmware install with the resolved OTA manifest URL. Progress lands on\n * `status()`/`onStatus()`. (The host resolves the manifest URL — developer override,\n * host pin, or Engine release pin resolution stays with the OTA config; the stuck/retry watchdog is its own\n * resilience layer on top of this command.)\n */\n install: (otaVersionUrl?: string | null): Promise<OtaStartAckEvent> => BluetoothSdk.startOtaUpdate(otaVersionUrl),\n // Deferred: this facade entry was intended to become the engine-owned retry/check\n // action, but BluetoothSdk.checkForOtaUpdate() only returns a boolean. Exposing it\n // here would make callers think the rich otaUpdateAvailable read model is refreshed,\n // while the original view still depends on the host-side manifest compare to build\n // versionName/updates/totalSize. Keep that behavior unchanged until the whole rich\n // availability check moves into engine.\n // retry: () => BluetoothSdk.checkForOtaUpdate(),\n /**\n * Keep glasses awake while an OTA session is actively progressing.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n ping: () => BluetoothSdk.ping(),\n /** Resolve and compare the current glasses against the OTA manifest, then update the OTA snapshot. */\n checkForUpdates: (options?: OtaCheckCurrentGlassesOptions) => checkCurrentGlassesForUpdate(options),\n /** Return bundled release changelogs crossed between two coordinated product versions, newest first. */\n getReleaseChangelogs: (fromVersion?: string | null, toVersion?: string | null): ReleaseChangelog[] =>\n BluetoothSdk.getReleaseChangelogs(fromVersion, toVersion),\n /** Clear the available-update prompt state. */\n clearUpdateAvailable: () => useGlassesStore.getState().setOtaUpdateAvailable(null),\n /** Clear active progress/status before entering a fresh install flow. */\n clearProgress: () => {\n const store = useGlassesStore.getState()\n store.setOtaProgress(null)\n store.setOtaStatus(null)\n },\n /**\n * Replace the pending update sequence after an in-flow firmware revalidation.\n * Kept as a named OTA policy operation so host screens do not mutate the raw\n * glasses store.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n replacePendingUpdateSequence: (updates: OtaUpdateInfo[\"updates\"]): OtaUpdateInfo | null => {\n const store = useGlassesStore.getState()\n const current = store.otaUpdateAvailable\n if (!current) return null\n const next = {...current, updates}\n store.setOtaUpdateAvailable(next)\n return next\n },\n /**\n * Clear stale build metadata before returning to the update-check screen.\n * This forces the next version_info event through both the native observable\n * store and the engine projection after an APK reboot.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n clearBuildNumberForNextCheck: () => {\n useGlassesStore.getState().setGlassesInfo({buildNumber: \"\"})\n },\n /**\n * Mark MTK as already applied during this app session until the glasses reboot/disconnect.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n markMtkUpdatedThisSession: (updated: boolean) => useGlassesStore.getState().setMtkUpdatedThisSession(updated),\n\n /**\n * The OTA install state machine (unified `ota_status` sessions, build >= 37).\n * The host progress screen attaches on mount, detaches on unmount, and renders\n * the snapshot; every watchdog/retry/reconnect rule lives in the coordinator.\n */\n installSession: {\n /** Select Wi-Fi or capability-gated hotspot transport for this checked manifest. */\n prepare: (result: OtaCheckCurrentGlassesResult) => otaInstallCoordinator.prepare(result),\n /** Bind the machine to the mounted progress screen. Idempotent per attach/detach cycle. */\n attach: () => otaInstallCoordinator.attach(),\n /** Unbind on unmount: clears all timers/listeners and resets session state. */\n detach: () => otaInstallCoordinator.detach(),\n /** Retry after a failure: clear state and re-send ota_start (if connected). */\n retry: () => otaInstallCoordinator.retry(),\n /** Terminal cleanup for Continue/Done, including hotspot route teardown. */\n finish: () => otaInstallCoordinator.finish(),\n /** Abandon an interrupted session: await finish() then drop the session's status/progress. */\n discard: () => otaInstallCoordinator.discard(),\n /** Current install read model (displayState/errorMsg/lockout + glasses OTA data). */\n snapshot: (): OtaInstallSnapshot => otaInstallCoordinator.snapshot(),\n /** Subscribe to install snapshot changes (deduped on projected JSON). Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaInstallSnapshot) => void): (() => void) => otaInstallCoordinator.onSnapshot(cb),\n },\n\n /** Current available-update info (versionName/updates/totalSize), or null. */\n updateAvailable: (): OtaUpdateInfo | null => useGlassesStore.getState().otaUpdateAvailable,\n /** Current OTA install status (stepType/phase/percent/status/error), or null. */\n status: (): OtaStatus | null => useGlassesStore.getState().otaStatus,\n /** Current OTA read model for update prompt/progress screens. */\n snapshot: (): OtaSnapshot => projectSnapshot(),\n\n /** Subscribe to OTA availability changes (info or null when cleared). Returns an unsubscribe. */\n onUpdateAvailable: (cb: (info: OtaUpdateInfo | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaUpdateAvailable\n return useGlassesStore.subscribe(() => {\n const info = useGlassesStore.getState().otaUpdateAvailable\n if (info === last) return\n last = info\n cb(info)\n })\n },\n\n /** Subscribe to OTA install status changes. Returns an unsubscribe. */\n onStatus: (cb: (status: OtaStatus | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaStatus\n return useGlassesStore.subscribe(() => {\n const status = useGlassesStore.getState().otaStatus\n if (status === last) return\n last = status\n cb(status)\n })\n },\n\n /** Subscribe to OTA snapshot changes. Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectSnapshot())\n return useGlassesStore.subscribe(() => {\n const snap = projectSnapshot()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ota.js","sourceRoot":"","sources":["../../src/facades/ota.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ota facade — `engine.ota`: the OEM-facing OTA read/observe surface. Engine's\n * OtaService projects the glasses' OTA BLE events into the engine store; this facade\n * exposes the snapshot + change subscriptions behind the shared OTA flow exported by\n * `@mentra/engine/ota`. Hosts retain only their surrounding navigation and theme/i18n adapters.\n *\n * Availability checks live in engine. Install orchestration lives in engine too:\n * `installSession` fronts the OtaInstallCoordinator state machine (WP 8B) — the host\n * progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk\"\nimport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStartAckEvent,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n} from \"@mentra/bluetooth-sdk\"\nimport {isGlassesConnected, isGlassesReady, useGlassesStore} from \"../stores/glasses\"\nimport {resolveOtaManifestUrl} from \"../services/otaManifestUrl\"\nimport {otaInstallCoordinator, type OtaInstallSnapshot} from \"../services/OtaInstallCoordinator\"\nimport {startGlassesStatusProjection} from \"../services/GlassesStatusProjection\"\nimport {startOtaService} from \"../services/OtaService\"\nimport {\n checkCurrentGlassesForUpdate,\n type OtaCheckCurrentGlassesOptions,\n type OtaCheckCurrentGlassesResult,\n} from \"../services/OtaUpdateCheckService\"\n\nfunction projectSnapshot() {\n const s = useGlassesStore.getState()\n return {\n connected: isGlassesConnected(s.connection),\n ready: isGlassesReady(s.connection),\n buildNumber: s.buildNumber || null,\n appVersion: s.appVersion || null,\n mtkFirmwareVersion: s.mtkFirmwareVersion || null,\n besFirmwareVersion: s.besFirmwareVersion || null,\n batteryLevel: s.batteryLevel >= 0 ? s.batteryLevel : null,\n hotspotOtaVersion: s.hotspotOtaVersion ?? 0,\n wifiConnected: s.wifi.state === \"connected\",\n wifiStatusKnown: s.wifiStatusKnown,\n manifestUrl: resolveOtaManifestUrl(s.otaVersionUrl, s.buildNumber),\n updateAvailable: s.otaUpdateAvailable,\n status: s.otaStatus,\n legacyProgress: s.otaProgress,\n inProgress: s.otaInProgress,\n mtkUpdatedThisSession: s.mtkUpdatedThisSession,\n }\n}\n\nexport type OtaSnapshot = ReturnType<typeof projectSnapshot>\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n OtaInstallSnapshot,\n OtaCheckCurrentGlassesOptions,\n OtaCheckCurrentGlassesResult,\n}\n\nexport const ota = {\n // --- actions ---\n /**\n * Start the device-status and OTA projections without starting the authenticated\n * cloud connection or miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.\n * Idempotent and safe when the full engine runtime is already running.\n */\n initialize: async () => {\n const hydrated = startGlassesStatusProjection()\n startOtaService()\n await hydrated\n },\n /**\n * Start the firmware install with the resolved OTA manifest URL. Progress lands on\n * `status()`/`onStatus()`. (The host resolves the manifest URL — developer override,\n * host pin, or Engine release pin resolution stays with the OTA config; the stuck/retry watchdog is its own\n * resilience layer on top of this command.)\n */\n install: (otaVersionUrl?: string | null): Promise<OtaStartAckEvent> => BluetoothSdk.startOtaUpdate(otaVersionUrl),\n // Deferred: this facade entry was intended to become the engine-owned retry/check\n // action, but BluetoothSdk.checkForOtaUpdate() only returns a boolean. Exposing it\n // here would make callers think the rich otaUpdateAvailable read model is refreshed,\n // while the original view still depends on the host-side manifest compare to build\n // versionName/updates/totalSize. Keep that behavior unchanged until the whole rich\n // availability check moves into engine.\n // retry: () => BluetoothSdk.checkForOtaUpdate(),\n /**\n * Keep glasses awake while an OTA session is actively progressing.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n ping: () => BluetoothSdk.ping(),\n /** Resolve and compare the current glasses against the OTA manifest, then update the OTA snapshot. */\n checkForUpdates: (options?: OtaCheckCurrentGlassesOptions) => checkCurrentGlassesForUpdate(options),\n /** Return bundled release changelogs crossed between two coordinated product versions, newest first. */\n getReleaseChangelogs: (fromVersion?: string | null, toVersion?: string | null): ReleaseChangelog[] =>\n BluetoothSdk.getReleaseChangelogs(fromVersion, toVersion),\n /** Clear the available-update prompt state. */\n clearUpdateAvailable: () => useGlassesStore.getState().setOtaUpdateAvailable(null),\n /** Clear active progress/status before entering a fresh install flow. */\n clearProgress: () => {\n const store = useGlassesStore.getState()\n store.setOtaProgress(null)\n store.setOtaStatus(null)\n },\n /**\n * Replace the pending update sequence after an in-flow firmware revalidation.\n * Kept as a named OTA policy operation so host screens do not mutate the raw\n * glasses store.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n replacePendingUpdateSequence: (updates: OtaUpdateInfo[\"updates\"]): OtaUpdateInfo | null => {\n const store = useGlassesStore.getState()\n const current = store.otaUpdateAvailable\n if (!current) return null\n const next = {...current, updates}\n store.setOtaUpdateAvailable(next)\n return next\n },\n /**\n * Clear stale build metadata before returning to the update-check screen.\n * This forces the next version_info event through both the native observable\n * store and the engine projection after an APK reboot.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n clearBuildNumberForNextCheck: () => {\n useGlassesStore.getState().setGlassesInfo({buildNumber: \"\"})\n },\n /**\n * Mark MTK as already applied during this app session until the glasses reboot/disconnect.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n markMtkUpdatedThisSession: (updated: boolean) => useGlassesStore.getState().setMtkUpdatedThisSession(updated),\n\n /**\n * The OTA install state machine (unified `ota_status` sessions, build >= 37).\n * The host progress screen attaches on mount, detaches on unmount, and renders\n * the snapshot; every watchdog/retry/reconnect rule lives in the coordinator.\n */\n installSession: {\n /** Select Wi-Fi or capability-gated hotspot transport for this checked manifest. */\n prepare: (result: OtaCheckCurrentGlassesResult) => otaInstallCoordinator.prepare(result),\n /** Bind the machine to the mounted progress screen. Idempotent per attach/detach cycle. */\n attach: () => otaInstallCoordinator.attach(),\n /** Unbind on unmount: clears all timers/listeners and resets session state. */\n detach: () => otaInstallCoordinator.detach(),\n /** Retry after a failure: clear state and re-send ota_start (if connected). */\n retry: () => otaInstallCoordinator.retry(),\n /** Terminal cleanup for Continue/Done, including hotspot route teardown. */\n finish: () => otaInstallCoordinator.finish(),\n /** Abandon an interrupted session: await finish() then drop the session's status/progress. */\n discard: () => otaInstallCoordinator.discard(),\n /** Current install read model (displayState/errorMsg/lockout + glasses OTA data). */\n snapshot: (): OtaInstallSnapshot => otaInstallCoordinator.snapshot(),\n /** Subscribe to install snapshot changes (deduped on projected JSON). Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaInstallSnapshot) => void): (() => void) => otaInstallCoordinator.onSnapshot(cb),\n },\n\n /** Current available-update info (versionName/updates/totalSize), or null. */\n updateAvailable: (): OtaUpdateInfo | null => useGlassesStore.getState().otaUpdateAvailable,\n /** Current OTA install status (stepType/phase/percent/status/error), or null. */\n status: (): OtaStatus | null => useGlassesStore.getState().otaStatus,\n /** Current OTA read model for update prompt/progress screens. */\n snapshot: (): OtaSnapshot => projectSnapshot(),\n\n /** Subscribe to OTA availability changes (info or null when cleared). Returns an unsubscribe. */\n onUpdateAvailable: (cb: (info: OtaUpdateInfo | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaUpdateAvailable\n return useGlassesStore.subscribe(() => {\n const info = useGlassesStore.getState().otaUpdateAvailable\n if (info === last) return\n last = info\n cb(info)\n })\n },\n\n /** Subscribe to OTA install status changes. Returns an unsubscribe. */\n onStatus: (cb: (status: OtaStatus | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaStatus\n return useGlassesStore.subscribe(() => {\n const status = useGlassesStore.getState().otaStatus\n if (status === last) return\n last = status\n cb(status)\n })\n },\n\n /** Subscribe to OTA snapshot changes. Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectSnapshot())\n return useGlassesStore.subscribe(() => {\n const snap = projectSnapshot()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n}\n"]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export const ENGINE_RELEASE_METADATA = Object.freeze({
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"familyBaseVersion": "3.1.0",
|
|
4
|
-
"releaseIdentity": "3.1.0-dev.
|
|
5
|
-
"releaseSetId": "mentra-3.1.0-dev.
|
|
6
|
-
"sourceCommit": "
|
|
7
|
-
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.1.0/mentra-live-ota-3.1.0-dev.
|
|
8
|
-
"otaManifestSha256": "
|
|
4
|
+
"releaseIdentity": "3.1.0-dev.96",
|
|
5
|
+
"releaseSetId": "mentra-3.1.0-dev.96",
|
|
6
|
+
"sourceCommit": "dc0cedc622a383421f9e5b918b2865c30f8f28dd",
|
|
7
|
+
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.1.0/mentra-live-ota-3.1.0-dev.96.json",
|
|
8
|
+
"otaManifestSha256": "205f2dc478e89f36f2c0ebb586b41723d85eeaa62f24ae05754c7c91d7215392"
|
|
9
9
|
});
|
|
10
10
|
//# sourceMappingURL=releaseMetadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,uBAAuB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACpF,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,cAAc;IACjC,cAAc,EAAE,qBAAqB;IACrC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,uHAAuH;IACzI,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface EngineReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.1.0\",\n \"releaseIdentity\": \"3.1.0-dev.
|
|
1
|
+
{"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,uBAAuB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACpF,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,cAAc;IACjC,cAAc,EAAE,qBAAqB;IACrC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,uHAAuH;IACzI,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface EngineReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.1.0\",\n \"releaseIdentity\": \"3.1.0-dev.96\",\n \"releaseSetId\": \"mentra-3.1.0-dev.96\",\n \"sourceCommit\": \"dc0cedc622a383421f9e5b918b2865c30f8f28dd\",\n \"otaManifestUrl\": \"https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.1.0/mentra-live-ota-3.1.0-dev.96.json\",\n \"otaManifestSha256\": \"205f2dc478e89f36f2c0ebb586b41723d85eeaa62f24ae05754c7c91d7215392\"\n})\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -40,6 +40,6 @@ export { DUMMY_APPLET, saveAppsOrder, getAppsOrder, sortAppsByPackageNamePriorit
|
|
|
40
40
|
export { decideDevLaunchRoute, type DecideDevLaunchOptions, type DevLaunchResult, type DevManifest, } from "./utils/devMiniappLaunch";
|
|
41
41
|
export { HardwareCompatibility, type CompatibilityResult } from "./utils/hardware";
|
|
42
42
|
export { BgTimer, throttle, debounce } from "./utils/timers";
|
|
43
|
-
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes, HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, vuzixZ100, mentraDisplay, } from "./types";
|
|
43
|
+
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes, HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, nimo, vuzixZ100, mentraDisplay, } from "./types";
|
|
44
44
|
export type { HardwareRequirement, CameraCapabilities, DisplayCapabilities, MicrophoneCapabilities, SpeakerCapabilities, IMUCapabilities, ButtonCapabilities, LightCapabilities, PowerCapabilities, Capabilities, AppletType, AppPermissionType, AppletPermission, AppletInterface, ClientApp, } from "./types";
|
|
45
45
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/build/index.js
CHANGED
|
@@ -42,5 +42,5 @@ export { decideDevLaunchRoute, } from "./utils/devMiniappLaunch";
|
|
|
42
42
|
export { HardwareCompatibility } from "./utils/hardware";
|
|
43
43
|
export { BgTimer, throttle, debounce } from "./utils/timers";
|
|
44
44
|
// Hardware types and capability profiles.
|
|
45
|
-
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes, HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, vuzixZ100, mentraDisplay, } from "./types";
|
|
45
|
+
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes, HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, nimo, vuzixZ100, mentraDisplay, } from "./types";
|
|
46
46
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAyB/B,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,qEAAqE;AACrE,kDAAkD;AAClD,OAAO,EAAC,QAAQ,EAAE,UAAU,EAAC,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,+BAA+B,CAAA;AAExG,8CAA8C;AAC9C,OAAO,EAAC,oBAAoB,EAAC,MAAM,kBAAkB,CAAA;AAGrD,2DAA2D;AAC3D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,mBAAmB,GAGpB,MAAM,6BAA6B,CAAA;AACpC,yEAAyE;AACzE,OAAO,EACL,eAAe,EACf,yBAAyB,GAI1B,MAAM,kCAAkC,CAAA;AAazC,uEAAuE;AACvE,2DAA2D;AAC3D,OAAO,EACL,wBAAwB,EACxB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAC,kBAAkB,EAAC,MAAM,4BAA4B,CAAA;AAW7D,OAAO,EACL,iBAAiB,EACjB,8BAA8B,EAC9B,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,uCAAuC,EACvC,yCAAyC,GAC1C,MAAM,4BAA4B,CAAA;AAMnC,OAAO,EAAC,uBAAuB,EAAC,MAAM,6CAA6C,CAAA;AACnF,OAAO,EAAC,wBAAwB,EAAC,MAAM,wCAAwC,CAAA;AAe/E,+EAA+E;AAC/E,OAAO,EAAC,eAAe,EAAC,MAAM,qBAAqB,CAAA;AAEnD,yEAAyE;AACzE,6CAA6C;AAC7C,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,6BAA6B,EAC7B,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,OAAO,EACP,QAAQ,EACR,OAAO,EACP,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,4BAA4B,EAC5B,gBAAgB,GAGjB,MAAM,eAAe,CAAA;AAEtB,4EAA4E;AAC5E,OAAO,EACL,oBAAoB,GAIrB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,qBAAqB,EAA2B,MAAM,kBAAkB,CAAA;AAChF,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAC,MAAM,gBAAgB,CAAA;AAE1D,0CAA0C;AAC1C,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,WAAW,EACX,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,aAAa,GACd,MAAM,SAAS,CAAA","sourcesContent":["/**\n * `@mentra/engine` — the OEM-facing main entry.\n *\n * The `engine` namespace (configure/start/stop + typed domain facades), the\n * public contract/read-model types, and the pure helpers host UI legitimately\n * renders with (decision functions, sort/order helpers, policy constants,\n * capability tables, timers). Judgment rule: read models, commands, pure\n * functions and types belong here; anything that mutates runtime state or\n * exposes a raw store/service remains private to the MentraOS host.\n * See cloud-v2/docs/issues/020-glasses-status-boundary/integration-review.md §D.\n */\n\n// The namespaced OEM-facing engine API (the \"(A) host API\"). See ./engine.\nexport {engine} from \"./engine\"\nexport type {\n ReportAttachmentInput,\n ReportContext,\n ReportDetails,\n ReportStatus,\n ReportTrigger,\n ReportSubmitResult,\n EngineSubmitReportInput,\n} from \"./facades/reports\"\nexport type {IslandNotification, IslandNotificationKind} from \"./facades/notifications\"\nexport type {WifiSearchResult} from \"./facades/glassesWifi\"\nexport type {IdentitySnapshot} from \"./services/PairingIdentity\"\nexport type {DisplayMirrorEvent} from \"./facades/displayMirror\"\nexport type {\n IslandConfigureOptions,\n IslandAuth,\n IslandConfigValues,\n IslandAnalytics,\n IslandUiSeams,\n ScanQrOptions,\n ScanQrResult,\n SubjectTokenType,\n} from \"./runtime/bootstrap\"\n\n// Settings contract: the typed key registry (schema descriptors — the same\n// surface engine.settings.descriptor()/keys() reads), the per-key React hook\n// (the hook layer, same precedent as the apps hooks below), and the pure\n// device-model key helpers. The raw useSettingsStore stays internal;\n// imperative access goes through engine.settings.\nexport {SETTINGS, useSetting} from \"./stores/settings\"\nexport {MENTRA_LIVE_SETTING_KEYS, getBluetoothSettingKeysForDevice} from \"./stores/bluetoothSettingKeys\"\n\n// Runtime-shared constants and contract DTOs.\nexport {ISLAND_SETTINGS_KEYS} from \"./runtime/config\"\nexport type {CloudClientStatusSnapshot, MiniappAuthToken, InteropAuditEvent, TtsSynthesisResult} from \"./runtime/config\"\n\n// Pure readiness predicates over glasses connection state.\nexport {\n isGlassesConnected,\n isGlassesReady,\n isGlassesLinkLayerBusy,\n waitForGlassesReady,\n type GlassesConnectionStatus,\n type WaitForGlassesReadyOptions,\n} from \"./services/GlassesReadiness\"\n// Pure connect/reconnect decision helpers (host UI renders the outcome).\nexport {\n decideReconnect,\n decideConnectButtonAction,\n type ReconnectDecision,\n type ReconnectDecisionInput,\n type ConnectButtonAction,\n} from \"./services/ConnectionCoordinator\"\n\n// OTA read-model types for host OTA UI (progress screen, error mapping,\n// progress section) — the check/install machinery itself is internal.\nexport type {\n VersionInfo,\n MtkPatch,\n BesFirmware,\n VersionJson,\n OtaCheckResult,\n OtaCheckCurrentGlassesResult,\n OtaCheckCurrentGlassesOptions,\n} from \"./services/OtaUpdateCheckService\"\n// OTA install policy (watchdog timings + failure copy) + display-state\n// derivation, consumed by the OTA screens and their tests.\nexport {\n MINIMUM_OTA_STATUS_BUILD,\n MAX_RETRIES,\n RETRY_INTERVAL_MS,\n PROGRESS_TIMEOUT_MS,\n DOWNLOAD_STUCK_TIMEOUT_MS,\n MTK_INSTALL_TIMEOUT_MS,\n GLOBAL_OTA_TIMEOUT_MS,\n PING_INTERVAL_MS,\n QUERY_REPLY_TIMEOUT_MS,\n BES_RESTART_TIMEOUT_MS,\n OtaProgressMessages,\n} from \"./services/otaInstallPolicy\"\nexport {deriveDisplayState} from \"./services/otaDisplayState\"\nexport type {DisplayState} from \"./services/otaDisplayState\"\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n OtaSnapshot,\n OtaInstallSnapshot,\n} from \"./facades/ota\"\nexport {\n beginOtaAutoChain,\n clearOtaAutoChainReconnectWait,\n isOtaAutoChainActive,\n otaAutoChainFingerprint,\n otaAutoChainReconnectWaitRemaining,\n stopOtaAutoChain,\n tryAdvanceOtaAutoChain,\n MAX_OTA_AUTO_CHAIN_PASSES,\n OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS,\n} from \"./services/OtaAutoChain\"\nexport type {OtaAutoChainAdvanceResult} from \"./services/OtaAutoChain\"\nexport {\n BES_INSTALL_RESTART_MESSAGE,\n getOtaErrorMessage,\n shouldRequireGlassesRebootForBesFailure,\n shouldShowChangeWifiForOtaDownloadFailure,\n} from \"./services/OtaErrorMapping\"\n\n// Gallery read models: engine.gallery.onNotice payload types, the media\n// permission helper + display-name derivation host gallery UI uses, and the\n// glasses-camera DTO types (re-exported through the host @/types/asg shim).\nexport type {GalleryNotice, GalleryNoticeCode} from \"./services/asg/galleryNotices\"\nexport {MediaLibraryPermissions} from \"./utils/permissions/MediaLibraryPermissions\"\nexport {deriveGalleryDisplayName} from \"./utils/permissions/galleryDisplayName\"\nexport type {\n PhotoInfo,\n CaptureFile,\n CaptureGroup,\n GalleryResponse,\n ServerStatus,\n HealthResponse,\n GalleryEvent,\n} from \"./types/asg\"\n\n// Bluetooth SDK event types host UI subscribes to via engine facades (the\n// BluetoothSdk singleton passthrough itself is internal).\nexport type {PairFailureEvent, GlassesNotReadyEvent} from \"@mentra/bluetooth-sdk\"\n\n// Cloud connection status enum (read model; the connection store is internal).\nexport {WebSocketStatus} from \"./stores/connection\"\n\n// App-list hook layer + pure list helpers (the raw useAppStatusStore and\n// installAppStoreHooks wiring are internal).\nexport {\n DUMMY_APPLET,\n saveAppsOrder,\n getAppsOrder,\n sortAppsByPackageNamePriority,\n saveLastOpenTime,\n getLastOpenTime,\n sortAppsByLastOpenTime,\n useApps,\n useStart,\n useStop,\n useSetForeground,\n useClearForeground,\n useRefresh,\n useStopAll,\n useInstall,\n useUninstall,\n useActiveApps,\n useActiveBackgroundApps,\n useBackgroundApps,\n useActiveForegroundApp,\n useForegroundApp,\n useActiveBackgroundAppsCount,\n useLocalMiniApps,\n type StartOptions,\n type OrderMap,\n} from \"./stores/apps\"\n\n// Pure dev-miniapp launch-route decision (registration itself is internal).\nexport {\n decideDevLaunchRoute,\n type DecideDevLaunchOptions,\n type DevLaunchResult,\n type DevManifest,\n} from \"./utils/devMiniappLaunch\"\nexport {HardwareCompatibility, type CompatibilityResult} from \"./utils/hardware\"\nexport {BgTimer, throttle, debounce} from \"./utils/timers\"\n\n// Hardware types and capability profiles.\nexport {\n HardwareType,\n HardwareRequirementLevel,\n DeviceTypes,\n ControllerTypes,\n HARDWARE_CAPABILITIES,\n getModelCapabilities,\n simulatedGlasses,\n evenRealitiesG1,\n evenRealitiesG2,\n mentraLive,\n vuzixZ100,\n mentraDisplay,\n} from \"./types\"\nexport type {\n HardwareRequirement,\n CameraCapabilities,\n DisplayCapabilities,\n MicrophoneCapabilities,\n SpeakerCapabilities,\n IMUCapabilities,\n ButtonCapabilities,\n LightCapabilities,\n PowerCapabilities,\n Capabilities,\n AppletType,\n AppPermissionType,\n AppletPermission,\n AppletInterface,\n ClientApp,\n} from \"./types\"\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAyB/B,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,qEAAqE;AACrE,kDAAkD;AAClD,OAAO,EAAC,QAAQ,EAAE,UAAU,EAAC,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,+BAA+B,CAAA;AAExG,8CAA8C;AAC9C,OAAO,EAAC,oBAAoB,EAAC,MAAM,kBAAkB,CAAA;AAGrD,2DAA2D;AAC3D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,mBAAmB,GAGpB,MAAM,6BAA6B,CAAA;AACpC,yEAAyE;AACzE,OAAO,EACL,eAAe,EACf,yBAAyB,GAI1B,MAAM,kCAAkC,CAAA;AAazC,uEAAuE;AACvE,2DAA2D;AAC3D,OAAO,EACL,wBAAwB,EACxB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAC,kBAAkB,EAAC,MAAM,4BAA4B,CAAA;AAW7D,OAAO,EACL,iBAAiB,EACjB,8BAA8B,EAC9B,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,uCAAuC,EACvC,yCAAyC,GAC1C,MAAM,4BAA4B,CAAA;AAMnC,OAAO,EAAC,uBAAuB,EAAC,MAAM,6CAA6C,CAAA;AACnF,OAAO,EAAC,wBAAwB,EAAC,MAAM,wCAAwC,CAAA;AAe/E,+EAA+E;AAC/E,OAAO,EAAC,eAAe,EAAC,MAAM,qBAAqB,CAAA;AAEnD,yEAAyE;AACzE,6CAA6C;AAC7C,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,6BAA6B,EAC7B,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,OAAO,EACP,QAAQ,EACR,OAAO,EACP,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,4BAA4B,EAC5B,gBAAgB,GAGjB,MAAM,eAAe,CAAA;AAEtB,4EAA4E;AAC5E,OAAO,EACL,oBAAoB,GAIrB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,qBAAqB,EAA2B,MAAM,kBAAkB,CAAA;AAChF,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAC,MAAM,gBAAgB,CAAA;AAE1D,0CAA0C;AAC1C,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,WAAW,EACX,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,UAAU,EACV,IAAI,EACJ,SAAS,EACT,aAAa,GACd,MAAM,SAAS,CAAA","sourcesContent":["/**\n * `@mentra/engine` — the OEM-facing main entry.\n *\n * The `engine` namespace (configure/start/stop + typed domain facades), the\n * public contract/read-model types, and the pure helpers host UI legitimately\n * renders with (decision functions, sort/order helpers, policy constants,\n * capability tables, timers). Judgment rule: read models, commands, pure\n * functions and types belong here; anything that mutates runtime state or\n * exposes a raw store/service remains private to the MentraOS host.\n * See cloud-v2/docs/issues/020-glasses-status-boundary/integration-review.md §D.\n */\n\n// The namespaced OEM-facing engine API (the \"(A) host API\"). See ./engine.\nexport {engine} from \"./engine\"\nexport type {\n ReportAttachmentInput,\n ReportContext,\n ReportDetails,\n ReportStatus,\n ReportTrigger,\n ReportSubmitResult,\n EngineSubmitReportInput,\n} from \"./facades/reports\"\nexport type {IslandNotification, IslandNotificationKind} from \"./facades/notifications\"\nexport type {WifiSearchResult} from \"./facades/glassesWifi\"\nexport type {IdentitySnapshot} from \"./services/PairingIdentity\"\nexport type {DisplayMirrorEvent} from \"./facades/displayMirror\"\nexport type {\n IslandConfigureOptions,\n IslandAuth,\n IslandConfigValues,\n IslandAnalytics,\n IslandUiSeams,\n ScanQrOptions,\n ScanQrResult,\n SubjectTokenType,\n} from \"./runtime/bootstrap\"\n\n// Settings contract: the typed key registry (schema descriptors — the same\n// surface engine.settings.descriptor()/keys() reads), the per-key React hook\n// (the hook layer, same precedent as the apps hooks below), and the pure\n// device-model key helpers. The raw useSettingsStore stays internal;\n// imperative access goes through engine.settings.\nexport {SETTINGS, useSetting} from \"./stores/settings\"\nexport {MENTRA_LIVE_SETTING_KEYS, getBluetoothSettingKeysForDevice} from \"./stores/bluetoothSettingKeys\"\n\n// Runtime-shared constants and contract DTOs.\nexport {ISLAND_SETTINGS_KEYS} from \"./runtime/config\"\nexport type {CloudClientStatusSnapshot, MiniappAuthToken, InteropAuditEvent, TtsSynthesisResult} from \"./runtime/config\"\n\n// Pure readiness predicates over glasses connection state.\nexport {\n isGlassesConnected,\n isGlassesReady,\n isGlassesLinkLayerBusy,\n waitForGlassesReady,\n type GlassesConnectionStatus,\n type WaitForGlassesReadyOptions,\n} from \"./services/GlassesReadiness\"\n// Pure connect/reconnect decision helpers (host UI renders the outcome).\nexport {\n decideReconnect,\n decideConnectButtonAction,\n type ReconnectDecision,\n type ReconnectDecisionInput,\n type ConnectButtonAction,\n} from \"./services/ConnectionCoordinator\"\n\n// OTA read-model types for host OTA UI (progress screen, error mapping,\n// progress section) — the check/install machinery itself is internal.\nexport type {\n VersionInfo,\n MtkPatch,\n BesFirmware,\n VersionJson,\n OtaCheckResult,\n OtaCheckCurrentGlassesResult,\n OtaCheckCurrentGlassesOptions,\n} from \"./services/OtaUpdateCheckService\"\n// OTA install policy (watchdog timings + failure copy) + display-state\n// derivation, consumed by the OTA screens and their tests.\nexport {\n MINIMUM_OTA_STATUS_BUILD,\n MAX_RETRIES,\n RETRY_INTERVAL_MS,\n PROGRESS_TIMEOUT_MS,\n DOWNLOAD_STUCK_TIMEOUT_MS,\n MTK_INSTALL_TIMEOUT_MS,\n GLOBAL_OTA_TIMEOUT_MS,\n PING_INTERVAL_MS,\n QUERY_REPLY_TIMEOUT_MS,\n BES_RESTART_TIMEOUT_MS,\n OtaProgressMessages,\n} from \"./services/otaInstallPolicy\"\nexport {deriveDisplayState} from \"./services/otaDisplayState\"\nexport type {DisplayState} from \"./services/otaDisplayState\"\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n OtaSnapshot,\n OtaInstallSnapshot,\n} from \"./facades/ota\"\nexport {\n beginOtaAutoChain,\n clearOtaAutoChainReconnectWait,\n isOtaAutoChainActive,\n otaAutoChainFingerprint,\n otaAutoChainReconnectWaitRemaining,\n stopOtaAutoChain,\n tryAdvanceOtaAutoChain,\n MAX_OTA_AUTO_CHAIN_PASSES,\n OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS,\n} from \"./services/OtaAutoChain\"\nexport type {OtaAutoChainAdvanceResult} from \"./services/OtaAutoChain\"\nexport {\n BES_INSTALL_RESTART_MESSAGE,\n getOtaErrorMessage,\n shouldRequireGlassesRebootForBesFailure,\n shouldShowChangeWifiForOtaDownloadFailure,\n} from \"./services/OtaErrorMapping\"\n\n// Gallery read models: engine.gallery.onNotice payload types, the media\n// permission helper + display-name derivation host gallery UI uses, and the\n// glasses-camera DTO types (re-exported through the host @/types/asg shim).\nexport type {GalleryNotice, GalleryNoticeCode} from \"./services/asg/galleryNotices\"\nexport {MediaLibraryPermissions} from \"./utils/permissions/MediaLibraryPermissions\"\nexport {deriveGalleryDisplayName} from \"./utils/permissions/galleryDisplayName\"\nexport type {\n PhotoInfo,\n CaptureFile,\n CaptureGroup,\n GalleryResponse,\n ServerStatus,\n HealthResponse,\n GalleryEvent,\n} from \"./types/asg\"\n\n// Bluetooth SDK event types host UI subscribes to via engine facades (the\n// BluetoothSdk singleton passthrough itself is internal).\nexport type {PairFailureEvent, GlassesNotReadyEvent} from \"@mentra/bluetooth-sdk\"\n\n// Cloud connection status enum (read model; the connection store is internal).\nexport {WebSocketStatus} from \"./stores/connection\"\n\n// App-list hook layer + pure list helpers (the raw useAppStatusStore and\n// installAppStoreHooks wiring are internal).\nexport {\n DUMMY_APPLET,\n saveAppsOrder,\n getAppsOrder,\n sortAppsByPackageNamePriority,\n saveLastOpenTime,\n getLastOpenTime,\n sortAppsByLastOpenTime,\n useApps,\n useStart,\n useStop,\n useSetForeground,\n useClearForeground,\n useRefresh,\n useStopAll,\n useInstall,\n useUninstall,\n useActiveApps,\n useActiveBackgroundApps,\n useBackgroundApps,\n useActiveForegroundApp,\n useForegroundApp,\n useActiveBackgroundAppsCount,\n useLocalMiniApps,\n type StartOptions,\n type OrderMap,\n} from \"./stores/apps\"\n\n// Pure dev-miniapp launch-route decision (registration itself is internal).\nexport {\n decideDevLaunchRoute,\n type DecideDevLaunchOptions,\n type DevLaunchResult,\n type DevManifest,\n} from \"./utils/devMiniappLaunch\"\nexport {HardwareCompatibility, type CompatibilityResult} from \"./utils/hardware\"\nexport {BgTimer, throttle, debounce} from \"./utils/timers\"\n\n// Hardware types and capability profiles.\nexport {\n HardwareType,\n HardwareRequirementLevel,\n DeviceTypes,\n ControllerTypes,\n HARDWARE_CAPABILITIES,\n getModelCapabilities,\n simulatedGlasses,\n evenRealitiesG1,\n evenRealitiesG2,\n mentraLive,\n nimo,\n vuzixZ100,\n mentraDisplay,\n} from \"./types\"\nexport type {\n HardwareRequirement,\n CameraCapabilities,\n DisplayCapabilities,\n MicrophoneCapabilities,\n SpeakerCapabilities,\n IMUCapabilities,\n ButtonCapabilities,\n LightCapabilities,\n PowerCapabilities,\n Capabilities,\n AppletType,\n AppPermissionType,\n AppletPermission,\n AppletInterface,\n ClientApp,\n} from \"./types\"\n"]}
|
|
@@ -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
|
import { type DisplayProfile, type WrapOptions, type BreakMode } from "../utils/display";
|
|
16
16
|
/**
|
|
@@ -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
|
import { createDisplayToolkit, G1_PROFILE, G2_PROFILE, Z100_PROFILE, NEX_PROFILE, ColumnComposer, } from "../utils/display";
|
|
16
16
|
import { ISLAND_SETTINGS_KEYS } from "../runtime/config";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DisplayProcessor.js","sourceRoot":"","sources":["../../src/services/DisplayProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DisplayProcessor\n *\n * Processes display events with pixel-accurate text wrapping using the same\n * display-utils library as the cloud. This ensures the mobile preview matches\n * exactly what is shown on the glasses.\n *\n * Key responsibilities:\n * 1. Intercept display events before sending to native SGC\n * 2. Wrap text using the correct device profile (G1, etc.)\n * 3. Ensure GlassesDisplayMirror shows exactly what glasses will show\n *\n * @see cloud/issues/026-mobile-display-processor for design docs\n */\n\nimport {\n createDisplayToolkit,\n G1_PROFILE,\n G2_PROFILE,\n Z100_PROFILE,\n NEX_PROFILE,\n TextMeasurer,\n TextWrapper,\n ColumnComposer,\n type DisplayProfile,\n type WrapOptions,\n type BreakMode,\n} from \"../utils/display\"\n\nimport {ISLAND_SETTINGS_KEYS} from \"../runtime/config\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore} from \"../stores/settings\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Supported device models for display processing\n */\nexport type DeviceModel = \"g1\" | \"g2\" | \"z100\" | \"nex\" | \"mach1\" | \"mentra-live\" | \"simulated\" | \"unknown\"\n\n/**\n * Display event types that we process\n */\nexport type DisplayLayoutType =\n | \"text_wall\"\n | \"text_line\"\n | \"text_rows\"\n | \"reference_card\"\n | \"double_text_wall\"\n | \"bitmap_view\"\n\n/**\n * Raw display event from the cloud/WebSocket\n */\nexport interface DisplayEvent {\n view: \"main\" | \"dashboard\"\n layoutType?: DisplayLayoutType\n layout?: {\n layoutType: DisplayLayoutType\n text?: string | string[] // string for text_wall/text_line, string[] for text_rows\n title?: string\n topText?: string\n bottomText?: string\n breakMode?: BreakMode\n data?: string // For bitmap_view\n x?: number // bitmap_view container position/size (forwarded to native, used by G2)\n y?: number\n width?: number\n height?: number\n [key: string]: unknown\n }\n text?: string | string[]\n title?: string\n topText?: string\n bottomText?: string\n breakMode?: BreakMode\n [key: string]: unknown\n}\n\n/**\n * Processed display event with guaranteed wrapped text\n */\nexport interface ProcessedDisplayEvent extends DisplayEvent {\n /** Marks this event as processed */\n _processed: true\n /** The device profile used for processing */\n _profile: string\n /** Pre-split lines for text_wall/text_line (for easy rendering) */\n _lines?: string[]\n /** Original layout type before processing (e.g., double_text_wall -> text_wall) */\n _originalLayoutType?: DisplayLayoutType\n /** Column composition metadata for double_text_wall */\n _composedColumns?: {\n leftLines: string[]\n rightLines: string[]\n config: {\n leftColumnWidthPx: number\n rightColumnStartPx: number\n rightColumnWidthPx: number\n maxLines: number\n leftMarginSpaces?: number\n }\n }\n}\n\n/**\n * Options for the DisplayProcessor\n */\nexport interface DisplayProcessorOptions {\n /** Default break mode for text wrapping */\n breakMode?: BreakMode\n /** Whether to log processing details */\n debug?: boolean\n}\n\n// =============================================================================\n// Placeholder Replacement\n// =============================================================================\n\n/**\n * Placeholder values that can be replaced in display text.\n * These match the placeholders used in CoreManager.kt/CoreManager.swift\n */\ninterface PlaceholderValues {\n /** Current time in 12-hour format (e.g., \"2:30 PM\") */\n TIME12: string\n /** Current time in 24-hour format (e.g., \"14:30\") */\n TIME24: string\n /** Current date (e.g., \"1/22\") */\n DATE: string\n /** Glasses battery level (e.g., \"85%\" or \"\" if unknown) */\n GBATT: string\n /** Connection status */\n CONNECTION_STATUS: string\n}\n\n/**\n * Get current placeholder values from device state\n */\nfunction getPlaceholderValues(): PlaceholderValues {\n const now = new Date()\n\n // Format time in 12-hour format\n const hours12 = now.getHours() % 12 || 12\n const minutes = now.getMinutes().toString().padStart(2, \"0\")\n const ampm = now.getHours() >= 12 ? \"PM\" : \"AM\"\n const TIME12 = `${hours12}:${minutes} ${ampm}`\n\n // Format time in 24-hour format\n const hours24 = now.getHours().toString().padStart(2, \"0\")\n const TIME24 = `${hours24}:${minutes}`\n\n // Format date\n const month = now.getMonth() + 1\n const day = now.getDate()\n const DATE = `${month}/${day}`\n\n // Battery + connection read from the engine glasses store directly (was a host\n // glassesStatus hook).\n const batteryLevel = useGlassesStore.getState().batteryLevel ?? -1\n const GBATT = batteryLevel === -1 ? \"\" : `${batteryLevel}%`\n\n // Connection status\n const connected = isGlassesConnected(useGlassesStore.getState().connection)\n const CONNECTION_STATUS = connected ? \"Connected\" : \"\"\n\n return {TIME12, TIME24, DATE, GBATT, CONNECTION_STATUS}\n}\n\n/**\n * Replace placeholders in text with actual values.\n * Placeholders are in format $NAME$ (e.g., $GBATT$, $TIME12$)\n *\n * @param text - Text containing placeholders\n * @returns Text with placeholders replaced\n */\nfunction replacePlaceholders(text: string): string {\n if (!text || !text.includes(\"$\")) {\n return text\n }\n\n const values = getPlaceholderValues()\n\n return text\n .replace(/\\$TIME12\\$/g, values.TIME12)\n .replace(/\\$TIME24\\$/g, values.TIME24)\n .replace(/\\$DATE\\$/g, values.DATE)\n .replace(/\\$GBATT\\$/g, values.GBATT)\n .replace(/\\$CONNECTION_STATUS\\$/g, values.CONNECTION_STATUS)\n .replace(/\\$no_datetime\\$/g, `${values.DATE}, ${values.TIME12}`)\n}\n\nfunction isBreakMode(value: unknown): value is BreakMode {\n return value === \"character\" || value === \"character-no-hyphen\" || value === \"word\" || value === \"strict-word\"\n}\n\n// =============================================================================\n// Device Profile Mapping\n// =============================================================================\n\n/**\n * Map device model names to display profiles\n */\nconst DEVICE_PROFILES: Record<DeviceModel, DisplayProfile> = {\n \"g1\": G1_PROFILE,\n \"g2\": G2_PROFILE,\n \"z100\": Z100_PROFILE,\n \"nex\": NEX_PROFILE,\n \"mach1\": Z100_PROFILE, // Mach1 uses same hardware as Vuzix Z100\n \"mentra-live\": G1_PROFILE, // Mentra Live has no display, uses G1 as fallback\n \"simulated\": G1_PROFILE, // Simulated uses G1 profile\n \"unknown\": G1_PROFILE, // Default to G1\n}\n\n/**\n * Normalize various model name strings to our DeviceModel type\n */\nfunction normalizeModelName(modelName: string | null | undefined): DeviceModel {\n if (!modelName) return \"unknown\"\n\n const lower = modelName.toLowerCase()\n\n if (lower.includes(\"g2\") || lower.includes(\"even realities g2\")) {\n return \"g2\"\n }\n if (lower.includes(\"g1\") || lower.includes(\"even realities\")) {\n return \"g1\"\n }\n if (lower.includes(\"z100\") || lower.includes(\"vuzix\")) {\n return \"z100\"\n }\n if (lower.includes(\"nex\") || lower.includes(\"mentra display\")) {\n return \"nex\"\n }\n if (lower.includes(\"mach1\") || lower.includes(\"mach 1\")) {\n return \"mach1\"\n }\n if (lower.includes(\"mentra live\") || lower.includes(\"mentra-live\")) {\n return \"mentra-live\"\n }\n if (lower.includes(\"simulated\") || lower.includes(\"simulator\")) {\n return \"simulated\"\n }\n\n return \"unknown\"\n}\n\n// =============================================================================\n// DisplayProcessor Class\n// =============================================================================\n\n/**\n * Processes display events with pixel-accurate text wrapping.\n *\n * Usage:\n * ```typescript\n * const processor = DisplayProcessor.getInstance()\n *\n * // When glasses connect\n * processor.setDeviceModel(\"Even Realities G1\")\n *\n * // Process display events\n * const processed = processor.processDisplayEvent(rawEvent)\n * ```\n */\nexport class DisplayProcessor {\n private static instance: DisplayProcessor | null = null\n\n private measurer: TextMeasurer\n private wrapper: TextWrapper\n private composer: ColumnComposer\n private profile: DisplayProfile\n private deviceModel: DeviceModel = \"unknown\"\n private options: DisplayProcessorOptions\n\n private runtimeAttached = false\n private unsubscribeGlassesStatus: (() => void) | null = null\n\n private constructor(options: DisplayProcessorOptions = {}) {\n this.options = {\n breakMode: \"character-no-hyphen\",\n debug: false,\n ...options,\n }\n\n // Initialize with default G1 profile\n const engine = createDisplayToolkit(G1_PROFILE, {\n breakMode: this.options.breakMode,\n })\n\n this.measurer = engine.measurer\n this.wrapper = engine.wrapper\n this.composer = new ColumnComposer(engine.profile, this.options.breakMode)\n this.profile = engine.profile\n\n // Engine stores may not be hydrated yet at module-load time; attachToRuntime()\n // is called again by the host after app services start.\n this.attachToRuntime()\n }\n\n /**\n * Read the current default wearable and subscribe to engine glasses-status changes.\n * Idempotent — safe to call again after app services start.\n */\n public attachToRuntime(): void {\n if (this.runtimeAttached) {\n return\n }\n\n // Seed the device profile from the saved default wearable, read off the engine\n // settings store directly (was a host settings hook).\n const defaultWearable = useSettingsStore.getState().getSetting(ISLAND_SETTINGS_KEYS.defaultWearable) as\n | string\n | undefined\n if (defaultWearable) {\n this.setDeviceModel(defaultWearable)\n console.log(`DISPLAY_PROCESSOR: Initialized DisplayProcessor with default wearable: ${defaultWearable}`)\n }\n\n // Track device-model changes off the engine glasses store directly (was a host\n // subscribeGlassesStatus hook).\n this.unsubscribeGlassesStatus = useGlassesStore.subscribe(\n (s) => s.deviceModel,\n (deviceModel) => {\n if (deviceModel) this.setDeviceModel(String(deviceModel))\n },\n )\n\n this.runtimeAttached = true\n }\n\n /** Detach runtime subscriptions installed by attachToRuntime(). */\n public detachFromRuntime(): void {\n this.unsubscribeGlassesStatus?.()\n this.unsubscribeGlassesStatus = null\n this.runtimeAttached = false\n }\n\n /**\n * Get the singleton instance\n */\n public static getInstance(options?: DisplayProcessorOptions): DisplayProcessor {\n if (!DisplayProcessor.instance) {\n DisplayProcessor.instance = new DisplayProcessor(options)\n }\n return DisplayProcessor.instance\n }\n\n /**\n * Reset the singleton (useful for testing)\n */\n public static resetInstance(): void {\n DisplayProcessor.instance?.detachFromRuntime()\n DisplayProcessor.instance = null\n }\n\n // ===========================================================================\n // Device Profile Management\n // ===========================================================================\n\n /**\n * Set the device model and update the display profile accordingly.\n * Call this when glasses connect.\n *\n * @param modelName - The model name from the connected glasses (e.g., \"Even Realities G1\")\n */\n public setDeviceModel(modelName: string | null | undefined): void {\n const normalizedModel = normalizeModelName(modelName)\n\n if (normalizedModel === this.deviceModel) {\n return // No change needed\n }\n\n this.deviceModel = normalizedModel\n const newProfile = DEVICE_PROFILES[normalizedModel]\n\n if (newProfile !== this.profile) {\n this.updateProfile(newProfile)\n }\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Device model set to: ${normalizedModel} (from: ${modelName})`)\n }\n }\n\n /**\n * Update the display profile and recreate engine\n */\n private updateProfile(newProfile: DisplayProfile): void {\n const engine = createDisplayToolkit(newProfile, {\n breakMode: this.options.breakMode,\n })\n\n this.measurer = engine.measurer\n this.wrapper = engine.wrapper\n this.composer = new ColumnComposer(newProfile, this.options.breakMode)\n this.profile = engine.profile\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Profile updated to: ${newProfile.id}`)\n }\n }\n\n /**\n * Get the current device model\n */\n public getDeviceModel(): DeviceModel {\n return this.deviceModel\n }\n\n /**\n * Get the current display profile\n */\n public getProfile(): DisplayProfile {\n return this.profile\n }\n\n // ===========================================================================\n // Display Event Processing\n // ===========================================================================\n\n /**\n * Process a display event, wrapping text as needed.\n *\n * @param event - Raw display event from WebSocket\n * @returns Processed event with wrapped text\n */\n public processDisplayEvent(event: DisplayEvent): ProcessedDisplayEvent {\n // Already processed? Return as-is\n if ((event as ProcessedDisplayEvent)._processed) {\n return event as ProcessedDisplayEvent\n }\n\n // Get layout type from either root or nested layout object\n const layoutType = event.layoutType || event.layout?.layoutType\n const layout = event.layout || event\n\n if (!layoutType) {\n // No layout type - pass through\n return {\n ...event,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n\n switch (layoutType) {\n case \"text_wall\":\n case \"text_line\":\n return this.processTextWall(event, layout)\n\n case \"text_rows\":\n return this.processTextRows(event, layout)\n\n case \"reference_card\":\n return this.processReferenceCard(event, layout)\n\n case \"double_text_wall\":\n return this.processDoubleTextWall(event, layout)\n\n case \"bitmap_view\":\n // Bitmap views don't need text processing\n return {\n ...event,\n _processed: true,\n _profile: this.profile.id,\n }\n\n default:\n // Unknown layout type - pass through\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Unknown layout type: ${layoutType}`)\n }\n return {\n ...event,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n }\n\n /**\n * Process text_wall or text_line layout\n */\n private processTextWall(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n // text_wall/text_line always have string text, not string[]\n const rawText = layout.text\n const text = typeof rawText === \"string\" ? rawText : \"\"\n\n // Replace placeholders BEFORE wrapping (so we measure actual content)\n const textWithPlaceholders = replacePlaceholders(text)\n const breakMode = this.getEventBreakMode(event, layout)\n\n // Wrap the text\n const lines = this.wrapText(textWithPlaceholders, breakMode ? {breakMode} : undefined)\n const wrappedText = lines.join(\"\\n\")\n\n // Update both root and nested layout if present\n const processedLayout = event.layout\n ? {\n ...event.layout,\n text: wrappedText,\n }\n : undefined\n\n return {\n ...event,\n // Store original text with placeholders for debugging\n _originalText: text,\n text: wrappedText,\n layout: processedLayout,\n _processed: true,\n _profile: this.profile.id,\n _lines: lines,\n }\n }\n\n /**\n * Process text_rows layout\n */\n private processTextRows(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n const textField = layout.text\n const rows: string[] = Array.isArray(textField) ? textField : []\n\n // Replace placeholders and wrap each row\n const breakMode = this.getEventBreakMode(event, layout)\n const wrappedRows = rows.map((row: string) => {\n const rowWithPlaceholders = replacePlaceholders(row)\n const lines = this.wrapText(rowWithPlaceholders, breakMode ? {breakMode} : undefined)\n return lines.join(\"\\n\")\n })\n\n const processedLayout = event.layout\n ? {\n ...event.layout,\n text: wrappedRows as string | string[],\n }\n : undefined\n\n return {\n ...event,\n text: wrappedRows as string | string[],\n layout: processedLayout,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n\n /**\n * Process reference_card layout\n */\n private processReferenceCard(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n const title = layout.title || \"\"\n // reference_card text is always string, not string[]\n const rawText = layout.text\n const text = typeof rawText === \"string\" ? rawText : \"\"\n\n // Replace placeholders BEFORE wrapping\n const titleWithPlaceholders = replacePlaceholders(title)\n const textWithPlaceholders = replacePlaceholders(text)\n const breakMode = this.getEventBreakMode(event, layout)\n\n // Wrap title and text separately\n // Title typically gets 1 line, text gets remaining lines\n const wrappedTitle = this.wrapText(titleWithPlaceholders, {maxLines: 1, ...(breakMode ? {breakMode} : {})})\n const wrappedText = this.wrapText(textWithPlaceholders, {\n maxLines: this.profile.maxLines - 1,\n ...(breakMode ? {breakMode} : {}),\n })\n\n const processedLayout = event.layout\n ? {\n ...event.layout,\n title: wrappedTitle.join(\"\\n\"),\n text: wrappedText.join(\"\\n\"),\n }\n : undefined\n\n return {\n ...event,\n title: wrappedTitle.join(\"\\n\"),\n text: wrappedText.join(\"\\n\"),\n layout: processedLayout,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n\n /**\n * Process double_text_wall layout\n *\n * Uses ColumnComposer to create a fully composed string with both columns\n * merged line-by-line with pixel-precise space alignment. This is the single\n * source of truth for double_text_wall composition, replacing duplicate\n * implementations in native iOS (G1Text.swift) and Android (G1Text.kt).\n *\n * The composed text is sent to native as a regular text_wall - native just\n * chunks and sends it without any re-wrapping or column composition.\n */\n private processDoubleTextWall(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n const leftText = layout.topText || \"\"\n const rightText = layout.bottomText || \"\"\n\n // Replace placeholders BEFORE composition (so we measure actual content)\n const leftTextWithPlaceholders = replacePlaceholders(leftText)\n const rightTextWithPlaceholders = replacePlaceholders(rightText)\n const breakMode = this.getEventBreakMode(event, layout)\n const composer =\n breakMode && breakMode !== this.options.breakMode ? new ColumnComposer(this.profile, breakMode) : this.composer\n\n // Use ColumnComposer for pixel-precise column composition\n const result = composer.composeDoubleTextWall(leftTextWithPlaceholders, rightTextWithPlaceholders)\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] double_text_wall composed:`)\n console.log(` Left lines: ${result.leftLines.length}`)\n console.log(` Right lines: ${result.rightLines.length}`)\n console.log(` Config: ${JSON.stringify(result.config)}`)\n }\n\n // The composed text is a single string with both columns merged\n // Native will receive this as a text_wall and just chunk & send it\n const processedLayout = event.layout\n ? {\n ...event.layout,\n // Keep original topText/bottomText for reference but add composed text\n topText: leftTextWithPlaceholders,\n bottomText: rightTextWithPlaceholders,\n // The composed text is what native should actually display\n _composedText: result.composedText,\n }\n : undefined\n\n return {\n ...event,\n // Override the layout type to text_wall since we've pre-composed the columns\n // This tells native to use sendTextWall instead of sendDoubleTextWall\n layoutType: \"text_wall\" as DisplayLayoutType,\n text: result.composedText,\n // Keep original values for debugging/preview (with placeholders replaced)\n topText: leftTextWithPlaceholders,\n bottomText: rightTextWithPlaceholders,\n // Store original values with placeholders for debugging\n _originalTopText: leftText,\n _originalBottomText: rightText,\n layout: processedLayout\n ? {\n ...processedLayout,\n layoutType: \"text_wall\" as DisplayLayoutType,\n text: result.composedText,\n }\n : undefined,\n _processed: true,\n _profile: this.profile.id,\n _originalLayoutType: \"double_text_wall\",\n _composedColumns: {\n leftLines: result.leftLines,\n rightLines: result.rightLines,\n config: result.config,\n },\n }\n }\n\n // ===========================================================================\n // Text Wrapping Utilities\n // ===========================================================================\n\n /**\n * Wrap text using the current profile\n *\n * @param text - Text to wrap\n * @param options - Optional override options\n * @returns Array of wrapped lines\n */\n public wrapText(text: string, options?: WrapOptions): string[] {\n if (!text) return [\"\"]\n\n const result = this.wrapper.wrap(text, options)\n return result.lines\n }\n\n private getEventBreakMode(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): BreakMode | undefined {\n const breakMode = layout.breakMode ?? event.breakMode\n return isBreakMode(breakMode) ? breakMode : undefined\n }\n\n /**\n * Measure the pixel width of text\n *\n * @param text - Text to measure\n * @returns Width in pixels\n */\n public measureText(text: string): number {\n return this.measurer.measureText(text)\n }\n\n /**\n * Check if text fits on a single line\n *\n * @param text - Text to check\n * @returns true if text fits without wrapping\n */\n public fitsOnSingleLine(text: string): boolean {\n return this.measurer.measureText(text) <= this.profile.displayWidthPx\n }\n\n /**\n * Get the display width in pixels\n */\n public getDisplayWidth(): number {\n return this.profile.displayWidthPx\n }\n\n /**\n * Get the maximum number of lines\n */\n public getMaxLines(): number {\n return this.profile.maxLines\n }\n\n /**\n * Get detailed text measurement\n */\n public measureTextDetailed(text: string) {\n return this.measurer.measureTextDetailed(text)\n }\n\n // ===========================================================================\n // Break Mode Control\n // ===========================================================================\n\n /**\n * Set the break mode for text wrapping\n *\n * @param breakMode - 'character' | 'word' | 'strict-word'\n */\n public setBreakMode(breakMode: BreakMode): void {\n if (this.options.breakMode === breakMode) return\n\n this.options.breakMode = breakMode\n this.updateProfile(this.profile) // Recreate wrapper with new break mode\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Break mode set to: ${breakMode}`)\n }\n }\n\n /**\n * Get the current break mode\n */\n public getBreakMode(): BreakMode {\n return this.options.breakMode || \"character\"\n }\n}\n\nexport const displayProcessor = DisplayProcessor.getInstance()\nexport default displayProcessor\n"]}
|
|
1
|
+
{"version":3,"file":"DisplayProcessor.js","sourceRoot":"","sources":["../../src/services/DisplayProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DisplayProcessor\n *\n * Processes display events with pixel-accurate text wrapping using the same\n * Engine display utilities. This ensures the mobile preview matches exactly\n * what is shown on the glasses.\n *\n * Key responsibilities:\n * 1. Intercept display events before sending to native SGC\n * 2. Wrap text using the correct device profile (G1, etc.)\n * 3. Ensure GlassesDisplayMirror shows exactly what glasses will show\n *\n * @see notes/miniapp-display-api-redesign.md for the current display design\n */\n\nimport {\n createDisplayToolkit,\n G1_PROFILE,\n G2_PROFILE,\n Z100_PROFILE,\n NEX_PROFILE,\n TextMeasurer,\n TextWrapper,\n ColumnComposer,\n type DisplayProfile,\n type WrapOptions,\n type BreakMode,\n} from \"../utils/display\"\n\nimport {ISLAND_SETTINGS_KEYS} from \"../runtime/config\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore} from \"../stores/settings\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Supported device models for display processing\n */\nexport type DeviceModel = \"g1\" | \"g2\" | \"z100\" | \"nex\" | \"mach1\" | \"mentra-live\" | \"simulated\" | \"unknown\"\n\n/**\n * Display event types that we process\n */\nexport type DisplayLayoutType =\n | \"text_wall\"\n | \"text_line\"\n | \"text_rows\"\n | \"reference_card\"\n | \"double_text_wall\"\n | \"bitmap_view\"\n\n/**\n * Raw display event from the cloud/WebSocket\n */\nexport interface DisplayEvent {\n view: \"main\" | \"dashboard\"\n layoutType?: DisplayLayoutType\n layout?: {\n layoutType: DisplayLayoutType\n text?: string | string[] // string for text_wall/text_line, string[] for text_rows\n title?: string\n topText?: string\n bottomText?: string\n breakMode?: BreakMode\n data?: string // For bitmap_view\n x?: number // bitmap_view container position/size (forwarded to native, used by G2)\n y?: number\n width?: number\n height?: number\n [key: string]: unknown\n }\n text?: string | string[]\n title?: string\n topText?: string\n bottomText?: string\n breakMode?: BreakMode\n [key: string]: unknown\n}\n\n/**\n * Processed display event with guaranteed wrapped text\n */\nexport interface ProcessedDisplayEvent extends DisplayEvent {\n /** Marks this event as processed */\n _processed: true\n /** The device profile used for processing */\n _profile: string\n /** Pre-split lines for text_wall/text_line (for easy rendering) */\n _lines?: string[]\n /** Original layout type before processing (e.g., double_text_wall -> text_wall) */\n _originalLayoutType?: DisplayLayoutType\n /** Column composition metadata for double_text_wall */\n _composedColumns?: {\n leftLines: string[]\n rightLines: string[]\n config: {\n leftColumnWidthPx: number\n rightColumnStartPx: number\n rightColumnWidthPx: number\n maxLines: number\n leftMarginSpaces?: number\n }\n }\n}\n\n/**\n * Options for the DisplayProcessor\n */\nexport interface DisplayProcessorOptions {\n /** Default break mode for text wrapping */\n breakMode?: BreakMode\n /** Whether to log processing details */\n debug?: boolean\n}\n\n// =============================================================================\n// Placeholder Replacement\n// =============================================================================\n\n/**\n * Placeholder values that can be replaced in display text.\n * These match the placeholders used in CoreManager.kt/CoreManager.swift\n */\ninterface PlaceholderValues {\n /** Current time in 12-hour format (e.g., \"2:30 PM\") */\n TIME12: string\n /** Current time in 24-hour format (e.g., \"14:30\") */\n TIME24: string\n /** Current date (e.g., \"1/22\") */\n DATE: string\n /** Glasses battery level (e.g., \"85%\" or \"\" if unknown) */\n GBATT: string\n /** Connection status */\n CONNECTION_STATUS: string\n}\n\n/**\n * Get current placeholder values from device state\n */\nfunction getPlaceholderValues(): PlaceholderValues {\n const now = new Date()\n\n // Format time in 12-hour format\n const hours12 = now.getHours() % 12 || 12\n const minutes = now.getMinutes().toString().padStart(2, \"0\")\n const ampm = now.getHours() >= 12 ? \"PM\" : \"AM\"\n const TIME12 = `${hours12}:${minutes} ${ampm}`\n\n // Format time in 24-hour format\n const hours24 = now.getHours().toString().padStart(2, \"0\")\n const TIME24 = `${hours24}:${minutes}`\n\n // Format date\n const month = now.getMonth() + 1\n const day = now.getDate()\n const DATE = `${month}/${day}`\n\n // Battery + connection read from the engine glasses store directly (was a host\n // glassesStatus hook).\n const batteryLevel = useGlassesStore.getState().batteryLevel ?? -1\n const GBATT = batteryLevel === -1 ? \"\" : `${batteryLevel}%`\n\n // Connection status\n const connected = isGlassesConnected(useGlassesStore.getState().connection)\n const CONNECTION_STATUS = connected ? \"Connected\" : \"\"\n\n return {TIME12, TIME24, DATE, GBATT, CONNECTION_STATUS}\n}\n\n/**\n * Replace placeholders in text with actual values.\n * Placeholders are in format $NAME$ (e.g., $GBATT$, $TIME12$)\n *\n * @param text - Text containing placeholders\n * @returns Text with placeholders replaced\n */\nfunction replacePlaceholders(text: string): string {\n if (!text || !text.includes(\"$\")) {\n return text\n }\n\n const values = getPlaceholderValues()\n\n return text\n .replace(/\\$TIME12\\$/g, values.TIME12)\n .replace(/\\$TIME24\\$/g, values.TIME24)\n .replace(/\\$DATE\\$/g, values.DATE)\n .replace(/\\$GBATT\\$/g, values.GBATT)\n .replace(/\\$CONNECTION_STATUS\\$/g, values.CONNECTION_STATUS)\n .replace(/\\$no_datetime\\$/g, `${values.DATE}, ${values.TIME12}`)\n}\n\nfunction isBreakMode(value: unknown): value is BreakMode {\n return value === \"character\" || value === \"character-no-hyphen\" || value === \"word\" || value === \"strict-word\"\n}\n\n// =============================================================================\n// Device Profile Mapping\n// =============================================================================\n\n/**\n * Map device model names to display profiles\n */\nconst DEVICE_PROFILES: Record<DeviceModel, DisplayProfile> = {\n \"g1\": G1_PROFILE,\n \"g2\": G2_PROFILE,\n \"z100\": Z100_PROFILE,\n \"nex\": NEX_PROFILE,\n \"mach1\": Z100_PROFILE, // Mach1 uses same hardware as Vuzix Z100\n \"mentra-live\": G1_PROFILE, // Mentra Live has no display, uses G1 as fallback\n \"simulated\": G1_PROFILE, // Simulated uses G1 profile\n \"unknown\": G1_PROFILE, // Default to G1\n}\n\n/**\n * Normalize various model name strings to our DeviceModel type\n */\nfunction normalizeModelName(modelName: string | null | undefined): DeviceModel {\n if (!modelName) return \"unknown\"\n\n const lower = modelName.toLowerCase()\n\n if (lower.includes(\"g2\") || lower.includes(\"even realities g2\")) {\n return \"g2\"\n }\n if (lower.includes(\"g1\") || lower.includes(\"even realities\")) {\n return \"g1\"\n }\n if (lower.includes(\"z100\") || lower.includes(\"vuzix\")) {\n return \"z100\"\n }\n if (lower.includes(\"nex\") || lower.includes(\"mentra display\")) {\n return \"nex\"\n }\n if (lower.includes(\"mach1\") || lower.includes(\"mach 1\")) {\n return \"mach1\"\n }\n if (lower.includes(\"mentra live\") || lower.includes(\"mentra-live\")) {\n return \"mentra-live\"\n }\n if (lower.includes(\"simulated\") || lower.includes(\"simulator\")) {\n return \"simulated\"\n }\n\n return \"unknown\"\n}\n\n// =============================================================================\n// DisplayProcessor Class\n// =============================================================================\n\n/**\n * Processes display events with pixel-accurate text wrapping.\n *\n * Usage:\n * ```typescript\n * const processor = DisplayProcessor.getInstance()\n *\n * // When glasses connect\n * processor.setDeviceModel(\"Even Realities G1\")\n *\n * // Process display events\n * const processed = processor.processDisplayEvent(rawEvent)\n * ```\n */\nexport class DisplayProcessor {\n private static instance: DisplayProcessor | null = null\n\n private measurer: TextMeasurer\n private wrapper: TextWrapper\n private composer: ColumnComposer\n private profile: DisplayProfile\n private deviceModel: DeviceModel = \"unknown\"\n private options: DisplayProcessorOptions\n\n private runtimeAttached = false\n private unsubscribeGlassesStatus: (() => void) | null = null\n\n private constructor(options: DisplayProcessorOptions = {}) {\n this.options = {\n breakMode: \"character-no-hyphen\",\n debug: false,\n ...options,\n }\n\n // Initialize with default G1 profile\n const engine = createDisplayToolkit(G1_PROFILE, {\n breakMode: this.options.breakMode,\n })\n\n this.measurer = engine.measurer\n this.wrapper = engine.wrapper\n this.composer = new ColumnComposer(engine.profile, this.options.breakMode)\n this.profile = engine.profile\n\n // Engine stores may not be hydrated yet at module-load time; attachToRuntime()\n // is called again by the host after app services start.\n this.attachToRuntime()\n }\n\n /**\n * Read the current default wearable and subscribe to engine glasses-status changes.\n * Idempotent — safe to call again after app services start.\n */\n public attachToRuntime(): void {\n if (this.runtimeAttached) {\n return\n }\n\n // Seed the device profile from the saved default wearable, read off the engine\n // settings store directly (was a host settings hook).\n const defaultWearable = useSettingsStore.getState().getSetting(ISLAND_SETTINGS_KEYS.defaultWearable) as\n | string\n | undefined\n if (defaultWearable) {\n this.setDeviceModel(defaultWearable)\n console.log(`DISPLAY_PROCESSOR: Initialized DisplayProcessor with default wearable: ${defaultWearable}`)\n }\n\n // Track device-model changes off the engine glasses store directly (was a host\n // subscribeGlassesStatus hook).\n this.unsubscribeGlassesStatus = useGlassesStore.subscribe(\n (s) => s.deviceModel,\n (deviceModel) => {\n if (deviceModel) this.setDeviceModel(String(deviceModel))\n },\n )\n\n this.runtimeAttached = true\n }\n\n /** Detach runtime subscriptions installed by attachToRuntime(). */\n public detachFromRuntime(): void {\n this.unsubscribeGlassesStatus?.()\n this.unsubscribeGlassesStatus = null\n this.runtimeAttached = false\n }\n\n /**\n * Get the singleton instance\n */\n public static getInstance(options?: DisplayProcessorOptions): DisplayProcessor {\n if (!DisplayProcessor.instance) {\n DisplayProcessor.instance = new DisplayProcessor(options)\n }\n return DisplayProcessor.instance\n }\n\n /**\n * Reset the singleton (useful for testing)\n */\n public static resetInstance(): void {\n DisplayProcessor.instance?.detachFromRuntime()\n DisplayProcessor.instance = null\n }\n\n // ===========================================================================\n // Device Profile Management\n // ===========================================================================\n\n /**\n * Set the device model and update the display profile accordingly.\n * Call this when glasses connect.\n *\n * @param modelName - The model name from the connected glasses (e.g., \"Even Realities G1\")\n */\n public setDeviceModel(modelName: string | null | undefined): void {\n const normalizedModel = normalizeModelName(modelName)\n\n if (normalizedModel === this.deviceModel) {\n return // No change needed\n }\n\n this.deviceModel = normalizedModel\n const newProfile = DEVICE_PROFILES[normalizedModel]\n\n if (newProfile !== this.profile) {\n this.updateProfile(newProfile)\n }\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Device model set to: ${normalizedModel} (from: ${modelName})`)\n }\n }\n\n /**\n * Update the display profile and recreate engine\n */\n private updateProfile(newProfile: DisplayProfile): void {\n const engine = createDisplayToolkit(newProfile, {\n breakMode: this.options.breakMode,\n })\n\n this.measurer = engine.measurer\n this.wrapper = engine.wrapper\n this.composer = new ColumnComposer(newProfile, this.options.breakMode)\n this.profile = engine.profile\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Profile updated to: ${newProfile.id}`)\n }\n }\n\n /**\n * Get the current device model\n */\n public getDeviceModel(): DeviceModel {\n return this.deviceModel\n }\n\n /**\n * Get the current display profile\n */\n public getProfile(): DisplayProfile {\n return this.profile\n }\n\n // ===========================================================================\n // Display Event Processing\n // ===========================================================================\n\n /**\n * Process a display event, wrapping text as needed.\n *\n * @param event - Raw display event from WebSocket\n * @returns Processed event with wrapped text\n */\n public processDisplayEvent(event: DisplayEvent): ProcessedDisplayEvent {\n // Already processed? Return as-is\n if ((event as ProcessedDisplayEvent)._processed) {\n return event as ProcessedDisplayEvent\n }\n\n // Get layout type from either root or nested layout object\n const layoutType = event.layoutType || event.layout?.layoutType\n const layout = event.layout || event\n\n if (!layoutType) {\n // No layout type - pass through\n return {\n ...event,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n\n switch (layoutType) {\n case \"text_wall\":\n case \"text_line\":\n return this.processTextWall(event, layout)\n\n case \"text_rows\":\n return this.processTextRows(event, layout)\n\n case \"reference_card\":\n return this.processReferenceCard(event, layout)\n\n case \"double_text_wall\":\n return this.processDoubleTextWall(event, layout)\n\n case \"bitmap_view\":\n // Bitmap views don't need text processing\n return {\n ...event,\n _processed: true,\n _profile: this.profile.id,\n }\n\n default:\n // Unknown layout type - pass through\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Unknown layout type: ${layoutType}`)\n }\n return {\n ...event,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n }\n\n /**\n * Process text_wall or text_line layout\n */\n private processTextWall(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n // text_wall/text_line always have string text, not string[]\n const rawText = layout.text\n const text = typeof rawText === \"string\" ? rawText : \"\"\n\n // Replace placeholders BEFORE wrapping (so we measure actual content)\n const textWithPlaceholders = replacePlaceholders(text)\n const breakMode = this.getEventBreakMode(event, layout)\n\n // Wrap the text\n const lines = this.wrapText(textWithPlaceholders, breakMode ? {breakMode} : undefined)\n const wrappedText = lines.join(\"\\n\")\n\n // Update both root and nested layout if present\n const processedLayout = event.layout\n ? {\n ...event.layout,\n text: wrappedText,\n }\n : undefined\n\n return {\n ...event,\n // Store original text with placeholders for debugging\n _originalText: text,\n text: wrappedText,\n layout: processedLayout,\n _processed: true,\n _profile: this.profile.id,\n _lines: lines,\n }\n }\n\n /**\n * Process text_rows layout\n */\n private processTextRows(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n const textField = layout.text\n const rows: string[] = Array.isArray(textField) ? textField : []\n\n // Replace placeholders and wrap each row\n const breakMode = this.getEventBreakMode(event, layout)\n const wrappedRows = rows.map((row: string) => {\n const rowWithPlaceholders = replacePlaceholders(row)\n const lines = this.wrapText(rowWithPlaceholders, breakMode ? {breakMode} : undefined)\n return lines.join(\"\\n\")\n })\n\n const processedLayout = event.layout\n ? {\n ...event.layout,\n text: wrappedRows as string | string[],\n }\n : undefined\n\n return {\n ...event,\n text: wrappedRows as string | string[],\n layout: processedLayout,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n\n /**\n * Process reference_card layout\n */\n private processReferenceCard(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n const title = layout.title || \"\"\n // reference_card text is always string, not string[]\n const rawText = layout.text\n const text = typeof rawText === \"string\" ? rawText : \"\"\n\n // Replace placeholders BEFORE wrapping\n const titleWithPlaceholders = replacePlaceholders(title)\n const textWithPlaceholders = replacePlaceholders(text)\n const breakMode = this.getEventBreakMode(event, layout)\n\n // Wrap title and text separately\n // Title typically gets 1 line, text gets remaining lines\n const wrappedTitle = this.wrapText(titleWithPlaceholders, {maxLines: 1, ...(breakMode ? {breakMode} : {})})\n const wrappedText = this.wrapText(textWithPlaceholders, {\n maxLines: this.profile.maxLines - 1,\n ...(breakMode ? {breakMode} : {}),\n })\n\n const processedLayout = event.layout\n ? {\n ...event.layout,\n title: wrappedTitle.join(\"\\n\"),\n text: wrappedText.join(\"\\n\"),\n }\n : undefined\n\n return {\n ...event,\n title: wrappedTitle.join(\"\\n\"),\n text: wrappedText.join(\"\\n\"),\n layout: processedLayout,\n _processed: true,\n _profile: this.profile.id,\n }\n }\n\n /**\n * Process double_text_wall layout\n *\n * Uses ColumnComposer to create a fully composed string with both columns\n * merged line-by-line with pixel-precise space alignment. This is the single\n * source of truth for double_text_wall composition, replacing duplicate\n * implementations in native iOS (G1Text.swift) and Android (G1Text.kt).\n *\n * The composed text is sent to native as a regular text_wall - native just\n * chunks and sends it without any re-wrapping or column composition.\n */\n private processDoubleTextWall(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): ProcessedDisplayEvent {\n const leftText = layout.topText || \"\"\n const rightText = layout.bottomText || \"\"\n\n // Replace placeholders BEFORE composition (so we measure actual content)\n const leftTextWithPlaceholders = replacePlaceholders(leftText)\n const rightTextWithPlaceholders = replacePlaceholders(rightText)\n const breakMode = this.getEventBreakMode(event, layout)\n const composer =\n breakMode && breakMode !== this.options.breakMode ? new ColumnComposer(this.profile, breakMode) : this.composer\n\n // Use ColumnComposer for pixel-precise column composition\n const result = composer.composeDoubleTextWall(leftTextWithPlaceholders, rightTextWithPlaceholders)\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] double_text_wall composed:`)\n console.log(` Left lines: ${result.leftLines.length}`)\n console.log(` Right lines: ${result.rightLines.length}`)\n console.log(` Config: ${JSON.stringify(result.config)}`)\n }\n\n // The composed text is a single string with both columns merged\n // Native will receive this as a text_wall and just chunk & send it\n const processedLayout = event.layout\n ? {\n ...event.layout,\n // Keep original topText/bottomText for reference but add composed text\n topText: leftTextWithPlaceholders,\n bottomText: rightTextWithPlaceholders,\n // The composed text is what native should actually display\n _composedText: result.composedText,\n }\n : undefined\n\n return {\n ...event,\n // Override the layout type to text_wall since we've pre-composed the columns\n // This tells native to use sendTextWall instead of sendDoubleTextWall\n layoutType: \"text_wall\" as DisplayLayoutType,\n text: result.composedText,\n // Keep original values for debugging/preview (with placeholders replaced)\n topText: leftTextWithPlaceholders,\n bottomText: rightTextWithPlaceholders,\n // Store original values with placeholders for debugging\n _originalTopText: leftText,\n _originalBottomText: rightText,\n layout: processedLayout\n ? {\n ...processedLayout,\n layoutType: \"text_wall\" as DisplayLayoutType,\n text: result.composedText,\n }\n : undefined,\n _processed: true,\n _profile: this.profile.id,\n _originalLayoutType: \"double_text_wall\",\n _composedColumns: {\n leftLines: result.leftLines,\n rightLines: result.rightLines,\n config: result.config,\n },\n }\n }\n\n // ===========================================================================\n // Text Wrapping Utilities\n // ===========================================================================\n\n /**\n * Wrap text using the current profile\n *\n * @param text - Text to wrap\n * @param options - Optional override options\n * @returns Array of wrapped lines\n */\n public wrapText(text: string, options?: WrapOptions): string[] {\n if (!text) return [\"\"]\n\n const result = this.wrapper.wrap(text, options)\n return result.lines\n }\n\n private getEventBreakMode(\n event: DisplayEvent,\n layout: DisplayEvent | NonNullable<DisplayEvent[\"layout\"]>,\n ): BreakMode | undefined {\n const breakMode = layout.breakMode ?? event.breakMode\n return isBreakMode(breakMode) ? breakMode : undefined\n }\n\n /**\n * Measure the pixel width of text\n *\n * @param text - Text to measure\n * @returns Width in pixels\n */\n public measureText(text: string): number {\n return this.measurer.measureText(text)\n }\n\n /**\n * Check if text fits on a single line\n *\n * @param text - Text to check\n * @returns true if text fits without wrapping\n */\n public fitsOnSingleLine(text: string): boolean {\n return this.measurer.measureText(text) <= this.profile.displayWidthPx\n }\n\n /**\n * Get the display width in pixels\n */\n public getDisplayWidth(): number {\n return this.profile.displayWidthPx\n }\n\n /**\n * Get the maximum number of lines\n */\n public getMaxLines(): number {\n return this.profile.maxLines\n }\n\n /**\n * Get detailed text measurement\n */\n public measureTextDetailed(text: string) {\n return this.measurer.measureTextDetailed(text)\n }\n\n // ===========================================================================\n // Break Mode Control\n // ===========================================================================\n\n /**\n * Set the break mode for text wrapping\n *\n * @param breakMode - 'character' | 'word' | 'strict-word'\n */\n public setBreakMode(breakMode: BreakMode): void {\n if (this.options.breakMode === breakMode) return\n\n this.options.breakMode = breakMode\n this.updateProfile(this.profile) // Recreate wrapper with new break mode\n\n if (this.options.debug) {\n console.log(`[DisplayProcessor] Break mode set to: ${breakMode}`)\n }\n }\n\n /**\n * Get the current break mode\n */\n public getBreakMode(): BreakMode {\n return this.options.breakMode || \"character\"\n }\n}\n\nexport const displayProcessor = DisplayProcessor.getInstance()\nexport default displayProcessor\n"]}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* LocalDisplayManager
|
|
3
3
|
*
|
|
4
4
|
* Phone-side arbiter for display requests originating from LOCAL miniapps
|
|
5
|
-
* (the @mentra/miniapp SDK).
|
|
6
|
-
*
|
|
7
|
-
* for the features that matter on the phone:
|
|
5
|
+
* (the @mentra/miniapp SDK). Preserves the retired cloud display manager's
|
|
6
|
+
* user-facing behavior for the features that matter on the phone:
|
|
8
7
|
*
|
|
9
8
|
* - boot message ("Starting <AppName>…") with a bounded window
|
|
10
9
|
* - durationMs auto-clear
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalDisplayManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalDisplayManager.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"LocalDisplayManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalDisplayManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* LocalDisplayManager
|
|
3
3
|
*
|
|
4
4
|
* Phone-side arbiter for display requests originating from LOCAL miniapps
|
|
5
|
-
* (the @mentra/miniapp SDK).
|
|
6
|
-
*
|
|
7
|
-
* for the features that matter on the phone:
|
|
5
|
+
* (the @mentra/miniapp SDK). Preserves the retired cloud display manager's
|
|
6
|
+
* user-facing behavior for the features that matter on the phone:
|
|
8
7
|
*
|
|
9
8
|
* - boot message ("Starting <AppName>…") with a bounded window
|
|
10
9
|
* - durationMs auto-clear
|