@mentra/engine 0.1.0-dev.0 → 3.1.0-dev.4

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 (503) hide show
  1. package/README.md +55 -18
  2. package/build/bluetooth-sdk/debug.d.ts +2 -0
  3. package/build/bluetooth-sdk/debug.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/debug.js +2 -0
  5. package/build/bluetooth-sdk/debug.js.map +1 -0
  6. package/build/bluetooth-sdk/index.d.ts +3 -0
  7. package/build/bluetooth-sdk/index.d.ts.map +1 -0
  8. package/build/bluetooth-sdk/index.js +3 -0
  9. package/build/bluetooth-sdk/index.js.map +1 -0
  10. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  11. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  13. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  14. package/build/bluetooth-sdk/react.d.ts +2 -0
  15. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/react.js +2 -0
  17. package/build/bluetooth-sdk/react.js.map +1 -0
  18. package/build/bluetooth-sdk/types.d.ts +2 -0
  19. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/types.js +2 -0
  21. package/build/bluetooth-sdk/types.js.map +1 -0
  22. package/build/engine.d.ts +24 -16
  23. package/build/engine.d.ts.map +1 -1
  24. package/build/engine.js +9 -4
  25. package/build/engine.js.map +1 -1
  26. package/build/facades/dev.d.ts +3 -2
  27. package/build/facades/dev.d.ts.map +1 -1
  28. package/build/facades/dev.js +18 -12
  29. package/build/facades/dev.js.map +1 -1
  30. package/build/facades/display.d.ts +1 -1
  31. package/build/facades/display.d.ts.map +1 -1
  32. package/build/facades/display.js +1 -1
  33. package/build/facades/display.js.map +1 -1
  34. package/build/facades/gallery.js +1 -1
  35. package/build/facades/gallery.js.map +1 -1
  36. package/build/facades/glasses.d.ts +4 -13
  37. package/build/facades/glasses.d.ts.map +1 -1
  38. package/build/facades/glasses.js +21 -6
  39. package/build/facades/glasses.js.map +1 -1
  40. package/build/facades/glassesSettings.d.ts.map +1 -1
  41. package/build/facades/glassesSettings.js +1 -0
  42. package/build/facades/glassesSettings.js.map +1 -1
  43. package/build/facades/miniapps.d.ts +4 -0
  44. package/build/facades/miniapps.d.ts.map +1 -1
  45. package/build/facades/miniapps.js +5 -0
  46. package/build/facades/miniapps.js.map +1 -1
  47. package/build/facades/ota.d.ts +14 -16
  48. package/build/facades/ota.d.ts.map +1 -1
  49. package/build/facades/ota.js +22 -7
  50. package/build/facades/ota.js.map +1 -1
  51. package/build/facades/pairing.d.ts +8 -5
  52. package/build/facades/pairing.d.ts.map +1 -1
  53. package/build/facades/pairing.js +12 -10
  54. package/build/facades/pairing.js.map +1 -1
  55. package/build/facades/permissions.d.ts +10 -0
  56. package/build/facades/permissions.d.ts.map +1 -1
  57. package/build/facades/permissions.js +10 -0
  58. package/build/facades/permissions.js.map +1 -1
  59. package/build/facades/phoneNotifications.d.ts +0 -4
  60. package/build/facades/phoneNotifications.d.ts.map +1 -1
  61. package/build/facades/phoneNotifications.js +4 -14
  62. package/build/facades/phoneNotifications.js.map +1 -1
  63. package/build/facades/speech.d.ts +7 -6
  64. package/build/facades/speech.d.ts.map +1 -1
  65. package/build/facades/speech.js +1 -1
  66. package/build/facades/speech.js.map +1 -1
  67. package/build/generated/releaseMetadata.d.ts +12 -0
  68. package/build/generated/releaseMetadata.d.ts.map +1 -0
  69. package/build/generated/releaseMetadata.js +10 -0
  70. package/build/generated/releaseMetadata.js.map +1 -0
  71. package/build/index.d.ts +10 -8
  72. package/build/index.d.ts.map +1 -1
  73. package/build/index.js +6 -5
  74. package/build/index.js.map +1 -1
  75. package/build/react/MentraLiveOtaFlow.d.ts +38 -0
  76. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  77. package/build/react/MentraLiveOtaFlow.js +528 -0
  78. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  79. package/build/react/index.d.ts +2 -0
  80. package/build/react/index.d.ts.map +1 -0
  81. package/build/react/index.js +2 -0
  82. package/build/react/index.js.map +1 -0
  83. package/build/react/useEngineSnapshot.d.ts +2 -0
  84. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  85. package/build/react/useEngineSnapshot.js +14 -0
  86. package/build/react/useEngineSnapshot.js.map +1 -0
  87. package/build/runtime/bootstrap.d.ts +24 -1
  88. package/build/runtime/bootstrap.d.ts.map +1 -1
  89. package/build/runtime/bootstrap.js +17 -0
  90. package/build/runtime/bootstrap.js.map +1 -1
  91. package/build/runtime/scanQrSeam.d.ts +7 -0
  92. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  93. package/build/runtime/scanQrSeam.js +16 -0
  94. package/build/runtime/scanQrSeam.js.map +1 -0
  95. package/build/services/AppRegistry.d.ts +41 -57
  96. package/build/services/AppRegistry.d.ts.map +1 -1
  97. package/build/services/AppRegistry.js +208 -144
  98. package/build/services/AppRegistry.js.map +1 -1
  99. package/build/services/AudioCloudUplink.d.ts +12 -0
  100. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  101. package/build/services/AudioCloudUplink.js +22 -1
  102. package/build/services/AudioCloudUplink.js.map +1 -1
  103. package/build/services/AudioPlaybackService.d.ts +41 -2
  104. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  105. package/build/services/AudioPlaybackService.js +250 -33
  106. package/build/services/AudioPlaybackService.js.map +1 -1
  107. package/build/services/BlobStore.d.ts +2 -1
  108. package/build/services/BlobStore.d.ts.map +1 -1
  109. package/build/services/BlobStore.js +17 -9
  110. package/build/services/BlobStore.js.map +1 -1
  111. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  112. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  113. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  114. package/build/services/CloudClientService.d.ts +15 -0
  115. package/build/services/CloudClientService.d.ts.map +1 -1
  116. package/build/services/CloudClientService.js +93 -1
  117. package/build/services/CloudClientService.js.map +1 -1
  118. package/build/services/DeviceEventRouter.js +5 -5
  119. package/build/services/DeviceEventRouter.js.map +1 -1
  120. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  121. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  122. package/build/services/ForegroundLocationPermission.js +12 -0
  123. package/build/services/ForegroundLocationPermission.js.map +1 -0
  124. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  125. package/build/services/GlassesSettingsSync.js +9 -3
  126. package/build/services/GlassesSettingsSync.js.map +1 -1
  127. package/build/services/GlassesStatusProjection.d.ts +2 -1
  128. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  129. package/build/services/GlassesStatusProjection.js +15 -8
  130. package/build/services/GlassesStatusProjection.js.map +1 -1
  131. package/build/services/HotspotOtaTransport.d.ts +29 -0
  132. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  133. package/build/services/HotspotOtaTransport.js +146 -0
  134. package/build/services/HotspotOtaTransport.js.map +1 -0
  135. package/build/services/HotspotShutdown.d.ts +17 -0
  136. package/build/services/HotspotShutdown.d.ts.map +1 -0
  137. package/build/services/HotspotShutdown.js +29 -0
  138. package/build/services/HotspotShutdown.js.map +1 -0
  139. package/build/services/LocalDisplayManager.d.ts +15 -0
  140. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  141. package/build/services/LocalDisplayManager.js +106 -20
  142. package/build/services/LocalDisplayManager.js.map +1 -1
  143. package/build/services/LocalMiniappRuntime.d.ts +74 -2
  144. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  145. package/build/services/LocalMiniappRuntime.js +785 -291
  146. package/build/services/LocalMiniappRuntime.js.map +1 -1
  147. package/build/services/LocalMiniappStorage.d.ts +32 -0
  148. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  149. package/build/services/LocalMiniappStorage.js +66 -0
  150. package/build/services/LocalMiniappStorage.js.map +1 -0
  151. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  152. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  153. package/build/services/LocalMiniappUserIdentity.js +43 -0
  154. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  155. package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
  156. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  157. package/build/services/LocalSttFallbackCoordinator.js +18 -12
  158. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  159. package/build/services/MicStateCoordinator.d.ts +42 -1
  160. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  161. package/build/services/MicStateCoordinator.js +141 -3
  162. package/build/services/MicStateCoordinator.js.map +1 -1
  163. package/build/services/MiniappLauncher.d.ts.map +1 -1
  164. package/build/services/MiniappLauncher.js +23 -3
  165. package/build/services/MiniappLauncher.js.map +1 -1
  166. package/build/services/MiniappLiveness.d.ts +12 -0
  167. package/build/services/MiniappLiveness.d.ts.map +1 -0
  168. package/build/services/MiniappLiveness.js +16 -0
  169. package/build/services/MiniappLiveness.js.map +1 -0
  170. package/build/services/NativeHttpResponse.d.ts +3 -0
  171. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  172. package/build/services/NativeHttpResponse.js +6 -0
  173. package/build/services/NativeHttpResponse.js.map +1 -0
  174. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  175. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  176. package/build/services/OtaArtifactDownloader.js +226 -0
  177. package/build/services/OtaArtifactDownloader.js.map +1 -0
  178. package/build/services/OtaAutoChain.d.ts +34 -0
  179. package/build/services/OtaAutoChain.d.ts.map +1 -0
  180. package/build/services/OtaAutoChain.js +83 -0
  181. package/build/services/OtaAutoChain.js.map +1 -0
  182. package/build/services/OtaErrorMapping.d.ts +18 -0
  183. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  184. package/build/services/OtaErrorMapping.js +63 -0
  185. package/build/services/OtaErrorMapping.js.map +1 -0
  186. package/build/services/OtaInstallCoordinator.d.ts +95 -15
  187. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  188. package/build/services/OtaInstallCoordinator.js +577 -130
  189. package/build/services/OtaInstallCoordinator.js.map +1 -1
  190. package/build/services/OtaService.d.ts.map +1 -1
  191. package/build/services/OtaService.js +8 -1
  192. package/build/services/OtaService.js.map +1 -1
  193. package/build/services/OtaUpdateCheckService.d.ts +39 -4
  194. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  195. package/build/services/OtaUpdateCheckService.js +138 -22
  196. package/build/services/OtaUpdateCheckService.js.map +1 -1
  197. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  198. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  199. package/build/services/PhoneCalendarHelpers.js +157 -0
  200. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  201. package/build/services/PhoneCalendarService.d.ts +5 -0
  202. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  203. package/build/services/PhoneCalendarService.js +45 -0
  204. package/build/services/PhoneCalendarService.js.map +1 -0
  205. package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
  206. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  207. package/build/services/PhoneCameraFovCoordinator.js +194 -0
  208. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  209. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  210. package/build/services/PhoneNotificationsSync.js +12 -10
  211. package/build/services/PhoneNotificationsSync.js.map +1 -1
  212. package/build/services/PhonePhotoCoordinator.d.ts +26 -2
  213. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  214. package/build/services/PhonePhotoCoordinator.js +79 -9
  215. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  216. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  217. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  218. package/build/services/PhoneStreamCoordinator.js +125 -13
  219. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  220. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  221. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  222. package/build/services/PhoneVideoCoordinator.js +10 -0
  223. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  224. package/build/services/SceneRenderer.d.ts.map +1 -1
  225. package/build/services/SceneRenderer.js +15 -0
  226. package/build/services/SceneRenderer.js.map +1 -1
  227. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  228. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  229. package/build/services/SentenceTtsPipeline.js +67 -0
  230. package/build/services/SentenceTtsPipeline.js.map +1 -0
  231. package/build/services/SupportProfileSync.d.ts +22 -0
  232. package/build/services/SupportProfileSync.d.ts.map +1 -0
  233. package/build/services/SupportProfileSync.js +213 -0
  234. package/build/services/SupportProfileSync.js.map +1 -0
  235. package/build/services/TranscriptionRouting.d.ts +12 -0
  236. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  237. package/build/services/TranscriptionRouting.js +24 -0
  238. package/build/services/TranscriptionRouting.js.map +1 -0
  239. package/build/services/TtsTextSanitizer.d.ts +5 -0
  240. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  241. package/build/services/TtsTextSanitizer.js +61 -0
  242. package/build/services/TtsTextSanitizer.js.map +1 -0
  243. package/build/services/WifiAdbRequest.d.ts +17 -0
  244. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  245. package/build/services/WifiAdbRequest.js +35 -0
  246. package/build/services/WifiAdbRequest.js.map +1 -0
  247. package/build/services/asg/asgCameraApi.d.ts +43 -0
  248. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  249. package/build/services/asg/asgCameraApi.js +509 -26
  250. package/build/services/asg/asgCameraApi.js.map +1 -1
  251. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  252. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  253. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  254. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  255. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  256. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  257. package/build/services/asg/cameraRollExportLedger.js +78 -0
  258. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  259. package/build/services/asg/galleryNotices.d.ts +1 -1
  260. package/build/services/asg/galleryNotices.d.ts.map +1 -1
  261. package/build/services/asg/galleryNotices.js.map +1 -1
  262. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  263. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  264. package/build/services/asg/galleryPathMigration.js +26 -0
  265. package/build/services/asg/galleryPathMigration.js.map +1 -0
  266. package/build/services/asg/gallerySettingsService.d.ts +1 -0
  267. package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
  268. package/build/services/asg/gallerySettingsService.js +2 -0
  269. package/build/services/asg/gallerySettingsService.js.map +1 -1
  270. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  271. package/build/services/asg/gallerySyncService.js +162 -56
  272. package/build/services/asg/gallerySyncService.js.map +1 -1
  273. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  274. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  275. package/build/services/asg/galleryTransferLedger.js +225 -0
  276. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  277. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  278. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  279. package/build/services/asg/localNetworkTransport.js +144 -0
  280. package/build/services/asg/localNetworkTransport.js.map +1 -0
  281. package/build/services/asg/localStorageService.d.ts +18 -0
  282. package/build/services/asg/localStorageService.d.ts.map +1 -1
  283. package/build/services/asg/localStorageService.js +168 -19
  284. package/build/services/asg/localStorageService.js.map +1 -1
  285. package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
  286. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
  287. package/build/services/asg/mediaProcessingQueue.js +193 -62
  288. package/build/services/asg/mediaProcessingQueue.js.map +1 -1
  289. package/build/services/audioPlaybackAssets.d.ts +8 -0
  290. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  291. package/build/services/audioPlaybackAssets.js +7 -0
  292. package/build/services/audioPlaybackAssets.js.map +1 -0
  293. package/build/services/gallerySyncClock.js +1 -1
  294. package/build/services/gallerySyncClock.js.map +1 -1
  295. package/build/services/glassesClockSync.d.ts.map +1 -1
  296. package/build/services/glassesClockSync.js +6 -2
  297. package/build/services/glassesClockSync.js.map +1 -1
  298. package/build/services/manifestActions.d.ts +7 -0
  299. package/build/services/manifestActions.d.ts.map +1 -0
  300. package/build/services/manifestActions.js +25 -0
  301. package/build/services/manifestActions.js.map +1 -0
  302. package/build/services/otaDisplayState.d.ts +23 -12
  303. package/build/services/otaDisplayState.d.ts.map +1 -1
  304. package/build/services/otaDisplayState.js +36 -14
  305. package/build/services/otaDisplayState.js.map +1 -1
  306. package/build/services/otaInstallPolicy.d.ts +16 -4
  307. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  308. package/build/services/otaInstallPolicy.js +24 -3
  309. package/build/services/otaInstallPolicy.js.map +1 -1
  310. package/build/services/otaLegacyMapping.d.ts +1 -1
  311. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  312. package/build/services/otaLegacyMapping.js.map +1 -1
  313. package/build/services/otaManifestPolicy.d.ts +14 -0
  314. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  315. package/build/services/otaManifestPolicy.js +19 -0
  316. package/build/services/otaManifestPolicy.js.map +1 -0
  317. package/build/services/otaManifestUrl.d.ts +3 -0
  318. package/build/services/otaManifestUrl.d.ts.map +1 -0
  319. package/build/services/otaManifestUrl.js +38 -0
  320. package/build/services/otaManifestUrl.js.map +1 -0
  321. package/build/services/slimStreamStatus.d.ts +11 -0
  322. package/build/services/slimStreamStatus.d.ts.map +1 -1
  323. package/build/services/slimStreamStatus.js +14 -4
  324. package/build/services/slimStreamStatus.js.map +1 -1
  325. package/build/stores/apps.d.ts.map +1 -1
  326. package/build/stores/apps.js +11 -0
  327. package/build/stores/apps.js.map +1 -1
  328. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  329. package/build/stores/bluetoothSettingKeys.js +2 -0
  330. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  331. package/build/stores/gallerySync.d.ts +2 -0
  332. package/build/stores/gallerySync.d.ts.map +1 -1
  333. package/build/stores/gallerySync.js +2 -0
  334. package/build/stores/gallerySync.js.map +1 -1
  335. package/build/stores/glasses.d.ts.map +1 -1
  336. package/build/stores/glasses.js +3 -0
  337. package/build/stores/glasses.js.map +1 -1
  338. package/build/stores/settings.d.ts +17 -0
  339. package/build/stores/settings.d.ts.map +1 -1
  340. package/build/stores/settings.js +157 -17
  341. package/build/stores/settings.js.map +1 -1
  342. package/build/types/applet.d.ts +2 -0
  343. package/build/types/applet.d.ts.map +1 -1
  344. package/build/types/applet.js.map +1 -1
  345. package/build/types/asg.d.ts +7 -0
  346. package/build/types/asg.d.ts.map +1 -1
  347. package/build/types/asg.js.map +1 -1
  348. package/build/types/enums.d.ts +2 -25
  349. package/build/types/enums.d.ts.map +1 -1
  350. package/build/types/enums.js +2 -27
  351. package/build/types/enums.js.map +1 -1
  352. package/build/types/hardware.d.ts +4 -13
  353. package/build/types/hardware.d.ts.map +1 -1
  354. package/build/types/hardware.js +15 -3
  355. package/build/types/hardware.js.map +1 -1
  356. package/build/types/index.d.ts +2 -6
  357. package/build/types/index.d.ts.map +1 -1
  358. package/build/types/index.js +2 -6
  359. package/build/types/index.js.map +1 -1
  360. package/build/utils/configuredDevHost.d.ts +6 -0
  361. package/build/utils/configuredDevHost.d.ts.map +1 -0
  362. package/build/utils/configuredDevHost.js +19 -0
  363. package/build/utils/configuredDevHost.js.map +1 -0
  364. package/build/utils/devMiniappLaunch.d.ts +19 -8
  365. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  366. package/build/utils/devMiniappLaunch.js +144 -21
  367. package/build/utils/devMiniappLaunch.js.map +1 -1
  368. package/build/utils/diagnosticContext.d.ts.map +1 -1
  369. package/build/utils/diagnosticContext.js +15 -17
  370. package/build/utils/diagnosticContext.js.map +1 -1
  371. package/build/utils/hardware/hardware.d.ts.map +1 -1
  372. package/build/utils/hardware/hardware.js +7 -3
  373. package/build/utils/hardware/hardware.js.map +1 -1
  374. package/build/utils/miniappDiagnostics.d.ts +64 -0
  375. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  376. package/build/utils/miniappDiagnostics.js +173 -0
  377. package/build/utils/miniappDiagnostics.js.map +1 -0
  378. package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
  379. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
  380. package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
  381. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
  382. package/build/utils/timers/timers.d.ts.map +1 -1
  383. package/build/utils/timers/timers.js +55 -18
  384. package/build/utils/timers/timers.js.map +1 -1
  385. package/package.json +59 -31
  386. package/src/assets/silence.wav +0 -0
  387. package/src/bluetooth-sdk/debug.ts +1 -0
  388. package/src/bluetooth-sdk/index.ts +2 -0
  389. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  390. package/src/bluetooth-sdk/react.ts +1 -0
  391. package/src/bluetooth-sdk/types.ts +1 -0
  392. package/src/engine.ts +9 -4
  393. package/src/facades/dev.ts +17 -12
  394. package/src/facades/display.ts +1 -1
  395. package/src/facades/gallery.ts +1 -1
  396. package/src/facades/glasses.ts +20 -7
  397. package/src/facades/glassesSettings.ts +5 -0
  398. package/src/facades/miniapps.ts +7 -0
  399. package/src/facades/ota.ts +23 -8
  400. package/src/facades/pairing.ts +15 -11
  401. package/src/facades/permissions.ts +14 -0
  402. package/src/facades/phoneNotifications.ts +4 -13
  403. package/src/facades/speech.ts +21 -7
  404. package/src/generated/releaseMetadata.ts +20 -0
  405. package/src/index.ts +39 -13
  406. package/src/react/MentraLiveOtaFlow.tsx +856 -0
  407. package/src/react/index.ts +7 -0
  408. package/src/react/useEngineSnapshot.ts +16 -0
  409. package/src/runtime/bootstrap.ts +33 -1
  410. package/src/runtime/scanQrSeam.ts +20 -0
  411. package/src/services/AppRegistry.ts +240 -149
  412. package/src/services/AudioCloudUplink.ts +23 -1
  413. package/src/services/AudioPlaybackService.ts +287 -38
  414. package/src/services/BlobStore.ts +22 -9
  415. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  416. package/src/services/CloudClientService.ts +96 -1
  417. package/src/services/DeviceEventRouter.ts +5 -5
  418. package/src/services/ForegroundLocationPermission.ts +24 -0
  419. package/src/services/GlassesSettingsSync.ts +9 -3
  420. package/src/services/GlassesStatusProjection.ts +16 -8
  421. package/src/services/HotspotOtaTransport.ts +184 -0
  422. package/src/services/HotspotShutdown.ts +41 -0
  423. package/src/services/LocalDisplayManager.ts +112 -21
  424. package/src/services/LocalMiniappRuntime.ts +967 -346
  425. package/src/services/LocalMiniappStorage.ts +82 -0
  426. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  427. package/src/services/LocalSttFallbackCoordinator.ts +19 -12
  428. package/src/services/MicStateCoordinator.ts +169 -4
  429. package/src/services/MiniappLauncher.ts +30 -3
  430. package/src/services/MiniappLiveness.ts +24 -0
  431. package/src/services/NativeHttpResponse.ts +6 -0
  432. package/src/services/OtaArtifactDownloader.ts +312 -0
  433. package/src/services/OtaAutoChain.ts +106 -0
  434. package/src/services/OtaErrorMapping.ts +80 -0
  435. package/src/services/OtaInstallCoordinator.ts +649 -144
  436. package/src/services/OtaService.ts +11 -5
  437. package/src/services/OtaUpdateCheckService.ts +181 -21
  438. package/src/services/PhoneCalendarHelpers.ts +212 -0
  439. package/src/services/PhoneCalendarService.ts +65 -0
  440. package/src/services/PhoneCameraFovCoordinator.ts +210 -0
  441. package/src/services/PhoneNotificationsSync.ts +12 -10
  442. package/src/services/PhonePhotoCoordinator.ts +116 -18
  443. package/src/services/PhoneStreamCoordinator.ts +139 -25
  444. package/src/services/PhoneVideoCoordinator.ts +11 -0
  445. package/src/services/SceneRenderer.ts +16 -0
  446. package/src/services/SentenceTtsPipeline.ts +106 -0
  447. package/src/services/SupportProfileSync.ts +218 -0
  448. package/src/services/TranscriptionRouting.ts +37 -0
  449. package/src/services/TtsTextSanitizer.ts +66 -0
  450. package/src/services/WifiAdbRequest.ts +53 -0
  451. package/src/services/asg/asgCameraApi.ts +615 -33
  452. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  453. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  454. package/src/services/asg/galleryNotices.ts +1 -0
  455. package/src/services/asg/galleryPathMigration.ts +22 -0
  456. package/src/services/asg/gallerySettingsService.ts +3 -0
  457. package/src/services/asg/gallerySyncService.ts +184 -73
  458. package/src/services/asg/galleryTransferLedger.ts +312 -0
  459. package/src/services/asg/localNetworkTransport.ts +169 -0
  460. package/src/services/asg/localStorageService.ts +179 -24
  461. package/src/services/asg/mediaProcessingQueue.ts +209 -62
  462. package/src/services/audioPlaybackAssets.ts +8 -0
  463. package/src/services/gallerySyncClock.ts +1 -1
  464. package/src/services/glassesClockSync.ts +6 -2
  465. package/src/services/manifestActions.ts +30 -0
  466. package/src/services/otaDisplayState.ts +58 -17
  467. package/src/services/otaInstallPolicy.ts +30 -4
  468. package/src/services/otaLegacyMapping.ts +1 -1
  469. package/src/services/otaManifestPolicy.ts +42 -0
  470. package/src/services/otaManifestUrl.ts +44 -0
  471. package/src/services/slimStreamStatus.ts +16 -5
  472. package/src/stores/apps.ts +12 -0
  473. package/src/stores/bluetoothSettingKeys.ts +2 -0
  474. package/src/stores/gallerySync.ts +4 -0
  475. package/src/stores/glasses.ts +3 -0
  476. package/src/stores/settings.ts +179 -18
  477. package/src/types/applet.ts +2 -0
  478. package/src/types/asg.ts +7 -0
  479. package/src/types/enums.ts +3 -28
  480. package/src/types/hardware.ts +20 -13
  481. package/src/types/index.ts +2 -6
  482. package/src/utils/configuredDevHost.ts +17 -0
  483. package/src/utils/devMiniappLaunch.ts +151 -23
  484. package/src/utils/diagnosticContext.ts +17 -17
  485. package/src/utils/hardware/hardware.ts +7 -9
  486. package/src/utils/miniappDiagnostics.ts +226 -0
  487. package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
  488. package/src/utils/timers/timers.ts +57 -21
  489. package/build/devtools.d.ts +0 -11
  490. package/build/devtools.d.ts.map +0 -1
  491. package/build/devtools.js +0 -13
  492. package/build/devtools.js.map +0 -1
  493. package/build/internal.d.ts +0 -66
  494. package/build/internal.d.ts.map +0 -1
  495. package/build/internal.js +0 -89
  496. package/build/internal.js.map +0 -1
  497. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  498. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  499. package/build/services/asgOtaVersionUrl.js +0 -36
  500. package/build/services/asgOtaVersionUrl.js.map +0 -1
  501. package/src/devtools.ts +0 -13
  502. package/src/internal.ts +0 -158
  503. package/src/services/asgOtaVersionUrl.ts +0 -41
@@ -22,10 +22,13 @@ import { permissions, PermissionFeatures } from "../../facades/permissions";
22
22
  import { asgCameraApi } from "./asgCameraApi";
23
23
  import { gallerySettingsService } from "./gallerySettingsService";
24
24
  import { gallerySyncNotifications } from "./gallerySyncNotifications";
25
+ import { localNetworkTransport } from "./localNetworkTransport";
25
26
  import { localStorageService } from "./localStorageService";
26
27
  import { mediaProcessingQueue } from "./mediaProcessingQueue";
27
28
  import { validateCaptureMetadataForDownload } from "./galleryMediaValidation";
28
29
  import { emitGalleryNotice } from "./galleryNotices";
30
+ import { galleryTransferLedger } from "./galleryTransferLedger";
31
+ import { cameraRollExportCoordinator } from "./cameraRollExportCoordinator";
29
32
  // Timing constants
30
33
  const TIMING = {
31
34
  HOTSPOT_CONNECT_DELAY_MS: 3000, // Increased from 1000ms - hotspot needs time to broadcast and become discoverable
@@ -87,6 +90,7 @@ class GallerySyncService {
87
90
  this.appStateSubscription = AppState.addEventListener("change", this.handleAppStateChange);
88
91
  this.hotspotListenerRegistered = true;
89
92
  this.isInitialized = true;
93
+ void cameraRollExportCoordinator.initialize();
90
94
  // console.log("[GallerySyncService] Initialized")
91
95
  // Check for resumable sync on startup
92
96
  this.checkForResumableSync();
@@ -95,6 +99,7 @@ class GallerySyncService {
95
99
  * Cleanup - remove event listeners
96
100
  */
97
101
  cleanup() {
102
+ void localNetworkTransport.disconnect();
98
103
  if (this.hotspotListenerRegistered) {
99
104
  GlobalEventEmitter.removeListener("hotspot_status_change", this.handleHotspotStatusChange);
100
105
  GlobalEventEmitter.removeListener("hotspot_error", this.handleHotspotError);
@@ -109,6 +114,7 @@ class GallerySyncService {
109
114
  this.appStateSubscription.remove();
110
115
  this.appStateSubscription = null;
111
116
  }
117
+ cameraRollExportCoordinator.cleanup();
112
118
  if (this.hotspotConnectionTimeout) {
113
119
  BgTimer.clearTimeout(this.hotspotConnectionTimeout);
114
120
  this.hotspotConnectionTimeout = null;
@@ -118,6 +124,10 @@ class GallerySyncService {
118
124
  this.hotspotRequestTimeout = null;
119
125
  }
120
126
  this.syncStartPromise = null;
127
+ useGallerySyncStore.getState().setSyncStarting(false);
128
+ this.waitingForWifiRetry = false;
129
+ this.wifiSettingsOpenedAt = null;
130
+ this.startAborted = false;
121
131
  this.isInitialized = false;
122
132
  console.log("[GallerySyncService] Cleaned up");
123
133
  }
@@ -153,6 +163,7 @@ class GallerySyncService {
153
163
  this.hotspotRequestTimeout = null;
154
164
  }
155
165
  gallerySyncNotifications.showSyncError("Glasses disconnected");
166
+ void localNetworkTransport.disconnect();
156
167
  };
157
168
  /**
158
169
  * Handle app state changes to auto-retry sync when user returns from settings
@@ -162,6 +173,8 @@ class GallerySyncService {
162
173
  if (nextAppState !== "active") {
163
174
  return;
164
175
  }
176
+ // Camera-roll backfill is phone-local and must resume independently of glasses/WiFi.
177
+ void cameraRollExportCoordinator.resume("app foreground");
165
178
  // Only auto-retry if we were waiting for WiFi
166
179
  if (!this.waitingForWifiRetry) {
167
180
  return;
@@ -174,41 +187,46 @@ class GallerySyncService {
174
187
  if (!glassesConnected) {
175
188
  console.log("[GallerySyncService] Glasses disconnected - not retrying sync");
176
189
  this.waitingForWifiRetry = false;
190
+ this.wifiSettingsOpenedAt = null;
177
191
  return;
178
192
  }
193
+ // The user has returned from the WiFi settings prompt, so the previous
194
+ // "Sync failed" state is no longer actionable. Make the button available
195
+ // immediately while the native WiFi state catches up; a successful check
196
+ // below will start the sync automatically.
197
+ if (store.syncState === "error" && store.lastError?.startsWith("WiFi disabled")) {
198
+ store.setSyncState("idle");
199
+ }
179
200
  // Check if WiFi is now enabled (Android only)
180
201
  // Use retry logic because WiFi status takes time to propagate after user enables it
181
202
  if (Platform.OS === "android") {
182
203
  const MAX_RETRIES = 5;
183
- const RETRY_DELAY_MS = 1000; // Wait 500ms between checks
204
+ const RETRY_DELAY_MS = 1000;
184
205
  console.log("[GallerySyncService] Waiting for WiFi to initialize (may take a moment after enabling)...");
185
206
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
186
207
  try {
187
208
  await new Promise((resolve) => BgTimer.setTimeout(() => resolve(), RETRY_DELAY_MS));
188
- const netState = await NetInfo.fetch();
189
- console.log(`[GallerySyncService] WiFi check attempt ${attempt}/${MAX_RETRIES}: enabled=${netState.isWifiEnabled}`);
190
- if (netState.isWifiEnabled === true) {
209
+ // NetInfo can remain stale after Android's WiFi settings close. Use
210
+ // the same native source as the normal sync preflight.
211
+ const wifiEnabled = await WifiManager.isEnabled();
212
+ console.log(`[GallerySyncService] WiFi check attempt ${attempt}/${MAX_RETRIES}: enabled=${wifiEnabled}`);
213
+ if (wifiEnabled) {
191
214
  console.log("[GallerySyncService] ✅ WiFi is now enabled - auto-retrying sync");
192
215
  this.waitingForWifiRetry = false;
193
216
  this.wifiSettingsOpenedAt = null; // Clear cooldown timestamp
194
- // Clear previous error state
195
- store.setSyncState("idle");
196
217
  // Auto-retry sync
197
218
  await this.startSync();
198
219
  return;
199
220
  }
200
- // If this was the last attempt, log and give up
201
- if (attempt === MAX_RETRIES) {
202
- console.log("[GallerySyncService] ❌ WiFi still disabled after all retries - user may need to tap sync manually");
203
- this.waitingForWifiRetry = false;
204
- this.wifiSettingsOpenedAt = null; // Clear cooldown timestamp
205
- }
206
221
  }
207
222
  catch (error) {
208
223
  console.warn(`[GallerySyncService] Failed to check WiFi status on attempt ${attempt}:`, error);
209
224
  // Continue to next retry
210
225
  }
211
226
  }
227
+ console.log("[GallerySyncService] WiFi not detected after retries - leaving sync available for manual retry");
228
+ this.waitingForWifiRetry = false;
229
+ this.wifiSettingsOpenedAt = null;
212
230
  }
213
231
  };
214
232
  /**
@@ -294,8 +312,10 @@ class GallerySyncService {
294
312
  console.log("[GallerySyncService] ⚠️ Sync start already in progress, joining existing attempt");
295
313
  return this.syncStartPromise;
296
314
  }
315
+ useGallerySyncStore.getState().setSyncStarting(true);
297
316
  this.syncStartPromise = this.runStartSync().finally(() => {
298
317
  this.syncStartPromise = null;
318
+ useGallerySyncStore.getState().setSyncStarting(false);
299
319
  });
300
320
  return this.syncStartPromise;
301
321
  }
@@ -401,8 +421,6 @@ class GallerySyncService {
401
421
  connected: glassesConnected,
402
422
  hotspotEnabled: glassesHotspot !== null,
403
423
  });
404
- // Reset processing queue only after pre-flight passes — avoids clobbering an active session
405
- mediaProcessingQueue.reset();
406
424
  // Request all permissions upfront so user isn't interrupted during WiFi/download
407
425
  console.log("[GallerySyncService] 🔐 Step 1/6: Requesting permissions...");
408
426
  // 1. Notification permission (for background sync progress)
@@ -434,6 +452,22 @@ class GallerySyncService {
434
452
  console.log("[GallerySyncService] Pre-flight aborted after location permission");
435
453
  return;
436
454
  }
455
+ if (Platform.OS === "android") {
456
+ console.log("[GallerySyncService] 📡 Checking local WiFi permission...");
457
+ const hasLocalWifiPermission = await permissions.check(PermissionFeatures.LOCAL_WIFI);
458
+ if (!hasLocalWifiPermission) {
459
+ const granted = await permissions.request(PermissionFeatures.LOCAL_WIFI);
460
+ if (!granted) {
461
+ store.setSyncError("Local WiFi permission is required for gallery sync");
462
+ await gallerySyncNotifications.showSyncError("Allow WiFi access to connect to your glasses");
463
+ return;
464
+ }
465
+ }
466
+ if (this.shouldAbortPreFlight()) {
467
+ console.log("[GallerySyncService] Pre-flight aborted after local WiFi permission");
468
+ return;
469
+ }
470
+ }
437
471
  // 3. Camera roll permission (if auto-save is enabled)
438
472
  const shouldAutoSave = await gallerySettingsService.getAutoSaveToCameraRoll();
439
473
  console.log(`[GallerySyncService] 📸 Auto-save to camera roll: ${shouldAutoSave}`);
@@ -444,9 +478,10 @@ class GallerySyncService {
444
478
  console.log("[GallerySyncService] ⚠️ Camera roll permission not granted - requesting...");
445
479
  const granted = await MediaLibraryPermissions.requestPermission();
446
480
  if (!granted) {
447
- console.warn("[GallerySyncService] ❌ Camera roll permission denied - photos will still sync to app");
448
- // Don't block sync - photos will still be downloaded to app storage
449
- // They just won't be saved to the camera roll
481
+ console.warn("[GallerySyncService] ❌ Camera roll permission denied - auto-save sync cannot continue");
482
+ store.setSyncError("Camera-roll permission required while automatic saving is enabled");
483
+ emitGalleryNotice({ code: "camera_roll_permission_required" });
484
+ return;
450
485
  }
451
486
  else {
452
487
  console.log("[GallerySyncService] ✅ Camera roll permission granted");
@@ -635,12 +670,21 @@ class GallerySyncService {
635
670
  console.log("[GallerySyncService] ℹ️ Glasses hotspot not currently enabled");
636
671
  console.log("[GallerySyncService] ➡️ Will request hotspot activation");
637
672
  }
673
+ // Every fallible pre-flight gate has passed. It is now safe to replace the previous
674
+ // in-memory queue; startFileDownload immediately recovers its durable ledger work.
675
+ mediaProcessingQueue.reset();
638
676
  if (isAlreadyConnected && currentGlassesHotspot) {
639
- console.log("[GallerySyncService] 🚀 Skipping hotspot request - already connected!");
640
677
  const hotspotInfo = currentGlassesHotspot;
641
678
  store.setHotspotInfo(hotspotInfo);
642
679
  store.setSyncState("connecting_wifi");
643
- await this.startFileDownload(hotspotInfo);
680
+ if (localNetworkTransport.supportsScopedConnection() && !localNetworkTransport.isScopedConnectionActive()) {
681
+ console.log("[GallerySyncService] 📡 System SSID matches; establishing scoped glasses transport");
682
+ await this.connectToHotspotWifi(hotspotInfo);
683
+ }
684
+ else {
685
+ console.log("[GallerySyncService] 🚀 Skipping hotspot request - already connected!");
686
+ await this.startFileDownload(hotspotInfo);
687
+ }
644
688
  return;
645
689
  }
646
690
  // Request hotspot
@@ -773,7 +817,7 @@ class GallerySyncService {
773
817
  preConnectSSID = await WifiManager.getCurrentWifiSSID();
774
818
  console.log(`[GallerySyncService] 📡 Current WiFi SSID: "${preConnectSSID}"`);
775
819
  // Check if already connected (shouldn't happen, but good to verify)
776
- if (preConnectSSID === hotspotInfo.ssid) {
820
+ if (!localNetworkTransport.supportsScopedConnection() && preConnectSSID === hotspotInfo.ssid) {
777
821
  console.log("[GallerySyncService] ✅ Already connected to target SSID! Proceeding to download.");
778
822
  appStateSubscription.remove();
779
823
  const totalWifiDuration = Date.now() - wifiConnectStartTime;
@@ -790,8 +834,7 @@ class GallerySyncService {
790
834
  console.warn(`[GallerySyncService] ⚠️ Could not get current SSID: ${preError?.message}`);
791
835
  console.warn("[GallerySyncService] ⚠️ Error code:", preError?.code);
792
836
  }
793
- // Use connectToProtectedSSID with joinOnce=false for persistent connection
794
- console.log(`[GallerySyncService] 🔌 Calling WifiManager.connectToProtectedSSID...`);
837
+ console.log(`[GallerySyncService] 🔌 Connecting the glasses-local transport...`);
795
838
  console.log(`[GallerySyncService] 🔌 Parameters:`);
796
839
  console.log(`[GallerySyncService] - SSID: "${hotspotInfo.ssid}"`);
797
840
  console.log(`[GallerySyncService] - Password: ${"*".repeat(hotspotInfo.password.length)}`);
@@ -800,9 +843,9 @@ class GallerySyncService {
800
843
  const connectCallStartTime = Date.now();
801
844
  appBackgrounded = false; // Reset flag for this attempt
802
845
  appBackgroundTime = null;
803
- await WifiManager.connectToProtectedSSID(hotspotInfo.ssid, hotspotInfo.password, false, false);
846
+ await localNetworkTransport.connect(hotspotInfo.ssid, hotspotInfo.password);
804
847
  const connectCallDuration = Date.now() - connectCallStartTime;
805
- console.log(`[GallerySyncService] ✅ WifiManager.connectToProtectedSSID returned successfully`);
848
+ console.log(`[GallerySyncService] ✅ Glasses-local transport connected successfully`);
806
849
  console.log(`[GallerySyncService] ⏱️ Library call duration: ${connectCallDuration}ms`);
807
850
  console.log(`[GallerySyncService] 📱 App was backgrounded during call: ${appBackgrounded}`);
808
851
  if (appBackgrounded && appBackgroundTime) {
@@ -860,7 +903,9 @@ class GallerySyncService {
860
903
  console.log("[GallerySyncService] 👂 App state listener removed");
861
904
  // Final verification: Check SSID one more time before starting download
862
905
  try {
863
- const finalSSID = await WifiManager.getCurrentWifiSSID();
906
+ const finalSSID = localNetworkTransport.isScopedConnectionActive()
907
+ ? hotspotInfo.ssid
908
+ : await WifiManager.getCurrentWifiSSID();
864
909
  console.log(`[GallerySyncService] 📶 Final SSID check before download: "${finalSSID}"`);
865
910
  if (Platform.OS === "android") {
866
911
  // Some local builds can have stale generated typings for the Bluetooth SDK module.
@@ -891,7 +936,7 @@ class GallerySyncService {
891
936
  const probeController = new AbortController();
892
937
  const probeTimeout = BgTimer.setTimeout(() => probeController.abort(), 1000); // 1 second timeout per probe
893
938
  const probeStartTime = Date.now();
894
- const probeResponse = await fetch(`http://${hotspotInfo.ip}:8089/api/health`, {
939
+ const probeResponse = await localNetworkTransport.fetch(`http://${hotspotInfo.ip}:8089/api/health`, {
895
940
  method: "GET",
896
941
  signal: probeController.signal,
897
942
  });
@@ -1064,13 +1109,40 @@ class GallerySyncService {
1064
1109
  }
1065
1110
  }
1066
1111
  finally {
1112
+ // Release the scoped Android Network on every terminal path. This is idempotent with
1113
+ // closeHotspot(), and intentionally leaves Android 9/iOS legacy routing unchanged.
1114
+ await localNetworkTransport.disconnect();
1067
1115
  // L2: Guarantee listener cleanup on all exit paths (cancel, success, error, exhaustion)
1068
1116
  appStateSubscription.remove();
1069
1117
  }
1070
1118
  }
1071
1119
  async fetchSyncManifest(clientId, lastSyncTime) {
1072
- const syncResponse = await asgCameraApi.syncWithServer(clientId, lastSyncTime, true);
1073
- return (syncResponse.data || syncResponse);
1120
+ const v3 = typeof asgCameraApi.getV3Manifest === "function" ? await asgCameraApi.getV3Manifest() : null;
1121
+ if (v3) {
1122
+ const downloadedFiles = await localStorageService.getDownloadedFiles();
1123
+ await localStorageService.reconcileRemoteCaptures(v3.captures.map((capture) => capture.capture_id), downloadedFiles);
1124
+ return {
1125
+ api_version: 3,
1126
+ client_id: clientId,
1127
+ // The ledger is a crash-recovery journal, not proof that app-private media survived an
1128
+ // Android restore or reinstall. Suppress a remote capture only when both records agree.
1129
+ captures: v3.captures.filter((capture) => !downloadedFiles[capture.capture_id] || !galleryTransferLedger.isLocallyCommitted(capture.capture_id)),
1130
+ changed_files: [],
1131
+ deleted_files: [],
1132
+ server_time: v3.server_time,
1133
+ total_changed: v3.captures.length,
1134
+ total_size: v3.captures.reduce((total, capture) => total + capture.total_size, 0),
1135
+ };
1136
+ }
1137
+ // Old firmware remains on the exact v2 endpoint/schema. Avoid expensive inline thumbnails;
1138
+ // video thumbnails are fetched as small side downloads with their primary media.
1139
+ const syncResponse = await asgCameraApi.syncWithServer(clientId, lastSyncTime, false);
1140
+ const data = (syncResponse.data || syncResponse);
1141
+ if (data.captures) {
1142
+ data.captures = data.captures.filter((capture) => !galleryTransferLedger.isLocallyCommitted(capture.capture_id));
1143
+ }
1144
+ data.changed_files = (data.changed_files || []).filter((file) => !galleryTransferLedger.isFileLocallyCommitted(file.name));
1145
+ return data;
1074
1146
  }
1075
1147
  /**
1076
1148
  * Resolve sync manifest: detect skew, optionally fix clock, retry full sync when needed.
@@ -1125,6 +1197,10 @@ class GallerySyncService {
1125
1197
  // Set up the API client
1126
1198
  asgCameraApi.setServer(hotspotInfo.ip, 8089);
1127
1199
  console.log("[GallerySyncService] ✅ API client configured");
1200
+ const recovery = await mediaProcessingQueue.retryPending();
1201
+ if (recovery.retried > 0 || recovery.failed > 0) {
1202
+ console.log(`[GallerySyncService] ♻️ Recovery: ${recovery.retried} completed, ${recovery.failed} still pending`);
1203
+ }
1128
1204
  // Get sync state and files to download
1129
1205
  // IMPORTANT: This creates a SNAPSHOT of files at this moment based on last_sync_time.
1130
1206
  // Any photos taken AFTER this call (during the sync) will NOT be included in this sync.
@@ -1159,16 +1235,21 @@ class GallerySyncService {
1159
1235
  console.log(`[GallerySyncService] - Captures: ${syncData.captures?.length || 0}`);
1160
1236
  if (isSyncManifestEmpty(syncData)) {
1161
1237
  console.log("[GallerySyncService] ✅ No new files to sync - already up to date!");
1162
- store.setSyncComplete();
1238
+ if (galleryTransferLedger.hasPendingRecovery()) {
1239
+ store.setSyncError("Gallery export or acknowledgement needs retry");
1240
+ }
1241
+ else {
1242
+ store.setSyncComplete();
1243
+ }
1163
1244
  await this.onSyncComplete(0, 0);
1164
1245
  return;
1165
1246
  }
1166
1247
  // Detect API version and route to appropriate download path
1167
- const useCaptures = syncData.api_version === 2 && syncData.captures && syncData.captures.length > 0;
1248
+ const useCaptures = (syncData.api_version || 0) >= 2 && syncData.captures && syncData.captures.length > 0;
1168
1249
  if (useCaptures) {
1169
1250
  // New capture-aware sync path
1170
1251
  const captures = syncData.captures;
1171
- console.log(`[GallerySyncService] 📊 Found ${captures.length} captures to download (api_version=2)`);
1252
+ console.log(`[GallerySyncService] 📊 Found ${captures.length} captures to download (api_version=${syncData.api_version})`);
1172
1253
  captures.slice(0, 5).forEach((c, idx) => {
1173
1254
  console.log(`[GallerySyncService] ${idx + 1}. ${c.capture_id} (${c.type}, ${c.files.length} files, ${(c.total_size / 1024).toFixed(1)} KB)`);
1174
1255
  });
@@ -1260,7 +1341,7 @@ class GallerySyncService {
1260
1341
  const downloadResult = await asgCameraApi.batchSyncFiles(files, true, (current, total, fileName, fileProgress, downloadedFile) => {
1261
1342
  // CRITICAL: This callback MUST NOT throw!
1262
1343
  // RNFS progress callbacks run inside native bridge — throwing here causes
1263
- // EXC_BAD_ACCESS. Cancellation is handled via AbortSignal → RNFS.stopDownload.
1344
+ // EXC_BAD_ACCESS. Cancellation is handled via AbortSignal → the active transport.
1264
1345
  // Check if cancelled — just return, abort signal will stop the download
1265
1346
  if (this.abortController?.signal.aborted) {
1266
1347
  return;
@@ -1345,6 +1426,7 @@ class GallerySyncService {
1345
1426
  shouldAutoSave: !!shouldAutoSave,
1346
1427
  thumbnailPath: downloadedFile.thumbnailPath,
1347
1428
  deleteFromGlasses: [downloadedFile.name],
1429
+ protocolVersion: 1,
1348
1430
  });
1349
1431
  }
1350
1432
  }
@@ -1375,18 +1457,6 @@ class GallerySyncService {
1375
1457
  currentStore.onFileComplete(lastFileName);
1376
1458
  }
1377
1459
  }
1378
- // Save downloaded files metadata (skip auxiliary files from gallery entries)
1379
- for (const photoInfo of downloadResult.downloaded) {
1380
- // Skip HDR brackets and IMU sidecars — they shouldn't appear as separate gallery items
1381
- const isAuxiliary = photoInfo.name?.match(/_ev-?\d+\.(jpg|jpeg)$/i) ||
1382
- photoInfo.name?.match(/\.imu\.json$/i) ||
1383
- photoInfo.name?.match(/\/ev-?\d+\.jpe?g$/i) ||
1384
- photoInfo.name?.match(/\/imu\.json$/i);
1385
- if (isAuxiliary)
1386
- continue;
1387
- const downloadedFile = localStorageService.convertToDownloadedFile(photoInfo, photoInfo.filePath || "", photoInfo.thumbnailPath, defaultWearable);
1388
- await localStorageService.saveDownloadedFile(downloadedFile);
1389
- }
1390
1460
  // Update queue index to final position
1391
1461
  await localStorageService.updateSyncQueueIndex(files.length);
1392
1462
  // Mark failed files in store
@@ -1398,6 +1468,16 @@ class GallerySyncService {
1398
1468
  console.log("[GallerySyncService] ⏳ Waiting for processing queue to drain...");
1399
1469
  await mediaProcessingQueue.waitUntilDrained();
1400
1470
  console.log("[GallerySyncService] ✅ Processing queue drained");
1471
+ // Download success is not destination success. Export, validation, metadata, and
1472
+ // acknowledgement failures are reported asynchronously by the processing queue; fold them
1473
+ // back into the legacy result so its timestamp watermark cannot skip the source forever.
1474
+ const processingFailures = new Set(useGallerySyncStore.getState().failedFiles);
1475
+ for (const file of files) {
1476
+ if (processingFailures.has(file.name) && !downloadResult.failed.includes(file.name)) {
1477
+ downloadResult.failed.push(file.name);
1478
+ }
1479
+ }
1480
+ failedCount = downloadResult.failed.length;
1401
1481
  // Update sync state — only advance watermark if files were downloaded.
1402
1482
  // If any failed, set it before the oldest failure so they get retried.
1403
1483
  let syncWatermark = serverTime;
@@ -1453,8 +1533,12 @@ class GallerySyncService {
1453
1533
  console.log(`[GallerySyncService] - Total data (lifetime): ${((currentSyncState.total_size + downloadResult.total_size) /
1454
1534
  1024 /
1455
1535
  1024).toFixed(2)} MB`);
1456
- // Complete
1457
- store.setSyncComplete();
1536
+ if (failedCount > 0 || galleryTransferLedger.hasPendingRecovery()) {
1537
+ store.setSyncError(`${failedCount || "Some"} gallery items need retry`);
1538
+ }
1539
+ else {
1540
+ store.setSyncComplete();
1541
+ }
1458
1542
  await this.onSyncComplete(downloadedCount, failedCount);
1459
1543
  }
1460
1544
  catch (error) {
@@ -1539,6 +1623,7 @@ class GallerySyncService {
1539
1623
  bracketPaths: result.bracketPaths,
1540
1624
  sidecarPath: result.sidecarPath,
1541
1625
  thumbnailData: capture.thumbnail_data,
1626
+ thumbnailPath: result.thumbnailPath,
1542
1627
  captureDir: result.captureDir,
1543
1628
  timestamp: capture.timestamp,
1544
1629
  totalSize: capture.total_size,
@@ -1547,6 +1632,7 @@ class GallerySyncService {
1547
1632
  shouldProcess: !!shouldProcessImages,
1548
1633
  shouldAutoSave: !!shouldAutoSave,
1549
1634
  deleteFromGlasses: [capture.capture_id],
1635
+ protocolVersion: capture.files.some((file) => !!file.etag) ? 3 : 2,
1550
1636
  });
1551
1637
  }
1552
1638
  catch (captureError) {
@@ -1631,7 +1717,12 @@ class GallerySyncService {
1631
1717
  total_size: currentSyncState.total_size + totalSizeDownloaded,
1632
1718
  });
1633
1719
  }
1634
- store.setSyncComplete();
1720
+ if (failedCount > 0 || galleryTransferLedger.hasPendingRecovery()) {
1721
+ store.setSyncError(`${failedCount || "Some"} gallery items need retry`);
1722
+ }
1723
+ else {
1724
+ store.setSyncComplete();
1725
+ }
1635
1726
  await this.onSyncComplete(downloadedCount, failedCount);
1636
1727
  }
1637
1728
  catch (error) {
@@ -1689,12 +1780,24 @@ class GallerySyncService {
1689
1780
  // } catch (error) {
1690
1781
  // console.error(`[GallerySyncService] Failed to get post-sync inventory:`, error)
1691
1782
  // }
1692
- // Clear the queue
1693
- console.log("[GallerySyncService] 🧹 Clearing sync queue...");
1694
- await localStorageService.clearSyncQueue();
1695
- // Show completion notification
1696
- console.log("[GallerySyncService] 📱 Showing completion notification...");
1697
- await gallerySyncNotifications.showSyncComplete(downloadedCount, failedCount);
1783
+ const hasPendingRecovery = galleryTransferLedger.hasPendingRecovery();
1784
+ if (!hasPendingRecovery && failedCount === 0) {
1785
+ console.log("[GallerySyncService] 🧹 Clearing completed sync queue...");
1786
+ await localStorageService.clearSyncQueue();
1787
+ }
1788
+ else {
1789
+ console.log("[GallerySyncService] ♻️ Keeping recovery state for unfinished export/ack work");
1790
+ }
1791
+ if (hasPendingRecovery || failedCount > 0) {
1792
+ console.log("[GallerySyncService] 📱 Showing retry-required notification...");
1793
+ await gallerySyncNotifications.showSyncError(failedCount > 0
1794
+ ? `${failedCount} gallery item${failedCount === 1 ? "" : "s"} will be retried`
1795
+ : "Gallery export or acknowledgement will be retried");
1796
+ }
1797
+ else {
1798
+ console.log("[GallerySyncService] 📱 Showing completion notification...");
1799
+ await gallerySyncNotifications.showSyncComplete(downloadedCount, 0);
1800
+ }
1698
1801
  // Close hotspot if we opened it
1699
1802
  const store = useGallerySyncStore.getState();
1700
1803
  if (store.syncServiceOpenedHotspot) {
@@ -1707,8 +1810,10 @@ class GallerySyncService {
1707
1810
  // Clear glasses gallery count immediately after successful sync
1708
1811
  // This ensures UI shows 0 items remaining right away
1709
1812
  // The subsequent query will update this if new photos were taken during sync
1710
- console.log("[GallerySyncService] 🔄 Clearing glasses gallery count (synced all items)");
1711
- store.clearGlassesGalleryStatus();
1813
+ if (!hasPendingRecovery && failedCount === 0) {
1814
+ console.log("[GallerySyncService] 🔄 Clearing glasses gallery count (synced all items)");
1815
+ store.clearGlassesGalleryStatus();
1816
+ }
1712
1817
  // Auto-reset to idle after 4 seconds to clear "Sync complete!" message,
1713
1818
  // then query glasses for any new content taken during the sync.
1714
1819
  // The query MUST happen after the reset — otherwise setGlassesGalleryStatus
@@ -1764,6 +1869,7 @@ class GallerySyncService {
1764
1869
  const store = useGallerySyncStore.getState();
1765
1870
  try {
1766
1871
  console.log("[GallerySyncService] Closing hotspot...");
1872
+ await localNetworkTransport.disconnect();
1767
1873
  await BluetoothSdk.setHotspotState(false);
1768
1874
  store.setSyncServiceOpenedHotspot(false);
1769
1875
  store.setHotspotInfo(null);
@@ -1824,7 +1930,7 @@ class GallerySyncService {
1824
1930
  }
1825
1931
  /** True while pre-flight startSync work is in flight (before sync state transitions). */
1826
1932
  isSyncStarting() {
1827
- return this.syncStartPromise !== null;
1933
+ return useGallerySyncStore.getState().syncStarting;
1828
1934
  }
1829
1935
  /**
1830
1936
  * Check if sync is currently in progress (hotspot/WiFi/download phases).