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

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
@@ -26,10 +26,13 @@ import {permissions, PermissionFeatures} from "../../facades/permissions"
26
26
  import {asgCameraApi} from "./asgCameraApi"
27
27
  import {gallerySettingsService} from "./gallerySettingsService"
28
28
  import {gallerySyncNotifications} from "./gallerySyncNotifications"
29
+ import {localNetworkTransport} from "./localNetworkTransport"
29
30
  import {localStorageService} from "./localStorageService"
30
31
  import {mediaProcessingQueue} from "./mediaProcessingQueue"
31
32
  import {validateCaptureMetadataForDownload} from "./galleryMediaValidation"
32
33
  import {emitGalleryNotice} from "./galleryNotices"
34
+ import {galleryTransferLedger} from "./galleryTransferLedger"
35
+ import {cameraRollExportCoordinator} from "./cameraRollExportCoordinator"
33
36
 
34
37
  // Timing constants
35
38
  const TIMING = {
@@ -111,6 +114,8 @@ class GallerySyncService {
111
114
  this.hotspotListenerRegistered = true
112
115
  this.isInitialized = true
113
116
 
117
+ void cameraRollExportCoordinator.initialize()
118
+
114
119
  // console.log("[GallerySyncService] Initialized")
115
120
 
116
121
  // Check for resumable sync on startup
@@ -121,6 +126,7 @@ class GallerySyncService {
121
126
  * Cleanup - remove event listeners
122
127
  */
123
128
  cleanup(): void {
129
+ void localNetworkTransport.disconnect()
124
130
  if (this.hotspotListenerRegistered) {
125
131
  GlobalEventEmitter.removeListener("hotspot_status_change", this.handleHotspotStatusChange)
126
132
  GlobalEventEmitter.removeListener("hotspot_error", this.handleHotspotError)
@@ -137,6 +143,7 @@ class GallerySyncService {
137
143
  this.appStateSubscription.remove()
138
144
  this.appStateSubscription = null
139
145
  }
146
+ cameraRollExportCoordinator.cleanup()
140
147
 
141
148
  if (this.hotspotConnectionTimeout) {
142
149
  BgTimer.clearTimeout(this.hotspotConnectionTimeout!)
@@ -149,6 +156,10 @@ class GallerySyncService {
149
156
  }
150
157
 
151
158
  this.syncStartPromise = null
159
+ useGallerySyncStore.getState().setSyncStarting(false)
160
+ this.waitingForWifiRetry = false
161
+ this.wifiSettingsOpenedAt = null
162
+ this.startAborted = false
152
163
  this.isInitialized = false
153
164
  console.log("[GallerySyncService] Cleaned up")
154
165
  }
@@ -191,6 +202,7 @@ class GallerySyncService {
191
202
  }
192
203
 
193
204
  gallerySyncNotifications.showSyncError("Glasses disconnected")
205
+ void localNetworkTransport.disconnect()
194
206
  }
195
207
 
196
208
  /**
@@ -202,6 +214,9 @@ class GallerySyncService {
202
214
  return
203
215
  }
204
216
 
217
+ // Camera-roll backfill is phone-local and must resume independently of glasses/WiFi.
218
+ void cameraRollExportCoordinator.resume("app foreground")
219
+
205
220
  // Only auto-retry if we were waiting for WiFi
206
221
  if (!this.waitingForWifiRetry) {
207
222
  return
@@ -217,14 +232,23 @@ class GallerySyncService {
217
232
  if (!glassesConnected) {
218
233
  console.log("[GallerySyncService] Glasses disconnected - not retrying sync")
219
234
  this.waitingForWifiRetry = false
235
+ this.wifiSettingsOpenedAt = null
220
236
  return
221
237
  }
222
238
 
239
+ // The user has returned from the WiFi settings prompt, so the previous
240
+ // "Sync failed" state is no longer actionable. Make the button available
241
+ // immediately while the native WiFi state catches up; a successful check
242
+ // below will start the sync automatically.
243
+ if (store.syncState === "error" && store.lastError?.startsWith("WiFi disabled")) {
244
+ store.setSyncState("idle")
245
+ }
246
+
223
247
  // Check if WiFi is now enabled (Android only)
224
248
  // Use retry logic because WiFi status takes time to propagate after user enables it
225
249
  if (Platform.OS === "android") {
226
250
  const MAX_RETRIES = 5
227
- const RETRY_DELAY_MS = 1000 // Wait 500ms between checks
251
+ const RETRY_DELAY_MS = 1000
228
252
 
229
253
  console.log("[GallerySyncService] Waiting for WiFi to initialize (may take a moment after enabling)...")
230
254
 
@@ -232,35 +256,28 @@ class GallerySyncService {
232
256
  try {
233
257
  await new Promise<void>((resolve) => BgTimer.setTimeout(() => resolve(), RETRY_DELAY_MS))
234
258
 
235
- const netState = await NetInfo.fetch()
236
- console.log(
237
- `[GallerySyncService] WiFi check attempt ${attempt}/${MAX_RETRIES}: enabled=${netState.isWifiEnabled}`,
238
- )
259
+ // NetInfo can remain stale after Android's WiFi settings close. Use
260
+ // the same native source as the normal sync preflight.
261
+ const wifiEnabled = await WifiManager.isEnabled()
262
+ console.log(`[GallerySyncService] WiFi check attempt ${attempt}/${MAX_RETRIES}: enabled=${wifiEnabled}`)
239
263
 
240
- if (netState.isWifiEnabled === true) {
264
+ if (wifiEnabled) {
241
265
  console.log("[GallerySyncService] ✅ WiFi is now enabled - auto-retrying sync")
242
266
  this.waitingForWifiRetry = false
243
267
  this.wifiSettingsOpenedAt = null // Clear cooldown timestamp
244
- // Clear previous error state
245
- store.setSyncState("idle")
246
268
  // Auto-retry sync
247
269
  await this.startSync()
248
270
  return
249
271
  }
250
-
251
- // If this was the last attempt, log and give up
252
- if (attempt === MAX_RETRIES) {
253
- console.log(
254
- "[GallerySyncService] ❌ WiFi still disabled after all retries - user may need to tap sync manually",
255
- )
256
- this.waitingForWifiRetry = false
257
- this.wifiSettingsOpenedAt = null // Clear cooldown timestamp
258
- }
259
272
  } catch (error) {
260
273
  console.warn(`[GallerySyncService] Failed to check WiFi status on attempt ${attempt}:`, error)
261
274
  // Continue to next retry
262
275
  }
263
276
  }
277
+
278
+ console.log("[GallerySyncService] WiFi not detected after retries - leaving sync available for manual retry")
279
+ this.waitingForWifiRetry = false
280
+ this.wifiSettingsOpenedAt = null
264
281
  }
265
282
  }
266
283
 
@@ -367,8 +384,10 @@ class GallerySyncService {
367
384
  return this.syncStartPromise
368
385
  }
369
386
 
387
+ useGallerySyncStore.getState().setSyncStarting(true)
370
388
  this.syncStartPromise = this.runStartSync().finally(() => {
371
389
  this.syncStartPromise = null
390
+ useGallerySyncStore.getState().setSyncStarting(false)
372
391
  })
373
392
  return this.syncStartPromise
374
393
  }
@@ -491,9 +510,6 @@ class GallerySyncService {
491
510
  hotspotEnabled: glassesHotspot !== null,
492
511
  })
493
512
 
494
- // Reset processing queue only after pre-flight passes — avoids clobbering an active session
495
- mediaProcessingQueue.reset()
496
-
497
513
  // Request all permissions upfront so user isn't interrupted during WiFi/download
498
514
  console.log("[GallerySyncService] 🔐 Step 1/6: Requesting permissions...")
499
515
 
@@ -526,6 +542,23 @@ class GallerySyncService {
526
542
  return
527
543
  }
528
544
 
545
+ if (Platform.OS === "android") {
546
+ console.log("[GallerySyncService] 📡 Checking local WiFi permission...")
547
+ const hasLocalWifiPermission = await permissions.check(PermissionFeatures.LOCAL_WIFI)
548
+ if (!hasLocalWifiPermission) {
549
+ const granted = await permissions.request(PermissionFeatures.LOCAL_WIFI)
550
+ if (!granted) {
551
+ store.setSyncError("Local WiFi permission is required for gallery sync")
552
+ await gallerySyncNotifications.showSyncError("Allow WiFi access to connect to your glasses")
553
+ return
554
+ }
555
+ }
556
+ if (this.shouldAbortPreFlight()) {
557
+ console.log("[GallerySyncService] Pre-flight aborted after local WiFi permission")
558
+ return
559
+ }
560
+ }
561
+
529
562
  // 3. Camera roll permission (if auto-save is enabled)
530
563
  const shouldAutoSave = await gallerySettingsService.getAutoSaveToCameraRoll()
531
564
  console.log(`[GallerySyncService] 📸 Auto-save to camera roll: ${shouldAutoSave}`)
@@ -536,9 +569,10 @@ class GallerySyncService {
536
569
  console.log("[GallerySyncService] ⚠️ Camera roll permission not granted - requesting...")
537
570
  const granted = await MediaLibraryPermissions.requestPermission()
538
571
  if (!granted) {
539
- console.warn("[GallerySyncService] ❌ Camera roll permission denied - photos will still sync to app")
540
- // Don't block sync - photos will still be downloaded to app storage
541
- // They just won't be saved to the camera roll
572
+ console.warn("[GallerySyncService] ❌ Camera roll permission denied - auto-save sync cannot continue")
573
+ store.setSyncError("Camera-roll permission required while automatic saving is enabled")
574
+ emitGalleryNotice({code: "camera_roll_permission_required"})
575
+ return
542
576
  } else {
543
577
  console.log("[GallerySyncService] ✅ Camera roll permission granted")
544
578
  }
@@ -739,12 +773,21 @@ class GallerySyncService {
739
773
  console.log("[GallerySyncService] ➡️ Will request hotspot activation")
740
774
  }
741
775
 
776
+ // Every fallible pre-flight gate has passed. It is now safe to replace the previous
777
+ // in-memory queue; startFileDownload immediately recovers its durable ledger work.
778
+ mediaProcessingQueue.reset()
779
+
742
780
  if (isAlreadyConnected && currentGlassesHotspot) {
743
- console.log("[GallerySyncService] 🚀 Skipping hotspot request - already connected!")
744
781
  const hotspotInfo: HotspotInfo = currentGlassesHotspot
745
782
  store.setHotspotInfo(hotspotInfo)
746
783
  store.setSyncState("connecting_wifi")
747
- await this.startFileDownload(hotspotInfo)
784
+ if (localNetworkTransport.supportsScopedConnection() && !localNetworkTransport.isScopedConnectionActive()) {
785
+ console.log("[GallerySyncService] 📡 System SSID matches; establishing scoped glasses transport")
786
+ await this.connectToHotspotWifi(hotspotInfo)
787
+ } else {
788
+ console.log("[GallerySyncService] 🚀 Skipping hotspot request - already connected!")
789
+ await this.startFileDownload(hotspotInfo)
790
+ }
748
791
  return
749
792
  }
750
793
 
@@ -900,7 +943,7 @@ class GallerySyncService {
900
943
  console.log(`[GallerySyncService] 📡 Current WiFi SSID: "${preConnectSSID}"`)
901
944
 
902
945
  // Check if already connected (shouldn't happen, but good to verify)
903
- if (preConnectSSID === hotspotInfo.ssid) {
946
+ if (!localNetworkTransport.supportsScopedConnection() && preConnectSSID === hotspotInfo.ssid) {
904
947
  console.log("[GallerySyncService] ✅ Already connected to target SSID! Proceeding to download.")
905
948
  appStateSubscription.remove()
906
949
 
@@ -919,8 +962,7 @@ class GallerySyncService {
919
962
  console.warn("[GallerySyncService] ⚠️ Error code:", preError?.code)
920
963
  }
921
964
 
922
- // Use connectToProtectedSSID with joinOnce=false for persistent connection
923
- console.log(`[GallerySyncService] 🔌 Calling WifiManager.connectToProtectedSSID...`)
965
+ console.log(`[GallerySyncService] 🔌 Connecting the glasses-local transport...`)
924
966
  console.log(`[GallerySyncService] 🔌 Parameters:`)
925
967
  console.log(`[GallerySyncService] - SSID: "${hotspotInfo.ssid}"`)
926
968
  console.log(`[GallerySyncService] - Password: ${"*".repeat(hotspotInfo.password.length)}`)
@@ -931,10 +973,10 @@ class GallerySyncService {
931
973
  appBackgrounded = false // Reset flag for this attempt
932
974
  appBackgroundTime = null
933
975
 
934
- await WifiManager.connectToProtectedSSID(hotspotInfo.ssid, hotspotInfo.password, false, false)
976
+ await localNetworkTransport.connect(hotspotInfo.ssid, hotspotInfo.password)
935
977
 
936
978
  const connectCallDuration = Date.now() - connectCallStartTime
937
- console.log(`[GallerySyncService] ✅ WifiManager.connectToProtectedSSID returned successfully`)
979
+ console.log(`[GallerySyncService] ✅ Glasses-local transport connected successfully`)
938
980
  console.log(`[GallerySyncService] ⏱️ Library call duration: ${connectCallDuration}ms`)
939
981
  console.log(`[GallerySyncService] 📱 App was backgrounded during call: ${appBackgrounded}`)
940
982
  if (appBackgrounded && appBackgroundTime) {
@@ -960,9 +1002,9 @@ class GallerySyncService {
960
1002
  lastSeenSSID = currentSSID || "null"
961
1003
 
962
1004
  console.log(
963
- `[GallerySyncService] 🍎 Verify poll ${i + 1}/${maxVerifyAttempts}: Current="${currentSSID}", Target="${
964
- hotspotInfo.ssid
965
- }"`,
1005
+ `[GallerySyncService] 🍎 Verify poll ${
1006
+ i + 1
1007
+ }/${maxVerifyAttempts}: Current="${currentSSID}", Target="${hotspotInfo.ssid}"`,
966
1008
  )
967
1009
 
968
1010
  if (currentSSID === hotspotInfo.ssid) {
@@ -1014,7 +1056,9 @@ class GallerySyncService {
1014
1056
 
1015
1057
  // Final verification: Check SSID one more time before starting download
1016
1058
  try {
1017
- const finalSSID = await WifiManager.getCurrentWifiSSID()
1059
+ const finalSSID = localNetworkTransport.isScopedConnectionActive()
1060
+ ? hotspotInfo.ssid
1061
+ : await WifiManager.getCurrentWifiSSID()
1018
1062
  console.log(`[GallerySyncService] 📶 Final SSID check before download: "${finalSSID}"`)
1019
1063
  if (Platform.OS === "android") {
1020
1064
  // Some local builds can have stale generated typings for the Bluetooth SDK module.
@@ -1050,7 +1094,7 @@ class GallerySyncService {
1050
1094
  const probeTimeout = BgTimer.setTimeout(() => probeController.abort(), 1000) // 1 second timeout per probe
1051
1095
 
1052
1096
  const probeStartTime = Date.now()
1053
- const probeResponse = await fetch(`http://${hotspotInfo.ip}:8089/api/health`, {
1097
+ const probeResponse = await localNetworkTransport.fetch(`http://${hotspotInfo.ip}:8089/api/health`, {
1054
1098
  method: "GET",
1055
1099
  signal: probeController.signal,
1056
1100
  })
@@ -1252,14 +1296,49 @@ class GallerySyncService {
1252
1296
  await this.closeHotspot()
1253
1297
  }
1254
1298
  } finally {
1299
+ // Release the scoped Android Network on every terminal path. This is idempotent with
1300
+ // closeHotspot(), and intentionally leaves Android 9/iOS legacy routing unchanged.
1301
+ await localNetworkTransport.disconnect()
1255
1302
  // L2: Guarantee listener cleanup on all exit paths (cancel, success, error, exhaustion)
1256
1303
  appStateSubscription.remove()
1257
1304
  }
1258
1305
  }
1259
1306
 
1260
1307
  private async fetchSyncManifest(clientId: string, lastSyncTime: number): Promise<SyncManifestData> {
1261
- const syncResponse = await asgCameraApi.syncWithServer(clientId, lastSyncTime, true)
1262
- return (syncResponse.data || syncResponse) as SyncManifestData
1308
+ const v3 = typeof asgCameraApi.getV3Manifest === "function" ? await asgCameraApi.getV3Manifest() : null
1309
+ if (v3) {
1310
+ const downloadedFiles = await localStorageService.getDownloadedFiles()
1311
+ await localStorageService.reconcileRemoteCaptures(
1312
+ v3.captures.map((capture) => capture.capture_id),
1313
+ downloadedFiles,
1314
+ )
1315
+ return {
1316
+ api_version: 3,
1317
+ client_id: clientId,
1318
+ // The ledger is a crash-recovery journal, not proof that app-private media survived an
1319
+ // Android restore or reinstall. Suppress a remote capture only when both records agree.
1320
+ captures: v3.captures.filter(
1321
+ (capture) =>
1322
+ !downloadedFiles[capture.capture_id] || !galleryTransferLedger.isLocallyCommitted(capture.capture_id),
1323
+ ),
1324
+ changed_files: [],
1325
+ deleted_files: [],
1326
+ server_time: v3.server_time,
1327
+ total_changed: v3.captures.length,
1328
+ total_size: v3.captures.reduce((total, capture) => total + capture.total_size, 0),
1329
+ }
1330
+ }
1331
+ // Old firmware remains on the exact v2 endpoint/schema. Avoid expensive inline thumbnails;
1332
+ // video thumbnails are fetched as small side downloads with their primary media.
1333
+ const syncResponse = await asgCameraApi.syncWithServer(clientId, lastSyncTime, false)
1334
+ const data = (syncResponse.data || syncResponse) as SyncManifestData
1335
+ if (data.captures) {
1336
+ data.captures = data.captures.filter((capture) => !galleryTransferLedger.isLocallyCommitted(capture.capture_id))
1337
+ }
1338
+ data.changed_files = (data.changed_files || []).filter(
1339
+ (file) => !galleryTransferLedger.isFileLocallyCommitted(file.name),
1340
+ )
1341
+ return data
1263
1342
  }
1264
1343
 
1265
1344
  /**
@@ -1328,6 +1407,13 @@ class GallerySyncService {
1328
1407
  asgCameraApi.setServer(hotspotInfo.ip, 8089)
1329
1408
  console.log("[GallerySyncService] ✅ API client configured")
1330
1409
 
1410
+ const recovery = await mediaProcessingQueue.retryPending()
1411
+ if (recovery.retried > 0 || recovery.failed > 0) {
1412
+ console.log(
1413
+ `[GallerySyncService] ♻️ Recovery: ${recovery.retried} completed, ${recovery.failed} still pending`,
1414
+ )
1415
+ }
1416
+
1331
1417
  // Get sync state and files to download
1332
1418
  // IMPORTANT: This creates a SNAPSHOT of files at this moment based on last_sync_time.
1333
1419
  // Any photos taken AFTER this call (during the sync) will NOT be included in this sync.
@@ -1367,18 +1453,24 @@ class GallerySyncService {
1367
1453
 
1368
1454
  if (isSyncManifestEmpty(syncData)) {
1369
1455
  console.log("[GallerySyncService] ✅ No new files to sync - already up to date!")
1370
- store.setSyncComplete()
1456
+ if (galleryTransferLedger.hasPendingRecovery()) {
1457
+ store.setSyncError("Gallery export or acknowledgement needs retry")
1458
+ } else {
1459
+ store.setSyncComplete()
1460
+ }
1371
1461
  await this.onSyncComplete(0, 0)
1372
1462
  return
1373
1463
  }
1374
1464
 
1375
1465
  // Detect API version and route to appropriate download path
1376
- const useCaptures = syncData.api_version === 2 && syncData.captures && syncData.captures.length > 0
1466
+ const useCaptures = (syncData.api_version || 0) >= 2 && syncData.captures && syncData.captures.length > 0
1377
1467
 
1378
1468
  if (useCaptures) {
1379
1469
  // New capture-aware sync path
1380
1470
  const captures: CaptureGroup[] = syncData.captures!
1381
- console.log(`[GallerySyncService] 📊 Found ${captures.length} captures to download (api_version=2)`)
1471
+ console.log(
1472
+ `[GallerySyncService] 📊 Found ${captures.length} captures to download (api_version=${syncData.api_version})`,
1473
+ )
1382
1474
 
1383
1475
  captures.slice(0, 5).forEach((c: CaptureGroup, idx: number) => {
1384
1476
  console.log(
@@ -1500,7 +1592,7 @@ class GallerySyncService {
1500
1592
  (current, total, fileName, fileProgress, downloadedFile) => {
1501
1593
  // CRITICAL: This callback MUST NOT throw!
1502
1594
  // RNFS progress callbacks run inside native bridge — throwing here causes
1503
- // EXC_BAD_ACCESS. Cancellation is handled via AbortSignal → RNFS.stopDownload.
1595
+ // EXC_BAD_ACCESS. Cancellation is handled via AbortSignal → the active transport.
1504
1596
 
1505
1597
  // Check if cancelled — just return, abort signal will stop the download
1506
1598
  if (this.abortController?.signal.aborted) {
@@ -1597,6 +1689,7 @@ class GallerySyncService {
1597
1689
  shouldAutoSave: !!shouldAutoSave,
1598
1690
  thumbnailPath: downloadedFile.thumbnailPath,
1599
1691
  deleteFromGlasses: [downloadedFile.name],
1692
+ protocolVersion: 1,
1600
1693
  })
1601
1694
  }
1602
1695
  }
@@ -1634,25 +1727,6 @@ class GallerySyncService {
1634
1727
  }
1635
1728
  }
1636
1729
 
1637
- // Save downloaded files metadata (skip auxiliary files from gallery entries)
1638
- for (const photoInfo of downloadResult.downloaded) {
1639
- // Skip HDR brackets and IMU sidecars — they shouldn't appear as separate gallery items
1640
- const isAuxiliary =
1641
- photoInfo.name?.match(/_ev-?\d+\.(jpg|jpeg)$/i) ||
1642
- photoInfo.name?.match(/\.imu\.json$/i) ||
1643
- photoInfo.name?.match(/\/ev-?\d+\.jpe?g$/i) ||
1644
- photoInfo.name?.match(/\/imu\.json$/i)
1645
- if (isAuxiliary) continue
1646
-
1647
- const downloadedFile = localStorageService.convertToDownloadedFile(
1648
- photoInfo,
1649
- photoInfo.filePath || "",
1650
- photoInfo.thumbnailPath,
1651
- defaultWearable,
1652
- )
1653
- await localStorageService.saveDownloadedFile(downloadedFile)
1654
- }
1655
-
1656
1730
  // Update queue index to final position
1657
1731
  await localStorageService.updateSyncQueueIndex(files.length)
1658
1732
 
@@ -1667,6 +1741,17 @@ class GallerySyncService {
1667
1741
  await mediaProcessingQueue.waitUntilDrained()
1668
1742
  console.log("[GallerySyncService] ✅ Processing queue drained")
1669
1743
 
1744
+ // Download success is not destination success. Export, validation, metadata, and
1745
+ // acknowledgement failures are reported asynchronously by the processing queue; fold them
1746
+ // back into the legacy result so its timestamp watermark cannot skip the source forever.
1747
+ const processingFailures = new Set(useGallerySyncStore.getState().failedFiles)
1748
+ for (const file of files) {
1749
+ if (processingFailures.has(file.name) && !downloadResult.failed.includes(file.name)) {
1750
+ downloadResult.failed.push(file.name)
1751
+ }
1752
+ }
1753
+ failedCount = downloadResult.failed.length
1754
+
1670
1755
  // Update sync state — only advance watermark if files were downloaded.
1671
1756
  // If any failed, set it before the oldest failure so they get retried.
1672
1757
  let syncWatermark = serverTime
@@ -1730,8 +1815,11 @@ class GallerySyncService {
1730
1815
  ).toFixed(2)} MB`,
1731
1816
  )
1732
1817
 
1733
- // Complete
1734
- store.setSyncComplete()
1818
+ if (failedCount > 0 || galleryTransferLedger.hasPendingRecovery()) {
1819
+ store.setSyncError(`${failedCount || "Some"} gallery items need retry`)
1820
+ } else {
1821
+ store.setSyncComplete()
1822
+ }
1735
1823
  await this.onSyncComplete(downloadedCount, failedCount)
1736
1824
  } catch (error: any) {
1737
1825
  mediaProcessingQueue.abort()
@@ -1795,7 +1883,9 @@ class GallerySyncService {
1795
1883
 
1796
1884
  try {
1797
1885
  console.log(
1798
- `[GallerySyncService] 📦 Downloading capture ${i + 1}/${captures.length}: ${capture.capture_id} (${capture.files.length} files)`,
1886
+ `[GallerySyncService] 📦 Downloading capture ${i + 1}/${captures.length}: ${capture.capture_id} (${
1887
+ capture.files.length
1888
+ } files)`,
1799
1889
  )
1800
1890
 
1801
1891
  validateCaptureMetadataForDownload(capture)
@@ -1833,6 +1923,7 @@ class GallerySyncService {
1833
1923
  bracketPaths: result.bracketPaths,
1834
1924
  sidecarPath: result.sidecarPath,
1835
1925
  thumbnailData: capture.thumbnail_data,
1926
+ thumbnailPath: result.thumbnailPath,
1836
1927
  captureDir: result.captureDir,
1837
1928
  timestamp: capture.timestamp,
1838
1929
  totalSize: capture.total_size,
@@ -1841,6 +1932,7 @@ class GallerySyncService {
1841
1932
  shouldProcess: !!shouldProcessImages,
1842
1933
  shouldAutoSave: !!shouldAutoSave,
1843
1934
  deleteFromGlasses: [capture.capture_id],
1935
+ protocolVersion: capture.files.some((file) => !!file.etag) ? 3 : 2,
1844
1936
  })
1845
1937
  } catch (captureError: any) {
1846
1938
  if (captureError?.message === "Sync cancelled") throw captureError
@@ -1929,7 +2021,11 @@ class GallerySyncService {
1929
2021
  })
1930
2022
  }
1931
2023
 
1932
- store.setSyncComplete()
2024
+ if (failedCount > 0 || galleryTransferLedger.hasPendingRecovery()) {
2025
+ store.setSyncError(`${failedCount || "Some"} gallery items need retry`)
2026
+ } else {
2027
+ store.setSyncComplete()
2028
+ }
1933
2029
  await this.onSyncComplete(downloadedCount, failedCount)
1934
2030
  } catch (error: any) {
1935
2031
  mediaProcessingQueue.abort()
@@ -1993,13 +2089,25 @@ class GallerySyncService {
1993
2089
  // console.error(`[GallerySyncService] Failed to get post-sync inventory:`, error)
1994
2090
  // }
1995
2091
 
1996
- // Clear the queue
1997
- console.log("[GallerySyncService] 🧹 Clearing sync queue...")
1998
- await localStorageService.clearSyncQueue()
2092
+ const hasPendingRecovery = galleryTransferLedger.hasPendingRecovery()
2093
+ if (!hasPendingRecovery && failedCount === 0) {
2094
+ console.log("[GallerySyncService] 🧹 Clearing completed sync queue...")
2095
+ await localStorageService.clearSyncQueue()
2096
+ } else {
2097
+ console.log("[GallerySyncService] ♻️ Keeping recovery state for unfinished export/ack work")
2098
+ }
1999
2099
 
2000
- // Show completion notification
2001
- console.log("[GallerySyncService] 📱 Showing completion notification...")
2002
- await gallerySyncNotifications.showSyncComplete(downloadedCount, failedCount)
2100
+ if (hasPendingRecovery || failedCount > 0) {
2101
+ console.log("[GallerySyncService] 📱 Showing retry-required notification...")
2102
+ await gallerySyncNotifications.showSyncError(
2103
+ failedCount > 0
2104
+ ? `${failedCount} gallery item${failedCount === 1 ? "" : "s"} will be retried`
2105
+ : "Gallery export or acknowledgement will be retried",
2106
+ )
2107
+ } else {
2108
+ console.log("[GallerySyncService] 📱 Showing completion notification...")
2109
+ await gallerySyncNotifications.showSyncComplete(downloadedCount, 0)
2110
+ }
2003
2111
 
2004
2112
  // Close hotspot if we opened it
2005
2113
  const store = useGallerySyncStore.getState()
@@ -2013,8 +2121,10 @@ class GallerySyncService {
2013
2121
  // Clear glasses gallery count immediately after successful sync
2014
2122
  // This ensures UI shows 0 items remaining right away
2015
2123
  // The subsequent query will update this if new photos were taken during sync
2016
- console.log("[GallerySyncService] 🔄 Clearing glasses gallery count (synced all items)")
2017
- store.clearGlassesGalleryStatus()
2124
+ if (!hasPendingRecovery && failedCount === 0) {
2125
+ console.log("[GallerySyncService] 🔄 Clearing glasses gallery count (synced all items)")
2126
+ store.clearGlassesGalleryStatus()
2127
+ }
2018
2128
 
2019
2129
  // Auto-reset to idle after 4 seconds to clear "Sync complete!" message,
2020
2130
  // then query glasses for any new content taken during the sync.
@@ -2082,6 +2192,7 @@ class GallerySyncService {
2082
2192
 
2083
2193
  try {
2084
2194
  console.log("[GallerySyncService] Closing hotspot...")
2195
+ await localNetworkTransport.disconnect()
2085
2196
  await BluetoothSdk.setHotspotState(false)
2086
2197
  store.setSyncServiceOpenedHotspot(false)
2087
2198
  store.setHotspotInfo(null)
@@ -2149,7 +2260,7 @@ class GallerySyncService {
2149
2260
 
2150
2261
  /** True while pre-flight startSync work is in flight (before sync state transitions). */
2151
2262
  isSyncStarting(): boolean {
2152
- return this.syncStartPromise !== null
2263
+ return useGallerySyncStore.getState().syncStarting
2153
2264
  }
2154
2265
 
2155
2266
  /**