@glassly/engine 0.1.0-dev.99 → 0.2.8-dev.445

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.
Files changed (501) hide show
  1. package/README.md +28 -0
  2. package/build/engine.d.ts +32 -10
  3. package/build/engine.d.ts.map +1 -1
  4. package/build/engine.js +24 -16
  5. package/build/engine.js.map +1 -1
  6. package/build/facades/dev.d.ts +9 -0
  7. package/build/facades/dev.d.ts.map +1 -1
  8. package/build/facades/dev.js +9 -0
  9. package/build/facades/dev.js.map +1 -1
  10. package/build/facades/display.d.ts +10 -3
  11. package/build/facades/display.d.ts.map +1 -1
  12. package/build/facades/display.js +22 -8
  13. package/build/facades/display.js.map +1 -1
  14. package/build/facades/displayMirror.d.ts +11 -0
  15. package/build/facades/displayMirror.d.ts.map +1 -1
  16. package/build/facades/displayMirror.js +22 -0
  17. package/build/facades/displayMirror.js.map +1 -1
  18. package/build/facades/glasses.d.ts +31 -1
  19. package/build/facades/glasses.d.ts.map +1 -1
  20. package/build/facades/glasses.js +51 -0
  21. package/build/facades/glasses.js.map +1 -1
  22. package/build/facades/memory.d.ts +0 -6
  23. package/build/facades/memory.d.ts.map +1 -1
  24. package/build/facades/memory.js +1 -9
  25. package/build/facades/memory.js.map +1 -1
  26. package/build/facades/miniapps.d.ts +3 -1
  27. package/build/facades/miniapps.d.ts.map +1 -1
  28. package/build/facades/miniapps.js +3 -1
  29. package/build/facades/miniapps.js.map +1 -1
  30. package/build/facades/pairing.d.ts.map +1 -1
  31. package/build/facades/pairing.js +5 -4
  32. package/build/facades/pairing.js.map +1 -1
  33. package/build/facades/permissions.d.ts +2 -0
  34. package/build/facades/permissions.d.ts.map +1 -1
  35. package/build/facades/permissions.js +48 -0
  36. package/build/facades/permissions.js.map +1 -1
  37. package/build/facades/phoneNotifications.d.ts +20 -9
  38. package/build/facades/phoneNotifications.d.ts.map +1 -1
  39. package/build/facades/phoneNotifications.js +33 -26
  40. package/build/facades/phoneNotifications.js.map +1 -1
  41. package/build/facades/settings.d.ts.map +1 -1
  42. package/build/facades/settings.js +1 -2
  43. package/build/facades/settings.js.map +1 -1
  44. package/build/generated/releaseMetadata.js +4 -4
  45. package/build/generated/releaseMetadata.js.map +1 -1
  46. package/build/index.d.ts +6 -4
  47. package/build/index.d.ts.map +1 -1
  48. package/build/index.js +5 -4
  49. package/build/index.js.map +1 -1
  50. package/build/react/MentraLiveOtaFlow.js +2 -2
  51. package/build/react/MentraLiveOtaFlow.js.map +1 -1
  52. package/build/react/useMentraLiveOta.d.ts.map +1 -1
  53. package/build/react/useMentraLiveOta.js +8 -7
  54. package/build/react/useMentraLiveOta.js.map +1 -1
  55. package/build/runtime/config.d.ts +1 -1
  56. package/build/runtime/config.d.ts.map +1 -1
  57. package/build/runtime/config.js.map +1 -1
  58. package/build/services/AppRegistry.d.ts +4 -1
  59. package/build/services/AppRegistry.d.ts.map +1 -1
  60. package/build/services/AppRegistry.js +21 -1
  61. package/build/services/AppRegistry.js.map +1 -1
  62. package/build/services/BlobStore.d.ts +2 -2
  63. package/build/services/BlobStore.js +3 -3
  64. package/build/services/BlobStore.js.map +1 -1
  65. package/build/services/CloudClientService.d.ts +7 -3
  66. package/build/services/CloudClientService.d.ts.map +1 -1
  67. package/build/services/CloudClientService.js +34 -9
  68. package/build/services/CloudClientService.js.map +1 -1
  69. package/build/services/DevServerBridge.d.ts +1 -18
  70. package/build/services/DevServerBridge.d.ts.map +1 -1
  71. package/build/services/DevServerBridge.js +9 -8
  72. package/build/services/DevServerBridge.js.map +1 -1
  73. package/build/services/DeviceEventRouter.d.ts.map +1 -1
  74. package/build/services/DeviceEventRouter.js +58 -71
  75. package/build/services/DeviceEventRouter.js.map +1 -1
  76. package/build/services/DisplayDiagnostics.d.ts +5 -0
  77. package/build/services/DisplayDiagnostics.d.ts.map +1 -0
  78. package/build/services/DisplayDiagnostics.js +105 -0
  79. package/build/services/DisplayDiagnostics.js.map +1 -0
  80. package/build/services/DisplayProcessor.d.ts +6 -7
  81. package/build/services/DisplayProcessor.d.ts.map +1 -1
  82. package/build/services/DisplayProcessor.js +17 -45
  83. package/build/services/DisplayProcessor.js.map +1 -1
  84. package/build/services/GestureDotsService.d.ts +10 -4
  85. package/build/services/GestureDotsService.d.ts.map +1 -1
  86. package/build/services/GestureDotsService.js +70 -16
  87. package/build/services/GestureDotsService.js.map +1 -1
  88. package/build/services/GlassesKeyboardInput.d.ts +77 -0
  89. package/build/services/GlassesKeyboardInput.d.ts.map +1 -0
  90. package/build/services/GlassesKeyboardInput.js +261 -0
  91. package/build/services/GlassesKeyboardInput.js.map +1 -0
  92. package/build/services/GlassesSensorService.d.ts +47 -0
  93. package/build/services/GlassesSensorService.d.ts.map +1 -0
  94. package/build/services/GlassesSensorService.js +242 -0
  95. package/build/services/GlassesSensorService.js.map +1 -0
  96. package/build/services/GlassesTouchInput.d.ts +14 -0
  97. package/build/services/GlassesTouchInput.d.ts.map +1 -0
  98. package/build/services/GlassesTouchInput.js +107 -0
  99. package/build/services/GlassesTouchInput.js.map +1 -0
  100. package/build/services/HeadingService.d.ts +0 -6
  101. package/build/services/HeadingService.d.ts.map +1 -1
  102. package/build/services/HeadingService.js +0 -27
  103. package/build/services/HeadingService.js.map +1 -1
  104. package/build/services/HotspotShutdown.d.ts.map +1 -1
  105. package/build/services/HotspotShutdown.js +2 -1
  106. package/build/services/HotspotShutdown.js.map +1 -1
  107. package/build/services/JSCrashloopReportService.js +2 -2
  108. package/build/services/JSCrashloopReportService.js.map +1 -1
  109. package/build/services/JSRouter.d.ts +6 -4
  110. package/build/services/JSRouter.d.ts.map +1 -1
  111. package/build/services/JSRouter.js +15 -13
  112. package/build/services/JSRouter.js.map +1 -1
  113. package/build/services/LocalDisplayManager.d.ts +35 -7
  114. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  115. package/build/services/LocalDisplayManager.js +105 -27
  116. package/build/services/LocalDisplayManager.js.map +1 -1
  117. package/build/services/LocalMiniappDataMigration.d.ts +1 -1
  118. package/build/services/LocalMiniappDataMigration.js +1 -1
  119. package/build/services/LocalMiniappDataMigration.js.map +1 -1
  120. package/build/services/LocalMiniappRuntime.d.ts +64 -11
  121. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  122. package/build/services/LocalMiniappRuntime.js +441 -35
  123. package/build/services/LocalMiniappRuntime.js.map +1 -1
  124. package/build/services/LocalSttFallbackCoordinator.d.ts +3 -0
  125. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  126. package/build/services/LocalSttFallbackCoordinator.js +27 -8
  127. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  128. package/build/services/MemoryStore.d.ts +8 -33
  129. package/build/services/MemoryStore.d.ts.map +1 -1
  130. package/build/services/MemoryStore.js +30 -56
  131. package/build/services/MemoryStore.js.map +1 -1
  132. package/build/services/MiniappEngine.d.ts +3 -3
  133. package/build/services/MiniappEngine.js +7 -7
  134. package/build/services/MiniappEngine.js.map +1 -1
  135. package/build/services/MiniappLauncher.d.ts +8 -0
  136. package/build/services/MiniappLauncher.d.ts.map +1 -1
  137. package/build/services/MiniappLauncher.js +19 -1
  138. package/build/services/MiniappLauncher.js.map +1 -1
  139. package/build/services/MirrorService.d.ts +24 -0
  140. package/build/services/MirrorService.d.ts.map +1 -0
  141. package/build/services/MirrorService.js +132 -0
  142. package/build/services/MirrorService.js.map +1 -0
  143. package/build/services/NativeNavigationService.d.ts +2 -3
  144. package/build/services/NativeNavigationService.d.ts.map +1 -1
  145. package/build/services/NativeNavigationService.js +24 -21
  146. package/build/services/NativeNavigationService.js.map +1 -1
  147. package/build/services/NavigationHandlers.d.ts.map +1 -1
  148. package/build/services/NavigationHandlers.js +10 -5
  149. package/build/services/NavigationHandlers.js.map +1 -1
  150. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  151. package/build/services/OtaInstallCoordinator.js +24 -23
  152. package/build/services/OtaInstallCoordinator.js.map +1 -1
  153. package/build/services/PairedGlassesLatch.d.ts +7 -0
  154. package/build/services/PairedGlassesLatch.d.ts.map +1 -0
  155. package/build/services/PairedGlassesLatch.js +38 -0
  156. package/build/services/PairedGlassesLatch.js.map +1 -0
  157. package/build/services/PhoneActivity.d.ts +23 -0
  158. package/build/services/PhoneActivity.d.ts.map +1 -0
  159. package/build/services/PhoneActivity.js +111 -0
  160. package/build/services/PhoneActivity.js.map +1 -0
  161. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -1
  162. package/build/services/PhoneCameraFovCoordinator.js +4 -3
  163. package/build/services/PhoneCameraFovCoordinator.js.map +1 -1
  164. package/build/services/PhoneNotificationsSync.d.ts +40 -6
  165. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  166. package/build/services/PhoneNotificationsSync.js +160 -84
  167. package/build/services/PhoneNotificationsSync.js.map +1 -1
  168. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  169. package/build/services/PhonePhotoCoordinator.js +6 -5
  170. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  171. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  172. package/build/services/PhoneStreamCoordinator.js +8 -7
  173. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  174. package/build/services/STTModelManager.d.ts +3 -0
  175. package/build/services/STTModelManager.d.ts.map +1 -1
  176. package/build/services/STTModelManager.js +15 -1
  177. package/build/services/STTModelManager.js.map +1 -1
  178. package/build/services/SceneRenderer.d.ts +43 -2
  179. package/build/services/SceneRenderer.d.ts.map +1 -1
  180. package/build/services/SceneRenderer.js +123 -8
  181. package/build/services/SceneRenderer.js.map +1 -1
  182. package/build/services/StreamLifecycleController.d.ts.map +1 -1
  183. package/build/services/StreamLifecycleController.js +6 -14
  184. package/build/services/StreamLifecycleController.js.map +1 -1
  185. package/build/services/TTSModelManager.js +1 -1
  186. package/build/services/TTSModelManager.js.map +1 -1
  187. package/build/services/UIRouter.d.ts +2 -2
  188. package/build/services/UIRouter.js +5 -5
  189. package/build/services/UIRouter.js.map +1 -1
  190. package/build/services/asg/galleryPathMigration.js +1 -1
  191. package/build/services/asg/galleryPathMigration.js.map +1 -1
  192. package/build/services/asg/gallerySyncService.js +2 -2
  193. package/build/services/asg/gallerySyncService.js.map +1 -1
  194. package/build/services/asg/localStorageService.d.ts.map +1 -1
  195. package/build/services/asg/localStorageService.js +3 -3
  196. package/build/services/asg/localStorageService.js.map +1 -1
  197. package/build/services/debug/DashboardOpenTrace.d.ts +32 -0
  198. package/build/services/debug/DashboardOpenTrace.d.ts.map +1 -0
  199. package/build/services/debug/DashboardOpenTrace.js +128 -0
  200. package/build/services/debug/DashboardOpenTrace.js.map +1 -0
  201. package/build/services/debug/dashboardOpenTimeline.d.ts +77 -0
  202. package/build/services/debug/dashboardOpenTimeline.d.ts.map +1 -0
  203. package/build/services/debug/dashboardOpenTimeline.js +195 -0
  204. package/build/services/debug/dashboardOpenTimeline.js.map +1 -0
  205. package/build/services/effectiveCapabilities.d.ts.map +1 -1
  206. package/build/services/effectiveCapabilities.js +25 -13
  207. package/build/services/effectiveCapabilities.js.map +1 -1
  208. package/build/services/gestureClaims.d.ts +34 -15
  209. package/build/services/gestureClaims.d.ts.map +1 -1
  210. package/build/services/gestureClaims.js +42 -21
  211. package/build/services/gestureClaims.js.map +1 -1
  212. package/build/services/manifestFields.d.ts +9 -0
  213. package/build/services/manifestFields.d.ts.map +1 -0
  214. package/build/services/manifestFields.js +26 -0
  215. package/build/services/manifestFields.js.map +1 -0
  216. package/build/services/memoryStoreInstance.d.ts +0 -10
  217. package/build/services/memoryStoreInstance.d.ts.map +1 -1
  218. package/build/services/memoryStoreInstance.js +2 -31
  219. package/build/services/memoryStoreInstance.js.map +1 -1
  220. package/build/services/mirrorSnapshot.d.ts +16 -0
  221. package/build/services/mirrorSnapshot.d.ts.map +1 -0
  222. package/build/services/mirrorSnapshot.js +102 -0
  223. package/build/services/mirrorSnapshot.js.map +1 -0
  224. package/build/services/nativeNavigationGate.d.ts +8 -0
  225. package/build/services/nativeNavigationGate.d.ts.map +1 -0
  226. package/build/services/nativeNavigationGate.js +12 -0
  227. package/build/services/nativeNavigationGate.js.map +1 -0
  228. package/build/services/notificationAppCatalog.d.ts +7 -0
  229. package/build/services/notificationAppCatalog.d.ts.map +1 -0
  230. package/build/services/notificationAppCatalog.js +16 -0
  231. package/build/services/notificationAppCatalog.js.map +1 -0
  232. package/build/services/notifications/notificationPolicy.d.ts +55 -0
  233. package/build/services/notifications/notificationPolicy.d.ts.map +1 -0
  234. package/build/services/notifications/notificationPolicy.js +41 -0
  235. package/build/services/notifications/notificationPolicy.js.map +1 -0
  236. package/build/services/pages/OverlayPages.d.ts +26 -0
  237. package/build/services/pages/OverlayPages.d.ts.map +1 -0
  238. package/build/services/pages/OverlayPages.js +80 -0
  239. package/build/services/pages/OverlayPages.js.map +1 -0
  240. package/build/services/pages/PageHost.d.ts +32 -0
  241. package/build/services/pages/PageHost.d.ts.map +1 -0
  242. package/build/services/pages/PageHost.js +99 -0
  243. package/build/services/pages/PageHost.js.map +1 -0
  244. package/build/services/pages/overlayApps.d.ts +25 -0
  245. package/build/services/pages/overlayApps.d.ts.map +1 -0
  246. package/build/services/pages/overlayApps.js +66 -0
  247. package/build/services/pages/overlayApps.js.map +1 -0
  248. package/build/services/pages/pageEligibility.d.ts +9 -0
  249. package/build/services/pages/pageEligibility.d.ts.map +1 -0
  250. package/build/services/pages/pageEligibility.js +27 -0
  251. package/build/services/pages/pageEligibility.js.map +1 -0
  252. package/build/services/settingsBridge.d.ts +58 -0
  253. package/build/services/settingsBridge.d.ts.map +1 -0
  254. package/build/services/settingsBridge.js +90 -0
  255. package/build/services/settingsBridge.js.map +1 -0
  256. package/build/services/speakerProfileStoreInstance.js +1 -1
  257. package/build/services/speakerProfileStoreInstance.js.map +1 -1
  258. package/build/services/uiShim.d.ts +1 -1
  259. package/build/services/uiShim.js +4 -4
  260. package/build/services/uiShim.js.map +1 -1
  261. package/build/stores/appVisibility.d.ts +28 -0
  262. package/build/stores/appVisibility.d.ts.map +1 -1
  263. package/build/stores/appVisibility.js +34 -0
  264. package/build/stores/appVisibility.js.map +1 -1
  265. package/build/stores/apps.d.ts +13 -0
  266. package/build/stores/apps.d.ts.map +1 -1
  267. package/build/stores/apps.js +66 -12
  268. package/build/stores/apps.js.map +1 -1
  269. package/build/stores/bluetoothSettingKeys.js +1 -1
  270. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  271. package/build/stores/display.d.ts +3 -3
  272. package/build/stores/display.d.ts.map +1 -1
  273. package/build/stores/display.js +16 -4
  274. package/build/stores/display.js.map +1 -1
  275. package/build/stores/glasses.d.ts.map +1 -1
  276. package/build/stores/glasses.js +14 -1
  277. package/build/stores/glasses.js.map +1 -1
  278. package/build/stores/settings.d.ts +1 -0
  279. package/build/stores/settings.d.ts.map +1 -1
  280. package/build/stores/settings.js +170 -44
  281. package/build/stores/settings.js.map +1 -1
  282. package/build/types/applet.d.ts +14 -1
  283. package/build/types/applet.d.ts.map +1 -1
  284. package/build/types/applet.js.map +1 -1
  285. package/build/types/capabilities/even-realities-g2.d.ts.map +1 -1
  286. package/build/types/capabilities/even-realities-g2.js +5 -0
  287. package/build/types/capabilities/even-realities-g2.js.map +1 -1
  288. package/build/types/capabilities/simulated-glasses.d.ts +1 -1
  289. package/build/types/capabilities/simulated-glasses.d.ts.map +1 -1
  290. package/build/types/capabilities/simulated-glasses.js +7 -4
  291. package/build/types/capabilities/simulated-glasses.js.map +1 -1
  292. package/build/types/hardware.d.ts +20 -1
  293. package/build/types/hardware.d.ts.map +1 -1
  294. package/build/types/hardware.js +2 -0
  295. package/build/types/hardware.js.map +1 -1
  296. package/build/types/index.d.ts +1 -0
  297. package/build/types/index.d.ts.map +1 -1
  298. package/build/types/index.js +1 -0
  299. package/build/types/index.js.map +1 -1
  300. package/build/utils/debouncedPatch.d.ts +3 -1
  301. package/build/utils/debouncedPatch.d.ts.map +1 -1
  302. package/build/utils/debouncedPatch.js +6 -3
  303. package/build/utils/debouncedPatch.js.map +1 -1
  304. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  305. package/build/utils/devMiniappLaunch.js +4 -3
  306. package/build/utils/devMiniappLaunch.js.map +1 -1
  307. package/build/utils/display/measurer/TextMeasurer.d.ts +2 -159
  308. package/build/utils/display/measurer/TextMeasurer.d.ts.map +1 -1
  309. package/build/utils/display/measurer/TextMeasurer.js +2 -272
  310. package/build/utils/display/measurer/TextMeasurer.js.map +1 -1
  311. package/build/utils/display/measurer/script-detection.d.ts +1 -52
  312. package/build/utils/display/measurer/script-detection.d.ts.map +1 -1
  313. package/build/utils/display/measurer/script-detection.js +2 -183
  314. package/build/utils/display/measurer/script-detection.js.map +1 -1
  315. package/build/utils/display/pixelArt.d.ts +3 -0
  316. package/build/utils/display/pixelArt.d.ts.map +1 -0
  317. package/build/utils/display/pixelArt.js +3 -0
  318. package/build/utils/display/pixelArt.js.map +1 -0
  319. package/build/utils/display/profiles/g1.d.ts +1 -32
  320. package/build/utils/display/profiles/g1.d.ts.map +1 -1
  321. package/build/utils/display/profiles/g1.js +2 -212
  322. package/build/utils/display/profiles/g1.js.map +1 -1
  323. package/build/utils/display/profiles/g2.d.ts +1 -12
  324. package/build/utils/display/profiles/g2.d.ts.map +1 -1
  325. package/build/utils/display/profiles/g2.js +2 -33
  326. package/build/utils/display/profiles/g2.js.map +1 -1
  327. package/build/utils/display/profiles/nex.d.ts +1 -9
  328. package/build/utils/display/profiles/nex.d.ts.map +1 -1
  329. package/build/utils/display/profiles/nex.js +2 -149
  330. package/build/utils/display/profiles/nex.js.map +1 -1
  331. package/build/utils/display/profiles/types.d.ts +1 -102
  332. package/build/utils/display/profiles/types.d.ts.map +1 -1
  333. package/build/utils/display/profiles/types.js.map +1 -1
  334. package/build/utils/display/profiles/z100.d.ts +1 -32
  335. package/build/utils/display/profiles/z100.d.ts.map +1 -1
  336. package/build/utils/display/profiles/z100.js +2 -181
  337. package/build/utils/display/profiles/z100.js.map +1 -1
  338. package/build/utils/display/scene/degrade.d.ts.map +1 -1
  339. package/build/utils/display/scene/degrade.js +4 -1
  340. package/build/utils/display/scene/degrade.js.map +1 -1
  341. package/build/utils/display/scene/differ.d.ts +13 -1
  342. package/build/utils/display/scene/differ.d.ts.map +1 -1
  343. package/build/utils/display/scene/differ.js +22 -0
  344. package/build/utils/display/scene/differ.js.map +1 -1
  345. package/build/utils/display/scene/index.d.ts +1 -1
  346. package/build/utils/display/scene/index.d.ts.map +1 -1
  347. package/build/utils/display/scene/index.js.map +1 -1
  348. package/build/utils/display/scene/process.d.ts.map +1 -1
  349. package/build/utils/display/scene/process.js +183 -11
  350. package/build/utils/display/scene/process.js.map +1 -1
  351. package/build/utils/display/scene/store.d.ts +1 -1
  352. package/build/utils/display/scene/store.d.ts.map +1 -1
  353. package/build/utils/display/scene/store.js +0 -0
  354. package/build/utils/display/scene/store.js.map +1 -1
  355. package/build/utils/display/scene/svgPath.d.ts +9 -0
  356. package/build/utils/display/scene/svgPath.d.ts.map +1 -0
  357. package/build/utils/display/scene/svgPath.js +167 -0
  358. package/build/utils/display/scene/svgPath.js.map +1 -0
  359. package/build/utils/display/scene/types.d.ts +2 -142
  360. package/build/utils/display/scene/types.d.ts.map +1 -1
  361. package/build/utils/display/scene/types.js +0 -0
  362. package/build/utils/display/scene/types.js.map +1 -1
  363. package/build/utils/display/wrapper/TextWrapper.d.ts +1 -101
  364. package/build/utils/display/wrapper/TextWrapper.d.ts.map +1 -1
  365. package/build/utils/display/wrapper/TextWrapper.js +2 -470
  366. package/build/utils/display/wrapper/TextWrapper.js.map +1 -1
  367. package/build/utils/display/wrapper/types.d.ts +2 -74
  368. package/build/utils/display/wrapper/types.d.ts.map +1 -1
  369. package/build/utils/display/wrapper/types.js +2 -10
  370. package/build/utils/display/wrapper/types.js.map +1 -1
  371. package/build/utils/hardware/hardware.js +1 -1
  372. package/build/utils/hardware/hardware.js.map +1 -1
  373. package/build/utils/timers/timers.d.ts.map +1 -1
  374. package/build/utils/timers/timers.js +26 -4
  375. package/build/utils/timers/timers.js.map +1 -1
  376. package/package.json +8 -8
  377. package/src/engine.ts +24 -15
  378. package/src/facades/dev.ts +10 -0
  379. package/src/facades/display.ts +21 -8
  380. package/src/facades/displayMirror.ts +29 -0
  381. package/src/facades/glasses.ts +61 -1
  382. package/src/facades/memory.ts +1 -12
  383. package/src/facades/miniapps.ts +4 -1
  384. package/src/facades/pairing.ts +8 -6
  385. package/src/facades/permissions.ts +46 -0
  386. package/src/facades/phoneNotifications.ts +45 -26
  387. package/src/facades/settings.ts +1 -2
  388. package/src/generated/releaseMetadata.ts +4 -4
  389. package/src/index.ts +6 -9
  390. package/src/react/MentraLiveOtaFlow.tsx +2 -2
  391. package/src/react/useMentraLiveOta.ts +14 -8
  392. package/src/runtime/config.ts +1 -1
  393. package/src/services/AppRegistry.ts +43 -7
  394. package/src/services/BlobStore.ts +3 -3
  395. package/src/services/CloudClientService.ts +37 -10
  396. package/src/services/DevServerBridge.ts +12 -10
  397. package/src/services/DeviceEventRouter.ts +73 -74
  398. package/src/services/DisplayDiagnostics.ts +107 -0
  399. package/src/services/DisplayProcessor.ts +20 -55
  400. package/src/services/GestureDotsService.ts +77 -16
  401. package/src/services/GlassesKeyboardInput.ts +306 -0
  402. package/src/services/GlassesSensorService.ts +233 -0
  403. package/src/services/GlassesTouchInput.ts +128 -0
  404. package/src/services/HeadingService.ts +0 -24
  405. package/src/services/HotspotShutdown.ts +3 -1
  406. package/src/services/JSCrashloopReportService.ts +2 -2
  407. package/src/services/JSRouter.ts +29 -14
  408. package/src/services/LocalDisplayManager.ts +112 -26
  409. package/src/services/LocalMiniappDataMigration.ts +1 -1
  410. package/src/services/LocalMiniappRuntime.ts +500 -43
  411. package/src/services/LocalSttFallbackCoordinator.ts +28 -7
  412. package/src/services/MemoryStore.ts +32 -80
  413. package/src/services/MiniappEngine.ts +7 -7
  414. package/src/services/MiniappLauncher.ts +25 -1
  415. package/src/services/MirrorService.ts +139 -0
  416. package/src/services/NativeNavigationService.ts +29 -25
  417. package/src/services/NavigationHandlers.ts +10 -5
  418. package/src/services/OtaInstallCoordinator.ts +36 -34
  419. package/src/services/PairedGlassesLatch.ts +39 -0
  420. package/src/services/PhoneActivity.ts +116 -0
  421. package/src/services/PhoneCameraFovCoordinator.ts +6 -4
  422. package/src/services/PhoneNotificationsSync.ts +185 -103
  423. package/src/services/PhonePhotoCoordinator.ts +9 -10
  424. package/src/services/PhoneStreamCoordinator.ts +13 -11
  425. package/src/services/STTModelManager.ts +15 -1
  426. package/src/services/SceneRenderer.ts +148 -10
  427. package/src/services/StreamLifecycleController.ts +9 -7
  428. package/src/services/TTSModelManager.ts +1 -1
  429. package/src/services/UIRouter.ts +5 -5
  430. package/src/services/asg/galleryPathMigration.ts +1 -1
  431. package/src/services/asg/gallerySyncService.ts +2 -2
  432. package/src/services/asg/localStorageService.ts +3 -3
  433. package/src/services/debug/DashboardOpenTrace.ts +153 -0
  434. package/src/services/debug/dashboardOpenTimeline.ts +237 -0
  435. package/src/services/effectiveCapabilities.ts +32 -13
  436. package/src/services/gestureClaims.ts +72 -23
  437. package/src/services/manifestFields.ts +23 -0
  438. package/src/services/memoryStoreInstance.ts +2 -34
  439. package/src/services/mirrorSnapshot.ts +116 -0
  440. package/src/services/nativeNavigationGate.ts +14 -0
  441. package/src/services/notificationAppCatalog.ts +21 -0
  442. package/src/services/notifications/notificationPolicy.ts +87 -0
  443. package/src/services/pages/OverlayPages.ts +86 -0
  444. package/src/services/pages/PageHost.ts +116 -0
  445. package/src/services/pages/overlayApps.ts +72 -0
  446. package/src/services/pages/pageEligibility.ts +30 -0
  447. package/src/services/settingsBridge.ts +111 -0
  448. package/src/services/speakerProfileStoreInstance.ts +1 -1
  449. package/src/services/uiShim.ts +4 -4
  450. package/src/stores/appVisibility.ts +45 -0
  451. package/src/stores/apps.ts +110 -32
  452. package/src/stores/bluetoothSettingKeys.ts +1 -1
  453. package/src/stores/display.ts +18 -7
  454. package/src/stores/glasses.ts +15 -1
  455. package/src/stores/settings.ts +175 -51
  456. package/src/types/applet.ts +14 -1
  457. package/src/types/capabilities/even-realities-g2.ts +6 -0
  458. package/src/types/capabilities/simulated-glasses.ts +8 -4
  459. package/src/types/hardware.ts +34 -1
  460. package/src/types/index.ts +1 -0
  461. package/src/utils/debouncedPatch.ts +8 -4
  462. package/src/utils/devMiniappLaunch.ts +5 -3
  463. package/src/utils/display/measurer/TextMeasurer.ts +3 -346
  464. package/src/utils/display/measurer/script-detection.ts +10 -218
  465. package/src/utils/display/pixelArt.ts +3 -0
  466. package/src/utils/display/profiles/g1.ts +2 -236
  467. package/src/utils/display/profiles/g2.ts +2 -39
  468. package/src/utils/display/profiles/nex.ts +2 -166
  469. package/src/utils/display/profiles/types.ts +9 -132
  470. package/src/utils/display/profiles/z100.ts +2 -198
  471. package/src/utils/display/scene/degrade.ts +4 -1
  472. package/src/utils/display/scene/differ.ts +25 -1
  473. package/src/utils/display/scene/index.ts +5 -0
  474. package/src/utils/display/scene/process.ts +196 -13
  475. package/src/utils/display/scene/store.ts +0 -0
  476. package/src/utils/display/scene/svgPath.ts +163 -0
  477. package/src/utils/display/scene/types.ts +0 -0
  478. package/src/utils/display/wrapper/TextWrapper.ts +2 -546
  479. package/src/utils/display/wrapper/types.ts +3 -102
  480. package/src/utils/hardware/hardware.ts +1 -1
  481. package/src/utils/timers/timers.ts +32 -4
  482. package/build/services/CustomDashboardModel.d.ts +0 -48
  483. package/build/services/CustomDashboardModel.d.ts.map +0 -1
  484. package/build/services/CustomDashboardModel.js +0 -73
  485. package/build/services/CustomDashboardModel.js.map +0 -1
  486. package/build/services/CustomDashboardService.d.ts +0 -63
  487. package/build/services/CustomDashboardService.d.ts.map +0 -1
  488. package/build/services/CustomDashboardService.js +0 -576
  489. package/build/services/CustomDashboardService.js.map +0 -1
  490. package/build/services/DashboardCoordinator.d.ts +0 -26
  491. package/build/services/DashboardCoordinator.d.ts.map +0 -1
  492. package/build/services/DashboardCoordinator.js +0 -125
  493. package/build/services/DashboardCoordinator.js.map +0 -1
  494. package/build/services/iosNotificationAppCatalog.d.ts +0 -13
  495. package/build/services/iosNotificationAppCatalog.d.ts.map +0 -1
  496. package/build/services/iosNotificationAppCatalog.js +0 -28
  497. package/build/services/iosNotificationAppCatalog.js.map +0 -1
  498. package/src/services/CustomDashboardModel.ts +0 -83
  499. package/src/services/CustomDashboardService.ts +0 -598
  500. package/src/services/DashboardCoordinator.ts +0 -121
  501. package/src/services/iosNotificationAppCatalog.ts +0 -39
@@ -3,16 +3,18 @@
3
3
  * firmware-rendered nav UI (`hasNativeNavigation`; G2 service 0x08 today).
4
4
  * NavigationHandlers drives enter/exit at trip boundaries; miniapp NATIVE_NAV
5
5
  * payloads (card fields, map bitmaps) are forwarded to the bluetooth-sdk.
6
- * While active, the glasses magnetometer feeds HeadingService so
7
- * session.heading serves the glasses compass instead of the phone's.
6
+ * While active, stock firmware streams its magnetometer heading; the device
7
+ * event router forwards it to session.compass like any glasses compass sample.
8
8
  */
9
9
 
10
+ import {useDisplayStore} from "../stores/display"
10
11
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
11
12
 
12
13
  import {ISLAND_SETTINGS_KEYS} from "../runtime/config"
13
14
  import {useSettingsStore} from "../stores/settings"
14
- import {DeviceTypes, getModelCapabilities} from "../types"
15
- import headingService from "./HeadingService"
15
+ import {DeviceTypes} from "../types"
16
+ import {getEffectiveCapabilities} from "./effectiveCapabilities"
17
+ import glassesSensorService from "./GlassesSensorService"
16
18
 
17
19
  const LOG_TAG = "NATIVE_NAV_SERVICE"
18
20
 
@@ -30,7 +32,6 @@ class NativeNavigationService {
30
32
  private static instance: NativeNavigationService | null = null
31
33
 
32
34
  private active = false
33
- private compassSub: {remove: () => void} | null = null
34
35
  private modeSub: {remove: () => void} | null = null
35
36
  /** Registered by NavigationHandlers; fires when the WEARER exits nav mode on the glasses. */
36
37
  private onGlassesExitCb: (() => void) | null = null
@@ -62,7 +63,9 @@ class NativeNavigationService {
62
63
  const defaultWearable = useSettingsStore.getState().getSetting(ISLAND_SETTINGS_KEYS.defaultWearable) as
63
64
  | DeviceTypes
64
65
  | undefined
65
- const capabilities = getModelCapabilities(defaultWearable || DeviceTypes.NONE)
66
+ // Effective, not model: custom firmware drops hasNativeNavigation so the
67
+ // miniapp's scene HUD owns the display (see effectiveCapabilities).
68
+ const capabilities = getEffectiveCapabilities(defaultWearable || DeviceTypes.NONE)
66
69
  return (
67
70
  capabilities.hasNativeNavigation === true &&
68
71
  typeof (BluetoothSdk as {navigationModeStart?: unknown}).navigationModeStart === "function"
@@ -74,10 +77,16 @@ class NativeNavigationService {
74
77
  if (!this.isSupported() || this.active) return
75
78
  console.log(`${LOG_TAG}: entering native nav mode for ${packageName}`)
76
79
  this.active = true
80
+ useDisplayStore.getState().setDisplayEvent({layout: {layoutType: "unavailable", reason: "firmware-navigation"}})
77
81
  this.attachListeners()
78
- void Promise.resolve(BluetoothSdk.navigationModeStart()).catch((err) => {
79
- console.error(`${LOG_TAG}: navigationModeStart failed:`, err)
80
- })
82
+ void glassesSensorService
83
+ .setNavigationActive(true)
84
+ .then(() => {
85
+ return this.active ? BluetoothSdk.navigationModeStart() : undefined
86
+ })
87
+ .catch((err) => {
88
+ console.error(`${LOG_TAG}: navigationModeStart failed:`, err)
89
+ })
81
90
  }
82
91
 
83
92
  /** The trip ended (arrived / stopped / errored). Safe to call when inactive. */
@@ -85,9 +94,13 @@ class NativeNavigationService {
85
94
  if (!this.active) return
86
95
  console.log(`${LOG_TAG}: exiting native nav mode (arrived=${arrived})`)
87
96
  this.teardown()
88
- void Promise.resolve(BluetoothSdk.navigationModeStop(arrived)).catch((err) => {
89
- console.error(`${LOG_TAG}: navigationModeStop failed:`, err)
90
- })
97
+ void Promise.resolve(BluetoothSdk.navigationModeStop(arrived))
98
+ .then(() => {
99
+ return glassesSensorService.setNavigationActive(false)
100
+ })
101
+ .catch((err) => {
102
+ console.error(`${LOG_TAG}: navigationModeStop failed:`, err)
103
+ })
91
104
  }
92
105
 
93
106
  /**
@@ -140,15 +153,6 @@ class NativeNavigationService {
140
153
  }
141
154
 
142
155
  private attachListeners(): void {
143
- // Glasses magnetometer → session.heading for the duration of the trip.
144
- headingService.setExternalSourceActive(true)
145
- this.compassSub?.remove()
146
- this.compassSub = BluetoothSdk.addListener("compass_heading", (event) => {
147
- const deg = Number(event.heading)
148
- if (!Number.isFinite(deg)) return
149
- headingService.pushExternalHeading(((deg % 360) + 360) % 360)
150
- })
151
-
152
156
  // Glasses-side exit ends the whole trip: release the compass override and
153
157
  // let NavigationHandlers stop navigation + notify the miniapp ("cancelled").
154
158
  // Phone-initiated exits (trip already ending) just tear down.
@@ -157,18 +161,18 @@ class NativeNavigationService {
157
161
  if (event.status === "exited" && this.active) {
158
162
  console.log(`${LOG_TAG}: nav mode exited natively (source=${event.source ?? "phone"})`)
159
163
  this.teardown()
160
- if (event.source === "glasses") this.onGlassesExitCb?.()
164
+ if (event.source === "glasses") {
165
+ this.onGlassesExitCb?.()
166
+ void glassesSensorService.setNavigationActive(false)
167
+ }
161
168
  }
162
169
  })
163
170
  }
164
171
 
165
172
  private teardown(): void {
166
173
  this.active = false
167
- this.compassSub?.remove()
168
- this.compassSub = null
169
174
  this.modeSub?.remove()
170
175
  this.modeSub = null
171
- headingService.setExternalSourceActive(false)
172
176
  }
173
177
  }
174
178
 
@@ -240,7 +240,12 @@ export class NavigationHandlers {
240
240
  // navigation mode for the duration of the trip.
241
241
  nativeNavigationService.onTripStart(packageName)
242
242
  }
243
- this.sendResult(packageName, requestId, result.ok, result, undefined)
243
+ // A refused start (`{ok: false, error}` from the token gate or the
244
+ // native navigator) is request DATA, not a wire failure: the SDK's
245
+ // navigation.start() contract is "resolves {ok, error?}, never throws".
246
+ // Sending it as ok:false on the wire made the SDK reject with its
247
+ // generic "Unknown error" and drop the real message.
248
+ this.sendResult(packageName, requestId, true, result)
244
249
  } catch (err) {
245
250
  console.error(`${LOG_TAG}: navigation start error:`, err)
246
251
  this.sendResult(packageName, requestId, false, undefined, {
@@ -263,7 +268,7 @@ export class NavigationHandlers {
263
268
  nativeNavigationService.onTripEnd(false)
264
269
  const navigation = navigationService
265
270
  const result = navigation ? await navigation.stop() : {ok: true}
266
- this.sendResult(packageName, requestId, result.ok, result, undefined)
271
+ this.sendResult(packageName, requestId, true, result)
267
272
  } else {
268
273
  this.sendResult(packageName, requestId, true, {ok: true}, undefined)
269
274
  }
@@ -284,7 +289,7 @@ export class NavigationHandlers {
284
289
  const result = navigation
285
290
  ? await navigation.simulateDeviation(offsetMeters)
286
291
  : {ok: false, error: "navigation adapter not configured"}
287
- this.sendResult(packageName, requestId, result.ok, result, undefined)
292
+ this.sendResult(packageName, requestId, true, result)
288
293
  } catch (err) {
289
294
  console.error(`${LOG_TAG}: navigation deviate error:`, err)
290
295
  this.sendResult(packageName, requestId, false, undefined, {
@@ -305,7 +310,7 @@ export class NavigationHandlers {
305
310
  const result = navigation
306
311
  ? await navigation.setWrongSidewalkOffset(enabled)
307
312
  : {ok: false, error: "navigation adapter not configured"}
308
- this.sendResult(packageName, requestId, result.ok, result, undefined)
313
+ this.sendResult(packageName, requestId, true, result)
309
314
  } catch (err) {
310
315
  console.error(`${LOG_TAG}: navigation setWrongSidewalkOffset error:`, err)
311
316
  this.sendResult(packageName, requestId, false, undefined, {
@@ -326,7 +331,7 @@ export class NavigationHandlers {
326
331
  const result = navigation
327
332
  ? await navigation.setSkipCrossings(enabled)
328
333
  : {ok: false, error: "navigation adapter not configured"}
329
- this.sendResult(packageName, requestId, result.ok, result, undefined)
334
+ this.sendResult(packageName, requestId, true, result)
330
335
  } catch (err) {
331
336
  console.error(`${LOG_TAG}: navigation setSkipCrossings error:`, err)
332
337
  this.sendResult(packageName, requestId, false, undefined, {
@@ -57,6 +57,8 @@ import {
57
57
  type OtaProtocolProfile,
58
58
  } from "./otaInstallPolicy"
59
59
 
60
+ import {BgTimer} from "../utils/timers"
61
+
60
62
  function isTerminalForWatchdog(d: DisplayState): boolean {
61
63
  return d === "complete" || d === "failed" || d === "restarting"
62
64
  }
@@ -239,18 +241,18 @@ class OtaInstallCoordinator {
239
241
  private lastRealMtkProgress = 0
240
242
 
241
243
  // Timer handles
242
- private globalTimeout: ReturnType<typeof setTimeout> | null = null
244
+ private globalTimeout: number | null = null
243
245
  private globalTimeoutStarted = false
244
- private retryTimeout: ReturnType<typeof setTimeout> | null = null
245
- private stuckTimeout: ReturnType<typeof setTimeout> | null = null
246
- private progressTimeout: ReturnType<typeof setTimeout> | null = null
247
- private pingInterval: ReturnType<typeof setInterval> | null = null
248
- private queryReplyTimeout: ReturnType<typeof setTimeout> | null = null
249
- private continueLockoutTimer: ReturnType<typeof setTimeout> | null = null
250
- private restartRecoveryTimeout: ReturnType<typeof setTimeout> | null = null
251
- private legacyApkSettleTimer: ReturnType<typeof setTimeout> | null = null
252
- private mtkStallDetectTimer: ReturnType<typeof setTimeout> | null = null
253
- private mtkSimTickTimer: ReturnType<typeof setInterval> | null = null
246
+ private retryTimeout: number | null = null
247
+ private stuckTimeout: number | null = null
248
+ private progressTimeout: number | null = null
249
+ private pingInterval: number | null = null
250
+ private queryReplyTimeout: number | null = null
251
+ private continueLockoutTimer: number | null = null
252
+ private restartRecoveryTimeout: number | null = null
253
+ private legacyApkSettleTimer: number | null = null
254
+ private mtkStallDetectTimer: number | null = null
255
+ private mtkSimTickTimer: number | null = null
254
256
 
255
257
  // Request / retry bookkeeping (no glasses source)
256
258
  // At most one apk-install status poll in flight (native rejects concurrent queries).
@@ -950,7 +952,7 @@ class OtaInstallCoordinator {
950
952
  if (active) {
951
953
  void BluetoothSdk.ping().catch(() => {})
952
954
  const pingIntervalMs = legacySession ? LEGACY_PING_INTERVAL_MS : PING_INTERVAL_MS
953
- this.pingInterval = setInterval(() => {
955
+ this.pingInterval = BgTimer.setInterval(() => {
954
956
  void BluetoothSdk.ping().catch(() => {})
955
957
  this.maybePollApkInstallStatus()
956
958
  }, pingIntervalMs)
@@ -990,7 +992,7 @@ class OtaInstallCoordinator {
990
992
  } else {
991
993
  const duration = stallDuration
992
994
  this.clearProgressTimeout()
993
- this.progressTimeout = setTimeout(() => {
995
+ this.progressTimeout = BgTimer.setTimeout(() => {
994
996
  this.progressTimeout = null
995
997
  if (isTerminalForWatchdog(this.computeDisplayStateNow())) return
996
998
  console.log(`[OTA_PROGRESS] watchdog: progress stalled for ${duration}ms, failing`)
@@ -1007,11 +1009,11 @@ class OtaInstallCoordinator {
1007
1009
  const lockoutMs = legacySession ? LEGACY_BES_CONTINUE_LOCKOUT_MS : BES_CONTINUE_LOCKOUT_MS
1008
1010
  const restartTimeoutMs = legacySession ? LEGACY_BES_RESTART_TIMEOUT_MS : BES_RESTART_TIMEOUT_MS
1009
1011
  this.setContinueButtonDisabled(true)
1010
- this.continueLockoutTimer = setTimeout(() => {
1012
+ this.continueLockoutTimer = BgTimer.setTimeout(() => {
1011
1013
  this.continueLockoutTimer = null
1012
1014
  this.setContinueButtonDisabled(false)
1013
1015
  }, lockoutMs)
1014
- this.restartRecoveryTimeout = setTimeout(() => {
1016
+ this.restartRecoveryTimeout = BgTimer.setTimeout(() => {
1015
1017
  this.restartRecoveryTimeout = null
1016
1018
  if (this.computeDisplayStateNow() !== "restarting") return
1017
1019
  console.log(`[OTA_PROGRESS] watchdog: glasses did not finish restarting in ${restartTimeoutMs}ms`)
@@ -1212,7 +1214,7 @@ class OtaInstallCoordinator {
1212
1214
  `[OTA_PROGRESS] legacy apk install complete — holding complete for ${LEGACY_APK_COMPLETION_SETTLE_MS}ms settle window`,
1213
1215
  )
1214
1216
  this.setLegacyApkSettleHold(true)
1215
- this.legacyApkSettleTimer = setTimeout(() => {
1217
+ this.legacyApkSettleTimer = BgTimer.setTimeout(() => {
1216
1218
  this.legacyApkSettleTimer = null
1217
1219
  console.log("[OTA_PROGRESS] legacy apk settle window elapsed — releasing complete")
1218
1220
  this.setLegacyApkSettleHold(false)
@@ -1292,7 +1294,7 @@ class OtaInstallCoordinator {
1292
1294
  realProgress >= LEGACY_MTK_STALL_ZONE_MIN_PERCENT && realProgress < LEGACY_MTK_STALL_ZONE_MAX_PERCENT
1293
1295
  if (!inStallZone) return
1294
1296
 
1295
- this.mtkStallDetectTimer = setTimeout(() => {
1297
+ this.mtkStallDetectTimer = BgTimer.setTimeout(() => {
1296
1298
  this.mtkStallDetectTimer = null
1297
1299
  const stalledAt = this.lastRealMtkProgress
1298
1300
  const prev = this.mtkSimulatedPercent
@@ -1304,12 +1306,12 @@ class OtaInstallCoordinator {
1304
1306
  `[OTA_PROGRESS] legacy mtk install stalled at ${stalledAt}%, simulating display progress from ${target}%`,
1305
1307
  )
1306
1308
  this.setMtkSimulatedPercent(target)
1307
- this.mtkSimTickTimer = setInterval(() => {
1309
+ this.mtkSimTickTimer = BgTimer.setInterval(() => {
1308
1310
  const current = this.mtkSimulatedPercent ?? stalledAt + 1
1309
1311
  const capped = Math.min(current + 1, LEGACY_MTK_SIM_CAP_PERCENT)
1310
1312
  this.setMtkSimulatedPercent(capped)
1311
1313
  if (capped >= LEGACY_MTK_SIM_CAP_PERCENT && this.mtkSimTickTimer) {
1312
- clearInterval(this.mtkSimTickTimer)
1314
+ BgTimer.clearInterval(this.mtkSimTickTimer)
1313
1315
  this.mtkSimTickTimer = null
1314
1316
  }
1315
1317
  }, LEGACY_MTK_SIM_TICK_MS)
@@ -1404,7 +1406,7 @@ class OtaInstallCoordinator {
1404
1406
  // session; a session that starts unified keeps the unified cap.
1405
1407
  const globalTimeoutMs =
1406
1408
  this.versionChangeSession || this.isLegacySessionShapeNow() ? LEGACY_GLOBAL_OTA_TIMEOUT_MS : GLOBAL_OTA_TIMEOUT_MS
1407
- this.globalTimeout = setTimeout(() => {
1409
+ this.globalTimeout = BgTimer.setTimeout(() => {
1408
1410
  this.globalTimeout = null
1409
1411
  this.globalTimeoutStarted = false
1410
1412
  if (isTerminalForWatchdog(this.computeDisplayStateNow())) return
@@ -1427,7 +1429,7 @@ class OtaInstallCoordinator {
1427
1429
  const legacySession = this.isLegacySessionShapeNow()
1428
1430
  const stuckTimeoutMs = legacySession ? LEGACY_DOWNLOAD_STUCK_TIMEOUT_MS : DOWNLOAD_STUCK_TIMEOUT_MS
1429
1431
 
1430
- this.stuckTimeout = setTimeout(() => {
1432
+ this.stuckTimeout = BgTimer.setTimeout(() => {
1431
1433
  this.stuckTimeout = null
1432
1434
  const d = this.computeDisplayStateNow()
1433
1435
  const state = useGlassesStore.getState()
@@ -1560,7 +1562,7 @@ class OtaInstallCoordinator {
1560
1562
  this.retryCount + 1
1561
1563
  }/${MAX_RETRIES})`,
1562
1564
  )
1563
- this.retryTimeout = setTimeout(() => {
1565
+ this.retryTimeout = BgTimer.setTimeout(() => {
1564
1566
  this.retryTimeout = null
1565
1567
  if (!isGlassesConnected(useGlassesStore.getState().connection)) {
1566
1568
  console.log("[OTA_PROGRESS] ota_start retry paused while disconnected; reconnect arbitration will resume")
@@ -1598,7 +1600,7 @@ class OtaInstallCoordinator {
1598
1600
  */
1599
1601
  private armQueryReplyFallback(reason: "reconnect" | "initial-mount" | "retry"): void {
1600
1602
  this.clearQueryReplyTimeout()
1601
- this.queryReplyTimeout = setTimeout(() => {
1603
+ this.queryReplyTimeout = BgTimer.setTimeout(() => {
1602
1604
  this.queryReplyTimeout = null
1603
1605
  const state = useGlassesStore.getState()
1604
1606
  // If we already got a useful reply, we'd have been cleared. Defensive
@@ -1633,28 +1635,28 @@ class OtaInstallCoordinator {
1633
1635
 
1634
1636
  private clearProgressTimeout(): void {
1635
1637
  if (this.progressTimeout) {
1636
- clearTimeout(this.progressTimeout)
1638
+ BgTimer.clearTimeout(this.progressTimeout)
1637
1639
  this.progressTimeout = null
1638
1640
  }
1639
1641
  }
1640
1642
 
1641
1643
  private clearRetryTimeout(): void {
1642
1644
  if (this.retryTimeout) {
1643
- clearTimeout(this.retryTimeout)
1645
+ BgTimer.clearTimeout(this.retryTimeout)
1644
1646
  this.retryTimeout = null
1645
1647
  }
1646
1648
  }
1647
1649
 
1648
1650
  private clearStuckTimeout(): void {
1649
1651
  if (this.stuckTimeout) {
1650
- clearTimeout(this.stuckTimeout)
1652
+ BgTimer.clearTimeout(this.stuckTimeout)
1651
1653
  this.stuckTimeout = null
1652
1654
  }
1653
1655
  }
1654
1656
 
1655
1657
  private clearGlobalTimeout(): void {
1656
1658
  if (this.globalTimeout) {
1657
- clearTimeout(this.globalTimeout)
1659
+ BgTimer.clearTimeout(this.globalTimeout)
1658
1660
  this.globalTimeout = null
1659
1661
  }
1660
1662
  this.globalTimeoutStarted = false
@@ -1662,46 +1664,46 @@ class OtaInstallCoordinator {
1662
1664
 
1663
1665
  private clearPingInterval(): void {
1664
1666
  if (this.pingInterval) {
1665
- clearInterval(this.pingInterval)
1667
+ BgTimer.clearInterval(this.pingInterval)
1666
1668
  this.pingInterval = null
1667
1669
  }
1668
1670
  }
1669
1671
 
1670
1672
  private clearQueryReplyTimeout(): void {
1671
1673
  if (this.queryReplyTimeout) {
1672
- clearTimeout(this.queryReplyTimeout)
1674
+ BgTimer.clearTimeout(this.queryReplyTimeout)
1673
1675
  this.queryReplyTimeout = null
1674
1676
  }
1675
1677
  }
1676
1678
 
1677
1679
  private clearContinueLockoutTimer(): void {
1678
1680
  if (this.continueLockoutTimer) {
1679
- clearTimeout(this.continueLockoutTimer)
1681
+ BgTimer.clearTimeout(this.continueLockoutTimer)
1680
1682
  this.continueLockoutTimer = null
1681
1683
  }
1682
1684
  }
1683
1685
 
1684
1686
  private clearRestartRecoveryTimeout(): void {
1685
1687
  if (this.restartRecoveryTimeout) {
1686
- clearTimeout(this.restartRecoveryTimeout)
1688
+ BgTimer.clearTimeout(this.restartRecoveryTimeout)
1687
1689
  this.restartRecoveryTimeout = null
1688
1690
  }
1689
1691
  }
1690
1692
 
1691
1693
  private clearLegacyApkSettleTimer(): void {
1692
1694
  if (this.legacyApkSettleTimer) {
1693
- clearTimeout(this.legacyApkSettleTimer)
1695
+ BgTimer.clearTimeout(this.legacyApkSettleTimer)
1694
1696
  this.legacyApkSettleTimer = null
1695
1697
  }
1696
1698
  }
1697
1699
 
1698
1700
  private clearMtkSimulationTimers(): void {
1699
1701
  if (this.mtkStallDetectTimer) {
1700
- clearTimeout(this.mtkStallDetectTimer)
1702
+ BgTimer.clearTimeout(this.mtkStallDetectTimer)
1701
1703
  this.mtkStallDetectTimer = null
1702
1704
  }
1703
1705
  if (this.mtkSimTickTimer) {
1704
- clearInterval(this.mtkSimTickTimer)
1706
+ BgTimer.clearInterval(this.mtkSimTickTimer)
1705
1707
  this.mtkSimTickTimer = null
1706
1708
  }
1707
1709
  }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * PairedGlassesLatch — records that this phone has, at some point, paired
3
+ * real glasses. Projects the pairing identity (see PairingIdentity) into the
4
+ * one-way `has_paired_glasses` setting: set the first time the identity reads
5
+ * `paired` to a non-simulated model, never cleared. Forgetting the glasses or
6
+ * switching models leaves it on, so what it unlocks (the Store, see
7
+ * stores/appVisibility PAIRED_GLASSES_PACKAGES) stays unlocked.
8
+ */
9
+ import {useSettingsStore, SETTINGS} from "../stores/settings"
10
+ import {DeviceTypes} from "../types"
11
+ import {projectPairingIdentity, subscribePairingIdentity, type IdentitySnapshot} from "./PairingIdentity"
12
+
13
+ /** Paired to real glasses: the simulated device is its own identity and does not count. */
14
+ export const isPairedToRealGlasses = (identity: IdentitySnapshot): boolean =>
15
+ identity.kind === "paired" && !identity.model.includes(DeviceTypes.SIMULATED)
16
+
17
+ let unsubscribe: (() => void) | null = null
18
+
19
+ function latch(identity: IdentitySnapshot): void {
20
+ if (identity.kind !== "paired" || !isPairedToRealGlasses(identity)) return
21
+ const store = useSettingsStore.getState()
22
+ if (store.getSetting(SETTINGS.has_paired_glasses.key) === true) return
23
+ console.log(`PairedGlassesLatch: first real pairing ("${identity.model}") -> has_paired_glasses`)
24
+ void Promise.resolve(store.setSetting(SETTINGS.has_paired_glasses.key, true, false)).then((r) => {
25
+ if (r.is_error()) console.warn("PairedGlassesLatch: failed to persist has_paired_glasses:", r.error)
26
+ })
27
+ }
28
+
29
+ /** Start after the persisted settings are loaded so an already-paired phone latches immediately. */
30
+ export function startPairedGlassesLatch(): void {
31
+ if (unsubscribe) return
32
+ latch(projectPairingIdentity())
33
+ unsubscribe = subscribePairingIdentity(latch)
34
+ }
35
+
36
+ export function stopPairedGlassesLatch(): void {
37
+ unsubscribe?.()
38
+ unsubscribe = null
39
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Phone activity — engine-owned, both platforms. Started by `engine.start()`.
3
+ *
4
+ * "Active" means the wearer can see the phone: the Glassly App is in the
5
+ * foreground, or the phone is unlocked. Crust reports lock state as
6
+ * `phone_lock_state` (iOS: protected-data availability; Android: screen on and
7
+ * keyguard hidden); React Native reports foregrounding. Consumers read
8
+ * `isPhoneActive()` at decision time — the dashboard reducer when a
9
+ * notification posts — and `onPhoneActivityChange` serves those that have to
10
+ * push the state somewhere, like the stock G2 firmware's notification ctrl.
11
+ */
12
+ import {AppState} from "react-native"
13
+ import type {AppStateStatus} from "react-native"
14
+ import CrustModule from "@glassly/crust"
15
+ import type {PhoneLockState} from "@glassly/crust"
16
+
17
+ type Listener = (active: boolean) => void
18
+
19
+ let started = false
20
+ let lockStateSubscription: {remove(): void} | null = null
21
+ let appStateSubscription: {remove(): void} | null = null
22
+ const listeners = new Set<Listener>()
23
+ const foregroundListeners = new Set<Listener>()
24
+
25
+ // Until native answers, assume locked so a failed query never reads as active.
26
+ const ASSUMED_LOCKED: PhoneLockState = {unlocked: false, passcodeSet: true}
27
+ let phoneLock: PhoneLockState = ASSUMED_LOCKED
28
+ let appForegrounded = false
29
+
30
+ /**
31
+ * A foregrounded app is proof on its own. Without a passcode the platform lock
32
+ * signal is meaningless (iOS reports protected data as always available), so
33
+ * only the foreground gate applies there.
34
+ */
35
+ export function computePhoneActive(lock: PhoneLockState, foregrounded: boolean): boolean {
36
+ if (foregrounded) return true
37
+ if (!lock.passcodeSet) return false
38
+ return lock.unlocked
39
+ }
40
+
41
+ export function isPhoneActive(): boolean {
42
+ return computePhoneActive(phoneLock, appForegrounded)
43
+ }
44
+
45
+ /**
46
+ * Whether the Glassly App itself is foregrounded, independent of the lock
47
+ * state that `isPhoneActive()` folds in. Background execution limits (timer
48
+ * coalescing, BLE pacing) follow this bit alone: a backgrounded app on an
49
+ * unlocked phone is still a backgrounded app.
50
+ */
51
+ export function isAppForegrounded(): boolean {
52
+ return appForegrounded
53
+ }
54
+
55
+ /** Fires on app foreground/background transitions only. See `isAppForegrounded`. */
56
+ export function onAppForegroundChange(listener: Listener): () => void {
57
+ foregroundListeners.add(listener)
58
+ return () => {
59
+ foregroundListeners.delete(listener)
60
+ }
61
+ }
62
+
63
+ export function onPhoneActivityChange(listener: Listener): () => void {
64
+ listeners.add(listener)
65
+ return () => {
66
+ listeners.delete(listener)
67
+ }
68
+ }
69
+
70
+ function update(next: {lock?: PhoneLockState; foregrounded?: boolean}): void {
71
+ const before = isPhoneActive()
72
+ const foregroundBefore = appForegrounded
73
+ if (next.lock) phoneLock = next.lock
74
+ if (next.foregrounded !== undefined) appForegrounded = next.foregrounded
75
+ if (appForegrounded !== foregroundBefore) {
76
+ for (const listener of Array.from(foregroundListeners)) listener(appForegrounded)
77
+ }
78
+ const after = isPhoneActive()
79
+ if (after === before) return
80
+ for (const listener of Array.from(listeners)) listener(after)
81
+ }
82
+
83
+ /**
84
+ * A suspended app misses lock events, so the state is re-read whenever the
85
+ * app changes foreground state, not only at start.
86
+ */
87
+ function refreshLockState(): void {
88
+ void Promise.resolve(CrustModule.getPhoneLockState())
89
+ .then((state) => {
90
+ if (started) update({lock: state})
91
+ })
92
+ .catch((err: unknown) => console.warn(`PhoneActivity: getPhoneLockState failed: ${(err as Error)?.message ?? err}`))
93
+ }
94
+
95
+ export function startPhoneActivityTracking(): void {
96
+ if (started) return
97
+ started = true
98
+ appForegrounded = AppState.currentState === "active"
99
+ lockStateSubscription = CrustModule.addListener("phone_lock_state", (state: PhoneLockState) => update({lock: state}))
100
+ appStateSubscription = AppState.addEventListener("change", (next: AppStateStatus) => {
101
+ update({foregrounded: next === "active"})
102
+ refreshLockState()
103
+ })
104
+ refreshLockState()
105
+ }
106
+
107
+ export function stopPhoneActivityTracking(): void {
108
+ started = false
109
+ lockStateSubscription?.remove()
110
+ lockStateSubscription = null
111
+ appStateSubscription?.remove()
112
+ appStateSubscription = null
113
+ phoneLock = ASSUMED_LOCKED
114
+ appForegrounded = false
115
+ foregroundListeners.clear()
116
+ }
@@ -1,5 +1,7 @@
1
1
  import BluetoothSdk, {type CameraFovRequest, type CameraFovResult} from "@glassly/bluetooth-sdk/internal"
2
2
 
3
+ import {BgTimer} from "../utils/timers"
4
+
3
5
  export const CAMERA_FOV_OVERRIDE_TTL_MS = 300_000
4
6
  export const CAMERA_FOV_OVERRIDE_REFRESH_MS = 120_000
5
7
  // Legacy ASG clients restart the camera HAL for an FOV update but cannot acknowledge
@@ -36,7 +38,7 @@ export class PhoneCameraFovCoordinator {
36
38
  private effectiveLeaseId: string | undefined
37
39
  private sequence = 0
38
40
  private queue: Promise<unknown> = Promise.resolve()
39
- private refreshTimer: ReturnType<typeof setTimeout> | undefined
41
+ private refreshTimer: number | undefined
40
42
  private legacyMode = false
41
43
 
42
44
  constructor(private readonly legacyRestartSettleMs = LEGACY_CAMERA_RESTART_SETTLE_MS) {}
@@ -147,7 +149,7 @@ export class PhoneCameraFovCoordinator {
147
149
  this.clearRefresh()
148
150
  const leaseId = this.effectiveLeaseId
149
151
  if (!leaseId) return
150
- this.refreshTimer = setTimeout(() => {
152
+ this.refreshTimer = BgTimer.setTimeout(() => {
151
153
  void this.enqueue(async () => {
152
154
  if (this.effectiveLeaseId !== leaseId) return
153
155
  const entry = [...this.overrides.values()].find((candidate) => candidate.leaseId === leaseId)
@@ -164,7 +166,7 @@ export class PhoneCameraFovCoordinator {
164
166
  }
165
167
 
166
168
  private clearRefresh(): void {
167
- if (this.refreshTimer) clearTimeout(this.refreshTimer)
169
+ if (this.refreshTimer) BgTimer.clearTimeout(this.refreshTimer)
168
170
  this.refreshTimer = undefined
169
171
  }
170
172
 
@@ -194,7 +196,7 @@ export class PhoneCameraFovCoordinator {
194
196
 
195
197
  private waitForLegacyCameraRestart(): Promise<void> {
196
198
  if (this.legacyRestartSettleMs <= 0) return Promise.resolve()
197
- return new Promise<void>((resolve) => setTimeout(resolve, this.legacyRestartSettleMs))
199
+ return new Promise<void>((resolve) => BgTimer.setTimeout(resolve, this.legacyRestartSettleMs))
198
200
  }
199
201
 
200
202
  private enqueue<T>(operation: () => Promise<T>): Promise<T> {