@glassly/engine 0.1.0-dev.99 → 0.2.9-beta.448

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
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Stage timeline of one dashboard open, for the dashboard open timing debug
3
+ * setting. The clock starts when the opening gesture reaches the phone (or
4
+ * when native received it, if the event carries that time); every stage is
5
+ * stamped as ms after that. No I/O: DashboardOpenTrace.ts feeds it.
6
+ */
7
+
8
+ export type DashboardOpenTrigger = "head-up" | "double-tap"
9
+
10
+ /** In order. `js` exists only when the gesture carried a native receipt time; `settled` needs CFW rev 27+. */
11
+ export const DASHBOARD_OPEN_STAGES = ["js", "showView", "slot", "frame", "presented", "settled"] as const
12
+ export type DashboardOpenStage = (typeof DASHBOARD_OPEN_STAGES)[number]
13
+
14
+ /** The stages every open must pass; the first one missing is where it stalled. */
15
+ const REQUIRED_STAGES: readonly DashboardOpenStage[] = ["showView", "slot", "frame", "presented"]
16
+
17
+ const STAGE_LABELS: Record<DashboardOpenStage, string> = {
18
+ js: "js",
19
+ showView: "showView",
20
+ slot: "slot",
21
+ frame: "frame",
22
+ presented: "shown",
23
+ settled: "settled",
24
+ }
25
+
26
+ export interface DashboardOpenTrace {
27
+ trigger: DashboardOpenTrigger
28
+ /** Further triggers of the same kind before the dashboard asked for the view. */
29
+ repeats: number
30
+ stages: Partial<Record<DashboardOpenStage, number>>
31
+ /** The first required stage that never arrived; absent once the glasses presented the frame. */
32
+ stalledAt?: DashboardOpenStage
33
+ /** What the glasses said when they reported the frame not presented. */
34
+ reason?: string
35
+ /** Since the overlay slot was last granted; null when it hasn't been this session. */
36
+ sinceLastOpenMs: number | null
37
+ /** How long the requesting overlay app had been connected at the gesture; negative when it connected after. */
38
+ appUpMs: number | null
39
+ /** How long the glasses had been connected at the gesture. */
40
+ glassesUpMs: number | null
41
+ }
42
+
43
+ export interface DashboardOpenTimelineDeps {
44
+ now(): number
45
+ setTimeout: (callback: () => void, ms: number) => number
46
+ clearTimeout: (handle: number) => void
47
+ /** A finished open. A gesture the dashboard never answered with showView is dropped silently. */
48
+ onFinished(trace: DashboardOpenTrace): void
49
+ }
50
+
51
+ /** A gesture not answered with showView by then did not open the dashboard; a later stage missing by then stalled. */
52
+ export const OPEN_WINDOW_MS = 15_000
53
+ /** How long to wait for the settle report once the frame was presented. */
54
+ export const SETTLE_GRACE_MS = 2_000
55
+ /** A native receipt time further back than this is on some other clock. */
56
+ const MAX_NATIVE_LAG_MS = 60_000
57
+
58
+ interface ActiveOpen {
59
+ trace: DashboardOpenTrace
60
+ startedAt: number
61
+ frameSeq: number | null
62
+ timer: number
63
+ }
64
+
65
+ export class DashboardOpenTimeline {
66
+ private active: ActiveOpen | null = null
67
+
68
+ constructor(private readonly deps: DashboardOpenTimelineDeps) {}
69
+
70
+ get tracing(): boolean {
71
+ return this.active !== null
72
+ }
73
+
74
+ /** The seq of the open's first overlay frame, once sent. */
75
+ get frameSeq(): number | null {
76
+ return this.active?.frameSeq ?? null
77
+ }
78
+
79
+ /**
80
+ * An opening gesture reached the phone. While an earlier one still waits
81
+ * for showView, the same gesture again only counts as a repeat (the clock
82
+ * keeps the first); a different gesture restarts the clock. Ignored once
83
+ * the open is under way.
84
+ */
85
+ trigger(
86
+ trigger: DashboardOpenTrigger,
87
+ context: {sinceLastOpenMs: number | null; glassesUpMs: number | null},
88
+ nativeAt?: number,
89
+ ): void {
90
+ const active = this.active
91
+ if (active) {
92
+ if (active.trace.stages.showView !== undefined) return
93
+ if (active.trace.trigger === trigger) {
94
+ active.trace.repeats++
95
+ return
96
+ }
97
+ this.cancel()
98
+ }
99
+ const now = this.deps.now()
100
+ const lag = nativeAt === undefined ? -1 : now - nativeAt
101
+ const native = nativeAt !== undefined && lag >= 0 && lag <= MAX_NATIVE_LAG_MS
102
+ this.active = {
103
+ trace: {trigger, repeats: 0, stages: native ? {js: lag} : {}, appUpMs: null, ...context},
104
+ startedAt: native ? nativeAt : now,
105
+ frameSeq: null,
106
+ timer: this.deps.setTimeout(() => this.expire(), OPEN_WINDOW_MS),
107
+ }
108
+ }
109
+
110
+ /** An overlay app asked for the dashboard view; `appConnectedAt` is when it connected, if known. */
111
+ showViewRequested(appConnectedAt: number | null): void {
112
+ const active = this.active
113
+ if (!active || active.trace.stages.showView !== undefined) return
114
+ active.trace.appUpMs = appConnectedAt === null ? null : active.startedAt - appConnectedAt
115
+ this.stamp("showView")
116
+ }
117
+
118
+ slotGranted(): void {
119
+ if (this.active?.trace.stages.showView !== undefined) this.stamp("slot")
120
+ }
121
+
122
+ /** The first overlay frame after the grant left for the glasses. */
123
+ frameSent(seq: number): void {
124
+ const active = this.active
125
+ if (!active || active.trace.stages.slot === undefined || active.frameSeq !== null) return
126
+ active.frameSeq = seq
127
+ this.stamp("frame")
128
+ }
129
+
130
+ /**
131
+ * The glasses reported a frame. A later frame presented folds ours in; ours
132
+ * not presented is noted, and the window still waits for a later one.
133
+ */
134
+ framePresented(seq: number, presented: boolean, reason?: string): void {
135
+ const active = this.active
136
+ if (!active || active.frameSeq === null || seq < active.frameSeq) return
137
+ if (active.trace.stages.presented !== undefined) return
138
+ if (!presented) {
139
+ if (seq === active.frameSeq) active.trace.reason = reason ?? "not presented"
140
+ return
141
+ }
142
+ this.stamp("presented")
143
+ this.deps.clearTimeout(active.timer)
144
+ active.timer = this.deps.setTimeout(() => this.finish(), SETTLE_GRACE_MS)
145
+ }
146
+
147
+ /** The glasses finished the animations of frame `seq` (and every frame before it). */
148
+ frameSettled(seq: number): void {
149
+ const active = this.active
150
+ if (!active || active.frameSeq === null || seq < active.frameSeq) return
151
+ this.stamp("presented")
152
+ this.stamp("settled")
153
+ this.finish()
154
+ }
155
+
156
+ cancel(): void {
157
+ if (!this.active) return
158
+ this.deps.clearTimeout(this.active.timer)
159
+ this.active = null
160
+ }
161
+
162
+ private stamp(stage: DashboardOpenStage): void {
163
+ const active = this.active
164
+ if (!active || active.trace.stages[stage] !== undefined) return
165
+ active.trace.stages[stage] = this.deps.now() - active.startedAt
166
+ }
167
+
168
+ private expire(): void {
169
+ const active = this.active
170
+ if (!active) return
171
+ if (active.trace.stages.showView === undefined) {
172
+ this.active = null
173
+ return
174
+ }
175
+ this.finish()
176
+ }
177
+
178
+ private finish(): void {
179
+ const active = this.active
180
+ if (!active) return
181
+ this.deps.clearTimeout(active.timer)
182
+ this.active = null
183
+ const {trace} = active
184
+ const stalledAt = REQUIRED_STAGES.find((stage) => trace.stages[stage] === undefined)
185
+ if (stalledAt) trace.stalledAt = stalledAt
186
+ else delete trace.reason
187
+ this.deps.onFinished(trace)
188
+ }
189
+ }
190
+
191
+ /** Notification title and body: the headline, the stage timeline, then the context that separates cold opens from warm ones. */
192
+ export function formatDashboardOpenTrace(trace: DashboardOpenTrace): {title: string; body: string} {
193
+ const shown = trace.stages.presented
194
+ const title =
195
+ trace.stalledAt === undefined && shown !== undefined
196
+ ? `Dashboard opened in ${formatMs(shown)} ms`
197
+ : `Dashboard open stalled before ${STAGE_LABELS[trace.stalledAt ?? "presented"]}`
198
+
199
+ const gesture = trace.repeats > 0 ? `${trace.trigger} ×${trace.repeats + 1}` : trace.trigger
200
+ const timeline = [`${gesture} 0`]
201
+ for (const stage of DASHBOARD_OPEN_STAGES) {
202
+ const at = trace.stages[stage]
203
+ if (at !== undefined) timeline.push(`${STAGE_LABELS[stage]} +${formatMs(at)}`)
204
+ }
205
+
206
+ const context = [
207
+ trace.sinceLastOpenMs === null
208
+ ? "first open this session"
209
+ : `last open ${formatDuration(trace.sinceLastOpenMs)} ago`,
210
+ ]
211
+ if (trace.appUpMs !== null) {
212
+ context.push(
213
+ trace.appUpMs < 0
214
+ ? `dashboard app connected ${formatDuration(-trace.appUpMs)} after the gesture`
215
+ : `dashboard app up ${formatDuration(trace.appUpMs)}`,
216
+ )
217
+ }
218
+ if (trace.glassesUpMs !== null) context.push(`glasses up ${formatDuration(trace.glassesUpMs)}`)
219
+
220
+ const lines = [timeline.join(" · "), context.join(" · ")]
221
+ if (trace.reason) lines.push(`glasses: ${trace.reason}`)
222
+ return {title, body: lines.join("\n")}
223
+ }
224
+
225
+ /** 5210 → "5,210". Hand-rolled so it doesn't depend on the runtime's Intl. */
226
+ function formatMs(ms: number): string {
227
+ return String(Math.round(ms)).replace(/\B(?=(\d{3})+(?!\d))/g, ",")
228
+ }
229
+
230
+ function formatDuration(ms: number): string {
231
+ if (ms < 1_000) return `${Math.round(ms)} ms`
232
+ if (ms < 60_000) return `${Math.round(ms / 1_000)} s`
233
+ if (ms < 3_600_000) return `${Math.round(ms / 60_000)} min`
234
+ const hours = Math.floor(ms / 3_600_000)
235
+ const minutes = Math.round((ms % 3_600_000) / 60_000)
236
+ return minutes > 0 ? `${hours} h ${minutes} min` : `${hours} h`
237
+ }
@@ -6,14 +6,18 @@
6
6
  * Native publishes the canvas into the glasses status (0 = none). Because
7
7
  * that path is phone-side rasterization, the stock firmware's container
8
8
  * pools (6 text / 4 image) don't bound a CFW frame either — element caps are
9
- * lifted alongside the canvas, bounded only to keep frames sane.
9
+ * lifted alongside the canvas, bounded only to keep frames sane. Firmware
10
+ * that draws vector shapes keeps 128 scene slots, so shape-heavy frames
11
+ * (a game board, a chart) get a larger shared text/shape budget.
10
12
  */
11
13
  import {useGlassesStore} from "../stores/glasses"
12
- import {DeviceTypes, getModelCapabilities, type Capabilities} from "../types"
13
- import {isGlasslyCfwFirmwareVersion} from "./CustomDashboardModel"
14
+ import {SETTINGS, useSettingsStore} from "../stores/settings"
15
+ import {ALL_DISPLAY_SHAPES, DeviceTypes, getModelCapabilities, type Capabilities} from "../types"
16
+ import {resolveNativeNavigation} from "./nativeNavigationGate"
14
17
 
15
18
  const CFW_MAX_TEXT_ELEMENTS = 24
16
19
  const CFW_MAX_IMAGE_ELEMENTS = 16
20
+ const CFW_VECTOR_MAX_ELEMENTS = 120
17
21
 
18
22
  export interface SceneCanvasSize {
19
23
  width: number
@@ -26,22 +30,37 @@ export function runtimeSceneCanvas(): SceneCanvasSize | null {
26
30
  return {width: sceneCanvasWidth, height: sceneCanvasHeight}
27
31
  }
28
32
 
33
+ function forceNativeNavigationOnCfw(): boolean {
34
+ return useSettingsStore.getState().getSetting(SETTINGS.cfw_native_navigation.key) === true
35
+ }
36
+
29
37
  export function getEffectiveCapabilities(model: DeviceTypes): Capabilities {
30
38
  const base = getModelCapabilities(model)
31
- const canvas = runtimeSceneCanvas()
32
- // The firmware marker lifts the caps even when no canvas has been published:
33
- // CFW classification rides the version string, and a G2 running Glassly CFW
34
- // always rasterizes phone-side regardless of whether native reported dims.
35
- const cfw = model === DeviceTypes.G2 && isGlasslyCfwFirmwareVersion(useGlassesStore.getState().firmwareVersion)
36
- if (!base.display || (!canvas && !cfw)) return base
39
+ // Only G2 CFW publishes a canvas; never let a stale value reshape another model.
40
+ const canvas = model === DeviceTypes.G2 ? runtimeSceneCanvas() : null
41
+ if (!base.display || !canvas) return base
42
+ // Glassly CFW supports the complete vector contract, including SVG and rotation.
43
+ // Upstream g2flash publishes a raster canvas with sceneVector=false.
44
+ const vector = useGlassesStore.getState().sceneVector === true
37
45
  return {
38
46
  ...base,
47
+ hasNativeNavigation: resolveNativeNavigation(base.hasNativeNavigation, true, forceNativeNavigationOnCfw()),
39
48
  display: {
40
49
  ...base.display,
41
- width: canvas?.width ?? base.display.width,
42
- height: canvas?.height ?? base.display.height,
43
- maxTextElements: Math.max(base.display.maxTextElements ?? 0, CFW_MAX_TEXT_ELEMENTS),
44
- maxImageElements: Math.max(base.display.maxImageElements ?? 0, CFW_MAX_IMAGE_ELEMENTS),
50
+ width: canvas.width,
51
+ height: canvas.height,
52
+ maxTextElements: Math.max(
53
+ base.display.maxTextElements ?? 0,
54
+ vector ? CFW_VECTOR_MAX_ELEMENTS : CFW_MAX_TEXT_ELEMENTS,
55
+ ),
56
+ // Vector firmware draws an image as one cached slot, the same as a shape.
57
+ maxImageElements: Math.max(
58
+ base.display.maxImageElements ?? 0,
59
+ vector ? CFW_VECTOR_MAX_ELEMENTS : CFW_MAX_IMAGE_ELEMENTS,
60
+ ),
61
+ ...(vector
62
+ ? {shapes: [...ALL_DISPLAY_SHAPES, "svg" as const], animation: true, rotation: true, depth: true}
63
+ : {}),
45
64
  },
46
65
  }
47
66
  }
@@ -1,28 +1,77 @@
1
1
  /**
2
- * Gesture-claim arbitration (CLAIM_GESTURES), split out of
3
- * LocalMiniappRuntime so it is unit-testable — the runtime module itself
4
- * pulls a native import surface bun can't parse.
2
+ * Gesture registrations in claim order. Exactly one miniapp receives each
3
+ * gesture: the last registration containing it wins. Named scopes let an
4
+ * app temporarily claim gestures without overwriting its persistent shortcuts.
5
+ * Releasing a scope restores the preceding registration; stopping removes all
6
+ * of the app's scopes. This module has no native dependencies.
5
7
  */
8
+ interface GestureRegistration {
9
+ packageName: string
10
+ scope: string
11
+ gestures: ReadonlySet<string>
12
+ }
6
13
 
7
- /**
8
- * True iff the miniapp in front of the user has claimed `gesture`.
9
- *
10
- * "In front" spans both screens. Most claiming apps are glasses-side: the
11
- * terminal runs as a background miniapp with the phone pocketed, so gating on
12
- * the phone's Compositor foreground alone left its double_tap claim inert and
13
- * the system dashboard kept opening mid-session. Glasses ownership is the
14
- * primary signal; the phone foreground is still honored for apps driven from
15
- * the handset. A claimer that owns neither screen is background and never
16
- * hijacks a system gesture.
17
- */
18
- export function claimsGesture(
19
- claims: ReadonlyMap<string, ReadonlySet<string>>,
20
- gesture: string,
21
- glassesOwner: string | null,
22
- phoneForeground: string | null,
23
- ): boolean {
24
- for (const pkg of [glassesOwner, phoneForeground]) {
25
- if (pkg && claims.get(pkg)?.has(gesture) === true) return true
14
+ export interface GestureClaimState {
15
+ registrations: readonly GestureRegistration[]
16
+ }
17
+
18
+ export interface GestureClaimChange {
19
+ packageName: string
20
+ gesture: string
21
+ held: boolean
22
+ }
23
+
24
+ export function emptyGestureClaims(): GestureClaimState {
25
+ return {registrations: []}
26
+ }
27
+
28
+ /** The single receiver of this gesture, regardless of how many scopes registered it. */
29
+ export function gestureClaimant(state: GestureClaimState, gesture: string): string | null {
30
+ for (let i = state.registrations.length - 1; i >= 0; i--) {
31
+ const registration = state.registrations[i]
32
+ if (registration.gestures.has(gesture)) return registration.packageName
26
33
  }
27
- return false
34
+ return null
35
+ }
36
+
37
+ /** Registration and current ownership differ when another app claimed more recently. */
38
+ export function hasGestureClaim(state: GestureClaimState, packageName: string, gesture: string): boolean {
39
+ return state.registrations.some((entry) => entry.packageName === packageName && entry.gestures.has(gesture))
40
+ }
41
+
42
+ function changesBetween(before: GestureClaimState, after: GestureClaimState): GestureClaimChange[] {
43
+ const gestures = new Set([...before.registrations, ...after.registrations].flatMap((entry) => [...entry.gestures]))
44
+ const changes: GestureClaimChange[] = []
45
+ for (const gesture of gestures) {
46
+ const was = gestureClaimant(before, gesture)
47
+ const now = gestureClaimant(after, gesture)
48
+ if (was === now) continue
49
+ if (was !== null) changes.push({packageName: was, gesture, held: false})
50
+ if (now !== null) changes.push({packageName: now, gesture, held: true})
51
+ }
52
+ return changes
53
+ }
54
+
55
+ /** Replace one scope's set. A nonempty registration always becomes the newest claim. */
56
+ export function setGestureClaims(
57
+ state: GestureClaimState,
58
+ packageName: string,
59
+ gestures: readonly string[],
60
+ scope = "default",
61
+ ): {state: GestureClaimState; changes: GestureClaimChange[]} {
62
+ const registrations = state.registrations.filter(
63
+ (entry) => entry.packageName !== packageName || entry.scope !== scope,
64
+ )
65
+ if (gestures.length) registrations.push({packageName, scope, gestures: new Set(gestures)})
66
+ const after = {registrations}
67
+ return {state: after, changes: changesBetween(state, after)}
68
+ }
69
+
70
+ /** Stop removes every scope without notifying the stopped app. */
71
+ export function dropGestureClaims(
72
+ state: GestureClaimState,
73
+ packageName: string,
74
+ ): {state: GestureClaimState; changes: GestureClaimChange[]} {
75
+ const after = {registrations: state.registrations.filter((entry) => entry.packageName !== packageName)}
76
+ return {state: after, changes: changesBetween(state, after).filter((change) => change.packageName !== packageName)}
28
77
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Pure normalizers for the free-text manifest fields (miniapp.json) that the
3
+ * installed-app projection carries onto ClientApp.
4
+ */
5
+
6
+ /** A non-empty manifest string, trimmed; anything else is absent. */
7
+ export function normalizeManifestText(raw: unknown): string | undefined {
8
+ if (typeof raw !== "string") return undefined
9
+ const trimmed = raw.trim()
10
+ return trimmed.length > 0 ? trimmed : undefined
11
+ }
12
+
13
+ /** Manifest tags: lowercase slugs, de-duplicated, non-strings dropped. */
14
+ export function normalizeManifestTags(raw: unknown): string[] {
15
+ if (!Array.isArray(raw)) return []
16
+ const out: string[] = []
17
+ for (const tag of raw) {
18
+ if (typeof tag !== "string") continue
19
+ const slug = tag.trim().toLowerCase()
20
+ if (slug.length > 0 && !out.includes(slug)) out.push(slug)
21
+ }
22
+ return out
23
+ }
@@ -9,42 +9,10 @@ import {AppState} from "react-native"
9
9
 
10
10
  import {storage as mmkvStorage} from "../utils/storage/storage"
11
11
  import {cloudClientService} from "./CloudClientService"
12
- import {EXTENDED_RETENTION, MemoryStore, STANDARD_RETENTION} from "./MemoryStore"
13
-
14
- /**
15
- * Persisted "Plus/Pro memory retention" flag. Cached in MMKV so a paying user
16
- * who relaunches offline keeps their full read window; only a DEFINITIVE
17
- * subscription answer may change it (the RevenueCatSetup effect passes
18
- * nothing on unknown/null customer info).
19
- */
20
- const RETENTION_EXTENDED_KEY = "memory_retention_extended"
21
-
22
- let retentionExtended = ((): boolean => {
23
- const result = mmkvStorage.load<boolean>(RETENTION_EXTENDED_KEY)
24
- return result.is_ok() && result.value === true
25
- })()
26
-
27
- /** Whether the extended (Plus/Pro) retention window is active right now. */
28
- export function isMemoryRetentionExtended(): boolean {
29
- return retentionExtended
30
- }
31
-
32
- /**
33
- * Flip the visible retention window. Called by the host app when the
34
- * subscription state resolves or changes. Downgrading freezes reads to the
35
- * standard window but deletes nothing — the older timeline stays stored and
36
- * reappears on re-upgrade (MemoryStore prunes at the extended bound for
37
- * every tier).
38
- */
39
- export function setMemoryRetentionExtended(extended: boolean): void {
40
- if (retentionExtended === extended) return
41
- retentionExtended = extended
42
- mmkvStorage.save(RETENTION_EXTENDED_KEY, extended)
43
- }
12
+ import {MemoryStore} from "./MemoryStore"
44
13
 
45
14
  export const memoryStore = new MemoryStore({
46
- getUserId: () => cloudClientService.resolveGlasslyUserId(),
47
- getRetention: () => (retentionExtended ? EXTENDED_RETENTION : STANDARD_RETENTION),
15
+ getUserId: () => cloudClientService.resolveUserId(),
48
16
  backend: {
49
17
  get(key: string): unknown | null {
50
18
  const result = mmkvStorage.load<unknown>(key)
@@ -0,0 +1,116 @@
1
+ import type {MirrorContent, MirrorElement, MirrorSnapshot} from "@glassly/miniapp"
2
+
3
+ export interface MirrorSource {
4
+ event: unknown
5
+ canvas: {width: number; height: number} | null
6
+ connected: boolean
7
+ model: string | null
8
+ battery: number
9
+ measureChar: (char: string) => number
10
+ now: number
11
+ }
12
+
13
+ const object = (v: unknown): Record<string, unknown> =>
14
+ v !== null && typeof v === "object" && !Array.isArray(v) ? (v as Record<string, unknown>) : {}
15
+ const number = (v: unknown, fallback = 0): number => (typeof v === "number" && Number.isFinite(v) ? v : fallback)
16
+ const string = (v: unknown): string => (typeof v === "string" ? v : "")
17
+
18
+ /** Copy and normalize host layouts at the public boundary; never leak store references. */
19
+ export function buildMirrorSnapshot(source: MirrorSource, revision: number): MirrorSnapshot {
20
+ const {now, connected, model, measureChar} = source
21
+ const event = object(source.event)
22
+ const layout = object(event.layout)
23
+ let canvas = source.canvas
24
+ let content: MirrorContent = {kind: "empty"}
25
+ const widths: Record<string, number> = {}
26
+ const date = new Date(now)
27
+ const pad = (n: number) => String(n).padStart(2, "0")
28
+ const parseText = (value: unknown) => {
29
+ const text = string(value)
30
+ .replace(/\$DATE\$/g, `${pad(date.getMonth() + 1)}/${pad(date.getDate())}`)
31
+ .replace(/\$TIME12\$/g, `${pad(date.getHours() % 12 || 12)}:${pad(date.getMinutes())}`)
32
+ .replace(/\$TIME24\$/g, `${pad(date.getHours())}:${pad(date.getMinutes())}`)
33
+ .replace(/\$GBATT\$/g, source.battery >= 0 ? `${source.battery}%` : "")
34
+ .replace(/\$CONNECTION_STATUS\$/g, connected ? "Connected" : "Disconnected")
35
+ for (const char of text) widths[char] = measureChar(char)
36
+ return text
37
+ }
38
+ const textElement = (id: string, text: unknown, x: number, y: number, w: number, h: number): MirrorElement => ({
39
+ id,
40
+ type: "text",
41
+ text: parseText(text),
42
+ box: {x, y, w, h},
43
+ change: "created",
44
+ })
45
+ if (!canvas) content = {kind: "unavailable", reason: "no-display"}
46
+ else if (layout.layoutType === "unavailable")
47
+ content = {kind: "unavailable", reason: string(layout.reason) || "unknown"}
48
+ else if (layout.layoutType === "scene") {
49
+ canvas = {width: number(layout.width, canvas.width), height: number(layout.height, canvas.height)}
50
+ const elements: MirrorElement[] = []
51
+ for (const raw of Array.isArray(layout.elements) ? layout.elements : []) {
52
+ const el = object(raw)
53
+ if (typeof el.id !== "string" || typeof el.type !== "string" || !el.box) continue
54
+ // SceneRenderer produces validated FrameElements. Serialization strips
55
+ // references; private native compiler/hash fields stay inside the host.
56
+ const {path: _path, contentHash: _hash, ...copy} = JSON.parse(JSON.stringify(el))
57
+ if (copy.type === "text") copy.text = parseText(copy.text)
58
+ elements.push(copy as MirrorElement)
59
+ }
60
+ content = elements.length ? {kind: "scene", elements, epoch: number(layout.sceneEpoch)} : {kind: "empty"}
61
+ } else if (layout.layoutType === "bitmap_view") {
62
+ content = {kind: "bitmap", data: string(layout.data)}
63
+ } else if (layout.layoutType && layout.layoutType !== "clear_view") {
64
+ const {width: w, height: h} = canvas
65
+ let elements: MirrorElement[] | null = null
66
+ switch (layout.layoutType) {
67
+ case "text_wall":
68
+ case "text_line":
69
+ elements = [textElement("text", layout.text, 0, 0, w, h)]
70
+ break
71
+ case "text_rows":
72
+ elements = [textElement("text", Array.isArray(layout.text) ? layout.text.join("\n") : "", 0, 0, w, h)]
73
+ break
74
+ case "reference_card":
75
+ elements = [
76
+ textElement("text", [string(layout.title), string(layout.text)].filter(Boolean).join("\n"), 0, 0, w, h),
77
+ ]
78
+ break
79
+ case "double_text_wall":
80
+ elements = [
81
+ textElement("top", layout.topText, 0, 0, w, h / 2),
82
+ textElement("bottom", layout.bottomText, 0, h / 2, w, h / 2),
83
+ ]
84
+ break
85
+ case "positioned_text":
86
+ elements = [
87
+ {
88
+ ...textElement(
89
+ "text",
90
+ layout.text,
91
+ number(layout.x),
92
+ number(layout.y),
93
+ number(layout.width, w),
94
+ number(layout.height, h),
95
+ ),
96
+ style: {border: number(layout.borderWidth), radius: number(layout.borderRadius)},
97
+ },
98
+ ]
99
+ break
100
+ }
101
+ content = elements
102
+ ? {kind: "scene", elements, epoch: 0}
103
+ : {kind: "unavailable", reason: `unsupported-layout:${string(layout.layoutType)}`}
104
+ }
105
+ return {
106
+ revision,
107
+ updatedAt: now,
108
+ connected,
109
+ model,
110
+ canvas,
111
+ view: event.view === "dashboard" ? "dashboard" : canvas ? "main" : null,
112
+ appId: typeof layout.appId === "string" ? layout.appId : null,
113
+ content,
114
+ glyphWidths: widths,
115
+ }
116
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The firmware nav UI is a stock-firmware feature. Custom firmware publishes a
3
+ * scene canvas, so the navigation miniapp draws its own HUD there and reads
4
+ * session.compass directly; native nav mode would only cover that up. The
5
+ * debug knob forces it back on for comparing both UIs on hardware.
6
+ */
7
+ export function resolveNativeNavigation(
8
+ modelSupports: boolean | undefined,
9
+ customFirmware: boolean,
10
+ forceOnCustomFirmware: boolean,
11
+ ): boolean | undefined {
12
+ if (modelSupports !== true) return modelSupports
13
+ return !customFirmware || forceOnCustomFirmware
14
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Seeded catalog of apps that post notifications, keyed by bundle id or
3
+ * package name. Where the phone cannot enumerate apps (iOS) the filter UI
4
+ * shows this catalog plus apps the glasses have reported, and firmware whose
5
+ * filter is an allowlist needs known ids so blocking one app does not take
6
+ * every not-yet-seen app down with it. Derived from the SDK's known-apps
7
+ * table so names live in one place.
8
+ */
9
+ import {KNOWN_APPS} from "@glassly/miniapp/known-apps"
10
+ import {Platform} from "react-native"
11
+
12
+ export interface NotificationApp {
13
+ appId: string
14
+ displayName: string
15
+ }
16
+
17
+ /** The catalog for the current phone platform. */
18
+ export function notificationAppCatalog(): NotificationApp[] {
19
+ const other = Platform.OS === "ios" ? "android" : "ios"
20
+ return KNOWN_APPS.filter((app) => app.platform !== other).map((app) => ({appId: app.id, displayName: app.name}))
21
+ }