@glassly/engine 0.1.0-dev.98 → 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
@@ -0,0 +1,163 @@
1
+ /** SVG path compiler shared by scene validation and native wire encoding.
2
+ * Ported from g2flash revision 21; no DOM, Node or mobile-platform dependencies. */
3
+ const u16 = (v: number) => [v & 255, (v >>> 8) & 255]
4
+ function integer(v: number, min: number, max: number, name: string): number {
5
+ if (!Number.isInteger(v) || v < min || v > max) throw new Error(`${name} outside ${min}..${max}: ${v}`)
6
+ return v
7
+ }
8
+ /** SVG d subset: absolute/relative M L H V Q C S T Z; implicit repetitions.
9
+ * Unsupported syntax is rejected. Each filled contour must explicitly close. */
10
+ export function svgPath(d: string): number[] {
11
+ const tokens = d.match(/[a-zA-Z]|[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:[eE][-+]?\d+)?/g) ?? []
12
+ const residue = d.replace(/[a-zA-Z]|[-+]?(?:\d*\.\d+|\d+\.?\d*)(?:[eE][-+]?\d+)?/g, "")
13
+ if (/[^\s,]/.test(residue)) throw new Error("Invalid SVG path syntax")
14
+ let i = 0,
15
+ cmd = "",
16
+ x = 0,
17
+ y = 0,
18
+ sx = 0,
19
+ sy = 0,
20
+ open = false,
21
+ previous = ""
22
+ let cx = 0,
23
+ cy = 0
24
+ const out: number[] = []
25
+ const emit = (op: number, ...coords: number[]) => {
26
+ out.push(op, ...coords.flatMap((v) => u16(integer(Math.round(v * 16), -32768, 32767, "Q4 coordinate"))))
27
+ }
28
+ const number = () => {
29
+ if (i >= tokens.length || /^[a-z]$/i.test(tokens[i])) throw new Error("Missing SVG coordinate")
30
+ const v = Number(tokens[i++])
31
+ if (!Number.isFinite(v)) throw new Error("Invalid number")
32
+ return v
33
+ }
34
+ while (i < tokens.length) {
35
+ if (/^[a-z]$/i.test(tokens[i])) cmd = tokens[i++]
36
+ if (!cmd || !/^[MLHVQCSTZ]$/i.test(cmd)) throw new Error(`Unsupported SVG command: ${cmd}`)
37
+ const op = cmd.toUpperCase(),
38
+ rel = cmd !== op
39
+ const pair = (): [number, number] => [number() + (rel ? x : 0), number() + (rel ? y : 0)]
40
+ if (op === "Z") {
41
+ if (!open) throw new Error("Z without an open contour")
42
+ emit(4)
43
+ x = sx
44
+ y = sy
45
+ open = false
46
+ previous = "Z"
47
+ cmd = ""
48
+ continue
49
+ }
50
+ if (op !== "M" && !open) throw new Error("Path must start with M")
51
+ if (op === "M") {
52
+ if (open) throw new Error("Filled contours must close with Z before another M")
53
+ ;[x, y] = pair()
54
+ sx = x
55
+ sy = y
56
+ open = true
57
+ emit(0, x, y)
58
+ cmd = rel ? "l" : "L"
59
+ } else if (op === "L" || op === "H" || op === "V") {
60
+ if (op === "L") [x, y] = pair()
61
+ else if (op === "H") x = number() + (rel ? x : 0)
62
+ else y = number() + (rel ? y : 0)
63
+ emit(1, x, y)
64
+ } else if (op === "Q" || op === "T") {
65
+ const c = op === "Q" ? pair() : previous === "Q" || previous === "T" ? [2 * x - cx, 2 * y - cy] : [x, y]
66
+ const end = pair()
67
+ emit(2, ...c, ...end)
68
+ ;[cx, cy] = c
69
+ ;[x, y] = end
70
+ } else {
71
+ const a = op === "C" ? pair() : previous === "C" || previous === "S" ? [2 * x - cx, 2 * y - cy] : [x, y]
72
+ const b = pair(),
73
+ end = pair()
74
+ emit(3, ...a, ...b, ...end)
75
+ ;[cx, cy] = b
76
+ ;[x, y] = end
77
+ }
78
+ previous = op
79
+ }
80
+ if (open || !out.length) throw new Error("Expected explicitly closed filled path")
81
+ return out
82
+ }
83
+
84
+ /** Check the same fixed-point subdivision and budgets as revision 21 firmware. */
85
+ export function compileSvgPath(d: string): {commands: number[]; edges: number} {
86
+ if (typeof d !== "string" || d.length > 65536) throw new Error("Invalid SVG path data")
87
+ const commands = svgPath(d)
88
+ if (commands.length > 8192) throw new Error("SVG path exceeds 8192 command bytes")
89
+ let edges = 0,
90
+ count = 0,
91
+ x = 0,
92
+ y = 0,
93
+ sx = 0,
94
+ sy = 0
95
+ const edge = (ax: number, ay: number, bx: number, by: number) => {
96
+ if ((ax !== bx || ay !== by) && ++edges > 512) throw new Error("SVG path exceeds 512 compiled edges")
97
+ }
98
+ const curve = (p: number[], depth: number): void => {
99
+ const u = [
100
+ 3 * p[2] - 2 * p[0] - p[6],
101
+ 3 * p[3] - 2 * p[1] - p[7],
102
+ 3 * p[4] - 2 * p[6] - p[0],
103
+ 3 * p[5] - 2 * p[7] - p[1],
104
+ ]
105
+ if (u.every((v) => Math.abs(v) <= 16)) {
106
+ edge(p[0], p[1], p[6], p[7])
107
+ return
108
+ }
109
+ if (depth === 8) throw new Error("SVG curve exceeds subdivision limit")
110
+ const a = new Array<number>(8),
111
+ b = new Array<number>(8)
112
+ for (let k = 0; k < 2; k++) {
113
+ const ab = Math.trunc((p[k] + p[k + 2]) / 2),
114
+ bc = Math.trunc((p[k + 2] + p[k + 4]) / 2),
115
+ cd = Math.trunc((p[k + 4] + p[k + 6]) / 2)
116
+ const abc = Math.trunc((ab + bc) / 2),
117
+ bcd = Math.trunc((bc + cd) / 2),
118
+ mid = Math.trunc((abc + bcd) / 2)
119
+ a[k] = p[k]
120
+ a[k + 2] = ab
121
+ a[k + 4] = abc
122
+ a[k + 6] = mid
123
+ b[k] = mid
124
+ b[k + 2] = bcd
125
+ b[k + 4] = cd
126
+ b[k + 6] = p[k + 6]
127
+ }
128
+ curve(a, depth + 1)
129
+ curve(b, depth + 1)
130
+ }
131
+ for (let i = 0; i < commands.length; ) {
132
+ const op = commands[i++],
133
+ pairs = op === 4 ? 0 : op === 3 ? 3 : op === 2 ? 2 : 1
134
+ if (++count > 1024) throw new Error("SVG path exceeds 1024 commands")
135
+ const p = [x, y]
136
+ for (let k = 0; k < pairs * 2; k++, i += 2) p.push(((commands[i] | (commands[i + 1] << 8)) << 16) >> 16)
137
+ if (op === 0) {
138
+ x = sx = p[2]
139
+ y = sy = p[3]
140
+ } else if (op === 4) {
141
+ edge(x, y, sx, sy)
142
+ x = sx
143
+ y = sy
144
+ } else if (op === 1) {
145
+ edge(x, y, p[2], p[3])
146
+ x = p[2]
147
+ y = p[3]
148
+ } else {
149
+ if (op === 2) {
150
+ p[6] = p[4]
151
+ p[7] = p[5]
152
+ for (let k = 0; k < 2; k++) {
153
+ p[k + 4] = Math.trunc((p[k + 6] + 2 * p[k + 2]) / 3)
154
+ p[k + 2] = Math.trunc((p[k] + 2 * p[k + 2]) / 3)
155
+ }
156
+ }
157
+ curve(p, 0)
158
+ x = p[6]
159
+ y = p[7]
160
+ }
161
+ }
162
+ return {commands, edges}
163
+ }
Binary file
@@ -1,546 +1,2 @@
1
- import {TextMeasurer} from "../measurer/TextMeasurer"
2
- import {isCJKCharacter, needsHyphenForBreak} from "../measurer/script-detection"
3
- import type {WrapOptions, WrapResult, LineMetrics, BreakMode} from "./types"
4
- import {DEFAULT_WRAP_OPTIONS} from "./types"
5
-
6
- /**
7
- * Wraps text to fit display constraints.
8
- *
9
- * Supports multiple break modes:
10
- * - 'character': Break mid-word with hyphen for 100% line utilization
11
- * - 'word': Break at word boundaries, hyphenate only if word > line width
12
- * - 'strict-word': Break at word boundaries only, no hyphenation
13
- *
14
- * Key features:
15
- * - Pixel-accurate wrapping (no abstract units)
16
- * - Hyphen-aware breaking (accounts for hyphen width)
17
- * - CJK support (breaks anywhere without hyphen)
18
- * - Preserves explicit newlines
19
- * - Respects byte limits for BLE transmission
20
- */
21
- export class TextWrapper {
22
- private readonly measurer: TextMeasurer
23
- private readonly defaultOptions: Required<WrapOptions>
24
-
25
- constructor(measurer: TextMeasurer, defaultOptions?: WrapOptions) {
26
- this.measurer = measurer
27
-
28
- const profile = measurer.getProfile()
29
- this.defaultOptions = {
30
- maxWidthPx: profile.displayWidthPx,
31
- maxLines: profile.maxLines,
32
- maxBytes: profile.maxPayloadBytes,
33
- ...DEFAULT_WRAP_OPTIONS,
34
- ...defaultOptions,
35
- }
36
- }
37
-
38
- /**
39
- * Wrap text to fit within constraints.
40
- *
41
- * @param text - Text to wrap (may contain \n for explicit breaks)
42
- * @param options - Override default options
43
- * @returns Wrap result with lines and metadata
44
- */
45
- wrap(text: string, options?: WrapOptions): WrapResult {
46
- const opts = this.mergeOptions(options)
47
- const {maxWidthPx, maxLines, maxBytes, breakMode, preserveNewlines} = opts
48
-
49
- if (!text || text.length === 0) {
50
- return this.createEmptyResult(opts)
51
- }
52
-
53
- // Split by explicit newlines if preserving them
54
- const paragraphs = preserveNewlines ? text.split("\n") : [text]
55
-
56
- const allLines: string[] = []
57
- const allMetrics: LineMetrics[] = []
58
- let totalBytes = 0
59
- let truncated = false
60
-
61
- for (let pIndex = 0; pIndex < paragraphs.length; pIndex++) {
62
- const paragraph = paragraphs[pIndex]
63
- const isFromNewline = pIndex > 0
64
-
65
- // Wrap this paragraph
66
- const paragraphLines = this.wrapParagraph(paragraph, maxWidthPx, breakMode, opts)
67
-
68
- for (let lIndex = 0; lIndex < paragraphLines.length; lIndex++) {
69
- const line = paragraphLines[lIndex]
70
- const lineBytes = this.measurer.getByteSize(line)
71
-
72
- // Check if we've exceeded limits
73
- if (allLines.length >= maxLines) {
74
- truncated = true
75
- break
76
- }
77
-
78
- if (totalBytes + lineBytes > maxBytes) {
79
- truncated = true
80
- break
81
- }
82
-
83
- const widthPx = this.measurer.measureText(line)
84
- const metrics: LineMetrics = {
85
- text: line,
86
- widthPx,
87
- bytes: lineBytes,
88
- utilizationPercent: Math.round((widthPx / maxWidthPx) * 100),
89
- endsWithHyphen: line.endsWith(opts.hyphenChar) && lIndex < paragraphLines.length - 1,
90
- fromExplicitNewline: isFromNewline && lIndex === 0,
91
- }
92
-
93
- allLines.push(line)
94
- allMetrics.push(metrics)
95
- totalBytes += lineBytes
96
-
97
- // Add newline byte between lines
98
- if (allLines.length < maxLines) {
99
- totalBytes += 1 // \n is 1 byte
100
- }
101
- }
102
-
103
- if (truncated) break
104
- }
105
-
106
- // Find max line width
107
- const maxLineWidthPx = allMetrics.reduce((max, m) => Math.max(max, m.widthPx), 0)
108
-
109
- return {
110
- lines: allLines,
111
- truncated,
112
- maxLineWidthPx,
113
- totalBytes,
114
- lineMetrics: allMetrics,
115
- originalText: text,
116
- breakMode,
117
- }
118
- }
119
-
120
- /**
121
- * Simple wrap returning just lines (convenience method).
122
- *
123
- * @param text - Text to wrap
124
- * @param options - Override default options
125
- * @returns Array of wrapped lines
126
- */
127
- wrapToLines(text: string, options?: WrapOptions): string[] {
128
- return this.wrap(text, options).lines
129
- }
130
-
131
- /**
132
- * Check if text needs wrapping.
133
- *
134
- * @param text - Text to check
135
- * @param maxWidthPx - Optional width override
136
- * @returns true if text exceeds single line
137
- */
138
- needsWrap(text: string, maxWidthPx?: number): boolean {
139
- const width = maxWidthPx ?? this.defaultOptions.maxWidthPx
140
- return this.measurer.measureText(text) > width || text.includes("\n")
141
- }
142
-
143
- /**
144
- * Get current default options.
145
- */
146
- getOptions(): Required<WrapOptions> {
147
- return {...this.defaultOptions}
148
- }
149
-
150
- /**
151
- * Get the measurer instance.
152
- */
153
- getMeasurer(): TextMeasurer {
154
- return this.measurer
155
- }
156
-
157
- /**
158
- * Wrap a single paragraph (no newlines) according to break mode.
159
- */
160
- private wrapParagraph(
161
- paragraph: string,
162
- maxWidthPx: number,
163
- breakMode: BreakMode,
164
- opts: Required<WrapOptions>,
165
- ): string[] {
166
- const trimmed = opts.trimLines ? paragraph.trim() : paragraph
167
-
168
- if (!trimmed) {
169
- return [""]
170
- }
171
-
172
- // Check if it fits on one line
173
- if (this.measurer.fitsInWidth(trimmed, maxWidthPx)) {
174
- return [trimmed]
175
- }
176
-
177
- switch (breakMode) {
178
- case "character":
179
- return this.wrapCharacterMode(trimmed, maxWidthPx, opts)
180
- case "character-no-hyphen":
181
- return this.wrapCharacterNoHyphenMode(trimmed, maxWidthPx, opts)
182
- case "word":
183
- return this.wrapWordMode(trimmed, maxWidthPx, opts)
184
- case "strict-word":
185
- return this.wrapStrictWordMode(trimmed, maxWidthPx, opts)
186
- default:
187
- return this.wrapCharacterMode(trimmed, maxWidthPx, opts)
188
- }
189
- }
190
-
191
- /**
192
- * Character break mode: Break mid-word with hyphen for 100% line utilization.
193
- */
194
- private wrapCharacterMode(text: string, maxWidthPx: number, opts: Required<WrapOptions>): string[] {
195
- return this.wrapCharacterModeInternal(text, maxWidthPx, opts, true)
196
- }
197
-
198
- /**
199
- * Character break mode without hyphen: Break mid-word cleanly without adding hyphen.
200
- */
201
- private wrapCharacterNoHyphenMode(text: string, maxWidthPx: number, opts: Required<WrapOptions>): string[] {
202
- return this.wrapCharacterModeInternal(text, maxWidthPx, opts, false)
203
- }
204
-
205
- /**
206
- * Internal character break implementation with configurable hyphenation.
207
- */
208
- private wrapCharacterModeInternal(
209
- text: string,
210
- maxWidthPx: number,
211
- opts: Required<WrapOptions>,
212
- useHyphen: boolean,
213
- ): string[] {
214
- const lines: string[] = []
215
- const hyphenWidth = this.measurer.measureChar(opts.hyphenChar)
216
-
217
- let currentLine = ""
218
- let currentWidth = 0
219
-
220
- const chars = Array.from(text)
221
-
222
- for (let i = 0; i < chars.length; i++) {
223
- const char = chars[i]
224
- const charWidth = this.measurer.measureChar(char)
225
-
226
- // Would this character fit?
227
- if (currentWidth + charWidth <= maxWidthPx) {
228
- currentLine += char
229
- currentWidth += charWidth
230
- } else {
231
- // Character doesn't fit - need to break
232
-
233
- // Determine if we need a hyphen
234
- const prevChar = currentLine.length > 0 ? currentLine[currentLine.length - 1] : ""
235
- const needsHyphen =
236
- useHyphen && currentLine.length >= opts.minCharsBeforeHyphen && needsHyphenForBreak(prevChar, char)
237
-
238
- if (needsHyphen) {
239
- // Back off characters until hyphen fits
240
- const result = this.backoffForHyphen(currentLine, currentWidth, maxWidthPx, hyphenWidth, opts)
241
-
242
- if (result.skipHyphen) {
243
- // Found a natural word boundary while backing off - no hyphen needed
244
- lines.push(result.line)
245
- } else {
246
- lines.push(result.line + opts.hyphenChar)
247
- }
248
-
249
- // Start new line with backed-off chars + current char
250
- currentLine = result.remainder + char
251
- currentWidth = this.measurer.measureText(currentLine)
252
- } else if (useHyphen === false && !isCJKCharacter(char) && char !== " ") {
253
- // No-hyphen mode: just break cleanly without hyphen
254
- const trimmedLine = opts.trimLines ? currentLine.trimEnd() : currentLine
255
- if (trimmedLine) {
256
- lines.push(trimmedLine)
257
- }
258
- currentLine = char
259
- currentWidth = charWidth
260
- } else {
261
- // No hyphen needed (CJK, space, punctuation)
262
- const trimmedLine = opts.trimLines ? currentLine.trimEnd() : currentLine
263
- if (trimmedLine) {
264
- lines.push(trimmedLine)
265
- }
266
- currentLine = char === " " ? "" : char
267
- currentWidth = char === " " ? 0 : charWidth
268
- }
269
- }
270
- }
271
-
272
- // Add remaining text
273
- if (currentLine) {
274
- const trimmedLine = opts.trimLines ? currentLine.trim() : currentLine
275
- if (trimmedLine) {
276
- lines.push(trimmedLine)
277
- }
278
- }
279
-
280
- return lines.length > 0 ? lines : [""]
281
- }
282
-
283
- /**
284
- * Word break mode: Break at word boundaries, hyphenate only if word > line width.
285
- */
286
- private wrapWordMode(text: string, maxWidthPx: number, opts: Required<WrapOptions>): string[] {
287
- const lines: string[] = []
288
- const words = this.splitIntoWords(text)
289
- const spaceWidth = this.measurer.getSpaceWidth()
290
-
291
- let currentLine = ""
292
- let currentWidth = 0
293
-
294
- for (const word of words) {
295
- const wordWidth = this.measurer.measureText(word)
296
- const needsSpace = currentLine.length > 0
297
- const totalWidth = currentWidth + (needsSpace ? spaceWidth : 0) + wordWidth
298
-
299
- if (totalWidth <= maxWidthPx) {
300
- // Word fits on current line
301
- if (needsSpace) {
302
- currentLine += " "
303
- currentWidth += spaceWidth
304
- }
305
- currentLine += word
306
- currentWidth += wordWidth
307
- } else {
308
- // Word doesn't fit
309
- if (currentLine.length > 0) {
310
- // Push current line and start new one
311
- lines.push(opts.trimLines ? currentLine.trim() : currentLine)
312
- currentLine = ""
313
- currentWidth = 0
314
- }
315
-
316
- // Check if word itself exceeds line width
317
- if (wordWidth > maxWidthPx) {
318
- // Word is too long - hyphenate it
319
- const hyphenatedLines = this.hyphenateLongWord(word, maxWidthPx, opts)
320
- for (let i = 0; i < hyphenatedLines.length - 1; i++) {
321
- lines.push(hyphenatedLines[i])
322
- }
323
- // Last piece becomes start of current line
324
- currentLine = hyphenatedLines[hyphenatedLines.length - 1]
325
- currentWidth = this.measurer.measureText(currentLine)
326
- } else {
327
- // Word fits on new line
328
- currentLine = word
329
- currentWidth = wordWidth
330
- }
331
- }
332
- }
333
-
334
- // Add remaining text
335
- if (currentLine) {
336
- const trimmedLine = opts.trimLines ? currentLine.trim() : currentLine
337
- if (trimmedLine) {
338
- lines.push(trimmedLine)
339
- }
340
- }
341
-
342
- return lines.length > 0 ? lines : [""]
343
- }
344
-
345
- /**
346
- * Strict word break mode: Break at word boundaries only, no hyphenation.
347
- * Long words will overflow the line.
348
- */
349
- private wrapStrictWordMode(text: string, maxWidthPx: number, opts: Required<WrapOptions>): string[] {
350
- const lines: string[] = []
351
- const words = this.splitIntoWords(text)
352
- const spaceWidth = this.measurer.getSpaceWidth()
353
-
354
- let currentLine = ""
355
- let currentWidth = 0
356
-
357
- for (const word of words) {
358
- const wordWidth = this.measurer.measureText(word)
359
- const needsSpace = currentLine.length > 0
360
- const totalWidth = currentWidth + (needsSpace ? spaceWidth : 0) + wordWidth
361
-
362
- if (totalWidth <= maxWidthPx) {
363
- // Word fits on current line
364
- if (needsSpace) {
365
- currentLine += " "
366
- currentWidth += spaceWidth
367
- }
368
- currentLine += word
369
- currentWidth += wordWidth
370
- } else {
371
- // Word doesn't fit
372
- if (currentLine.length > 0) {
373
- // Push current line
374
- lines.push(opts.trimLines ? currentLine.trim() : currentLine)
375
- }
376
- // Start new line with word (even if it overflows)
377
- currentLine = word
378
- currentWidth = wordWidth
379
- }
380
- }
381
-
382
- // Add remaining text
383
- if (currentLine) {
384
- const trimmedLine = opts.trimLines ? currentLine.trim() : currentLine
385
- if (trimmedLine) {
386
- lines.push(trimmedLine)
387
- }
388
- }
389
-
390
- return lines.length > 0 ? lines : [""]
391
- }
392
-
393
- /**
394
- * Split text into words, handling CJK characters specially.
395
- * CJK characters are treated as individual "words" since they can break anywhere.
396
- */
397
- private splitIntoWords(text: string): string[] {
398
- const words: string[] = []
399
- let currentWord = ""
400
-
401
- for (const char of text) {
402
- if (char === " " || char === "\t") {
403
- if (currentWord) {
404
- words.push(currentWord)
405
- currentWord = ""
406
- }
407
- } else if (isCJKCharacter(char)) {
408
- // CJK characters are individual words
409
- if (currentWord) {
410
- words.push(currentWord)
411
- currentWord = ""
412
- }
413
- words.push(char)
414
- } else {
415
- currentWord += char
416
- }
417
- }
418
-
419
- if (currentWord) {
420
- words.push(currentWord)
421
- }
422
-
423
- return words
424
- }
425
-
426
- /**
427
- * Hyphenate a word that's too long to fit on a single line.
428
- */
429
- private hyphenateLongWord(word: string, maxWidthPx: number, opts: Required<WrapOptions>): string[] {
430
- const lines: string[] = []
431
- const hyphenWidth = this.measurer.measureChar(opts.hyphenChar)
432
- const chars = Array.from(word)
433
-
434
- let currentLine = ""
435
- let currentWidth = 0
436
-
437
- for (let i = 0; i < chars.length; i++) {
438
- const char = chars[i]
439
- const charWidth = this.measurer.measureChar(char)
440
- const isLastChar = i === chars.length - 1
441
-
442
- // Check if we need to break (leaving room for hyphen if not last char)
443
- const widthNeeded = isLastChar ? charWidth : charWidth + hyphenWidth
444
-
445
- if (currentWidth + widthNeeded <= maxWidthPx) {
446
- currentLine += char
447
- currentWidth += charWidth
448
- } else {
449
- // Need to break - back off if needed to fit hyphen
450
- if (currentLine.length >= opts.minCharsBeforeHyphen) {
451
- const result = this.backoffForHyphen(currentLine, currentWidth, maxWidthPx, hyphenWidth, opts)
452
- if (result.skipHyphen) {
453
- lines.push(result.line)
454
- } else {
455
- lines.push(result.line + opts.hyphenChar)
456
- }
457
- currentLine = result.remainder + char
458
- currentWidth = this.measurer.measureText(currentLine)
459
- } else {
460
- // Not enough chars for hyphen, just break
461
- if (currentLine) {
462
- lines.push(currentLine)
463
- }
464
- currentLine = char
465
- currentWidth = charWidth
466
- }
467
- }
468
- }
469
-
470
- if (currentLine) {
471
- lines.push(currentLine)
472
- }
473
-
474
- return lines.length > 0 ? lines : [word]
475
- }
476
-
477
- /**
478
- * Back off characters from line end until hyphen fits.
479
- * Returns null if we back off to a space (natural break point - no hyphen needed).
480
- */
481
- private backoffForHyphen(
482
- line: string,
483
- lineWidth: number,
484
- maxWidthPx: number,
485
- hyphenWidth: number,
486
- opts: Required<WrapOptions>,
487
- ): {line: string; remainder: string; skipHyphen: boolean} {
488
- let adjustedLine = line
489
- let adjustedWidth = lineWidth
490
- let remainder = ""
491
-
492
- // Remove characters until hyphen fits
493
- while (adjustedWidth + hyphenWidth > maxWidthPx && adjustedLine.length > opts.minCharsBeforeHyphen) {
494
- const lastChar = adjustedLine[adjustedLine.length - 1]
495
- const lastCharWidth = this.measurer.measureChar(lastChar)
496
-
497
- adjustedLine = adjustedLine.slice(0, -1)
498
- adjustedWidth -= lastCharWidth
499
- remainder = lastChar + remainder
500
-
501
- // If we've backed off to a space, we've found a natural word boundary
502
- // No hyphen is needed - just trim the space and break there
503
- if (adjustedLine.length > 0 && adjustedLine[adjustedLine.length - 1] === " ") {
504
- // Trim trailing space from the line
505
- adjustedLine = adjustedLine.trimEnd()
506
- return {line: adjustedLine, remainder, skipHyphen: true}
507
- }
508
- }
509
-
510
- return {line: adjustedLine, remainder, skipHyphen: false}
511
- }
512
-
513
- /**
514
- * Merge user options with defaults.
515
- */
516
- private mergeOptions(options?: WrapOptions): Required<WrapOptions> {
517
- return {
518
- ...this.defaultOptions,
519
- ...options,
520
- }
521
- }
522
-
523
- /**
524
- * Create an empty result for empty input.
525
- */
526
- private createEmptyResult(opts: Required<WrapOptions>): WrapResult {
527
- return {
528
- lines: [""],
529
- truncated: false,
530
- maxLineWidthPx: 0,
531
- totalBytes: 0,
532
- lineMetrics: [
533
- {
534
- text: "",
535
- widthPx: 0,
536
- bytes: 0,
537
- utilizationPercent: 0,
538
- endsWithHyphen: false,
539
- fromExplicitNewline: false,
540
- },
541
- ],
542
- originalText: "",
543
- breakMode: opts.breakMode,
544
- }
545
- }
546
- }
1
+ // Moved into the SDK (@glassly/miniapp/display) so miniapps lay text out the way the host measures it; this path re-exports it for the engine.
2
+ export {TextWrapper} from "@glassly/miniapp/display"