@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
@@ -0,0 +1,618 @@
1
+ import * as RNFS from "@dr.pogodin/react-native-fs";
2
+ import { MediaLibraryPermissions } from "../../utils/permissions/MediaLibraryPermissions";
3
+ import { BgTimer } from "../../utils/timers";
4
+ import { cameraRollEntryId, cameraRollExportLedger, cameraRollGeneration, } from "./cameraRollExportLedger";
5
+ import { gallerySettingsService } from "./gallerySettingsService";
6
+ import { galleryTransferLedger } from "./galleryTransferLedger";
7
+ import { localStorageService } from "./localStorageService";
8
+ const TAG = "[CameraRollExport]";
9
+ const MIN_FREE_SPACE_BYTES = 100 * 1024 * 1024;
10
+ const MAX_RETRY_DELAY_MS = 30 * 60 * 1000;
11
+ class CameraRollExportCoordinator {
12
+ initialized = false;
13
+ initializing = null;
14
+ lifecycleGeneration = 0;
15
+ enabled = true;
16
+ running = false;
17
+ rerunRequested = false;
18
+ retryTimer = null;
19
+ activeEntryId = null;
20
+ clearInProgress = false;
21
+ deletingMediaNames = new Set();
22
+ listeners = new Set();
23
+ sourceWaiters = new Map();
24
+ async initialize() {
25
+ while (!this.initialized) {
26
+ if (!this.initializing) {
27
+ const generation = this.lifecycleGeneration;
28
+ this.initializing = this.initializeInternal(generation);
29
+ }
30
+ const initialization = this.initializing;
31
+ try {
32
+ await initialization;
33
+ }
34
+ finally {
35
+ if (this.initializing === initialization)
36
+ this.initializing = null;
37
+ }
38
+ }
39
+ }
40
+ cleanup() {
41
+ this.lifecycleGeneration += 1;
42
+ if (this.retryTimer != null)
43
+ BgTimer.clearTimeout(this.retryTimer);
44
+ this.retryTimer = null;
45
+ this.initialized = false;
46
+ this.rerunRequested = false;
47
+ const error = new Error("Camera-roll export coordinator stopped");
48
+ for (const id of [...this.sourceWaiters.keys()])
49
+ this.rejectSourceWaiters(id, error);
50
+ if (!this.running)
51
+ this.activeEntryId = null;
52
+ }
53
+ async initializeInternal(generation) {
54
+ cameraRollExportLedger.setDocumentDirectory(RNFS.DocumentDirectoryPath);
55
+ // A native camera-roll insert is atomic and cannot be cancelled. On a quick engine
56
+ // stop/start, let the old drain commit its receipt before the new lifecycle reconciles.
57
+ while (this.running) {
58
+ await new Promise((resolve) => BgTimer.setTimeout(resolve, 25));
59
+ }
60
+ if (generation !== this.lifecycleGeneration)
61
+ return;
62
+ const enabled = await gallerySettingsService.getAutoSaveToCameraRoll();
63
+ if (generation !== this.lifecycleGeneration)
64
+ return;
65
+ this.enabled = enabled;
66
+ await this.reconcileLocalIndex();
67
+ if (generation !== this.lifecycleGeneration)
68
+ return;
69
+ this.initialized = true;
70
+ this.emitSummary();
71
+ if (this.enabled)
72
+ void this.resume("startup");
73
+ }
74
+ /** Rebuild missing per-generation records after upgrading from legacy clients. */
75
+ async reconcileLocalIndex() {
76
+ const files = await localStorageService.getDownloadedFiles();
77
+ const liveIds = new Set();
78
+ const liveGenerationByMediaName = new Map();
79
+ for (const file of Object.values(files)) {
80
+ const id = cameraRollEntryId(file.name, file.size, file.modified);
81
+ liveIds.add(id);
82
+ liveGenerationByMediaName.set(file.name, id);
83
+ const current = cameraRollExportLedger.get(id);
84
+ const transfer = file.capture_id
85
+ ? galleryTransferLedger.get(file.capture_id)
86
+ : galleryTransferLedger.get(file.name);
87
+ const receipt = file.assetReceipt || transfer?.assetReceipt || current?.receipt;
88
+ const now = Date.now();
89
+ cameraRollExportLedger.put({
90
+ ...(current || {
91
+ id,
92
+ mediaName: file.name,
93
+ generation: cameraRollGeneration(file.name, file.size, file.modified),
94
+ filePath: file.filePath,
95
+ size: file.size,
96
+ modified: file.modified,
97
+ isVideo: file.is_video,
98
+ captureId: file.capture_id || transfer?.captureId,
99
+ priority: "HISTORICAL_BACKFILL",
100
+ attempts: 0,
101
+ createdAt: now,
102
+ updatedAt: now,
103
+ state: "LEGACY_UNKNOWN",
104
+ }),
105
+ filePath: file.filePath,
106
+ localPresent: true,
107
+ receipt,
108
+ requiresFullLibraryReconciliation: current?.requiresFullLibraryReconciliation ?? (!current && !receipt && !transfer),
109
+ state: receipt ? "EXPORTED" : this.nextEligibleState(current?.state),
110
+ });
111
+ }
112
+ // Explicit app deletion removes receipts through deleteLocalMedia/clearLocalMedia. An index
113
+ // miss here is not proof of deletion: recovery may not have rebuilt the row yet, and a load
114
+ // failure is represented as an empty index. Preserve exported receipts as hidden tombstones;
115
+ // they are the authoritative proof that prevents a duplicate native-library insert.
116
+ for (const entry of cameraRollExportLedger.list()) {
117
+ if (liveIds.has(entry.id))
118
+ continue;
119
+ if (entry.receipt) {
120
+ cameraRollExportLedger.update(entry.id, { state: "EXPORTED", localPresent: false });
121
+ continue;
122
+ }
123
+ // A different live generation with the same display name supersedes an unexported stale
124
+ // row. Never let its old path export the replacement's bytes under the wrong fingerprint.
125
+ if (liveGenerationByMediaName.has(entry.mediaName)) {
126
+ cameraRollExportLedger.remove(entry.id);
127
+ continue;
128
+ }
129
+ cameraRollExportLedger.update(entry.id, {
130
+ state: "MISSING_LOCAL",
131
+ localPresent: false,
132
+ lastError: "Local media is missing",
133
+ nextRetryAt: undefined,
134
+ });
135
+ }
136
+ }
137
+ nextEligibleState(current) {
138
+ if (!this.enabled)
139
+ return "NOT_REQUESTED";
140
+ // Reconciliation only calls this for files that are present in the durable local index.
141
+ // A previous filesystem miss was transient if that same generation is visible again.
142
+ if (current === "FAILED_PERMANENT")
143
+ return current;
144
+ return "QUEUED";
145
+ }
146
+ async recordIndexed(file, shouldAutoSave, priority = "HISTORICAL_BACKFILL", captureId) {
147
+ await this.initialize();
148
+ const id = cameraRollEntryId(file.name, file.size, file.modified);
149
+ const current = cameraRollExportLedger.get(id);
150
+ const now = Date.now();
151
+ const entry = cameraRollExportLedger.put({
152
+ ...(current || {
153
+ id,
154
+ mediaName: file.name,
155
+ generation: cameraRollGeneration(file.name, file.size, file.modified),
156
+ attempts: 0,
157
+ createdAt: now,
158
+ updatedAt: now,
159
+ }),
160
+ filePath: file.filePath,
161
+ size: file.size,
162
+ modified: file.modified,
163
+ isVideo: file.is_video,
164
+ captureId: captureId || file.capture_id || current?.captureId,
165
+ localPresent: true,
166
+ requiresFullLibraryReconciliation: current?.requiresFullLibraryReconciliation ?? false,
167
+ priority,
168
+ receipt: file.assetReceipt || current?.receipt,
169
+ state: file.assetReceipt || current?.receipt ? "EXPORTED" : shouldAutoSave ? "QUEUED" : "NOT_REQUESTED",
170
+ lastError: undefined,
171
+ nextRetryAt: undefined,
172
+ });
173
+ this.emitSummary();
174
+ return entry;
175
+ }
176
+ async isAutoSaveEnabled() {
177
+ await this.initialize();
178
+ return this.enabled;
179
+ }
180
+ /** Source deletion waits on this barrier while enabled; disabled exports remain safely app-local. */
181
+ async exportForSource(file, captureId) {
182
+ await this.initialize();
183
+ // A durable receipt proves this generation is already safe regardless of the current
184
+ // preference. Return it before enforcing disabled state so recovery can still ack the
185
+ // glasses after a previously-started export committed.
186
+ const entry = await this.recordIndexed(file, this.enabled, "SOURCE_BARRIER", captureId);
187
+ if (entry.receipt)
188
+ return entry.receipt;
189
+ if (!this.enabled)
190
+ return undefined;
191
+ try {
192
+ return await new Promise((resolve, reject) => {
193
+ const current = cameraRollExportLedger.get(entry.id);
194
+ if (current?.receipt) {
195
+ resolve(current.receipt);
196
+ return;
197
+ }
198
+ if (!current) {
199
+ reject(new Error("Camera-roll export was removed before its source barrier registered"));
200
+ return;
201
+ }
202
+ const waiters = this.sourceWaiters.get(entry.id) || [];
203
+ waiters.push({ resolve, reject });
204
+ this.sourceWaiters.set(entry.id, waiters);
205
+ // Re-read after registration so any future refactor that yields while installing a
206
+ // waiter still cannot miss a receipt committed by the active runner.
207
+ const registered = cameraRollExportLedger.get(entry.id);
208
+ if (registered?.receipt) {
209
+ this.resolveSourceWaiters(entry.id, registered.receipt);
210
+ return;
211
+ }
212
+ if (!registered) {
213
+ this.rejectSourceWaiters(entry.id, new Error("Camera-roll export was removed before its source barrier registered"));
214
+ return;
215
+ }
216
+ void this.resume("source barrier");
217
+ });
218
+ }
219
+ catch (error) {
220
+ // Turning auto-save off makes the durable app-local commit the source-of-truth. A native
221
+ // insert already in progress still finishes and returns its receipt; queued work may stop.
222
+ if (!this.enabled)
223
+ return undefined;
224
+ throw error;
225
+ }
226
+ }
227
+ async setEnabled(enabled) {
228
+ await this.initialize();
229
+ const previous = this.enabled;
230
+ await gallerySettingsService.setAutoSaveToCameraRoll(enabled);
231
+ try {
232
+ this.enabled = enabled;
233
+ if (!enabled && this.retryTimer != null) {
234
+ BgTimer.clearTimeout(this.retryTimer);
235
+ this.retryTimer = null;
236
+ }
237
+ for (const entry of cameraRollExportLedger.list()) {
238
+ if (entry.receipt || entry.state === "EXPORTED" || entry.state === "MISSING_LOCAL")
239
+ continue;
240
+ if (!enabled && entry.id !== this.activeEntryId) {
241
+ cameraRollExportLedger.update(entry.id, { state: "NOT_REQUESTED", nextRetryAt: undefined });
242
+ this.rejectSourceWaiters(entry.id, new Error("Automatic camera-roll saving was disabled"));
243
+ }
244
+ else if (enabled) {
245
+ cameraRollExportLedger.update(entry.id, { state: "QUEUED", nextRetryAt: undefined, lastError: undefined });
246
+ }
247
+ }
248
+ }
249
+ catch (error) {
250
+ this.enabled = previous;
251
+ await gallerySettingsService.setAutoSaveToCameraRoll(previous);
252
+ throw error;
253
+ }
254
+ this.emitSummary();
255
+ if (enabled)
256
+ void this.resume("setting enabled");
257
+ }
258
+ async resume(reason) {
259
+ const generation = this.lifecycleGeneration;
260
+ await this.initialize();
261
+ if (generation !== this.lifecycleGeneration)
262
+ return;
263
+ console.log(`${TAG} Resume requested: ${reason}`);
264
+ if (cameraRollExportLedger.list().some((entry) => entry.state === "BLOCKED_PERMISSION")) {
265
+ const hasPermission = await MediaLibraryPermissions.checkPermission();
266
+ const hasLimitedAccess = hasPermission && (await MediaLibraryPermissions.hasLimitedAccess());
267
+ if (generation !== this.lifecycleGeneration)
268
+ return;
269
+ if (hasPermission) {
270
+ for (const entry of cameraRollExportLedger.list()) {
271
+ if (entry.state === "BLOCKED_PERMISSION" && !(entry.requiresFullLibraryReconciliation && hasLimitedAccess)) {
272
+ cameraRollExportLedger.update(entry.id, { state: "QUEUED", lastError: undefined });
273
+ }
274
+ }
275
+ }
276
+ }
277
+ if (generation !== this.lifecycleGeneration)
278
+ return;
279
+ if (this.retryTimer != null) {
280
+ BgTimer.clearTimeout(this.retryTimer);
281
+ this.retryTimer = null;
282
+ }
283
+ if (this.running) {
284
+ this.rerunRequested = true;
285
+ while (this.running) {
286
+ await new Promise((resolve) => BgTimer.setTimeout(resolve, 25));
287
+ }
288
+ if (generation !== this.lifecycleGeneration)
289
+ return;
290
+ // The active drain normally consumes rerunRequested before releasing running. Keep
291
+ // this final durable-work check so a late handoff can never strand an eligible entry.
292
+ if (this.nextEntry())
293
+ await this.resume("work remained after concurrent resume");
294
+ return;
295
+ }
296
+ this.running = true;
297
+ this.emitSummary();
298
+ try {
299
+ do {
300
+ this.rerunRequested = false;
301
+ let entry = this.nextEntry();
302
+ while (entry && generation === this.lifecycleGeneration) {
303
+ await this.processEntry(entry, generation);
304
+ if (generation !== this.lifecycleGeneration)
305
+ break;
306
+ entry = this.nextEntry();
307
+ }
308
+ } while (this.rerunRequested && generation === this.lifecycleGeneration);
309
+ }
310
+ finally {
311
+ this.rerunRequested = false;
312
+ this.running = false;
313
+ if (generation === this.lifecycleGeneration) {
314
+ this.emitSummary();
315
+ this.scheduleRetry();
316
+ }
317
+ }
318
+ }
319
+ async retryNow() {
320
+ const generation = this.lifecycleGeneration;
321
+ await this.initialize();
322
+ // A recovered transfer may have rebuilt a missing local-index row since the last lifecycle
323
+ // reconciliation. Refresh before retrying so the same camera-roll generation becomes
324
+ // eligible again; never rewrite entry state underneath an active native insert.
325
+ while (this.running) {
326
+ await new Promise((resolve) => BgTimer.setTimeout(resolve, 25));
327
+ }
328
+ if (generation !== this.lifecycleGeneration)
329
+ return;
330
+ await this.reconcileLocalIndex();
331
+ if (generation !== this.lifecycleGeneration)
332
+ return;
333
+ for (const entry of cameraRollExportLedger.list()) {
334
+ if (entry.state === "FAILED_RETRYABLE" ||
335
+ entry.state === "BLOCKED_PERMISSION" ||
336
+ (entry.state === "MISSING_LOCAL" && entry.localPresent !== false)) {
337
+ cameraRollExportLedger.update(entry.id, { state: "QUEUED", nextRetryAt: undefined, lastError: undefined });
338
+ }
339
+ }
340
+ await this.resume("manual retry");
341
+ }
342
+ subscribe(listener) {
343
+ this.listeners.add(listener);
344
+ // `enabled` is loaded from durable settings during initialize(). Do not emit the
345
+ // default before that read completes or disabled users briefly see the toggle as on.
346
+ if (this.initialized)
347
+ listener(this.getSummary());
348
+ return () => this.listeners.delete(listener);
349
+ }
350
+ getSummary() {
351
+ const entries = cameraRollExportLedger
352
+ .list()
353
+ // Exported receipts with no local row are hidden deduplication tombstones. Unexported
354
+ // missing generations remain user-visible so data that can no longer be backfilled is
355
+ // never reported as successfully saved.
356
+ .filter((entry) => entry.localPresent !== false || entry.state === "MISSING_LOCAL");
357
+ const pendingStates = new Set([
358
+ "LEGACY_UNKNOWN",
359
+ "QUEUED",
360
+ "RECONCILING",
361
+ "EXPORTING",
362
+ "FAILED_RETRYABLE",
363
+ "BLOCKED_PERMISSION",
364
+ ]);
365
+ return {
366
+ enabled: this.enabled,
367
+ total: entries.length,
368
+ exported: entries.filter((entry) => entry.state === "EXPORTED").length,
369
+ pending: entries.filter((entry) => pendingStates.has(entry.state)).length,
370
+ failed: entries.filter((entry) => entry.state === "FAILED_RETRYABLE" || entry.state === "FAILED_PERMANENT")
371
+ .length,
372
+ blockedPermission: entries.filter((entry) => entry.state === "BLOCKED_PERMISSION").length,
373
+ fullAccessRequired: entries.filter((entry) => entry.state === "BLOCKED_PERMISSION" && entry.requiresFullLibraryReconciliation).length,
374
+ missing: entries.filter((entry) => entry.state === "MISSING_LOCAL").length,
375
+ bytesPending: entries
376
+ .filter((entry) => pendingStates.has(entry.state))
377
+ .reduce((sum, entry) => sum + entry.size, 0),
378
+ isRunning: this.running,
379
+ };
380
+ }
381
+ async countNotExported(mediaNames) {
382
+ await this.initialize();
383
+ const uniqueNames = [...new Set(mediaNames)];
384
+ if (uniqueNames.length === 0)
385
+ return 0;
386
+ const files = await localStorageService.getDownloadedFiles();
387
+ return uniqueNames.filter((name) => {
388
+ const file = files[name];
389
+ if (!file)
390
+ return true;
391
+ const entry = cameraRollExportLedger.get(cameraRollEntryId(file.name, file.size, file.modified));
392
+ return entry?.state !== "EXPORTED";
393
+ }).length;
394
+ }
395
+ /** Serialize local deletion against an in-flight native copy of the same item. */
396
+ async deleteLocalMedia(mediaName) {
397
+ this.deletingMediaNames.add(mediaName);
398
+ try {
399
+ while (this.activeEntryId && cameraRollExportLedger.get(this.activeEntryId)?.mediaName === mediaName) {
400
+ await new Promise((resolve) => BgTimer.setTimeout(resolve, 25));
401
+ }
402
+ const deleted = await localStorageService.deleteDownloadedFile(mediaName);
403
+ if (deleted) {
404
+ // An already-running export gets to finish and resolve its source barrier. Queued work
405
+ // cannot start while the name is in deletingMediaNames, so reject only after deletion
406
+ // is confirmed. A failed delete leaves the barrier intact and eligible for retry.
407
+ for (const entry of cameraRollExportLedger.list().filter((candidate) => candidate.mediaName === mediaName)) {
408
+ this.rejectSourceWaiters(entry.id, new Error("Local media was deleted before camera-roll export"));
409
+ }
410
+ cameraRollExportLedger.removeForMedia(mediaName);
411
+ }
412
+ return deleted;
413
+ }
414
+ finally {
415
+ this.deletingMediaNames.delete(mediaName);
416
+ this.emitSummary();
417
+ if (this.enabled)
418
+ void this.resume("local deletion finished");
419
+ }
420
+ }
421
+ /** Stop scheduling exports, finish the current native copy, then atomically clear app media + receipts. */
422
+ async clearLocalMedia() {
423
+ this.clearInProgress = true;
424
+ try {
425
+ while (this.activeEntryId) {
426
+ await new Promise((resolve) => BgTimer.setTimeout(resolve, 25));
427
+ }
428
+ await localStorageService.clearAllFiles();
429
+ // Let the active native copy deliver its receipt before rejecting queued barriers, and
430
+ // reject them only after the app media clear is confirmed. If clear fails, the durable
431
+ // work and its waiters remain eligible for retry.
432
+ for (const entry of cameraRollExportLedger.list()) {
433
+ this.rejectSourceWaiters(entry.id, new Error("Local media was deleted before camera-roll export"));
434
+ }
435
+ cameraRollExportLedger.clear();
436
+ }
437
+ finally {
438
+ this.clearInProgress = false;
439
+ this.emitSummary();
440
+ if (this.enabled)
441
+ void this.resume("local clear finished");
442
+ }
443
+ }
444
+ nextEntry() {
445
+ const now = Date.now();
446
+ return cameraRollExportLedger
447
+ .list()
448
+ .filter((entry) => {
449
+ if (entry.localPresent === false)
450
+ return false;
451
+ if (this.clearInProgress || this.deletingMediaNames.has(entry.mediaName))
452
+ return false;
453
+ if (entry.receipt || entry.state === "EXPORTED" || entry.state === "MISSING_LOCAL")
454
+ return false;
455
+ if (!this.enabled)
456
+ return false;
457
+ if (entry.state === "BLOCKED_PERMISSION" || entry.state === "FAILED_PERMANENT")
458
+ return false;
459
+ if (entry.state === "FAILED_RETRYABLE" && (entry.nextRetryAt || 0) > now)
460
+ return false;
461
+ return entry.state !== "NOT_REQUESTED";
462
+ })
463
+ .sort((a, b) => {
464
+ if (a.priority !== b.priority)
465
+ return a.priority === "SOURCE_BARRIER" ? -1 : 1;
466
+ return a.modified - b.modified;
467
+ })[0];
468
+ }
469
+ async processEntry(original, generation) {
470
+ let entry = original;
471
+ this.activeEntryId = entry.id;
472
+ try {
473
+ if (!this.enabled) {
474
+ cameraRollExportLedger.update(entry.id, { state: "NOT_REQUESTED", nextRetryAt: undefined });
475
+ this.rejectSourceWaiters(entry.id, new Error("Automatic camera-roll saving was disabled"));
476
+ return;
477
+ }
478
+ const exists = await RNFS.exists(entry.filePath);
479
+ if (generation !== this.lifecycleGeneration)
480
+ return;
481
+ if (!exists) {
482
+ cameraRollExportLedger.update(entry.id, { state: "MISSING_LOCAL", lastError: "Local media is missing" });
483
+ throw new Error("Local media is missing");
484
+ }
485
+ const permission = await MediaLibraryPermissions.checkPermission();
486
+ if (generation !== this.lifecycleGeneration)
487
+ return;
488
+ if (!permission) {
489
+ cameraRollExportLedger.update(entry.id, {
490
+ state: "BLOCKED_PERMISSION",
491
+ lastError: "Camera-roll permission is required",
492
+ });
493
+ throw new Error("Camera-roll permission is required");
494
+ }
495
+ const hasLimitedAccess = entry.requiresFullLibraryReconciliation && (await MediaLibraryPermissions.hasLimitedAccess());
496
+ if (generation !== this.lifecycleGeneration)
497
+ return;
498
+ if (hasLimitedAccess) {
499
+ cameraRollExportLedger.update(entry.id, {
500
+ state: "BLOCKED_PERMISSION",
501
+ lastError: "Full photo-library access is required to reconcile this legacy export safely",
502
+ });
503
+ throw new Error("Full photo-library access is required to reconcile this legacy export safely");
504
+ }
505
+ const fsInfo = await RNFS.getFSInfo();
506
+ if (generation !== this.lifecycleGeneration)
507
+ return;
508
+ if (fsInfo.freeSpace < entry.size + MIN_FREE_SPACE_BYTES) {
509
+ throw new Error("Insufficient free space for camera-roll export");
510
+ }
511
+ // A setting change can land while the filesystem and permission checks are in flight.
512
+ // Once the native save starts it must finish atomically, but do not begin a new save
513
+ // after the user has disabled automatic camera-roll exports.
514
+ if (!this.enabled) {
515
+ cameraRollExportLedger.update(entry.id, { state: "NOT_REQUESTED", nextRetryAt: undefined });
516
+ this.rejectSourceWaiters(entry.id, new Error("Automatic camera-roll saving was disabled"));
517
+ return;
518
+ }
519
+ entry = cameraRollExportLedger.update(entry.id, { state: "RECONCILING", lastError: undefined });
520
+ entry = cameraRollExportLedger.update(entry.id, { state: "EXPORTING" });
521
+ const result = await MediaLibraryPermissions.saveToLibraryWithReceipt(entry.filePath, entry.modified);
522
+ if (!result.success)
523
+ throw new Error(result.error || "Camera-roll export failed");
524
+ const receipt = {
525
+ platform: result.platform,
526
+ uri: result.uri,
527
+ identifier: result.identifier,
528
+ exportedAt: Date.now(),
529
+ };
530
+ entry = cameraRollExportLedger.update(entry.id, {
531
+ state: "EXPORTED",
532
+ receipt,
533
+ requiresFullLibraryReconciliation: false,
534
+ attempts: entry.attempts + 1,
535
+ nextRetryAt: undefined,
536
+ lastError: undefined,
537
+ });
538
+ try {
539
+ await this.mirrorReceipt(entry, receipt);
540
+ }
541
+ catch (mirrorError) {
542
+ // The per-generation ledger is the authoritative durable receipt. A secondary
543
+ // metadata mirror failure must not cause a duplicate insert or block source ack.
544
+ console.warn(`${TAG} Export receipt mirror failed for ${entry.mediaName}:`, mirrorError);
545
+ }
546
+ this.resolveSourceWaiters(entry.id, receipt);
547
+ }
548
+ catch (error) {
549
+ const message = error instanceof Error ? error.message : String(error);
550
+ const current = cameraRollExportLedger.get(entry.id);
551
+ if (current && current.state !== "BLOCKED_PERMISSION" && current.state !== "MISSING_LOCAL") {
552
+ const attempts = current.attempts + 1;
553
+ cameraRollExportLedger.update(entry.id, {
554
+ state: "FAILED_RETRYABLE",
555
+ attempts,
556
+ lastError: message,
557
+ nextRetryAt: Date.now() + Math.min(2 ** Math.min(attempts, 10) * 1000, MAX_RETRY_DELAY_MS),
558
+ });
559
+ }
560
+ this.rejectSourceWaiters(entry.id, error instanceof Error ? error : new Error(message));
561
+ console.warn(`${TAG} Export remains pending for ${entry.mediaName}: ${message}`);
562
+ }
563
+ finally {
564
+ if (this.activeEntryId === entry.id)
565
+ this.activeEntryId = null;
566
+ if (generation === this.lifecycleGeneration)
567
+ this.emitSummary();
568
+ }
569
+ }
570
+ async mirrorReceipt(entry, receipt) {
571
+ await localStorageService.updateDownloadedFileAssetReceipt(entry.mediaName, receipt);
572
+ const transfer = entry.captureId
573
+ ? galleryTransferLedger.get(entry.captureId)
574
+ : galleryTransferLedger.get(entry.mediaName);
575
+ if (transfer)
576
+ galleryTransferLedger.update(transfer.captureId, { assetReceipt: receipt });
577
+ }
578
+ scheduleRetry() {
579
+ if (!this.enabled || this.retryTimer != null)
580
+ return;
581
+ const next = cameraRollExportLedger
582
+ .list()
583
+ .filter((entry) => entry.state === "FAILED_RETRYABLE" && entry.nextRetryAt)
584
+ .sort((a, b) => (a.nextRetryAt || 0) - (b.nextRetryAt || 0))[0];
585
+ if (!next?.nextRetryAt)
586
+ return;
587
+ const generation = this.lifecycleGeneration;
588
+ this.retryTimer = BgTimer.setTimeout(() => {
589
+ this.retryTimer = null;
590
+ if (generation !== this.lifecycleGeneration)
591
+ return;
592
+ void this.resume("retry timer");
593
+ }, Math.max(0, next.nextRetryAt - Date.now()));
594
+ }
595
+ resolveSourceWaiters(id, receipt) {
596
+ for (const waiter of this.sourceWaiters.get(id) || [])
597
+ waiter.resolve(receipt);
598
+ this.sourceWaiters.delete(id);
599
+ }
600
+ rejectSourceWaiters(id, error) {
601
+ for (const waiter of this.sourceWaiters.get(id) || [])
602
+ waiter.reject(error);
603
+ this.sourceWaiters.delete(id);
604
+ }
605
+ emitSummary() {
606
+ const summary = this.getSummary();
607
+ for (const listener of this.listeners) {
608
+ try {
609
+ listener(summary);
610
+ }
611
+ catch (error) {
612
+ console.warn(`${TAG} Summary listener failed`, error);
613
+ }
614
+ }
615
+ }
616
+ }
617
+ export const cameraRollExportCoordinator = new CameraRollExportCoordinator();
618
+ //# sourceMappingURL=cameraRollExportCoordinator.js.map