@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.
- package/README.md +55 -18
- package/build/bluetooth-sdk/debug.d.ts +2 -0
- package/build/bluetooth-sdk/debug.d.ts.map +1 -0
- package/build/bluetooth-sdk/debug.js +2 -0
- package/build/bluetooth-sdk/debug.js.map +1 -0
- package/build/bluetooth-sdk/index.d.ts +3 -0
- package/build/bluetooth-sdk/index.d.ts.map +1 -0
- package/build/bluetooth-sdk/index.js +3 -0
- package/build/bluetooth-sdk/index.js.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.js +3 -0
- package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
- package/build/bluetooth-sdk/react.d.ts +2 -0
- package/build/bluetooth-sdk/react.d.ts.map +1 -0
- package/build/bluetooth-sdk/react.js +2 -0
- package/build/bluetooth-sdk/react.js.map +1 -0
- package/build/bluetooth-sdk/types.d.ts +2 -0
- package/build/bluetooth-sdk/types.d.ts.map +1 -0
- package/build/bluetooth-sdk/types.js +2 -0
- package/build/bluetooth-sdk/types.js.map +1 -0
- package/build/engine.d.ts +24 -16
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +9 -4
- package/build/engine.js.map +1 -1
- package/build/facades/dev.d.ts +3 -2
- package/build/facades/dev.d.ts.map +1 -1
- package/build/facades/dev.js +18 -12
- package/build/facades/dev.js.map +1 -1
- package/build/facades/display.d.ts +1 -1
- package/build/facades/display.d.ts.map +1 -1
- package/build/facades/display.js +1 -1
- package/build/facades/display.js.map +1 -1
- package/build/facades/gallery.js +1 -1
- package/build/facades/gallery.js.map +1 -1
- package/build/facades/glasses.d.ts +4 -13
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +21 -6
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/glassesSettings.d.ts.map +1 -1
- package/build/facades/glassesSettings.js +1 -0
- package/build/facades/glassesSettings.js.map +1 -1
- package/build/facades/miniapps.d.ts +4 -0
- package/build/facades/miniapps.d.ts.map +1 -1
- package/build/facades/miniapps.js +5 -0
- package/build/facades/miniapps.js.map +1 -1
- package/build/facades/ota.d.ts +14 -16
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +22 -7
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +8 -5
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +12 -10
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/permissions.d.ts +10 -0
- package/build/facades/permissions.d.ts.map +1 -1
- package/build/facades/permissions.js +10 -0
- package/build/facades/permissions.js.map +1 -1
- package/build/facades/phoneNotifications.d.ts +0 -4
- package/build/facades/phoneNotifications.d.ts.map +1 -1
- package/build/facades/phoneNotifications.js +4 -14
- package/build/facades/phoneNotifications.js.map +1 -1
- package/build/facades/speech.d.ts +7 -6
- package/build/facades/speech.d.ts.map +1 -1
- package/build/facades/speech.js +1 -1
- package/build/facades/speech.js.map +1 -1
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +10 -8
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -5
- package/build/index.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.d.ts +38 -0
- package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
- package/build/react/MentraLiveOtaFlow.js +528 -0
- package/build/react/MentraLiveOtaFlow.js.map +1 -0
- package/build/react/index.d.ts +2 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +2 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useEngineSnapshot.d.ts +2 -0
- package/build/react/useEngineSnapshot.d.ts.map +1 -0
- package/build/react/useEngineSnapshot.js +14 -0
- package/build/react/useEngineSnapshot.js.map +1 -0
- package/build/runtime/bootstrap.d.ts +24 -1
- package/build/runtime/bootstrap.d.ts.map +1 -1
- package/build/runtime/bootstrap.js +17 -0
- package/build/runtime/bootstrap.js.map +1 -1
- package/build/runtime/scanQrSeam.d.ts +7 -0
- package/build/runtime/scanQrSeam.d.ts.map +1 -0
- package/build/runtime/scanQrSeam.js +16 -0
- package/build/runtime/scanQrSeam.js.map +1 -0
- package/build/services/AppRegistry.d.ts +41 -57
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +208 -144
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/AudioCloudUplink.d.ts +12 -0
- package/build/services/AudioCloudUplink.d.ts.map +1 -1
- package/build/services/AudioCloudUplink.js +22 -1
- package/build/services/AudioCloudUplink.js.map +1 -1
- package/build/services/AudioPlaybackService.d.ts +41 -2
- package/build/services/AudioPlaybackService.d.ts.map +1 -1
- package/build/services/AudioPlaybackService.js +250 -33
- package/build/services/AudioPlaybackService.js.map +1 -1
- package/build/services/BlobStore.d.ts +2 -1
- package/build/services/BlobStore.d.ts.map +1 -1
- package/build/services/BlobStore.js +17 -9
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.js +13 -1
- package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
- package/build/services/CloudClientService.d.ts +15 -0
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +93 -1
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DeviceEventRouter.js +5 -5
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/ForegroundLocationPermission.d.ts +13 -0
- package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
- package/build/services/ForegroundLocationPermission.js +12 -0
- package/build/services/ForegroundLocationPermission.js.map +1 -0
- package/build/services/GlassesSettingsSync.d.ts.map +1 -1
- package/build/services/GlassesSettingsSync.js +9 -3
- package/build/services/GlassesSettingsSync.js.map +1 -1
- package/build/services/GlassesStatusProjection.d.ts +2 -1
- package/build/services/GlassesStatusProjection.d.ts.map +1 -1
- package/build/services/GlassesStatusProjection.js +15 -8
- package/build/services/GlassesStatusProjection.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts +29 -0
- package/build/services/HotspotOtaTransport.d.ts.map +1 -0
- package/build/services/HotspotOtaTransport.js +146 -0
- package/build/services/HotspotOtaTransport.js.map +1 -0
- package/build/services/HotspotShutdown.d.ts +17 -0
- package/build/services/HotspotShutdown.d.ts.map +1 -0
- package/build/services/HotspotShutdown.js +29 -0
- package/build/services/HotspotShutdown.js.map +1 -0
- package/build/services/LocalDisplayManager.d.ts +15 -0
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +106 -20
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +74 -2
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +785 -291
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalMiniappStorage.d.ts +32 -0
- package/build/services/LocalMiniappStorage.d.ts.map +1 -0
- package/build/services/LocalMiniappStorage.js +66 -0
- package/build/services/LocalMiniappStorage.js.map +1 -0
- package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
- package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
- package/build/services/LocalMiniappUserIdentity.js +43 -0
- package/build/services/LocalMiniappUserIdentity.js.map +1 -0
- package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js +18 -12
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/MicStateCoordinator.d.ts +42 -1
- package/build/services/MicStateCoordinator.d.ts.map +1 -1
- package/build/services/MicStateCoordinator.js +141 -3
- package/build/services/MicStateCoordinator.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts.map +1 -1
- package/build/services/MiniappLauncher.js +23 -3
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/MiniappLiveness.d.ts +12 -0
- package/build/services/MiniappLiveness.d.ts.map +1 -0
- package/build/services/MiniappLiveness.js +16 -0
- package/build/services/MiniappLiveness.js.map +1 -0
- package/build/services/NativeHttpResponse.d.ts +3 -0
- package/build/services/NativeHttpResponse.d.ts.map +1 -0
- package/build/services/NativeHttpResponse.js +6 -0
- package/build/services/NativeHttpResponse.js.map +1 -0
- package/build/services/OtaArtifactDownloader.d.ts +65 -0
- package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
- package/build/services/OtaArtifactDownloader.js +226 -0
- package/build/services/OtaArtifactDownloader.js.map +1 -0
- package/build/services/OtaAutoChain.d.ts +34 -0
- package/build/services/OtaAutoChain.d.ts.map +1 -0
- package/build/services/OtaAutoChain.js +83 -0
- package/build/services/OtaAutoChain.js.map +1 -0
- package/build/services/OtaErrorMapping.d.ts +18 -0
- package/build/services/OtaErrorMapping.d.ts.map +1 -0
- package/build/services/OtaErrorMapping.js +63 -0
- package/build/services/OtaErrorMapping.js.map +1 -0
- package/build/services/OtaInstallCoordinator.d.ts +95 -15
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +577 -130
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/OtaService.d.ts.map +1 -1
- package/build/services/OtaService.js +8 -1
- package/build/services/OtaService.js.map +1 -1
- package/build/services/OtaUpdateCheckService.d.ts +39 -4
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +138 -22
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/PhoneCalendarHelpers.d.ts +32 -0
- package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
- package/build/services/PhoneCalendarHelpers.js +157 -0
- package/build/services/PhoneCalendarHelpers.js.map +1 -0
- package/build/services/PhoneCalendarService.d.ts +5 -0
- package/build/services/PhoneCalendarService.d.ts.map +1 -0
- package/build/services/PhoneCalendarService.js +45 -0
- package/build/services/PhoneCalendarService.js.map +1 -0
- package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
- package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
- package/build/services/PhoneCameraFovCoordinator.js +194 -0
- package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +12 -10
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.d.ts +26 -2
- package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +79 -9
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts +8 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js +125 -13
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/PhoneVideoCoordinator.d.ts +2 -0
- package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
- package/build/services/PhoneVideoCoordinator.js +10 -0
- package/build/services/PhoneVideoCoordinator.js.map +1 -1
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +15 -0
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/SentenceTtsPipeline.d.ts +31 -0
- package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
- package/build/services/SentenceTtsPipeline.js +67 -0
- package/build/services/SentenceTtsPipeline.js.map +1 -0
- package/build/services/SupportProfileSync.d.ts +22 -0
- package/build/services/SupportProfileSync.d.ts.map +1 -0
- package/build/services/SupportProfileSync.js +213 -0
- package/build/services/SupportProfileSync.js.map +1 -0
- package/build/services/TranscriptionRouting.d.ts +12 -0
- package/build/services/TranscriptionRouting.d.ts.map +1 -0
- package/build/services/TranscriptionRouting.js +24 -0
- package/build/services/TranscriptionRouting.js.map +1 -0
- package/build/services/TtsTextSanitizer.d.ts +5 -0
- package/build/services/TtsTextSanitizer.d.ts.map +1 -0
- package/build/services/TtsTextSanitizer.js +61 -0
- package/build/services/TtsTextSanitizer.js.map +1 -0
- package/build/services/WifiAdbRequest.d.ts +17 -0
- package/build/services/WifiAdbRequest.d.ts.map +1 -0
- package/build/services/WifiAdbRequest.js +35 -0
- package/build/services/WifiAdbRequest.js.map +1 -0
- package/build/services/asg/asgCameraApi.d.ts +43 -0
- package/build/services/asg/asgCameraApi.d.ts.map +1 -1
- package/build/services/asg/asgCameraApi.js +509 -26
- package/build/services/asg/asgCameraApi.js.map +1 -1
- package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
- package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
- package/build/services/asg/cameraRollExportCoordinator.js +618 -0
- package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
- package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
- package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
- package/build/services/asg/cameraRollExportLedger.js +78 -0
- package/build/services/asg/cameraRollExportLedger.js.map +1 -0
- package/build/services/asg/galleryNotices.d.ts +1 -1
- package/build/services/asg/galleryNotices.d.ts.map +1 -1
- package/build/services/asg/galleryNotices.js.map +1 -1
- package/build/services/asg/galleryPathMigration.d.ts +3 -0
- package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
- package/build/services/asg/galleryPathMigration.js +26 -0
- package/build/services/asg/galleryPathMigration.js.map +1 -0
- package/build/services/asg/gallerySettingsService.d.ts +1 -0
- package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
- package/build/services/asg/gallerySettingsService.js +2 -0
- package/build/services/asg/gallerySettingsService.js.map +1 -1
- package/build/services/asg/gallerySyncService.d.ts.map +1 -1
- package/build/services/asg/gallerySyncService.js +162 -56
- package/build/services/asg/gallerySyncService.js.map +1 -1
- package/build/services/asg/galleryTransferLedger.d.ts +58 -0
- package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
- package/build/services/asg/galleryTransferLedger.js +225 -0
- package/build/services/asg/galleryTransferLedger.js.map +1 -0
- package/build/services/asg/localNetworkTransport.d.ts +15 -0
- package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
- package/build/services/asg/localNetworkTransport.js +144 -0
- package/build/services/asg/localNetworkTransport.js.map +1 -0
- package/build/services/asg/localStorageService.d.ts +18 -0
- package/build/services/asg/localStorageService.d.ts.map +1 -1
- package/build/services/asg/localStorageService.js +168 -19
- package/build/services/asg/localStorageService.js.map +1 -1
- package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
- package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
- package/build/services/asg/mediaProcessingQueue.js +193 -62
- package/build/services/asg/mediaProcessingQueue.js.map +1 -1
- package/build/services/audioPlaybackAssets.d.ts +8 -0
- package/build/services/audioPlaybackAssets.d.ts.map +1 -0
- package/build/services/audioPlaybackAssets.js +7 -0
- package/build/services/audioPlaybackAssets.js.map +1 -0
- package/build/services/gallerySyncClock.js +1 -1
- package/build/services/gallerySyncClock.js.map +1 -1
- package/build/services/glassesClockSync.d.ts.map +1 -1
- package/build/services/glassesClockSync.js +6 -2
- package/build/services/glassesClockSync.js.map +1 -1
- package/build/services/manifestActions.d.ts +7 -0
- package/build/services/manifestActions.d.ts.map +1 -0
- package/build/services/manifestActions.js +25 -0
- package/build/services/manifestActions.js.map +1 -0
- package/build/services/otaDisplayState.d.ts +23 -12
- package/build/services/otaDisplayState.d.ts.map +1 -1
- package/build/services/otaDisplayState.js +36 -14
- package/build/services/otaDisplayState.js.map +1 -1
- package/build/services/otaInstallPolicy.d.ts +16 -4
- package/build/services/otaInstallPolicy.d.ts.map +1 -1
- package/build/services/otaInstallPolicy.js +24 -3
- package/build/services/otaInstallPolicy.js.map +1 -1
- package/build/services/otaLegacyMapping.d.ts +1 -1
- package/build/services/otaLegacyMapping.d.ts.map +1 -1
- package/build/services/otaLegacyMapping.js.map +1 -1
- package/build/services/otaManifestPolicy.d.ts +14 -0
- package/build/services/otaManifestPolicy.d.ts.map +1 -0
- package/build/services/otaManifestPolicy.js +19 -0
- package/build/services/otaManifestPolicy.js.map +1 -0
- package/build/services/otaManifestUrl.d.ts +3 -0
- package/build/services/otaManifestUrl.d.ts.map +1 -0
- package/build/services/otaManifestUrl.js +38 -0
- package/build/services/otaManifestUrl.js.map +1 -0
- package/build/services/slimStreamStatus.d.ts +11 -0
- package/build/services/slimStreamStatus.d.ts.map +1 -1
- package/build/services/slimStreamStatus.js +14 -4
- package/build/services/slimStreamStatus.js.map +1 -1
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +11 -0
- package/build/stores/apps.js.map +1 -1
- package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
- package/build/stores/bluetoothSettingKeys.js +2 -0
- package/build/stores/bluetoothSettingKeys.js.map +1 -1
- package/build/stores/gallerySync.d.ts +2 -0
- package/build/stores/gallerySync.d.ts.map +1 -1
- package/build/stores/gallerySync.js +2 -0
- package/build/stores/gallerySync.js.map +1 -1
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js +3 -0
- package/build/stores/glasses.js.map +1 -1
- package/build/stores/settings.d.ts +17 -0
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +157 -17
- package/build/stores/settings.js.map +1 -1
- package/build/types/applet.d.ts +2 -0
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/types/asg.d.ts +7 -0
- package/build/types/asg.d.ts.map +1 -1
- package/build/types/asg.js.map +1 -1
- package/build/types/enums.d.ts +2 -25
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +2 -27
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +4 -13
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +15 -3
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +2 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +2 -6
- package/build/types/index.js.map +1 -1
- package/build/utils/configuredDevHost.d.ts +6 -0
- package/build/utils/configuredDevHost.d.ts.map +1 -0
- package/build/utils/configuredDevHost.js +19 -0
- package/build/utils/configuredDevHost.js.map +1 -0
- package/build/utils/devMiniappLaunch.d.ts +19 -8
- package/build/utils/devMiniappLaunch.d.ts.map +1 -1
- package/build/utils/devMiniappLaunch.js +144 -21
- package/build/utils/devMiniappLaunch.js.map +1 -1
- package/build/utils/diagnosticContext.d.ts.map +1 -1
- package/build/utils/diagnosticContext.js +15 -17
- package/build/utils/diagnosticContext.js.map +1 -1
- package/build/utils/hardware/hardware.d.ts.map +1 -1
- package/build/utils/hardware/hardware.js +7 -3
- package/build/utils/hardware/hardware.js.map +1 -1
- package/build/utils/miniappDiagnostics.d.ts +64 -0
- package/build/utils/miniappDiagnostics.d.ts.map +1 -0
- package/build/utils/miniappDiagnostics.js +173 -0
- package/build/utils/miniappDiagnostics.js.map +1 -0
- package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
- package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
- package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
- package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
- package/build/utils/timers/timers.d.ts.map +1 -1
- package/build/utils/timers/timers.js +55 -18
- package/build/utils/timers/timers.js.map +1 -1
- package/package.json +59 -31
- package/src/assets/silence.wav +0 -0
- package/src/bluetooth-sdk/debug.ts +1 -0
- package/src/bluetooth-sdk/index.ts +2 -0
- package/src/bluetooth-sdk/photo-receiver.ts +2 -0
- package/src/bluetooth-sdk/react.ts +1 -0
- package/src/bluetooth-sdk/types.ts +1 -0
- package/src/engine.ts +9 -4
- package/src/facades/dev.ts +17 -12
- package/src/facades/display.ts +1 -1
- package/src/facades/gallery.ts +1 -1
- package/src/facades/glasses.ts +20 -7
- package/src/facades/glassesSettings.ts +5 -0
- package/src/facades/miniapps.ts +7 -0
- package/src/facades/ota.ts +23 -8
- package/src/facades/pairing.ts +15 -11
- package/src/facades/permissions.ts +14 -0
- package/src/facades/phoneNotifications.ts +4 -13
- package/src/facades/speech.ts +21 -7
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +39 -13
- package/src/react/MentraLiveOtaFlow.tsx +856 -0
- package/src/react/index.ts +7 -0
- package/src/react/useEngineSnapshot.ts +16 -0
- package/src/runtime/bootstrap.ts +33 -1
- package/src/runtime/scanQrSeam.ts +20 -0
- package/src/services/AppRegistry.ts +240 -149
- package/src/services/AudioCloudUplink.ts +23 -1
- package/src/services/AudioPlaybackService.ts +287 -38
- package/src/services/BlobStore.ts +22 -9
- package/src/services/CloudAudioSubscriptionSync.ts +13 -1
- package/src/services/CloudClientService.ts +96 -1
- package/src/services/DeviceEventRouter.ts +5 -5
- package/src/services/ForegroundLocationPermission.ts +24 -0
- package/src/services/GlassesSettingsSync.ts +9 -3
- package/src/services/GlassesStatusProjection.ts +16 -8
- package/src/services/HotspotOtaTransport.ts +184 -0
- package/src/services/HotspotShutdown.ts +41 -0
- package/src/services/LocalDisplayManager.ts +112 -21
- package/src/services/LocalMiniappRuntime.ts +967 -346
- package/src/services/LocalMiniappStorage.ts +82 -0
- package/src/services/LocalMiniappUserIdentity.ts +46 -0
- package/src/services/LocalSttFallbackCoordinator.ts +19 -12
- package/src/services/MicStateCoordinator.ts +169 -4
- package/src/services/MiniappLauncher.ts +30 -3
- package/src/services/MiniappLiveness.ts +24 -0
- package/src/services/NativeHttpResponse.ts +6 -0
- package/src/services/OtaArtifactDownloader.ts +312 -0
- package/src/services/OtaAutoChain.ts +106 -0
- package/src/services/OtaErrorMapping.ts +80 -0
- package/src/services/OtaInstallCoordinator.ts +649 -144
- package/src/services/OtaService.ts +11 -5
- package/src/services/OtaUpdateCheckService.ts +181 -21
- package/src/services/PhoneCalendarHelpers.ts +212 -0
- package/src/services/PhoneCalendarService.ts +65 -0
- package/src/services/PhoneCameraFovCoordinator.ts +210 -0
- package/src/services/PhoneNotificationsSync.ts +12 -10
- package/src/services/PhonePhotoCoordinator.ts +116 -18
- package/src/services/PhoneStreamCoordinator.ts +139 -25
- package/src/services/PhoneVideoCoordinator.ts +11 -0
- package/src/services/SceneRenderer.ts +16 -0
- package/src/services/SentenceTtsPipeline.ts +106 -0
- package/src/services/SupportProfileSync.ts +218 -0
- package/src/services/TranscriptionRouting.ts +37 -0
- package/src/services/TtsTextSanitizer.ts +66 -0
- package/src/services/WifiAdbRequest.ts +53 -0
- package/src/services/asg/asgCameraApi.ts +615 -33
- package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
- package/src/services/asg/cameraRollExportLedger.ts +122 -0
- package/src/services/asg/galleryNotices.ts +1 -0
- package/src/services/asg/galleryPathMigration.ts +22 -0
- package/src/services/asg/gallerySettingsService.ts +3 -0
- package/src/services/asg/gallerySyncService.ts +184 -73
- package/src/services/asg/galleryTransferLedger.ts +312 -0
- package/src/services/asg/localNetworkTransport.ts +169 -0
- package/src/services/asg/localStorageService.ts +179 -24
- package/src/services/asg/mediaProcessingQueue.ts +209 -62
- package/src/services/audioPlaybackAssets.ts +8 -0
- package/src/services/gallerySyncClock.ts +1 -1
- package/src/services/glassesClockSync.ts +6 -2
- package/src/services/manifestActions.ts +30 -0
- package/src/services/otaDisplayState.ts +58 -17
- package/src/services/otaInstallPolicy.ts +30 -4
- package/src/services/otaLegacyMapping.ts +1 -1
- package/src/services/otaManifestPolicy.ts +42 -0
- package/src/services/otaManifestUrl.ts +44 -0
- package/src/services/slimStreamStatus.ts +16 -5
- package/src/stores/apps.ts +12 -0
- package/src/stores/bluetoothSettingKeys.ts +2 -0
- package/src/stores/gallerySync.ts +4 -0
- package/src/stores/glasses.ts +3 -0
- package/src/stores/settings.ts +179 -18
- package/src/types/applet.ts +2 -0
- package/src/types/asg.ts +7 -0
- package/src/types/enums.ts +3 -28
- package/src/types/hardware.ts +20 -13
- package/src/types/index.ts +2 -6
- package/src/utils/configuredDevHost.ts +17 -0
- package/src/utils/devMiniappLaunch.ts +151 -23
- package/src/utils/diagnosticContext.ts +17 -17
- package/src/utils/hardware/hardware.ts +7 -9
- package/src/utils/miniappDiagnostics.ts +226 -0
- package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
- package/src/utils/timers/timers.ts +57 -21
- package/build/devtools.d.ts +0 -11
- package/build/devtools.d.ts.map +0 -1
- package/build/devtools.js +0 -13
- package/build/devtools.js.map +0 -1
- package/build/internal.d.ts +0 -66
- package/build/internal.d.ts.map +0 -1
- package/build/internal.js +0 -89
- package/build/internal.js.map +0 -1
- package/build/services/asgOtaVersionUrl.d.ts +0 -2
- package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
- package/build/services/asgOtaVersionUrl.js +0 -36
- package/build/services/asgOtaVersionUrl.js.map +0 -1
- package/src/devtools.ts +0 -13
- package/src/internal.ts +0 -158
- package/src/services/asgOtaVersionUrl.ts +0 -41
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioPlaybackService.js","sourceRoot":"","sources":["../../src/services/AudioPlaybackService.ts"],"names":[],"mappings":"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","sourcesContent":["import {createAudioPlayer, AudioPlayer, AudioStatus, setAudioModeAsync} from \"expo-audio\"\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {BgTimer} from \"../utils/timers\"\n\nconst RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK = false\n\ninterface AudioPlayRequest {\n requestId: string\n audioUrl: string\n appId?: string\n volume?: number\n stopOtherAudio?: boolean\n}\n\ninterface PlaybackState {\n requestId: string\n appId?: string\n startTime: number\n completed: boolean // Guard against double callbacks\n onComplete: (requestId: string, success: boolean, error: string | null, duration: number | null) => void\n}\n\n/** Open request for a live PCM output stream (miniapp speaker.createStream). */\nexport interface AudioStreamOpenRequest {\n streamId: string\n appId: string\n /** PCM sample rate in Hz (16000 / 24000 / 48000). */\n sampleRate: number\n /** Channel count. v1 is mono. */\n channels: number\n volume?: number\n stopOtherAudio?: boolean\n /**\n * Called when the stream ends for any reason (drained after close, aborted,\n * interrupted by other audio, or native error).\n */\n onEnded: (streamId: string, success: boolean, error: string | null, durationMs: number | null) => void\n}\n\n/** One live PCM stream session, backed by native streaming audio. */\ninterface StreamState {\n streamId: string\n appId: string\n startTime: number\n ended: boolean // Guard against double onEnded\n onEnded: AudioStreamOpenRequest[\"onEnded\"]\n}\n\nclass AudioPlaybackService {\n private static instance: AudioPlaybackService | null = null\n // Reuse a single AudioPlayer to avoid AudioTrack exhaustion\n // Creating new ExoPlayer instances per request leads to -12 ENOMEM errors\n private player: AudioPlayer | null = null\n private currentPlayback: PlaybackState | null = null\n // Live PCM streams (speaker.createStream), keyed by streamId. The runtime\n // enforces one per app; stopOtherAudio interrupts across apps.\n private streams = new Map<string, StreamState>()\n private audioModeConfigured: boolean = false\n // Debounce timer for notifying native that audio stopped\n // Prevents mic toggle flicker when playing back-to-back audio\n // Uses BgTimer to work reliably when app is backgrounded on Android\n private audioStopDebounceTimer: number | null = null\n // Original glasses media volume captured before we bump it for A2DP playback.\n private glassesVolumeRestoreLevel: number | null = null\n private static readonly AUDIO_STOP_DEBOUNCE_MS = 1500\n private static readonly A2DP_TAIL_DRAIN_MS = 900\n /** If glasses report step volume at or below this, bump to FLOOR before A2DP playback. */\n private static readonly GLASSES_VOLUME_LOW_THRESHOLD = 2\n private static readonly GLASSES_VOLUME_FLOOR = 9\n\n private constructor() {}\n\n /**\n * Configure audio mode for playback, re-asserting it on EVERY play.\n *\n * This must run before each play — not just once — because other parts of the\n * app put the shared iOS AVAudioSession into a record-oriented category and\n * never restore it. In particular the phone mic (PhoneMic.swift) switches the\n * session to `.playAndRecord` (sometimes `.voiceChat`/earpiece routing) while\n * capturing and only deactivates it on stop, leaving the category sticky. A\n * miniapp like the Recorder records and then immediately plays back through\n * this service; if we kept the old \"configure once\" guard, playback would land\n * in the leftover `.playAndRecord` session and be inaudible on the phone\n * speaker (the symptom: the progress bar runs but no sound comes out). Calling\n * setAudioModeAsync with no `allowsRecording` maps to category `.playback`,\n * reclaiming the speaker route. `audioModeConfigured` is kept only to gate the\n * one-time log.\n */\n private async ensureAudioModeConfigured(): Promise<void> {\n try {\n await setAudioModeAsync({\n shouldPlayInBackground: true,\n playsInSilentMode: true,\n interruptionMode: \"duckOthers\",\n })\n if (!this.audioModeConfigured) {\n this.audioModeConfigured = true\n console.log(\"AUDIO: Audio mode configured for playback\")\n }\n } catch (error) {\n console.error(\"AUDIO: Failed to configure audio mode:\", error)\n // Don't block playback if audio mode config fails\n }\n }\n\n public static getInstance(): AudioPlaybackService {\n if (!AudioPlaybackService.instance) {\n AudioPlaybackService.instance = new AudioPlaybackService()\n }\n return AudioPlaybackService.instance\n }\n\n /**\n * Ensure we have a reusable player instance\n */\n private ensurePlayer(): AudioPlayer {\n if (!this.player) {\n console.log(\"AUDIO: Creating reusable AudioPlayer instance\")\n this.player = createAudioPlayer(null)\n\n // Add status listener once - it will handle all playback completions\n this.player.addListener(\"playbackStatusUpdate\", (status: AudioStatus) => {\n this.onPlaybackStatusUpdate(status)\n })\n }\n return this.player\n }\n\n private async getGlassesMediaVolumeWithTiming() {\n const startedAt = Date.now()\n try {\n const result = await BluetoothSdk.getGlassesMediaVolume()\n console.log(`AUDIO: Glasses media volume read completed in ${Date.now() - startedAt}ms`)\n return result\n } catch (error) {\n console.warn(\n `AUDIO: Glasses media volume read failed after ${Date.now() - startedAt}ms:`,\n error instanceof Error ? error.message : String(error),\n )\n throw error\n }\n }\n\n private async setGlassesMediaVolumeWithTiming(level: number) {\n const startedAt = Date.now()\n try {\n const result = await BluetoothSdk.setGlassesMediaVolume(level)\n console.log(`AUDIO: Glasses media volume set(${level}) completed in ${Date.now() - startedAt}ms`)\n return result\n } catch (error) {\n console.warn(\n `AUDIO: Glasses media volume set(${level}) failed after ${Date.now() - startedAt}ms:`,\n error instanceof Error ? error.message : String(error),\n )\n throw error\n }\n }\n\n /**\n * Mentra Live: raise glasses media volume over BLE when it is very low so A2DP prompts are audible.\n * Fail-open on unsupported devices, timeouts, or errors.\n */\n private async ensureGlassesMediaVolumeForA2dp(playback: PlaybackState): Promise<void> {\n if (this.glassesVolumeRestoreLevel !== null) {\n console.log(\n `AUDIO: Keeping bumped glasses media volume at ${AudioPlaybackService.GLASSES_VOLUME_FLOOR} during ongoing playback`,\n )\n return\n }\n\n try {\n const raw = await this.getGlassesMediaVolumeWithTiming()\n const level = Number(raw.level)\n const statusCode = Number(raw.statusCode)\n if (!Number.isFinite(level)) {\n console.log(\"AUDIO: Received glasses media volume response without numeric level:\", JSON.stringify(raw))\n return\n }\n const k900S = Number.isFinite(statusCode) && statusCode >= 0 ? ` K900_S=${statusCode}` : \"\"\n console.log(`AUDIO: Glasses media step volume (wearable knob, 0-15 scale): ${level}/15.${k900S}`)\n if (level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) {\n return\n }\n if (this.currentPlayback !== playback || playback.completed) {\n console.log(\"AUDIO: Skipping glasses volume bump; playback already ended\")\n return\n }\n console.log(`AUDIO: Raising glasses media volume (was ${level})`)\n await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR)\n if (this.currentPlayback === playback && !playback.completed) {\n this.glassesVolumeRestoreLevel = level\n } else if (RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {\n console.log(\"AUDIO: Restoring glasses volume immediately; playback ended during volume bump\")\n await this.setGlassesMediaVolumeWithTiming(level)\n } else {\n console.log(\"AUDIO: Leaving bumped glasses media volume unchanged after playback\")\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e)\n console.warn(\"AUDIO: Skipping glasses volume bump:\", msg)\n }\n }\n\n /**\n * Restore the user's original glasses media step volume after A2DP playback finishes.\n */\n private async restoreGlassesMediaVolume(): Promise<void> {\n const restoreLevel = this.glassesVolumeRestoreLevel\n if (restoreLevel === null) {\n return\n }\n if (!RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {\n this.glassesVolumeRestoreLevel = null\n console.log(\"AUDIO: Leaving bumped glasses media volume unchanged after playback\")\n return\n }\n\n try {\n console.log(`AUDIO: Restoring glasses media volume to ${restoreLevel}`)\n await this.setGlassesMediaVolumeWithTiming(restoreLevel)\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e)\n console.warn(`AUDIO: Failed to restore glasses volume to ${restoreLevel}:`, msg)\n } finally {\n this.glassesVolumeRestoreLevel = null\n }\n }\n\n private pauseFinishedPlayerAfterTail(playback: PlaybackState): void {\n BgTimer.setTimeout(() => {\n if (this.currentPlayback) return\n if (!this.player) return\n try {\n this.player.pause()\n console.log(\n `AUDIO: Paused finished player for ${playback.requestId} after ${AudioPlaybackService.A2DP_TAIL_DRAIN_MS}ms tail drain`,\n )\n } catch (e) {\n console.warn(\"AUDIO: Error pausing player after tail drain:\", e)\n }\n }, AudioPlaybackService.A2DP_TAIL_DRAIN_MS)\n }\n\n /**\n * Play audio from a URL.\n * Returns a promise that resolves with playback result when audio finishes or errors.\n */\n public async play(\n request: AudioPlayRequest,\n onComplete: (requestId: string, success: boolean, error: string | null, duration: number | null) => void,\n ): Promise<void> {\n const {requestId, audioUrl, appId, volume = 1.0, stopOtherAudio = true} = request\n\n console.log(`AUDIO: Play request ${requestId}${appId ? ` from ${appId}` : \"\"}: ${audioUrl}`)\n\n try {\n // Ensure audio mode is configured for background playback\n await this.ensureAudioModeConfigured()\n\n // Stop current playback if any (notify previous callback)\n if (stopOtherAudio && this.currentPlayback && !this.currentPlayback.completed) {\n console.log(`AUDIO: Interrupting current playback for new request`)\n this.interruptCurrentPlayback(true)\n }\n // Live PCM streams count as \"other audio\" too.\n if (stopOtherAudio) {\n await this.abortAllStreams()\n }\n\n // Get or create the reusable player\n const player = this.ensurePlayer()\n\n // Set volume\n player.volume = Math.max(0, Math.min(1, volume))\n\n // Store the new playback state\n const playback: PlaybackState = {\n requestId,\n appId,\n startTime: Date.now(),\n completed: false,\n onComplete,\n }\n this.currentPlayback = playback\n\n // Replace the source and play\n // Using replace() reuses the existing ExoPlayer/AudioTrack instead of creating new ones\n player.replace({uri: audioUrl})\n player.play()\n\n // Mentra Live volume reads can block up to 5s when the glasses don't\n // answer. Do not put that in front of playback; guard it against late\n // completion so a stale volume response cannot bump after this request is\n // already over.\n void this.ensureGlassesMediaVolumeForA2dp(playback)\n\n // Notify native that our app is playing audio\n // Used to suspend LC3 mic during audio playback to avoid MCU overload\n // Cancel any pending \"stop\" notification first (handles back-to-back audio)\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n this.audioStopDebounceTimer = null\n }\n BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of audio start:\", e)\n })\n\n console.log(`AUDIO: Started playback for ${requestId}`)\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error loading audio\"\n console.error(`AUDIO: Failed to play ${requestId}:`, errorMessage)\n void this.restoreGlassesMediaVolume()\n onComplete(requestId, false, errorMessage, null)\n }\n }\n\n /**\n * Interrupt current playback and notify its callback\n */\n private interruptCurrentPlayback(preserveGlassesMediaVolume: boolean = false): void {\n if (!this.currentPlayback || this.currentPlayback.completed) return\n\n const playback = this.currentPlayback\n playback.completed = true\n this.currentPlayback = null\n\n // Stop the player\n if (this.player) {\n try {\n this.player.pause()\n } catch (error) {\n console.error(\"AUDIO: Error pausing player:\", error)\n }\n }\n\n // Notify native that our app stopped playing audio (debounced)\n this.notifyAudioStopDebounced()\n if (!preserveGlassesMediaVolume) {\n void this.restoreGlassesMediaVolume()\n }\n\n // Notify that playback was interrupted\n const elapsedMs = Date.now() - playback.startTime\n playback.onComplete(playback.requestId, true, null, elapsedMs)\n console.log(`AUDIO: Interrupted ${playback.requestId} after ${elapsedMs}ms`)\n }\n\n /**\n * Handle playback status updates from expo-audio\n */\n private onPlaybackStatusUpdate(status: AudioStatus): void {\n const playback = this.currentPlayback\n\n // Guard against callbacks for unknown or completed playbacks\n if (!playback || playback.completed) {\n return\n }\n\n // Check if playback finished\n if (status.didJustFinish) {\n const durationMs = (status.duration || 0) * 1000 // expo-audio uses seconds\n console.log(`AUDIO: Playback finished for ${playback.requestId}, duration: ${durationMs}ms`)\n playback.completed = true\n\n // ExoPlayer can report finished before an A2DP sink has audibly drained\n // the last buffered audio. Pausing immediately can clip the tail on\n // Mentra Live; defer cleanup unless another playback has started.\n this.pauseFinishedPlayerAfterTail(playback)\n\n playback.onComplete(playback.requestId, true, null, durationMs)\n this.currentPlayback = null\n\n // Notify native that our app stopped playing audio (debounced)\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n return\n }\n\n // Detect silent playback failures: expo-audio doesn't surface errors to JS,\n // so when ExoPlayer fails to load/play a URL (network error, HTTP 500, etc.),\n // the player state goes to \"idle\" with nothing loaded and no buffering.\n // We wait 1500ms after play() to avoid false positives during initial load.\n if (status.playbackState === \"idle\" && !status.isBuffering && !status.isLoaded) {\n const elapsedMs = Date.now() - playback.startTime\n if (elapsedMs > 1500) {\n console.error(`AUDIO: Playback failed for ${playback.requestId} (player went idle after ${elapsedMs}ms)`)\n playback.completed = true\n playback.onComplete(playback.requestId, false, \"Playback failed (player went idle)\", null)\n this.currentPlayback = null\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n }\n }\n }\n\n /**\n * Notify native that audio stopped, with debouncing to prevent mic toggle flicker\n * when playing back-to-back audio files\n */\n private notifyAudioStopDebounced(): void {\n // Clear any existing timer\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n }\n\n // Set a new timer - if new audio starts within this window, the timer gets cancelled\n // Uses BgTimer to work reliably when app is backgrounded on Android\n this.audioStopDebounceTimer = BgTimer.setTimeout(() => {\n this.audioStopDebounceTimer = null\n BluetoothSdk.setOwnAppAudioPlaying(false).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of audio stop:\", e)\n })\n }, AudioPlaybackService.AUDIO_STOP_DEBOUNCE_MS)\n }\n\n // ── live PCM output streams (miniapp speaker.createStream) ────────────────\n\n /**\n * Open a live PCM stream session. Chunks are pushed with writeStreamChunk\n * into native streaming audio (AudioTrack on Android, AVAudioEngine on iOS),\n * following the media route such as A2DP to connected glasses.\n */\n public async openStream(request: AudioStreamOpenRequest): Promise<void> {\n const {streamId, appId, sampleRate, channels, volume = 1.0, stopOtherAudio = true} = request\n console.log(`AUDIO: Stream open ${streamId} from ${appId}: rate=${sampleRate} ch=${channels}`)\n\n await this.ensureAudioModeConfigured()\n\n if (stopOtherAudio) {\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(\"AUDIO: Interrupting current playback for new stream\")\n this.interruptCurrentPlayback(true)\n }\n await this.abortAllStreams(streamId)\n }\n\n await BluetoothSdk.pcmStreamOpen(streamId, sampleRate, channels, Math.max(0, Math.min(1, volume)))\n\n const stream: StreamState = {streamId, appId, startTime: Date.now(), ended: false, onEnded: request.onEnded}\n this.streams.set(streamId, stream)\n\n // Same LC3-mic-suspend dance as play(): cancel any pending \"stopped\"\n // notification and mark our app as playing audio.\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n this.audioStopDebounceTimer = null\n }\n BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of stream audio start:\", e)\n })\n\n // Guarded against the stream ending mid-read, same as the play() path.\n void this.ensureGlassesMediaVolumeForA2dpStream(stream)\n }\n\n /**\n * Append base64 PCM to an open stream. Resolves with the host-side backlog\n * in ms; the native write blocks while the backlog is above the\n * backpressure ceiling, so awaited writes self-throttle to realtime.\n */\n public async writeStreamChunk(streamId: string, base64: string): Promise<{bufferedMs: number}> {\n const stream = this.streams.get(streamId)\n if (!stream || stream.ended) {\n throw new Error(`stream ${streamId} is not open`)\n }\n try {\n return await BluetoothSdk.pcmStreamWrite(streamId, base64)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.endStream(stream, false, message, Date.now() - stream.startTime)\n throw error\n }\n }\n\n /** Drain the backlog, then finish. Resolves with the total played duration. */\n public async closeStream(streamId: string): Promise<{durationMs?: number}> {\n const stream = this.streams.get(streamId)\n if (!stream || stream.ended) {\n throw new Error(`stream ${streamId} is not open`)\n }\n try {\n const result = await BluetoothSdk.pcmStreamClose(streamId)\n this.endStream(stream, true, null, result?.durationMs ?? Date.now() - stream.startTime)\n return result ?? {}\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.endStream(stream, false, message, Date.now() - stream.startTime)\n throw error\n }\n }\n\n /** Stop immediately, dropping the backlog. Safe on unknown/ended ids. */\n public async abortStream(streamId: string): Promise<void> {\n const stream = this.streams.get(streamId)\n await BluetoothSdk.pcmStreamAbort(streamId).catch((e) => {\n console.warn(`AUDIO: Stream abort ${streamId} native call failed:`, e)\n })\n if (stream) {\n this.endStream(stream, true, null, Date.now() - stream.startTime)\n }\n }\n\n /** Abort every active stream (optionally sparing one about to replace them). */\n private async abortAllStreams(exceptStreamId?: string): Promise<void> {\n const streamIds = [...this.streams.values()]\n .filter((stream) => stream.streamId !== exceptStreamId)\n .map((stream) => stream.streamId)\n await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)))\n }\n\n /** Terminal bookkeeping for a stream: dedup, unregister, notify. */\n private endStream(stream: StreamState, success: boolean, error: string | null, durationMs: number | null): void {\n if (stream.ended) return\n stream.ended = true\n this.streams.delete(stream.streamId)\n // Only signal \"audio stopped\" when nothing else is making noise.\n if (this.streams.size === 0 && (!this.currentPlayback || this.currentPlayback.completed)) {\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n }\n stream.onEnded(stream.streamId, success, error, durationMs)\n }\n\n /** Stream twin of ensureGlassesMediaVolumeForA2dp, guarded by stream.ended. */\n private async ensureGlassesMediaVolumeForA2dpStream(stream: StreamState): Promise<void> {\n if (this.glassesVolumeRestoreLevel !== null) return\n try {\n const raw = await this.getGlassesMediaVolumeWithTiming()\n const level = Number(raw.level)\n if (!Number.isFinite(level) || level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) return\n if (stream.ended) return\n console.log(`AUDIO: Raising glasses media volume for stream (was ${level})`)\n await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR)\n if (!stream.ended) {\n this.glassesVolumeRestoreLevel = level\n } else {\n await this.setGlassesMediaVolumeWithTiming(level)\n }\n } catch (e) {\n console.warn(\"AUDIO: Skipping glasses volume bump for stream:\", e instanceof Error ? e.message : String(e))\n }\n }\n\n /**\n * Stop playback for a specific app.\n * If appId is not provided, stops all playback.\n */\n public async stopForApp(appId?: string): Promise<void> {\n // Abort this app's live PCM streams too (miniapp stop/disconnect path).\n const streamIds = [...this.streams.values()]\n .filter((stream) => !appId || stream.appId === appId)\n .map((stream) => stream.streamId)\n await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)))\n\n if (!this.currentPlayback || this.currentPlayback.completed) return\n\n if (!appId || this.currentPlayback.appId === appId) {\n console.log(`AUDIO: Stopping playback for app ${appId || \"(all)\"}`)\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Stop all audio playback\n */\n public async stopAll(): Promise<void> {\n await this.abortAllStreams()\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(\"AUDIO: Stopping all playback\")\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Check if audio is currently playing\n */\n public isPlaying(): boolean {\n return (this.currentPlayback !== null && !this.currentPlayback.completed) || this.streams.size > 0\n }\n\n /**\n * Get current playback app IDs (all active)\n */\n public getActiveAppIds(): string[] {\n const appIds = new Set<string>()\n if (this.currentPlayback && !this.currentPlayback.completed && this.currentPlayback.appId) {\n appIds.add(this.currentPlayback.appId)\n }\n for (const stream of this.streams.values()) appIds.add(stream.appId)\n return [...appIds]\n }\n\n /**\n * Get number of active playbacks\n */\n public getActiveCount(): number {\n return (this.currentPlayback && !this.currentPlayback.completed ? 1 : 0) + this.streams.size\n }\n\n /**\n * Release the player entirely (call when app is shutting down)\n */\n public release(): void {\n void this.abortAllStreams()\n if (this.currentPlayback && !this.currentPlayback.completed) {\n this.interruptCurrentPlayback()\n } else {\n void this.restoreGlassesMediaVolume()\n }\n\n if (this.player) {\n try {\n this.player.remove()\n console.log(\"AUDIO: Released AudioPlayer\")\n } catch (error) {\n console.error(\"AUDIO: Error releasing player:\", error)\n }\n this.player = null\n }\n }\n}\n\nconst audioPlaybackService = AudioPlaybackService.getInstance()\nexport default audioPlaybackService\n"]}
|
|
1
|
+
{"version":3,"file":"AudioPlaybackService.js","sourceRoot":"","sources":["../../src/services/AudioPlaybackService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAA4B,iBAAiB,EAAC,MAAM,YAAY,CAAA;AACzF,OAAO,YAAY,MAAM,gCAAgC,CAAA;AACzD,OAAO,EAAC,QAAQ,EAAE,QAAQ,EAAC,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAC,6BAA6B,EAAC,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAA;AAEzD,MAAM,qCAAqC,GAAG,KAAK,CAAA;AAuEnD,MAAM,oBAAoB;IAChB,MAAM,CAAC,QAAQ,GAAgC,IAAI,CAAA;IAC3D,4DAA4D;IAC5D,0EAA0E;IAClE,MAAM,GAAuB,IAAI,CAAA;IACzC,6EAA6E;IAC7E,6EAA6E;IACrE,cAAc,GAAyB,IAAI,CAAA;IAC3C,eAAe,GAAyB,IAAI,CAAA;IACpD,2EAA2E;IAC3E,6EAA6E;IAC7E,uDAAuD;IAC/C,gBAAgB,GAAG,IAAI,GAAG,EAAgC,CAAA;IAClE,0EAA0E;IAC1E,+DAA+D;IACvD,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAA;IACxC,mBAAmB,GAAY,KAAK,CAAA;IAC5C,yDAAyD;IACzD,8DAA8D;IAC9D,oEAAoE;IAC5D,sBAAsB,GAAkB,IAAI,CAAA;IACpD,0EAA0E;IAC1E,4EAA4E;IACpE,mBAAmB,GAAG,CAAC,CAAA;IACvB,uBAAuB,GAAyB,IAAI,CAAA;IAC5D,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAClE,sBAAsB,GAAG,IAAI,GAAG,EAAU,CAAA;IAClD,8EAA8E;IACtE,yBAAyB,GAAkB,IAAI,CAAA;IAC/C,MAAM,CAAU,sBAAsB,GAAG,IAAI,CAAA;IAC7C,MAAM,CAAU,kBAAkB,GAAG,GAAG,CAAA;IACxC,MAAM,CAAU,0BAA0B,GAAG,IAAI,CAAA;IACjD,MAAM,CAAU,sBAAsB,GAAG,GAAG,CAAA;IAC5C,MAAM,CAAU,+BAA+B,GAAG,MAAM,CAAA;IAChE,0FAA0F;IAClF,MAAM,CAAU,wBAAwB,GAAG,GAAG,CAAA;IAC9C,MAAM,CAAU,8BAA8B,GACpD,MAAM,CAAC,MAAM,CACX,IAAI,CAAC,KAAK,CACR,CAAC,oBAAoB,CAAC,sBAAsB,GAAG,oBAAoB,CAAC,+BAA+B,GAAG,CAAC,CAAC;QACtG,CAAC,IAAI,GAAG,CAAC,CAAC,CACb,CACF,GAAG,MAAM,CAAA;IACZ,0FAA0F;IAClF,MAAM,CAAU,4BAA4B,GAAG,CAAC,CAAA;IAChD,MAAM,CAAU,oBAAoB,GAAG,CAAC,CAAA;IAEhD,gBAAuB,CAAC;IAExB;;;;;;;;;;;;;;;OAeG;IACK,KAAK,CAAC,yBAAyB;QACrC,IAAI,CAAC;YACH,MAAM,iBAAiB,CAAC;gBACtB,sBAAsB,EAAE,IAAI;gBAC5B,iBAAiB,EAAE,IAAI;gBACvB,gBAAgB,EAAE,YAAY;aAC/B,CAAC,CAAA;YACF,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC9B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAA;gBAC/B,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;YAC1D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAA;YAC9D,kDAAkD;QACpD,CAAC;IACH,CAAC;IAEM,MAAM,CAAC,WAAW;QACvB,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC;YACnC,oBAAoB,CAAC,QAAQ,GAAG,IAAI,oBAAoB,EAAE,CAAA;QAC5D,CAAC;QACD,OAAO,oBAAoB,CAAC,QAAQ,CAAA;IACtC,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAA;YAC5D,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;YAErC,qEAAqE;YACrE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,sBAAsB,EAAE,CAAC,MAAmB,EAAE,EAAE;gBACtE,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAA;YACrC,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAA;IACpB,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,oBAAoB,CAAC,0BAA0B,CAAA;IACzF,CAAC;IAEO,gBAAgB;QACtB,OAAO,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,mBAAmB,CAAA;IACxG,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,uBAAuB;QACnC,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAAE,OAAM;QAChE,uEAAuE;QACvE,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,IAAI,QAAQ,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,mDAAmD,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAA;YACvF,OAAM;QACR,CAAC;QACD,IAAI,IAAI,CAAC,uBAAuB;YAAE,OAAO,IAAI,CAAC,uBAAuB,CAAA;QAErE,MAAM,QAAQ,GAAG,uBAAuB,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3F,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACzB,IAAI,MAAM,GAAG,KAAK,CAAA;YAClB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAC5B,IAAI,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,sCAAsC,oBAAoB,CAAC,sBAAsB,YAAY,CAAC,CAAA;gBAC1G,MAAM,YAAY,CAAC,aAAa,CAAC,QAAQ,EAAE,oBAAoB,CAAC,+BAA+B,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBACtG,MAAM,GAAG,IAAI,CAAA;gBACb,MAAM,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,oBAAoB,CAAC,8BAA8B,CAAC,CAAA;gBAChG,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAClC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;gBAC1E,CAAC,CAAC,CAAA;gBACF,MAAM,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;gBAC3C,MAAM,GAAG,KAAK,CAAA;gBACd,IAAI,CAAC,kBAAkB,EAAE,CAAA;gBACzB,OAAO,CAAC,GAAG,CAAC,0CAA0C,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,CAAC,CAAA;YACnF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,oEAAoE,EAAE,KAAK,CAAC,CAAA;YAC3F,CAAC;oBAAS,CAAC;gBACT,IAAI,MAAM;oBAAE,MAAM,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;YACzE,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;QACJ,IAAI,CAAC,uBAAuB,GAAG,MAAM,CAAA;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,CAAA;QACd,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,uBAAuB,KAAK,MAAM;gBAAE,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAA;QAClF,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,+BAA+B;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,qBAAqB,EAAE,CAAA;YACzD,OAAO,CAAC,GAAG,CAAC,iDAAiD,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,CAAC,CAAA;YACxF,OAAO,MAAM,CAAA;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,iDAAiD,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,KAAK,EAC5E,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAA;YACD,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,+BAA+B,CAAC,KAAa;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAA;YAC9D,OAAO,CAAC,GAAG,CAAC,mCAAmC,KAAK,kBAAkB,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,CAAC,CAAA;YACjG,OAAO,MAAM,CAAA;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,mCAAmC,KAAK,kBAAkB,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,KAAK,EACrF,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAA;YACD,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,+BAA+B,CAAC,QAAuB;QACnE,IAAI,IAAI,CAAC,yBAAyB,KAAK,IAAI,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CACT,iDAAiD,oBAAoB,CAAC,oBAAoB,0BAA0B,CACrH,CAAA;YACD,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,+BAA+B,EAAE,CAAA;YACxD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;YACzC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,sEAAsE,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;gBACxG,OAAM;YACR,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;YAC3F,OAAO,CAAC,GAAG,CAAC,iEAAiE,KAAK,OAAO,KAAK,EAAE,CAAC,CAAA;YACjG,IAAI,KAAK,GAAG,oBAAoB,CAAC,4BAA4B,EAAE,CAAC;gBAC9D,OAAM;YACR,CAAC;YACD,IAAI,IAAI,CAAC,eAAe,KAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAC5D,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAA;gBAC1E,OAAM;YACR,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,4CAA4C,KAAK,GAAG,CAAC,CAAA;YACjE,MAAM,IAAI,CAAC,+BAA+B,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAA;YACrF,IAAI,IAAI,CAAC,eAAe,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAC7D,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAA;YACxC,CAAC;iBAAM,IAAI,qCAAqC,EAAE,CAAC;gBACjD,OAAO,CAAC,GAAG,CAAC,gFAAgF,CAAC,CAAA;gBAC7F,MAAM,IAAI,CAAC,+BAA+B,CAAC,KAAK,CAAC,CAAA;YACnD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAA;YACpF,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACtD,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,yBAAyB;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,yBAAyB,CAAA;QACnD,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAM;QACR,CAAC;QACD,IAAI,CAAC,qCAAqC,EAAE,CAAC;YAC3C,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAA;YACrC,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAA;YAClF,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,4CAA4C,YAAY,EAAE,CAAC,CAAA;YACvE,MAAM,IAAI,CAAC,+BAA+B,CAAC,YAAY,CAAC,CAAA;QAC1D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACtD,OAAO,CAAC,IAAI,CAAC,8CAA8C,YAAY,GAAG,EAAE,GAAG,CAAC,CAAA;QAClF,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAA;QACvC,CAAC;IACH,CAAC;IAEO,oBAAoB,CAAC,QAAuB,EAAE,MAAc;QAClE,IAAI,IAAI,CAAC,cAAc,KAAK,QAAQ;YAAE,OAAM;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;YAC1B,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,EAAE,CAAA;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,wBAAwB,QAAQ,CAAC,SAAS,WAAW,MAAM,GAAG,EAAE,CAAC,CAAC,CAAA;QACjF,CAAC;QAED,IAAI,CAAC;YACH,qEAAqE;YACrE,qEAAqE;YACrE,yEAAyE;YACzE,6DAA6D;YAC7D,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;YACnC,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,CAAC,SAAS,WAAW,MAAM,EAAE,CAAC,CAAA;QACjF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,yBAAyB,QAAQ,CAAC,SAAS,WAAW,MAAM,GAAG,EAAE,CAAC,CAAC,CAAA;QAClF,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,cAAc,KAAK,QAAQ;gBAAE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;QAClE,CAAC;IACH,CAAC;IAEO,4BAA4B,CAAC,QAAuB;QAC1D,IAAI,QAAQ,CAAC,mBAAmB,EAAE,CAAC;YACjC,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAA;QAC/D,CAAC;QACD,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE;YACtB,0EAA0E;YAC1E,0EAA0E;YAC1E,oEAAoE;YACpE,IAAI,QAAQ,CAAC,mBAAmB,IAAI,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBACrG,6BAA6B,CAAC,QAAQ,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;YACpE,CAAC;YACD,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,GAAG,oBAAoB,CAAC,kBAAkB,oBAAoB,CAAC,CAAA;QACrG,CAAC,EAAE,oBAAoB,CAAC,kBAAkB,CAAC,CAAA;IAC7C,CAAC;IAEO,6BAA6B;QACnC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACnD,6BAA6B,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QAChD,CAAC;QACD,IAAI,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAA;IACrC,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,IAAI,CAAC,OAAyB,EAAE,UAAmC;QAC9E,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,cAAc,GAAG,IAAI,EAAE,mBAAmB,GAAG,KAAK,EAAC,GAAG,OAAO,CAAA;QAC9G,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,MAAM,eAAe,GACnB,IAAI,CAAC,eAAe;YACpB,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS;YAC/B,IAAI,CAAC,eAAe,CAAC,KAAK,KAAK,KAAK;YACpC,IAAI,CAAC,eAAe,CAAC,QAAQ,KAAK,QAAQ;YAC1C,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,GAAG,oBAAoB,CAAC,wBAAwB,CAAA;QACtF,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAC/D,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,SAAS,CAAC,SAAS;YACpB,SAAS,CAAC,KAAK,KAAK,KAAK;YACzB,SAAS,CAAC,QAAQ,KAAK,QAAQ;YAC/B,GAAG,GAAG,SAAS,CAAC,SAAS,GAAG,oBAAoB,CAAC,wBAAwB,CAC5E,CAAA;QACD,IAAI,eAAe,IAAI,gBAAgB,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,4CAA4C,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACrG,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;YAC9E,OAAM;QACR,CAAC;QAED,MAAM,OAAO,GAAyB,EAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAC,CAAA;QACzF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAE7C,OAAO,CAAC,GAAG,CAAC,uBAAuB,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC,CAAA;QAE5F,IAAI,CAAC;YACH,0DAA0D;YAC1D,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAA;YACtC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAA;gBACnD,OAAM;YACR,CAAC;YACD,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAA;YACpC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAA;gBACnD,OAAM;YACR,CAAC;YAED,wEAAwE;YACxE,wEAAwE;YACxE,0EAA0E;YAC1E,qEAAqE;YACrE,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;gBAC5D,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAA;gBACvE,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAA;YACrC,CAAC;YACD,+CAA+C;YAC/C,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAA;YAC9B,CAAC;YACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAA;gBACnD,OAAM;YACR,CAAC;YAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,IAAI,CAAC,6BAA6B,EAAE,CAAA;YACtC,CAAC;YAED,oCAAoC;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;YAElC,aAAa;YACb,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;YAEhD,+BAA+B;YAC/B,MAAM,QAAQ,GAAkB;gBAC9B,SAAS;gBACT,QAAQ;gBACR,mBAAmB,EAAE,OAAO,SAAS,EAAE;gBACvC,KAAK;gBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,SAAS,EAAE,KAAK;gBAChB,mBAAmB;gBACnB,UAAU;aACX,CAAA;YACD,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAA;YAC/B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YACvC,IAAI,CAAC,kBAAkB,EAAE,CAAA;YACzB,IAAI,QAAQ,CAAC,mBAAmB,EAAE,CAAC;gBACjC,6BAA6B,CAAC,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAA;YACnE,CAAC;YAED,8BAA8B;YAC9B,wFAAwF;YACxF,MAAM,CAAC,OAAO,CAAC,EAAC,GAAG,EAAE,QAAQ,EAAC,CAAC,CAAA;YAC/B,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAA;YAC9B,MAAM,CAAC,IAAI,EAAE,CAAA;YAEb,qEAAqE;YACrE,sEAAsE;YACtE,0EAA0E;YAC1E,gBAAgB;YAChB,KAAK,IAAI,CAAC,+BAA+B,CAAC,QAAQ,CAAC,CAAA;YAEnD,8CAA8C;YAC9C,sEAAsE;YACtE,4EAA4E;YAC5E,IAAI,IAAI,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;gBACzC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;gBACjD,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAA;YACpC,CAAC;YACD,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACnD,OAAO,CAAC,IAAI,CAAC,gDAAgD,EAAE,CAAC,CAAC,CAAA;YACnE,CAAC,CAAC,CAAA;YAEF,OAAO,CAAC,GAAG,CAAC,+BAA+B,SAAS,EAAE,CAAC,CAAA;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,mBAAmB,EAAE,CAAC;gBACxB,6BAA6B,CAAC,OAAO,SAAS,EAAE,EAAE,KAAK,CAAC,CAAA;YAC1D,CAAC;YACD,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAA;YAClG,IAAI,cAAc,EAAE,CAAC;gBACnB,cAAc,CAAC,SAAS,GAAG,IAAI,CAAA;gBAC/B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;gBAC3B,IAAI,CAAC,oBAAoB,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAA;YACrE,CAAC;YACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAA;gBACnD,OAAM;YACR,CAAC;YACD,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAA;YAC3F,OAAO,CAAC,KAAK,CAAC,yBAAyB,SAAS,GAAG,EAAE,YAAY,CAAC,CAAA;YAClE,KAAK,IAAI,CAAC,yBAAyB,EAAE,CAAA;YACrC,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;QAC3D,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,OAAO,EAAE,CAAC;gBACrD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,cAAc,CAAC,SAAiB;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACpD,IAAI,OAAO;YAAE,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;QAErC,IAAI,IAAI,CAAC,eAAe,EAAE,SAAS,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;YACrF,IAAI,CAAC,wBAAwB,EAAE,CAAA;QACjC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,wBAAwB,CAAC,6BAAsC,KAAK;QAC1E,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS;YAAE,OAAM;QAEnE,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAA;QACrC,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAA;QACzB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC3B,IAAI,QAAQ,CAAC,mBAAmB,EAAE,CAAC;YACjC,6BAA6B,CAAC,QAAQ,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;QACpE,CAAC;QACD,IAAI,CAAC,kBAAkB,EAAE,CAAA;QAEzB,qEAAqE;QACrE,qEAAqE;QACrE,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QAEnD,+DAA+D;QAC/D,IAAI,CAAC,wBAAwB,EAAE,CAAA;QAC/B,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAChC,KAAK,IAAI,CAAC,yBAAyB,EAAE,CAAA;QACvC,CAAC;QAED,uCAAuC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAA;QACjD,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,CAAA;QAC7E,OAAO,CAAC,GAAG,CAAC,sBAAsB,QAAQ,CAAC,SAAS,UAAU,SAAS,IAAI,CAAC,CAAA;IAC9E,CAAC;IAED;;OAEG;IACK,sBAAsB,CAAC,MAAmB;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAA;QAErC,6DAA6D;QAC7D,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;YACpC,OAAM;QACR,CAAC;QAED,6BAA6B;QAC7B,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA,CAAC,0BAA0B;YAC3E,OAAO,CAAC,GAAG,CAAC,gCAAgC,QAAQ,CAAC,SAAS,eAAe,UAAU,IAAI,CAAC,CAAA;YAC5F,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAA;YAEzB,wEAAwE;YACxE,oEAAoE;YACpE,yEAAyE;YACzE,IAAI,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAA;YAE3C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;YAC3B,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA;YAC5E,IAAI,CAAC,kBAAkB,EAAE,CAAA;YAEzB,+DAA+D;YAC/D,IAAI,CAAC,wBAAwB,EAAE,CAAA;YAC/B,KAAK,IAAI,CAAC,yBAAyB,EAAE,CAAA;YACrC,OAAM;QACR,CAAC;QAED,4EAA4E;QAC5E,8EAA8E;QAC9E,wEAAwE;QACxE,4EAA4E;QAC5E,IAAI,MAAM,CAAC,aAAa,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAA;YACjD,IAAI,SAAS,GAAG,IAAI,EAAE,CAAC;gBACrB,OAAO,CAAC,KAAK,CAAC,8BAA8B,QAAQ,CAAC,SAAS,4BAA4B,SAAS,KAAK,CAAC,CAAA;gBACzG,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAA;gBACzB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;gBAC3B,IAAI,QAAQ,CAAC,mBAAmB,EAAE,CAAC;oBACjC,6BAA6B,CAAC,QAAQ,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;gBACpE,CAAC;gBACD,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;gBACvD,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,oCAAoC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;gBACnG,IAAI,CAAC,kBAAkB,EAAE,CAAA;gBACzB,IAAI,CAAC,wBAAwB,EAAE,CAAA;gBAC/B,KAAK,IAAI,CAAC,yBAAyB,EAAE,CAAA;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,wBAAwB;QAC9B,2BAA2B;QAC3B,IAAI,IAAI,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YACzC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QACnD,CAAC;QAED,qFAAqF;QACrF,oEAAoE;QACpE,IAAI,CAAC,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE;YACpD,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAA;YAClC,8EAA8E;YAC9E,0EAA0E;YAC1E,yEAAyE;YACzE,IAAI,IAAI,CAAC,SAAS,EAAE;gBAAE,OAAM;YAC5B,YAAY,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACpD,OAAO,CAAC,IAAI,CAAC,+CAA+C,EAAE,CAAC,CAAC,CAAA;YAClE,CAAC,CAAC,CAAA;QACJ,CAAC,EAAE,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;IACjD,CAAC;IAED,6EAA6E;IAE7E;;;;OAIG;IACI,KAAK,CAAC,UAAU,CAAC,OAA+B;QACrD,MAAM,EAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,EAAE,cAAc,GAAG,IAAI,EAAC,GAAG,OAAO,CAAA;QAC5F,OAAO,CAAC,GAAG,CAAC,sBAAsB,QAAQ,SAAS,KAAK,UAAU,UAAU,OAAO,QAAQ,EAAE,CAAC,CAAA;QAE9F,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAA;QACtC,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAA;QAEpC,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;gBAC5D,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAA;gBAClE,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAA;YACrC,CAAC;YACD,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;QACtC,CAAC;QAED,MAAM,YAAY,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QAClG,IAAI,CAAC,6BAA6B,EAAE,CAAA;QAEpC,MAAM,MAAM,GAAgB;YAC1B,QAAQ;YACR,KAAK;YACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAA;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAClC,IAAI,CAAC,kBAAkB,EAAE,CAAA;QAEzB,wEAAwE;QACxE,8DAA8D;QAC9D,IAAI,IAAI,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YACzC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;YACjD,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAA;QACpC,CAAC;QACD,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACnD,OAAO,CAAC,IAAI,CAAC,uDAAuD,EAAE,CAAC,CAAC,CAAA;QAC1E,CAAC,CAAC,CAAA;QAEF,uEAAuE;QACvE,KAAK,IAAI,CAAC,qCAAqC,CAAC,MAAM,CAAC,CAAA;IACzD,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,MAAc;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,cAAc,CAAC,CAAA;QACnD,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;YACrE,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,+EAA+E;IACxE,KAAK,CAAC,WAAW,CAAC,QAAgB;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,cAAc,CAAC,CAAA;QACnD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;YAC1D,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;YACvF,OAAO,MAAM,IAAI,EAAE,CAAA;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;YACrE,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,yEAAyE;IAClE,KAAK,CAAC,WAAW,CAAC,QAAgB;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACzC,MAAM,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACtD,OAAO,CAAC,IAAI,CAAC,uBAAuB,QAAQ,sBAAsB,EAAE,CAAC,CAAC,CAAA;QACxE,CAAC,CAAC,CAAA;QACF,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;QACnE,CAAC;IACH,CAAC;IAED,gFAAgF;IACxE,KAAK,CAAC,eAAe,CAAC,cAAuB;QACnD,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;aACzC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,cAAc,CAAC;aACtD,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC5E,CAAC;IAED,oEAAoE;IAC5D,SAAS,CAAC,MAAmB,EAAE,OAAgB,EAAE,KAAoB,EAAE,UAAyB;QACtG,IAAI,MAAM,CAAC,KAAK;YAAE,OAAM;QACxB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACpC,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACzB,iEAAiE;QACjE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;YACzF,IAAI,CAAC,wBAAwB,EAAE,CAAA;YAC/B,KAAK,IAAI,CAAC,yBAAyB,EAAE,CAAA;QACvC,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;IAC7D,CAAC;IAED,+EAA+E;IACvE,KAAK,CAAC,qCAAqC,CAAC,MAAmB;QACrE,IAAI,IAAI,CAAC,yBAAyB,KAAK,IAAI;YAAE,OAAM;QACnD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,+BAA+B,EAAE,CAAA;YACxD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,oBAAoB,CAAC,4BAA4B;gBAAE,OAAM;YAChG,IAAI,MAAM,CAAC,KAAK;gBAAE,OAAM;YACxB,OAAO,CAAC,GAAG,CAAC,uDAAuD,KAAK,GAAG,CAAC,CAAA;YAC5E,MAAM,IAAI,CAAC,+BAA+B,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAA;YACrF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBAClB,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAA;YACxC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,+BAA+B,CAAC,KAAK,CAAC,CAAA;YACnD,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,iDAAiD,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7G,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,UAAU,CAAC,KAAc;QACpC,wEAAwE;QACxE,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;aACzC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC;aACpD,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QAE1E,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS;YAAE,OAAM;QAEnE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,oCAAoC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAA;YACnE,IAAI,CAAC,wBAAwB,EAAE,CAAA;QACjC,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO;QAClB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAA;QAC5B,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;YAC3C,IAAI,CAAC,wBAAwB,EAAE,CAAA;QACjC,CAAC;IACH,CAAC;IAED;;OAEG;IACI,SAAS;QACd,OAAO,CAAC,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAA;IACpG,CAAC;IAED;;OAEG;IACI,eAAe;QACpB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;QAChC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAC1F,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;QACxC,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACpE,OAAO,CAAC,GAAG,MAAM,CAAC,CAAA;IACpB,CAAC;IAED;;OAEG;IACI,cAAc;QACnB,OAAO,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAA;IAC9F,CAAC;IAED;;OAEG;IACI,OAAO;QACZ,KAAK,IAAI,CAAC,eAAe,EAAE,CAAA;QAC3B,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;YAC5D,IAAI,CAAC,wBAAwB,EAAE,CAAA;QACjC,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,yBAAyB,EAAE,CAAA;QACvC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;gBACpB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;YAC5C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAA;YACxD,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;YAClB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;QAC5B,CAAC;IACH,CAAC;;AAGH,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,WAAW,EAAE,CAAA;AAC/D,eAAe,oBAAoB,CAAA","sourcesContent":["import {createAudioPlayer, AudioPlayer, AudioStatus, setAudioModeAsync} from \"expo-audio\"\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {AppState, Platform} from \"react-native\"\nimport {BgTimer} from \"../utils/timers\"\nimport {setAudioCloudUplinkSuppressed} from \"./AudioCloudUplink\"\nimport {SILENT_AUDIO_SOURCE} from \"./audioPlaybackAssets\"\n\nconst RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK = false\n\ninterface AudioPlayRequest {\n requestId: string\n audioUrl: string\n appId?: string\n volume?: number\n stopOtherAudio?: boolean\n /**\n * Suppress microphone audio sent to cloud STT while this audio is audible.\n * Opt-in and off by default: the suppression is global to the uplink, so a\n * caller that sets this silences STT for every running app, not just itself.\n * No platform path sets it today (see AudioCloudUplink and OS-1741).\n */\n suppressCloudUplink?: boolean\n}\n\nexport type AudioPlaybackCompletionReason = \"completed\" | \"interrupted\" | \"error\"\n\ntype AudioPlaybackCompletion = (\n requestId: string,\n success: boolean,\n error: string | null,\n duration: number | null,\n reason: AudioPlaybackCompletionReason,\n) => void\n\ninterface PlaybackState {\n requestId: string\n audioUrl: string\n uplinkSuppressionId: string\n appId?: string\n startTime: number\n completed: boolean // Guard against double callbacks\n suppressCloudUplink: boolean\n onComplete: AudioPlaybackCompletion\n}\n\ninterface PendingPlaybackState {\n cancelled: boolean\n audioUrl: string\n appId?: string\n createdAt: number\n}\n\n/** Open request for a live PCM output stream (miniapp speaker.createStream). */\nexport interface AudioStreamOpenRequest {\n streamId: string\n appId: string\n /** PCM sample rate in Hz (16000 / 24000 / 48000). */\n sampleRate: number\n /** Channel count. v1 is mono. */\n channels: number\n volume?: number\n stopOtherAudio?: boolean\n /**\n * Called when the stream ends for any reason (drained after close, aborted,\n * interrupted by other audio, or native error).\n */\n onEnded: (streamId: string, success: boolean, error: string | null, durationMs: number | null) => void\n}\n\n/** One live PCM stream session, backed by native streaming audio. */\ninterface StreamState {\n streamId: string\n appId: string\n startTime: number\n ended: boolean // Guard against double onEnded\n onEnded: AudioStreamOpenRequest[\"onEnded\"]\n}\n\nclass AudioPlaybackService {\n private static instance: AudioPlaybackService | null = null\n // Reuse a single AudioPlayer to avoid AudioTrack exhaustion\n // Creating new ExoPlayer instances per request leads to -12 ENOMEM errors\n private player: AudioPlayer | null = null\n // The source currently loaded into the reusable player. Keep object identity\n // so a delayed tail cleanup from an older request cannot unload a newer one.\n private loadedPlayback: PlaybackState | null = null\n private currentPlayback: PlaybackState | null = null\n // Requests that entered play() but have not yet reached the native player.\n // Keeping these addressable prevents a cancelled request from starting after\n // an async audio-mode or stream-cleanup step finishes.\n private pendingPlaybacks = new Map<string, PendingPlaybackState>()\n // Live PCM streams (speaker.createStream), keyed by streamId. The runtime\n // enforces one per app; stopOtherAudio interrupts across apps.\n private streams = new Map<string, StreamState>()\n private audioModeConfigured: boolean = false\n // Debounce timer for notifying native that audio stopped\n // Prevents mic toggle flicker when playing back-to-back audio\n // Uses BgTimer to work reliably when app is backgrounded on Android\n private audioStopDebounceTimer: number | null = null\n // Mentra Live's A2DP route may go idle between prompts. Keep a short warm\n // window after actual audio so we only pre-roll the first sound after idle.\n private audioRouteWarmUntil = 0\n private audioRouteWarmupPromise: Promise<void> | null = null\n // Playback that opted into suppression stays suppressed briefly while its\n // A2DP tail drains. Track those completed sources so a later unsuppressed\n // sound can resume listening immediately instead of inheriting that gate.\n private tailUplinkSuppressions = new Set<string>()\n // Original glasses media volume captured before we bump it for A2DP playback.\n private glassesVolumeRestoreLevel: number | null = null\n private static readonly AUDIO_STOP_DEBOUNCE_MS = 1500\n private static readonly A2DP_TAIL_DRAIN_MS = 700\n private static readonly AUDIO_ROUTE_WARM_WINDOW_MS = 1500\n private static readonly AUDIO_ROUTE_PREWARM_MS = 200\n private static readonly AUDIO_ROUTE_PREWARM_SAMPLE_RATE = 16_000\n /** Break accidental same-app replay storms without affecting deliberate later replays. */\n private static readonly DUPLICATE_PLAY_WINDOW_MS = 750\n private static readonly AUDIO_ROUTE_PREWARM_PCM_BASE64 =\n \"AAAA\".repeat(\n Math.floor(\n (AudioPlaybackService.AUDIO_ROUTE_PREWARM_MS * AudioPlaybackService.AUDIO_ROUTE_PREWARM_SAMPLE_RATE * 2) /\n (1000 * 3),\n ),\n ) + \"AA==\"\n /** If glasses report step volume at or below this, bump to FLOOR before A2DP playback. */\n private static readonly GLASSES_VOLUME_LOW_THRESHOLD = 2\n private static readonly GLASSES_VOLUME_FLOOR = 9\n\n private constructor() {}\n\n /**\n * Configure audio mode for playback, re-asserting it on EVERY play.\n *\n * This must run before each play — not just once — because other parts of the\n * app put the shared iOS AVAudioSession into a record-oriented category and\n * never restore it. In particular the phone mic (PhoneMic.swift) switches the\n * session to `.playAndRecord` (sometimes `.voiceChat`/earpiece routing) while\n * capturing and only deactivates it on stop, leaving the category sticky. A\n * miniapp like the Recorder records and then immediately plays back through\n * this service; if we kept the old \"configure once\" guard, playback would land\n * in the leftover `.playAndRecord` session and be inaudible on the phone\n * speaker (the symptom: the progress bar runs but no sound comes out). Calling\n * setAudioModeAsync with no `allowsRecording` maps to category `.playback`,\n * reclaiming the speaker route. `audioModeConfigured` is kept only to gate the\n * one-time log.\n */\n private async ensureAudioModeConfigured(): Promise<void> {\n try {\n await setAudioModeAsync({\n shouldPlayInBackground: true,\n playsInSilentMode: true,\n interruptionMode: \"duckOthers\",\n })\n if (!this.audioModeConfigured) {\n this.audioModeConfigured = true\n console.log(\"AUDIO: Audio mode configured for playback\")\n }\n } catch (error) {\n console.error(\"AUDIO: Failed to configure audio mode:\", error)\n // Don't block playback if audio mode config fails\n }\n }\n\n public static getInstance(): AudioPlaybackService {\n if (!AudioPlaybackService.instance) {\n AudioPlaybackService.instance = new AudioPlaybackService()\n }\n return AudioPlaybackService.instance\n }\n\n /**\n * Ensure we have a reusable player instance\n */\n private ensurePlayer(): AudioPlayer {\n if (!this.player) {\n console.log(\"AUDIO: Creating reusable AudioPlayer instance\")\n this.player = createAudioPlayer(null)\n\n // Add status listener once - it will handle all playback completions\n this.player.addListener(\"playbackStatusUpdate\", (status: AudioStatus) => {\n this.onPlaybackStatusUpdate(status)\n })\n }\n return this.player\n }\n\n private markAudioRouteWarm(): void {\n this.audioRouteWarmUntil = Date.now() + AudioPlaybackService.AUDIO_ROUTE_WARM_WINDOW_MS\n }\n\n private isAudioRouteWarm(): boolean {\n return this.currentPlayback !== null || this.streams.size > 0 || Date.now() < this.audioRouteWarmUntil\n }\n\n /**\n * Wake a cold Android A2DP route with silent PCM before a user-facing sound.\n *\n * Do not call pcmStreamClose here: some Bluetooth routes do not advance an\n * idle AudioTrack playback head, so close waits for its drain timeout. After\n * exactly 200ms of silence we abort the stream instead, which releases the\n * pre-roll immediately and lets the real URL playback begin.\n */\n private async prewarmAudioRouteIfCold(): Promise<void> {\n if (Platform.OS !== \"android\" || this.isAudioRouteWarm()) return\n // This silent PCM pre-roll is only an anti-clipping optimization. Some\n // Android devices defer opening its AudioTrack until the host Activity\n // resumes even though the real URL player supports background playback.\n // Never let that optional pre-roll block a glasses-initiated prompt.\n if (AppState.currentState !== \"active\") {\n console.log(`AUDIO: Skipping cold-route prewarm while app is ${AppState.currentState}`)\n return\n }\n if (this.audioRouteWarmupPromise) return this.audioRouteWarmupPromise\n\n const streamId = `audio-route-prewarm-${Date.now()}-${Math.random().toString(36).slice(2)}`\n const warmup = (async () => {\n let opened = false\n const startedAt = Date.now()\n try {\n console.log(`AUDIO: Cold route; prewarming with ${AudioPlaybackService.AUDIO_ROUTE_PREWARM_MS}ms silence`)\n await BluetoothSdk.pcmStreamOpen(streamId, AudioPlaybackService.AUDIO_ROUTE_PREWARM_SAMPLE_RATE, 1, 1)\n opened = true\n await BluetoothSdk.pcmStreamWrite(streamId, AudioPlaybackService.AUDIO_ROUTE_PREWARM_PCM_BASE64)\n await new Promise<void>((resolve) => {\n BgTimer.setTimeout(resolve, AudioPlaybackService.AUDIO_ROUTE_PREWARM_MS)\n })\n await BluetoothSdk.pcmStreamAbort(streamId)\n opened = false\n this.markAudioRouteWarm()\n console.log(`AUDIO: Cold-route prewarm completed in ${Date.now() - startedAt}ms`)\n } catch (error) {\n console.warn(\"AUDIO: Cold-route prewarm failed; continuing with requested audio:\", error)\n } finally {\n if (opened) await BluetoothSdk.pcmStreamAbort(streamId).catch(() => {})\n }\n })()\n this.audioRouteWarmupPromise = warmup\n try {\n await warmup\n } finally {\n if (this.audioRouteWarmupPromise === warmup) this.audioRouteWarmupPromise = null\n }\n }\n\n private async getGlassesMediaVolumeWithTiming() {\n const startedAt = Date.now()\n try {\n const result = await BluetoothSdk.getGlassesMediaVolume()\n console.log(`AUDIO: Glasses media volume read completed in ${Date.now() - startedAt}ms`)\n return result\n } catch (error) {\n console.warn(\n `AUDIO: Glasses media volume read failed after ${Date.now() - startedAt}ms:`,\n error instanceof Error ? error.message : String(error),\n )\n throw error\n }\n }\n\n private async setGlassesMediaVolumeWithTiming(level: number) {\n const startedAt = Date.now()\n try {\n const result = await BluetoothSdk.setGlassesMediaVolume(level)\n console.log(`AUDIO: Glasses media volume set(${level}) completed in ${Date.now() - startedAt}ms`)\n return result\n } catch (error) {\n console.warn(\n `AUDIO: Glasses media volume set(${level}) failed after ${Date.now() - startedAt}ms:`,\n error instanceof Error ? error.message : String(error),\n )\n throw error\n }\n }\n\n /**\n * Mentra Live: raise glasses media volume over BLE when it is very low so A2DP prompts are audible.\n * Fail-open on unsupported devices, timeouts, or errors.\n */\n private async ensureGlassesMediaVolumeForA2dp(playback: PlaybackState): Promise<void> {\n if (this.glassesVolumeRestoreLevel !== null) {\n console.log(\n `AUDIO: Keeping bumped glasses media volume at ${AudioPlaybackService.GLASSES_VOLUME_FLOOR} during ongoing playback`,\n )\n return\n }\n\n try {\n const raw = await this.getGlassesMediaVolumeWithTiming()\n const level = Number(raw.level)\n const statusCode = Number(raw.statusCode)\n if (!Number.isFinite(level)) {\n console.log(\"AUDIO: Received glasses media volume response without numeric level:\", JSON.stringify(raw))\n return\n }\n const k900S = Number.isFinite(statusCode) && statusCode >= 0 ? ` K900_S=${statusCode}` : \"\"\n console.log(`AUDIO: Glasses media step volume (wearable knob, 0-15 scale): ${level}/15.${k900S}`)\n if (level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) {\n return\n }\n if (this.currentPlayback !== playback || playback.completed) {\n console.log(\"AUDIO: Skipping glasses volume bump; playback already ended\")\n return\n }\n console.log(`AUDIO: Raising glasses media volume (was ${level})`)\n await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR)\n if (this.currentPlayback === playback && !playback.completed) {\n this.glassesVolumeRestoreLevel = level\n } else if (RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {\n console.log(\"AUDIO: Restoring glasses volume immediately; playback ended during volume bump\")\n await this.setGlassesMediaVolumeWithTiming(level)\n } else {\n console.log(\"AUDIO: Leaving bumped glasses media volume unchanged after playback\")\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e)\n console.warn(\"AUDIO: Skipping glasses volume bump:\", msg)\n }\n }\n\n /**\n * Restore the user's original glasses media step volume after A2DP playback finishes.\n */\n private async restoreGlassesMediaVolume(): Promise<void> {\n const restoreLevel = this.glassesVolumeRestoreLevel\n if (restoreLevel === null) {\n return\n }\n if (!RESTORE_GLASSES_VOLUME_AFTER_PLAYBACK) {\n this.glassesVolumeRestoreLevel = null\n console.log(\"AUDIO: Leaving bumped glasses media volume unchanged after playback\")\n return\n }\n\n try {\n console.log(`AUDIO: Restoring glasses media volume to ${restoreLevel}`)\n await this.setGlassesMediaVolumeWithTiming(restoreLevel)\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e)\n console.warn(`AUDIO: Failed to restore glasses volume to ${restoreLevel}:`, msg)\n } finally {\n this.glassesVolumeRestoreLevel = null\n }\n }\n\n private unloadPlaybackSource(playback: PlaybackState, reason: string): void {\n if (this.loadedPlayback !== playback) return\n const player = this.player\n if (!player) {\n this.loadedPlayback = null\n return\n }\n\n try {\n player.pause()\n } catch (e) {\n console.warn(`AUDIO: Error pausing ${playback.requestId} during ${reason}:`, e)\n }\n\n try {\n // replace(null) fails native argument casting on iOS, while remove()\n // destroys the ExoPlayer that Android must reuse to avoid AudioTrack\n // exhaustion. Replacing with bundled silence detaches the previous media\n // item on both platforms and leaves the native player alive.\n player.replace(SILENT_AUDIO_SOURCE)\n console.log(`AUDIO: Cleared source for ${playback.requestId} during ${reason}`)\n } catch (e) {\n console.warn(`AUDIO: Error clearing ${playback.requestId} during ${reason}:`, e)\n } finally {\n if (this.loadedPlayback === playback) this.loadedPlayback = null\n }\n }\n\n private clearFinishedPlayerAfterTail(playback: PlaybackState): void {\n if (playback.suppressCloudUplink) {\n this.tailUplinkSuppressions.add(playback.uplinkSuppressionId)\n }\n BgTimer.setTimeout(() => {\n // ExoPlayer's completion event precedes the final A2DP audio reaching the\n // glasses. Keep cloud STT gated until that audible tail has drained, then\n // accept fresh microphone audio immediately without restarting LC3.\n if (playback.suppressCloudUplink && this.tailUplinkSuppressions.delete(playback.uplinkSuppressionId)) {\n setAudioCloudUplinkSuppressed(playback.uplinkSuppressionId, false)\n }\n this.unloadPlaybackSource(playback, `${AudioPlaybackService.A2DP_TAIL_DRAIN_MS}ms A2DP tail drain`)\n }, AudioPlaybackService.A2DP_TAIL_DRAIN_MS)\n }\n\n private releaseTailUplinkSuppressions(): void {\n for (const sourceId of this.tailUplinkSuppressions) {\n setAudioCloudUplinkSuppressed(sourceId, false)\n }\n this.tailUplinkSuppressions.clear()\n }\n\n /**\n * Play audio from a URL.\n * Returns a promise that resolves with playback result when audio finishes or errors.\n */\n public async play(request: AudioPlayRequest, onComplete: AudioPlaybackCompletion): Promise<void> {\n const {requestId, audioUrl, appId, volume = 1.0, stopOtherAudio = true, suppressCloudUplink = false} = request\n const now = Date.now()\n const activeDuplicate =\n this.currentPlayback &&\n !this.currentPlayback.completed &&\n this.currentPlayback.appId === appId &&\n this.currentPlayback.audioUrl === audioUrl &&\n now - this.currentPlayback.startTime < AudioPlaybackService.DUPLICATE_PLAY_WINDOW_MS\n const pendingDuplicate = [...this.pendingPlaybacks.values()].some(\n (candidate) =>\n !candidate.cancelled &&\n candidate.appId === appId &&\n candidate.audioUrl === audioUrl &&\n now - candidate.createdAt < AudioPlaybackService.DUPLICATE_PLAY_WINDOW_MS,\n )\n if (activeDuplicate || pendingDuplicate) {\n console.warn(`AUDIO: Suppressed duplicate play request ${requestId}${appId ? ` from ${appId}` : \"\"}`)\n onComplete(requestId, false, \"Duplicate audio request suppressed\", 0, \"error\")\n return\n }\n\n const pending: PendingPlaybackState = {cancelled: false, audioUrl, appId, createdAt: now}\n this.pendingPlaybacks.set(requestId, pending)\n\n console.log(`AUDIO: Play request ${requestId}${appId ? ` from ${appId}` : \"\"}: ${audioUrl}`)\n\n try {\n // Ensure audio mode is configured for background playback\n await this.ensureAudioModeConfigured()\n if (pending.cancelled) {\n onComplete(requestId, true, null, 0, \"interrupted\")\n return\n }\n await this.prewarmAudioRouteIfCold()\n if (pending.cancelled) {\n onComplete(requestId, true, null, 0, \"interrupted\")\n return\n }\n\n // URL playback reuses one native player, so replacing its source always\n // interrupts the previous URL even when stopOtherAudio is false. Notify\n // that request before replacing it so its promise cannot hang. The option\n // still controls whether separate PCM streams are interrupted below.\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(`AUDIO: Interrupting current URL playback for new request`)\n this.interruptCurrentPlayback(true)\n }\n // Live PCM streams count as \"other audio\" too.\n if (stopOtherAudio) {\n await this.abortAllStreams()\n }\n if (pending.cancelled) {\n onComplete(requestId, true, null, 0, \"interrupted\")\n return\n }\n\n if (!suppressCloudUplink) {\n this.releaseTailUplinkSuppressions()\n }\n\n // Get or create the reusable player\n const player = this.ensurePlayer()\n\n // Set volume\n player.volume = Math.max(0, Math.min(1, volume))\n\n // Store the new playback state\n const playback: PlaybackState = {\n requestId,\n audioUrl,\n uplinkSuppressionId: `url:${requestId}`,\n appId,\n startTime: Date.now(),\n completed: false,\n suppressCloudUplink,\n onComplete,\n }\n this.currentPlayback = playback\n this.pendingPlaybacks.delete(requestId)\n this.markAudioRouteWarm()\n if (playback.suppressCloudUplink) {\n setAudioCloudUplinkSuppressed(playback.uplinkSuppressionId, true)\n }\n\n // Replace the source and play\n // Using replace() reuses the existing ExoPlayer/AudioTrack instead of creating new ones\n player.replace({uri: audioUrl})\n this.loadedPlayback = playback\n player.play()\n\n // Mentra Live volume reads can block up to 5s when the glasses don't\n // answer. Do not put that in front of playback; guard it against late\n // completion so a stale volume response cannot bump after this request is\n // already over.\n void this.ensureGlassesMediaVolumeForA2dp(playback)\n\n // Notify native that our app is playing audio\n // Used to suspend LC3 mic during audio playback to avoid MCU overload\n // Cancel any pending \"stop\" notification first (handles back-to-back audio)\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n this.audioStopDebounceTimer = null\n }\n BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of audio start:\", e)\n })\n\n console.log(`AUDIO: Started playback for ${requestId}`)\n } catch (error) {\n if (suppressCloudUplink) {\n setAudioCloudUplinkSuppressed(`url:${requestId}`, false)\n }\n const failedPlayback = this.currentPlayback?.requestId === requestId ? this.currentPlayback : null\n if (failedPlayback) {\n failedPlayback.completed = true\n this.currentPlayback = null\n this.unloadPlaybackSource(failedPlayback, \"playback start failure\")\n }\n if (pending.cancelled) {\n onComplete(requestId, true, null, 0, \"interrupted\")\n return\n }\n const errorMessage = error instanceof Error ? error.message : \"Unknown error loading audio\"\n console.error(`AUDIO: Failed to play ${requestId}:`, errorMessage)\n void this.restoreGlassesMediaVolume()\n onComplete(requestId, false, errorMessage, null, \"error\")\n } finally {\n if (this.pendingPlaybacks.get(requestId) === pending) {\n this.pendingPlaybacks.delete(requestId)\n }\n }\n }\n\n /**\n * Cancel one URL playback without touching audio owned by another request.\n * Pending requests are prevented from reaching the native player; active\n * requests are paused synchronously before their completion callback fires.\n */\n public cancelPlayback(requestId: string): void {\n const pending = this.pendingPlaybacks.get(requestId)\n if (pending) pending.cancelled = true\n\n if (this.currentPlayback?.requestId === requestId && !this.currentPlayback.completed) {\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Interrupt current playback and notify its callback\n */\n private interruptCurrentPlayback(preserveGlassesMediaVolume: boolean = false): void {\n if (!this.currentPlayback || this.currentPlayback.completed) return\n\n const playback = this.currentPlayback\n playback.completed = true\n this.currentPlayback = null\n if (playback.suppressCloudUplink) {\n setAudioCloudUplinkSuppressed(playback.uplinkSuppressionId, false)\n }\n this.markAudioRouteWarm()\n\n // Pausing alone leaves the URI available to OS/Bluetooth media Play.\n // Unload it unless a newer request has already replaced this source.\n this.unloadPlaybackSource(playback, \"interruption\")\n\n // Notify native that our app stopped playing audio (debounced)\n this.notifyAudioStopDebounced()\n if (!preserveGlassesMediaVolume) {\n void this.restoreGlassesMediaVolume()\n }\n\n // Notify that playback was interrupted\n const elapsedMs = Date.now() - playback.startTime\n playback.onComplete(playback.requestId, true, null, elapsedMs, \"interrupted\")\n console.log(`AUDIO: Interrupted ${playback.requestId} after ${elapsedMs}ms`)\n }\n\n /**\n * Handle playback status updates from expo-audio\n */\n private onPlaybackStatusUpdate(status: AudioStatus): void {\n const playback = this.currentPlayback\n\n // Guard against callbacks for unknown or completed playbacks\n if (!playback || playback.completed) {\n return\n }\n\n // Check if playback finished\n if (status.didJustFinish) {\n const durationMs = (status.duration || 0) * 1000 // expo-audio uses seconds\n console.log(`AUDIO: Playback finished for ${playback.requestId}, duration: ${durationMs}ms`)\n playback.completed = true\n\n // ExoPlayer can report finished before an A2DP sink has audibly drained\n // the last buffered audio. Pausing immediately can clip the tail on\n // Mentra Live; defer cleanup and guard it against a newer loaded source.\n this.clearFinishedPlayerAfterTail(playback)\n\n this.currentPlayback = null\n playback.onComplete(playback.requestId, true, null, durationMs, \"completed\")\n this.markAudioRouteWarm()\n\n // Notify native that our app stopped playing audio (debounced)\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n return\n }\n\n // Detect silent playback failures: expo-audio doesn't surface errors to JS,\n // so when ExoPlayer fails to load/play a URL (network error, HTTP 500, etc.),\n // the player state goes to \"idle\" with nothing loaded and no buffering.\n // We wait 1500ms after play() to avoid false positives during initial load.\n if (status.playbackState === \"idle\" && !status.isBuffering && !status.isLoaded) {\n const elapsedMs = Date.now() - playback.startTime\n if (elapsedMs > 1500) {\n console.error(`AUDIO: Playback failed for ${playback.requestId} (player went idle after ${elapsedMs}ms)`)\n playback.completed = true\n this.currentPlayback = null\n if (playback.suppressCloudUplink) {\n setAudioCloudUplinkSuppressed(playback.uplinkSuppressionId, false)\n }\n this.unloadPlaybackSource(playback, \"playback failure\")\n playback.onComplete(playback.requestId, false, \"Playback failed (player went idle)\", null, \"error\")\n this.markAudioRouteWarm()\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n }\n }\n }\n\n /**\n * Notify native that audio stopped, with debouncing to prevent mic toggle flicker\n * when playing back-to-back audio files\n */\n private notifyAudioStopDebounced(): void {\n // Clear any existing timer\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n }\n\n // Set a new timer - if new audio starts within this window, the timer gets cancelled\n // Uses BgTimer to work reliably when app is backgrounded on Android\n this.audioStopDebounceTimer = BgTimer.setTimeout(() => {\n this.audioStopDebounceTimer = null\n // URL playback and live PCM streams may overlap when stopOtherAudio is false.\n // A URL that ends must not clear the native playback signal while another\n // source is still active, or the mic watchdog can interrupt that source.\n if (this.isPlaying()) return\n BluetoothSdk.setOwnAppAudioPlaying(false).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of audio stop:\", e)\n })\n }, AudioPlaybackService.AUDIO_STOP_DEBOUNCE_MS)\n }\n\n // ── live PCM output streams (miniapp speaker.createStream) ────────────────\n\n /**\n * Open a live PCM stream session. Chunks are pushed with writeStreamChunk\n * into native streaming audio (AudioTrack on Android, AVAudioEngine on iOS),\n * following the media route such as A2DP to connected glasses.\n */\n public async openStream(request: AudioStreamOpenRequest): Promise<void> {\n const {streamId, appId, sampleRate, channels, volume = 1.0, stopOtherAudio = true} = request\n console.log(`AUDIO: Stream open ${streamId} from ${appId}: rate=${sampleRate} ch=${channels}`)\n\n await this.ensureAudioModeConfigured()\n await this.prewarmAudioRouteIfCold()\n\n if (stopOtherAudio) {\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(\"AUDIO: Interrupting current playback for new stream\")\n this.interruptCurrentPlayback(true)\n }\n await this.abortAllStreams(streamId)\n }\n\n await BluetoothSdk.pcmStreamOpen(streamId, sampleRate, channels, Math.max(0, Math.min(1, volume)))\n this.releaseTailUplinkSuppressions()\n\n const stream: StreamState = {\n streamId,\n appId,\n startTime: Date.now(),\n ended: false,\n onEnded: request.onEnded,\n }\n this.streams.set(streamId, stream)\n this.markAudioRouteWarm()\n\n // Cancel any pending \"stopped\" notification and mark our app as playing\n // audio. PCM streams intentionally do not suppress cloud STT.\n if (this.audioStopDebounceTimer !== null) {\n BgTimer.clearTimeout(this.audioStopDebounceTimer)\n this.audioStopDebounceTimer = null\n }\n BluetoothSdk.setOwnAppAudioPlaying(true).catch((e) => {\n console.warn(\"AUDIO: Failed to notify native of stream audio start:\", e)\n })\n\n // Guarded against the stream ending mid-read, same as the play() path.\n void this.ensureGlassesMediaVolumeForA2dpStream(stream)\n }\n\n /**\n * Append base64 PCM to an open stream. Resolves with the host-side backlog\n * in ms; the native write blocks while the backlog is above the\n * backpressure ceiling, so awaited writes self-throttle to realtime.\n */\n public async writeStreamChunk(streamId: string, base64: string): Promise<{bufferedMs: number}> {\n const stream = this.streams.get(streamId)\n if (!stream || stream.ended) {\n throw new Error(`stream ${streamId} is not open`)\n }\n try {\n return await BluetoothSdk.pcmStreamWrite(streamId, base64)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.endStream(stream, false, message, Date.now() - stream.startTime)\n throw error\n }\n }\n\n /** Drain the backlog, then finish. Resolves with the total played duration. */\n public async closeStream(streamId: string): Promise<{durationMs?: number}> {\n const stream = this.streams.get(streamId)\n if (!stream || stream.ended) {\n throw new Error(`stream ${streamId} is not open`)\n }\n try {\n const result = await BluetoothSdk.pcmStreamClose(streamId)\n this.endStream(stream, true, null, result?.durationMs ?? Date.now() - stream.startTime)\n return result ?? {}\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.endStream(stream, false, message, Date.now() - stream.startTime)\n throw error\n }\n }\n\n /** Stop immediately, dropping the backlog. Safe on unknown/ended ids. */\n public async abortStream(streamId: string): Promise<void> {\n const stream = this.streams.get(streamId)\n await BluetoothSdk.pcmStreamAbort(streamId).catch((e) => {\n console.warn(`AUDIO: Stream abort ${streamId} native call failed:`, e)\n })\n if (stream) {\n this.endStream(stream, true, null, Date.now() - stream.startTime)\n }\n }\n\n /** Abort every active stream (optionally sparing one about to replace them). */\n private async abortAllStreams(exceptStreamId?: string): Promise<void> {\n const streamIds = [...this.streams.values()]\n .filter((stream) => stream.streamId !== exceptStreamId)\n .map((stream) => stream.streamId)\n await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)))\n }\n\n /** Terminal bookkeeping for a stream: dedup, unregister, notify. */\n private endStream(stream: StreamState, success: boolean, error: string | null, durationMs: number | null): void {\n if (stream.ended) return\n stream.ended = true\n this.streams.delete(stream.streamId)\n this.markAudioRouteWarm()\n // Only signal \"audio stopped\" when nothing else is making noise.\n if (this.streams.size === 0 && (!this.currentPlayback || this.currentPlayback.completed)) {\n this.notifyAudioStopDebounced()\n void this.restoreGlassesMediaVolume()\n }\n stream.onEnded(stream.streamId, success, error, durationMs)\n }\n\n /** Stream twin of ensureGlassesMediaVolumeForA2dp, guarded by stream.ended. */\n private async ensureGlassesMediaVolumeForA2dpStream(stream: StreamState): Promise<void> {\n if (this.glassesVolumeRestoreLevel !== null) return\n try {\n const raw = await this.getGlassesMediaVolumeWithTiming()\n const level = Number(raw.level)\n if (!Number.isFinite(level) || level > AudioPlaybackService.GLASSES_VOLUME_LOW_THRESHOLD) return\n if (stream.ended) return\n console.log(`AUDIO: Raising glasses media volume for stream (was ${level})`)\n await this.setGlassesMediaVolumeWithTiming(AudioPlaybackService.GLASSES_VOLUME_FLOOR)\n if (!stream.ended) {\n this.glassesVolumeRestoreLevel = level\n } else {\n await this.setGlassesMediaVolumeWithTiming(level)\n }\n } catch (e) {\n console.warn(\"AUDIO: Skipping glasses volume bump for stream:\", e instanceof Error ? e.message : String(e))\n }\n }\n\n /**\n * Stop playback for a specific app.\n * If appId is not provided, stops all playback.\n */\n public async stopForApp(appId?: string): Promise<void> {\n // Abort this app's live PCM streams too (miniapp stop/disconnect path).\n const streamIds = [...this.streams.values()]\n .filter((stream) => !appId || stream.appId === appId)\n .map((stream) => stream.streamId)\n await Promise.all(streamIds.map((streamId) => this.abortStream(streamId)))\n\n if (!this.currentPlayback || this.currentPlayback.completed) return\n\n if (!appId || this.currentPlayback.appId === appId) {\n console.log(`AUDIO: Stopping playback for app ${appId || \"(all)\"}`)\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Stop all audio playback\n */\n public async stopAll(): Promise<void> {\n await this.abortAllStreams()\n if (this.currentPlayback && !this.currentPlayback.completed) {\n console.log(\"AUDIO: Stopping all playback\")\n this.interruptCurrentPlayback()\n }\n }\n\n /**\n * Check if audio is currently playing\n */\n public isPlaying(): boolean {\n return (this.currentPlayback !== null && !this.currentPlayback.completed) || this.streams.size > 0\n }\n\n /**\n * Get current playback app IDs (all active)\n */\n public getActiveAppIds(): string[] {\n const appIds = new Set<string>()\n if (this.currentPlayback && !this.currentPlayback.completed && this.currentPlayback.appId) {\n appIds.add(this.currentPlayback.appId)\n }\n for (const stream of this.streams.values()) appIds.add(stream.appId)\n return [...appIds]\n }\n\n /**\n * Get number of active playbacks\n */\n public getActiveCount(): number {\n return (this.currentPlayback && !this.currentPlayback.completed ? 1 : 0) + this.streams.size\n }\n\n /**\n * Release the player entirely (call when app is shutting down)\n */\n public release(): void {\n void this.abortAllStreams()\n if (this.currentPlayback && !this.currentPlayback.completed) {\n this.interruptCurrentPlayback()\n } else {\n void this.restoreGlassesMediaVolume()\n }\n\n if (this.player) {\n try {\n this.player.remove()\n console.log(\"AUDIO: Released AudioPlayer\")\n } catch (error) {\n console.error(\"AUDIO: Error releasing player:\", error)\n }\n this.player = null\n this.loadedPlayback = null\n }\n }\n}\n\nconst audioPlaybackService = AudioPlaybackService.getInstance()\nexport default audioPlaybackService\n"]}
|
|
@@ -42,9 +42,10 @@ export declare class BlobStore {
|
|
|
42
42
|
private readonly hooks;
|
|
43
43
|
private readonly uploads;
|
|
44
44
|
private readonly readers;
|
|
45
|
-
/**
|
|
45
|
+
/** user + package → committed usage bytes, cached; invalidated on commit/delete/clear. */
|
|
46
46
|
private readonly usageCache;
|
|
47
47
|
constructor(hooks: BlobStoreHooks);
|
|
48
|
+
private currentIdentity;
|
|
48
49
|
private dirFor;
|
|
49
50
|
private metaPrefix;
|
|
50
51
|
private metaKey;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlobStore.d.ts","sourceRoot":"","sources":["../../src/services/BlobStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,OAAO,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAA;AAMhD,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,QAAqB,CAAA;AASlD,KAAK,UAAU,GAAG,CAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,EAAE,EAAE,OAAO,EACX,MAAM,CAAC,EAAE,OAAO,EAChB,KAAK,CAAC,EAAE;IAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,KAC9C,IAAI,CAAA;AAET,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,UAAU,CAAA;IACtB,oEAAoE;IACpE,SAAS,EAAE,MAAM,MAAM,CAAA;CACxB;AAmCD,qBAAa,SAAS;IAMR,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,
|
|
1
|
+
{"version":3,"file":"BlobStore.d.ts","sourceRoot":"","sources":["../../src/services/BlobStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,21 +45,27 @@ export class BlobStore {
|
|
|
45
45
|
hooks;
|
|
46
46
|
uploads = new Map(); // key: `${pkg} ${key}`
|
|
47
47
|
readers = new Map(); // key: host handle id
|
|
48
|
-
/**
|
|
48
|
+
/** user + package → committed usage bytes, cached; invalidated on commit/delete/clear. */
|
|
49
49
|
usageCache = new Map();
|
|
50
50
|
constructor(hooks) {
|
|
51
51
|
this.hooks = hooks;
|
|
52
52
|
}
|
|
53
53
|
// ---- path / meta helpers -------------------------------------------------
|
|
54
|
+
currentIdentity(packageName) {
|
|
55
|
+
const userId = this.hooks.getUserId().trim();
|
|
56
|
+
if (!userId)
|
|
57
|
+
throw new Error("Mentra user identity is unavailable");
|
|
58
|
+
const scope = `${userId}\0${packageName}`;
|
|
59
|
+
return { userId, scope };
|
|
60
|
+
}
|
|
54
61
|
dirFor(packageName) {
|
|
55
|
-
const
|
|
56
|
-
const dir = new Directory(Paths.document, ROOT_DIR_NAME, userId, sanitizeSegment(packageName));
|
|
62
|
+
const dir = new Directory(Paths.document, ROOT_DIR_NAME, sanitizeSegment(this.currentIdentity(packageName).userId), sanitizeSegment(packageName));
|
|
57
63
|
if (!dir.exists)
|
|
58
64
|
dir.create({ intermediates: true });
|
|
59
65
|
return dir;
|
|
60
66
|
}
|
|
61
67
|
metaPrefix(packageName) {
|
|
62
|
-
return `${META_KEY_ROOT}${sanitizeSegment(this.
|
|
68
|
+
return `${META_KEY_ROOT}${sanitizeSegment(this.currentIdentity(packageName).userId)}_${packageName}_`;
|
|
63
69
|
}
|
|
64
70
|
metaKey(packageName, key) {
|
|
65
71
|
return this.metaPrefix(packageName) + key;
|
|
@@ -104,19 +110,21 @@ export class BlobStore {
|
|
|
104
110
|
};
|
|
105
111
|
}
|
|
106
112
|
committedUsage(packageName) {
|
|
107
|
-
const
|
|
113
|
+
const { scope } = this.currentIdentity(packageName);
|
|
114
|
+
const cached = this.usageCache.get(scope);
|
|
108
115
|
if (cached !== undefined)
|
|
109
116
|
return cached;
|
|
110
117
|
let total = 0;
|
|
111
118
|
for (const m of this.allMeta(packageName))
|
|
112
119
|
total += m.bytes || 0;
|
|
113
|
-
this.usageCache.set(
|
|
120
|
+
this.usageCache.set(scope, total);
|
|
114
121
|
return total;
|
|
115
122
|
}
|
|
116
123
|
bumpUsage(packageName, delta) {
|
|
117
|
-
const
|
|
124
|
+
const { scope } = this.currentIdentity(packageName);
|
|
125
|
+
const cur = this.usageCache.get(scope);
|
|
118
126
|
if (cur !== undefined)
|
|
119
|
-
this.usageCache.set(
|
|
127
|
+
this.usageCache.set(scope, Math.max(0, cur + delta));
|
|
120
128
|
}
|
|
121
129
|
safeMd5(file, bytes) {
|
|
122
130
|
if (bytes > MD5_MAX_BYTES)
|
|
@@ -427,7 +435,7 @@ export class BlobStore {
|
|
|
427
435
|
catch {
|
|
428
436
|
/* best-effort */
|
|
429
437
|
}
|
|
430
|
-
this.usageCache.set(packageName, 0);
|
|
438
|
+
this.usageCache.set(this.currentIdentity(packageName).scope, 0);
|
|
431
439
|
this.hooks.sendResult(packageName, requestId, true);
|
|
432
440
|
}
|
|
433
441
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlobStore.js","sourceRoot":"","sources":["../../src/services/BlobStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BlobStore\n *\n * Host-side implementation of `session.blob` — persistent, per-(userId,\n * packageName) BINARY storage for local miniapps, keyed like SimpleStorage (its\n * small-string sibling). Extracted from LocalMiniappRuntime the same way\n * NavigationHandlers is, to keep the runtime file small.\n *\n * Generic byte store — it knows nothing about any specific format. Highlights:\n * - chunked write/read (BLOB_CREATE/WRITE/COMMIT, BLOB_OPEN_READ/READ) so no\n * single bridge message is large;\n * - `setFromUrl` downloads a URL straight to disk (File.downloadFileAsync) and\n * `importFile` runs the OS picker (File.pickFileAsync) — both keep bytes\n * entirely host-side;\n * - `share` hands a stored file to the OS share sheet.\n *\n * Layout (mirrors SimpleStorage's scoping):\n * bytes: Paths.document/mentra_blobs/{userId}/{packageName}/{fileName}\n * metadata: MMKV key mentraos_blobmeta_{userId}_{packageName}_{key} → StoredBlobMeta JSON\n *\n * The on-disk file name is a generated id plus a mime-derived extension (iOS\n * AVPlayer keys a local file's format off the path extension, so blobs played\n * via `session.speaker.play` must carry one); the logical `key` (caller-chosen)\n * is the MMKV key. This decouples the filesystem from arbitrary caller keys.\n *\n * expo-file-system's new API is synchronous (create/writeBytes/md5/size), so\n * streaming chunk writes do no async work.\n */\n\nimport {Buffer} from \"buffer\"\nimport Share from \"react-native-share\"\nimport {Directory, File, Paths, type FileHandle} from \"expo-file-system\"\n\nimport {MiniappErrorCode} from \"@mentra/miniapp\"\nimport {storage as mmkvStorage} from \"../utils/storage/storage\"\nimport {sanitizeSegment, shareFileName, withDiskExt} from \"./blobPaths\"\n\nconst LOG_TAG = \"LocalMiniappRuntime\"\n\n/** Per-app blob quota: 1 GB. */\nexport const BLOB_QUOTA_BYTES = 1024 * 1024 * 1024\nconst ROOT_DIR_NAME = \"mentra_blobs\"\n/** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one unique subdir per share). */\nconst SHARE_DIR_NAME = \"mentra_blob_share\"\nconst META_KEY_ROOT = \"mentraos_blobmeta_\"\n/** Cap md5 computation so we don't block the JS thread hashing a huge file. */\nconst MD5_MAX_BYTES = 50 * 1024 * 1024\n\n// Matches LocalMiniappRuntime.sendResult (see NavigationHandlers).\ntype SendResult = (\n packageName: string,\n requestId: string | undefined,\n ok: boolean,\n result?: unknown,\n error?: {code: MiniappErrorCode; message: string},\n) => void\n\nexport interface BlobStoreHooks {\n sendResult: SendResult\n /** Resolve the current user id (same source SimpleStorage uses). */\n getUserId: () => string\n}\n\ninterface StoredBlobMeta {\n key: string\n fileName: string\n name?: string\n mimeType: string\n bytes: number\n createdAt: number\n updatedAt: number\n md5?: string\n meta?: Record<string, string | number | boolean>\n}\n\ninterface ActiveUpload {\n packageName: string\n key: string\n fileName: string\n partFile: File\n handle: FileHandle\n bytes: number\n /** Bytes already committed under this key (overwrite target) — excluded from the quota check. */\n priorBytes: number\n name?: string\n mimeType: string\n meta?: Record<string, string | number | boolean>\n createdAt: number\n}\n\ninterface ActiveReader {\n packageName: string\n handle: FileHandle\n remaining: number\n}\n\nexport class BlobStore {\n private readonly uploads = new Map<string, ActiveUpload>() // key: `${pkg} ${key}`\n private readonly readers = new Map<string, ActiveReader>() // key: host handle id\n /** packageName → committed usage bytes, cached; invalidated on commit/delete/clear. */\n private readonly usageCache = new Map<string, number>()\n\n constructor(private readonly hooks: BlobStoreHooks) {}\n\n // ---- path / meta helpers -------------------------------------------------\n\n private dirFor(packageName: string): Directory {\n const userId = sanitizeSegment(this.hooks.getUserId())\n const dir = new Directory(Paths.document, ROOT_DIR_NAME, userId, sanitizeSegment(packageName))\n if (!dir.exists) dir.create({intermediates: true})\n return dir\n }\n\n private metaPrefix(packageName: string): string {\n return `${META_KEY_ROOT}${sanitizeSegment(this.hooks.getUserId())}_${packageName}_`\n }\n\n private metaKey(packageName: string, key: string): string {\n return this.metaPrefix(packageName) + key\n }\n\n private uploadKey(packageName: string, key: string): string {\n return `${packageName} ${key}`\n }\n\n private readMeta(packageName: string, key: string): StoredBlobMeta | null {\n const r = mmkvStorage.load<StoredBlobMeta>(this.metaKey(packageName, key))\n return r.is_ok() ? r.value : null\n }\n\n private writeMeta(packageName: string, meta: StoredBlobMeta): void {\n mmkvStorage.save(this.metaKey(packageName, meta.key), meta)\n }\n\n private allMeta(packageName: string): StoredBlobMeta[] {\n const prefix = this.metaPrefix(packageName)\n const out: StoredBlobMeta[] = []\n for (const k of mmkvStorage.getAllKeys()) {\n if (!k.startsWith(prefix)) continue\n const r = mmkvStorage.load<StoredBlobMeta>(k)\n if (r.is_ok() && r.value) out.push(r.value)\n }\n return out\n }\n\n private fileFor(packageName: string, fileName: string): File {\n return new File(this.dirFor(packageName), fileName)\n }\n\n /** Public API shape: stored meta + derived file:// uri. */\n private toBlobMeta(packageName: string, m: StoredBlobMeta) {\n return {\n key: m.key,\n name: m.name,\n mimeType: m.mimeType,\n bytes: m.bytes,\n createdAt: m.createdAt,\n updatedAt: m.updatedAt,\n md5: m.md5,\n uri: this.fileFor(packageName, m.fileName).uri,\n meta: m.meta,\n }\n }\n\n private committedUsage(packageName: string): number {\n const cached = this.usageCache.get(packageName)\n if (cached !== undefined) return cached\n let total = 0\n for (const m of this.allMeta(packageName)) total += m.bytes || 0\n this.usageCache.set(packageName, total)\n return total\n }\n\n private bumpUsage(packageName: string, delta: number): void {\n const cur = this.usageCache.get(packageName)\n if (cur !== undefined) this.usageCache.set(packageName, Math.max(0, cur + delta))\n }\n\n private safeMd5(file: File, bytes: number): string | undefined {\n if (bytes > MD5_MAX_BYTES) return undefined\n try {\n return file.md5 ?? undefined\n } catch {\n return undefined\n }\n }\n\n private makeId(): string {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}${Math.random()\n .toString(36)\n .slice(2, 6)}`\n }\n\n /** Would storing `incoming` bytes under `key` exceed the per-app quota? */\n private overQuota(packageName: string, key: string, incoming: number): boolean {\n const priorBytes = this.readMeta(packageName, key)?.bytes ?? 0\n return this.committedUsage(packageName) - priorBytes + incoming > BLOB_QUOTA_BYTES\n }\n\n /** Publish a file already sitting at `fileName` as the blob for `key`; returns its public meta. */\n private commitFile(\n packageName: string,\n key: string,\n fileName: string,\n mimeType: string,\n name: string | undefined,\n extraMeta: Record<string, string | number | boolean> | undefined,\n ) {\n // Attach a mime-derived extension to the on-disk name. Consumers that key\n // format off the path — iOS AVPlayer under `session.speaker.play` — cannot\n // open an extension-less file, even though the bytes are valid.\n const named = withDiskExt(fileName, mimeType)\n if (named !== fileName) {\n try {\n this.fileFor(packageName, fileName).rename(named)\n fileName = named\n } catch {\n /* keep the extension-less name — the blob still stores and shares fine */\n }\n }\n const prior = this.readMeta(packageName, key)\n if (prior && prior.fileName !== fileName) {\n this.deleteFileQuiet(packageName, prior.fileName)\n this.bumpUsage(packageName, -(prior.bytes || 0))\n }\n const finalFile = this.fileFor(packageName, fileName)\n const bytes = finalFile.size ?? 0\n const now = Date.now()\n const meta: StoredBlobMeta = {\n key,\n fileName,\n name,\n mimeType,\n bytes,\n createdAt: prior?.createdAt ?? now,\n updatedAt: now,\n md5: this.safeMd5(finalFile, bytes),\n meta: extraMeta,\n }\n this.writeMeta(packageName, meta)\n this.bumpUsage(packageName, bytes)\n return this.toBlobMeta(packageName, meta)\n }\n\n // ---- streaming write -----------------------------------------------------\n\n handleCreate(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n try {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mapKey = this.uploadKey(packageName, key)\n const existing = this.uploads.get(mapKey)\n if (existing) this.discardUpload(existing)\n\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n partFile.create({intermediates: true, overwrite: true})\n const handle = partFile.open()\n\n this.uploads.set(mapKey, {\n packageName,\n key,\n fileName,\n partFile,\n handle,\n bytes: 0,\n priorBytes: this.readMeta(packageName, key)?.bytes ?? 0,\n name: typeof payload.name === \"string\" ? payload.name : undefined,\n mimeType: typeof payload.mimeType === \"string\" ? payload.mimeType : \"application/octet-stream\",\n meta: (payload.meta as Record<string, string | number | boolean>) ?? undefined,\n createdAt: Date.now(),\n })\n this.hooks.sendResult(packageName, requestId, true, {key})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleWrite(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const up = this.uploads.get(this.uploadKey(packageName, key))\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n const chunk = Buffer.from((payload.base64 as string) ?? \"\", \"base64\")\n const bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength)\n // A seek write (offset present) patches existing bytes in place — used to\n // rewrite a container header on finalize; it does not grow the blob.\n if (typeof payload.offset === \"number\") {\n if (payload.offset < 0 || payload.offset + bytes.length > up.bytes) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_WRITE_FAILED,\n message: \"writeAt offset out of range (must stay within written bytes)\",\n })\n return\n }\n up.handle.offset = payload.offset\n up.handle.writeBytes(bytes)\n up.handle.offset = up.bytes // restore append position\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n return\n }\n // Exclude the prior blob under this key — it's freed on commit (overwrite).\n if (this.committedUsage(packageName) - up.priorBytes + up.bytes + bytes.length > BLOB_QUOTA_BYTES) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n up.handle.offset = up.bytes\n up.handle.writeBytes(bytes)\n up.bytes += bytes.length\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleCommit(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const mapKey = this.uploadKey(packageName, key)\n const up = this.uploads.get(mapKey)\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n up.handle.close()\n up.partFile.rename(up.fileName) // drop \".part\"\n const extraMeta = {\n ...(up.meta ?? {}),\n ...((payload.meta as Record<string, string | number | boolean>) ?? {}),\n }\n const meta = this.commitFile(packageName, key, up.fileName, up.mimeType, up.name, extraMeta)\n this.uploads.delete(mapKey)\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleAbort(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const mapKey = this.uploadKey(packageName, payload.key as string)\n const up = this.uploads.get(mapKey)\n if (up) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- download / import (host-side; no bytes cross the bridge) -------------\n\n async handleSetFromUrl(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const url = payload.url as string\n if (!key || !url) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, new Error(\"setFromUrl requires key + url\"))\n return\n }\n if (url.startsWith(\"file:\") || url.startsWith(\"javascript:\")) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_DOWNLOAD_FAILED,\n message: \"Unsupported URL scheme\",\n })\n return\n }\n const headers = payload.headers as Record<string, string> | undefined\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n try {\n const dl = await File.downloadFileAsync(url, partFile, {idempotent: true, ...(headers ? {headers} : {})})\n const size = dl.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n try {\n dl.delete()\n } catch {\n /* ignore */\n }\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n partFile.rename(fileName)\n const mimeType =\n (payload.mimeType as string) || inferMime(basename(url)) || this.fileFor(packageName, fileName).type || OCTET\n const name = (payload.name as string) || basename(url) || key\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n try {\n if (partFile.exists) partFile.delete()\n } catch {\n /* ignore */\n }\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_DOWNLOAD_FAILED, err)\n }\n }\n\n async handleImport(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mimeFilter = payload.mimeType as string | undefined\n\n let picked: File | File[] | null = null\n try {\n picked = await File.pickFileAsync(undefined, mimeFilter)\n } catch (err) {\n // Picker dismissed / cancelled (or unavailable) → resolve to null, not an error.\n console.log(`${LOG_TAG}: blob import picker dismissed`, err)\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n const file = Array.isArray(picked) ? picked[0] : picked\n if (!file) {\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n try {\n const size = file.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n const fileName = this.makeId()\n file.copy(this.fileFor(packageName, fileName))\n const name = basename(file.uri) || key\n const mimeType = mimeFilter || file.type || inferMime(name) || OCTET\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_IMPORT_FAILED, err)\n }\n }\n\n // ---- read ----------------------------------------------------------------\n\n handleGet(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n if (!meta || !this.fileFor(packageName, meta.fileName).exists) {\n if (meta) this.dropMeta(packageName, meta) // reconcile dangling meta\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n this.hooks.sendResult(packageName, requestId, true, this.toBlobMeta(packageName, meta))\n }\n\n handleList(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const blobs = this.allMeta(packageName)\n .filter((m) => this.fileFor(packageName, m.fileName).exists)\n .sort((a, b) => b.createdAt - a.createdAt)\n .map((m) => this.toBlobMeta(packageName, m))\n this.hooks.sendResult(packageName, requestId, true, {blobs})\n }\n\n handleUsage(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const metas = this.allMeta(packageName)\n this.hooks.sendResult(packageName, requestId, true, {\n bytes: metas.reduce((s, m) => s + (m.bytes || 0), 0),\n count: metas.length,\n quotaBytes: BLOB_QUOTA_BYTES,\n })\n }\n\n handleDelete(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const meta = this.readMeta(packageName, payload.key as string)\n if (meta) this.dropMeta(packageName, meta)\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n handleClear(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n try {\n // Abort any in-flight uploads / open readers first so nothing keeps writing\n // to a .part file in the directory we're about to delete.\n this.closeAppHandles(packageName)\n for (const m of this.allMeta(packageName)) mmkvStorage.remove(this.metaKey(packageName, m.key))\n const dir = this.dirFor(packageName)\n try {\n if (dir.exists) dir.delete()\n } catch {\n /* best-effort */\n }\n this.usageCache.set(packageName, 0)\n this.hooks.sendResult(packageName, requestId, true)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleOpenRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n try {\n const handle = file.open()\n const handleId = `r_${this.makeId()}`\n this.readers.set(handleId, {packageName, handle, remaining: meta.bytes})\n this.hooks.sendResult(packageName, requestId, true, {handle: handleId, meta: this.toBlobMeta(packageName, meta)})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (!reader || reader.packageName !== packageName) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: \"Unknown blob read handle\",\n })\n return\n }\n try {\n const want = Math.max(0, Math.min(Number(payload.maxBytes) || 1024 * 1024, reader.remaining))\n const bytes = want > 0 ? reader.handle.readBytes(want) : new Uint8Array(0)\n reader.remaining -= bytes.length\n const done = reader.remaining <= 0\n const base64 = bytes.length\n ? Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(\"base64\")\n : \"\"\n if (done) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true, {base64, done})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleCloseRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (reader && reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- share ---------------------------------------------------------------\n\n async handleShare(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n // The on-disk blob name is a generated id (mime extension attached at\n // commit; legacy blobs may lack it). react-native-share derives the shared\n // file's name + extension from the URL's path (its `filename` option only\n // applies to base64/data payloads, not file:// URLs), so sharing `file.uri`\n // directly would hand the recipient a machine-named file. Copy to a temp\n // file that carries the real display name + extension, share that, then\n // clean it up.\n const shareName = shareFileName(meta)\n // Copy into a per-share unique subdir so two concurrent shares that resolve\n // to the same display name can't clobber each other's temp file while\n // Share.open still references it. The file keeps `shareName` as its basename\n // so the OS share sheet shows the right name + extension.\n let tempDir: Directory | null = null\n try {\n tempDir = new Directory(Paths.cache, SHARE_DIR_NAME, this.makeId())\n tempDir.create({intermediates: true})\n const temp = new File(tempDir, shareName)\n file.copy(temp)\n await Share.open({\n url: temp.uri,\n type: meta.mimeType || OCTET,\n filename: shareName,\n })\n this.hooks.sendResult(packageName, requestId, true, {success: true})\n } catch (error: any) {\n if (error?.message?.includes(\"User did not share\")) {\n this.hooks.sendResult(packageName, requestId, true, {success: false, cancelled: true})\n } else {\n console.error(`${LOG_TAG}: blob share error:`, error)\n this.hooks.sendResult(packageName, requestId, true, {success: false})\n }\n } finally {\n if (tempDir) {\n try {\n if (tempDir.exists) tempDir.delete()\n } catch {\n /* ignore */\n }\n }\n }\n }\n\n // ---- lifecycle / cleanup -------------------------------------------------\n\n /** Called from LocalMiniappRuntime.unregisterApp — drop this app's in-flight state. */\n onAppGone(packageName: string): void {\n this.closeAppHandles(packageName)\n }\n\n /** Abort in-flight uploads + close open read handles for an app (no-op if none). */\n private closeAppHandles(packageName: string): void {\n for (const [k, up] of this.uploads) {\n if (up.packageName === packageName) {\n this.discardUpload(up)\n this.uploads.delete(k)\n }\n }\n for (const [k, reader] of this.readers) {\n if (reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(k)\n }\n }\n }\n\n private discardUpload(up: ActiveUpload): void {\n try {\n up.handle.close()\n } catch {\n /* ignore */\n }\n try {\n if (up.partFile.exists) up.partFile.delete()\n } catch {\n /* ignore */\n }\n }\n\n private dropMeta(packageName: string, meta: StoredBlobMeta): void {\n this.deleteFileQuiet(packageName, meta.fileName)\n mmkvStorage.remove(this.metaKey(packageName, meta.key))\n this.bumpUsage(packageName, -(meta.bytes || 0))\n }\n\n private deleteFileQuiet(packageName: string, fileName: string): void {\n try {\n const f = this.fileFor(packageName, fileName)\n if (f.exists) f.delete()\n } catch {\n /* ignore */\n }\n }\n\n private fail(packageName: string, requestId: string | undefined, code: MiniappErrorCode, err: unknown): void {\n console.error(`${LOG_TAG}: blob error [${code}]:`, err)\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code,\n message: err instanceof Error ? err.message : \"Blob error\",\n })\n }\n}\n\nconst OCTET = \"application/octet-stream\"\n\n/** Last path segment of a URL/URI, query stripped + percent-decoded. */\nfunction basename(uri: string): string {\n const noQuery = uri.split(\"?\")[0].split(\"#\")[0]\n const seg = noQuery.substring(noQuery.lastIndexOf(\"/\") + 1)\n try {\n return decodeURIComponent(seg)\n } catch {\n return seg\n }\n}\n\n/** Best-effort MIME from a filename extension. Returns undefined when unknown. */\nfunction inferMime(name: string): string | undefined {\n const dot = name.lastIndexOf(\".\")\n if (dot < 0) return undefined\n const ext = name.slice(dot + 1).toLowerCase()\n const map: Record<string, string> = {\n pdf: \"application/pdf\",\n epub: \"application/epub+zip\",\n zip: \"application/zip\",\n json: \"application/json\",\n txt: \"text/plain\",\n csv: \"text/csv\",\n html: \"text/html\",\n mp4: \"video/mp4\",\n mov: \"video/quicktime\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n m4a: \"audio/mp4\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n }\n return map[ext]\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BlobStore.js","sourceRoot":"","sources":["../../src/services/BlobStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BlobStore\n *\n * Host-side implementation of `session.blob` — persistent, per-(userId,\n * packageName) BINARY storage for local miniapps, keyed like SimpleStorage (its\n * small-string sibling). Extracted from LocalMiniappRuntime the same way\n * NavigationHandlers is, to keep the runtime file small.\n *\n * Generic byte store — it knows nothing about any specific format. Highlights:\n * - chunked write/read (BLOB_CREATE/WRITE/COMMIT, BLOB_OPEN_READ/READ) so no\n * single bridge message is large;\n * - `setFromUrl` downloads a URL straight to disk (File.downloadFileAsync) and\n * `importFile` runs the OS picker (File.pickFileAsync) — both keep bytes\n * entirely host-side;\n * - `share` hands a stored file to the OS share sheet.\n *\n * Layout (mirrors SimpleStorage's scoping):\n * bytes: Paths.document/mentra_blobs/{userId}/{packageName}/{fileName}\n * metadata: MMKV key mentraos_blobmeta_{userId}_{packageName}_{key} → StoredBlobMeta JSON\n *\n * The on-disk file name is a generated id plus a mime-derived extension (iOS\n * AVPlayer keys a local file's format off the path extension, so blobs played\n * via `session.speaker.play` must carry one); the logical `key` (caller-chosen)\n * is the MMKV key. This decouples the filesystem from arbitrary caller keys.\n *\n * expo-file-system's new API is synchronous (create/writeBytes/md5/size), so\n * streaming chunk writes do no async work.\n */\n\nimport {Buffer} from \"buffer\"\nimport Share from \"react-native-share\"\nimport {Directory, File, Paths, type FileHandle} from \"expo-file-system\"\n\nimport {MiniappErrorCode} from \"@mentra/miniapp\"\nimport {storage as mmkvStorage} from \"../utils/storage/storage\"\nimport {sanitizeSegment, shareFileName, withDiskExt} from \"./blobPaths\"\n\nconst LOG_TAG = \"LocalMiniappRuntime\"\n\n/** Per-app blob quota: 1 GB. */\nexport const BLOB_QUOTA_BYTES = 1024 * 1024 * 1024\nconst ROOT_DIR_NAME = \"mentra_blobs\"\n/** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one unique subdir per share). */\nconst SHARE_DIR_NAME = \"mentra_blob_share\"\nconst META_KEY_ROOT = \"mentraos_blobmeta_\"\n/** Cap md5 computation so we don't block the JS thread hashing a huge file. */\nconst MD5_MAX_BYTES = 50 * 1024 * 1024\n\n// Matches LocalMiniappRuntime.sendResult (see NavigationHandlers).\ntype SendResult = (\n packageName: string,\n requestId: string | undefined,\n ok: boolean,\n result?: unknown,\n error?: {code: MiniappErrorCode; message: string},\n) => void\n\nexport interface BlobStoreHooks {\n sendResult: SendResult\n /** Resolve the current user id (same source SimpleStorage uses). */\n getUserId: () => string\n}\n\ninterface StoredBlobMeta {\n key: string\n fileName: string\n name?: string\n mimeType: string\n bytes: number\n createdAt: number\n updatedAt: number\n md5?: string\n meta?: Record<string, string | number | boolean>\n}\n\ninterface ActiveUpload {\n packageName: string\n key: string\n fileName: string\n partFile: File\n handle: FileHandle\n bytes: number\n /** Bytes already committed under this key (overwrite target) — excluded from the quota check. */\n priorBytes: number\n name?: string\n mimeType: string\n meta?: Record<string, string | number | boolean>\n createdAt: number\n}\n\ninterface ActiveReader {\n packageName: string\n handle: FileHandle\n remaining: number\n}\n\nexport class BlobStore {\n private readonly uploads = new Map<string, ActiveUpload>() // key: `${pkg} ${key}`\n private readonly readers = new Map<string, ActiveReader>() // key: host handle id\n /** user + package → committed usage bytes, cached; invalidated on commit/delete/clear. */\n private readonly usageCache = new Map<string, number>()\n\n constructor(private readonly hooks: BlobStoreHooks) {}\n\n // ---- path / meta helpers -------------------------------------------------\n\n private currentIdentity(packageName: string): {userId: string; scope: string} {\n const userId = this.hooks.getUserId().trim()\n if (!userId) throw new Error(\"Mentra user identity is unavailable\")\n const scope = `${userId}\\0${packageName}`\n return {userId, scope}\n }\n\n private dirFor(packageName: string): Directory {\n const dir = new Directory(\n Paths.document,\n ROOT_DIR_NAME,\n sanitizeSegment(this.currentIdentity(packageName).userId),\n sanitizeSegment(packageName),\n )\n if (!dir.exists) dir.create({intermediates: true})\n return dir\n }\n\n private metaPrefix(packageName: string): string {\n return `${META_KEY_ROOT}${sanitizeSegment(this.currentIdentity(packageName).userId)}_${packageName}_`\n }\n\n private metaKey(packageName: string, key: string): string {\n return this.metaPrefix(packageName) + key\n }\n\n private uploadKey(packageName: string, key: string): string {\n return `${packageName} ${key}`\n }\n\n private readMeta(packageName: string, key: string): StoredBlobMeta | null {\n const r = mmkvStorage.load<StoredBlobMeta>(this.metaKey(packageName, key))\n return r.is_ok() ? r.value : null\n }\n\n private writeMeta(packageName: string, meta: StoredBlobMeta): void {\n mmkvStorage.save(this.metaKey(packageName, meta.key), meta)\n }\n\n private allMeta(packageName: string): StoredBlobMeta[] {\n const prefix = this.metaPrefix(packageName)\n const out: StoredBlobMeta[] = []\n for (const k of mmkvStorage.getAllKeys()) {\n if (!k.startsWith(prefix)) continue\n const r = mmkvStorage.load<StoredBlobMeta>(k)\n if (r.is_ok() && r.value) out.push(r.value)\n }\n return out\n }\n\n private fileFor(packageName: string, fileName: string): File {\n return new File(this.dirFor(packageName), fileName)\n }\n\n /** Public API shape: stored meta + derived file:// uri. */\n private toBlobMeta(packageName: string, m: StoredBlobMeta) {\n return {\n key: m.key,\n name: m.name,\n mimeType: m.mimeType,\n bytes: m.bytes,\n createdAt: m.createdAt,\n updatedAt: m.updatedAt,\n md5: m.md5,\n uri: this.fileFor(packageName, m.fileName).uri,\n meta: m.meta,\n }\n }\n\n private committedUsage(packageName: string): number {\n const {scope} = this.currentIdentity(packageName)\n const cached = this.usageCache.get(scope)\n if (cached !== undefined) return cached\n let total = 0\n for (const m of this.allMeta(packageName)) total += m.bytes || 0\n this.usageCache.set(scope, total)\n return total\n }\n\n private bumpUsage(packageName: string, delta: number): void {\n const {scope} = this.currentIdentity(packageName)\n const cur = this.usageCache.get(scope)\n if (cur !== undefined) this.usageCache.set(scope, Math.max(0, cur + delta))\n }\n\n private safeMd5(file: File, bytes: number): string | undefined {\n if (bytes > MD5_MAX_BYTES) return undefined\n try {\n return file.md5 ?? undefined\n } catch {\n return undefined\n }\n }\n\n private makeId(): string {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}${Math.random()\n .toString(36)\n .slice(2, 6)}`\n }\n\n /** Would storing `incoming` bytes under `key` exceed the per-app quota? */\n private overQuota(packageName: string, key: string, incoming: number): boolean {\n const priorBytes = this.readMeta(packageName, key)?.bytes ?? 0\n return this.committedUsage(packageName) - priorBytes + incoming > BLOB_QUOTA_BYTES\n }\n\n /** Publish a file already sitting at `fileName` as the blob for `key`; returns its public meta. */\n private commitFile(\n packageName: string,\n key: string,\n fileName: string,\n mimeType: string,\n name: string | undefined,\n extraMeta: Record<string, string | number | boolean> | undefined,\n ) {\n // Attach a mime-derived extension to the on-disk name. Consumers that key\n // format off the path — iOS AVPlayer under `session.speaker.play` — cannot\n // open an extension-less file, even though the bytes are valid.\n const named = withDiskExt(fileName, mimeType)\n if (named !== fileName) {\n try {\n this.fileFor(packageName, fileName).rename(named)\n fileName = named\n } catch {\n /* keep the extension-less name — the blob still stores and shares fine */\n }\n }\n const prior = this.readMeta(packageName, key)\n if (prior && prior.fileName !== fileName) {\n this.deleteFileQuiet(packageName, prior.fileName)\n this.bumpUsage(packageName, -(prior.bytes || 0))\n }\n const finalFile = this.fileFor(packageName, fileName)\n const bytes = finalFile.size ?? 0\n const now = Date.now()\n const meta: StoredBlobMeta = {\n key,\n fileName,\n name,\n mimeType,\n bytes,\n createdAt: prior?.createdAt ?? now,\n updatedAt: now,\n md5: this.safeMd5(finalFile, bytes),\n meta: extraMeta,\n }\n this.writeMeta(packageName, meta)\n this.bumpUsage(packageName, bytes)\n return this.toBlobMeta(packageName, meta)\n }\n\n // ---- streaming write -----------------------------------------------------\n\n handleCreate(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n try {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mapKey = this.uploadKey(packageName, key)\n const existing = this.uploads.get(mapKey)\n if (existing) this.discardUpload(existing)\n\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n partFile.create({intermediates: true, overwrite: true})\n const handle = partFile.open()\n\n this.uploads.set(mapKey, {\n packageName,\n key,\n fileName,\n partFile,\n handle,\n bytes: 0,\n priorBytes: this.readMeta(packageName, key)?.bytes ?? 0,\n name: typeof payload.name === \"string\" ? payload.name : undefined,\n mimeType: typeof payload.mimeType === \"string\" ? payload.mimeType : \"application/octet-stream\",\n meta: (payload.meta as Record<string, string | number | boolean>) ?? undefined,\n createdAt: Date.now(),\n })\n this.hooks.sendResult(packageName, requestId, true, {key})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleWrite(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const up = this.uploads.get(this.uploadKey(packageName, key))\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n const chunk = Buffer.from((payload.base64 as string) ?? \"\", \"base64\")\n const bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength)\n // A seek write (offset present) patches existing bytes in place — used to\n // rewrite a container header on finalize; it does not grow the blob.\n if (typeof payload.offset === \"number\") {\n if (payload.offset < 0 || payload.offset + bytes.length > up.bytes) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_WRITE_FAILED,\n message: \"writeAt offset out of range (must stay within written bytes)\",\n })\n return\n }\n up.handle.offset = payload.offset\n up.handle.writeBytes(bytes)\n up.handle.offset = up.bytes // restore append position\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n return\n }\n // Exclude the prior blob under this key — it's freed on commit (overwrite).\n if (this.committedUsage(packageName) - up.priorBytes + up.bytes + bytes.length > BLOB_QUOTA_BYTES) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n up.handle.offset = up.bytes\n up.handle.writeBytes(bytes)\n up.bytes += bytes.length\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleCommit(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const mapKey = this.uploadKey(packageName, key)\n const up = this.uploads.get(mapKey)\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n up.handle.close()\n up.partFile.rename(up.fileName) // drop \".part\"\n const extraMeta = {\n ...(up.meta ?? {}),\n ...((payload.meta as Record<string, string | number | boolean>) ?? {}),\n }\n const meta = this.commitFile(packageName, key, up.fileName, up.mimeType, up.name, extraMeta)\n this.uploads.delete(mapKey)\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleAbort(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const mapKey = this.uploadKey(packageName, payload.key as string)\n const up = this.uploads.get(mapKey)\n if (up) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- download / import (host-side; no bytes cross the bridge) -------------\n\n async handleSetFromUrl(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const url = payload.url as string\n if (!key || !url) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, new Error(\"setFromUrl requires key + url\"))\n return\n }\n if (url.startsWith(\"file:\") || url.startsWith(\"javascript:\")) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_DOWNLOAD_FAILED,\n message: \"Unsupported URL scheme\",\n })\n return\n }\n const headers = payload.headers as Record<string, string> | undefined\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n try {\n const dl = await File.downloadFileAsync(url, partFile, {idempotent: true, ...(headers ? {headers} : {})})\n const size = dl.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n try {\n dl.delete()\n } catch {\n /* ignore */\n }\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n partFile.rename(fileName)\n const mimeType =\n (payload.mimeType as string) || inferMime(basename(url)) || this.fileFor(packageName, fileName).type || OCTET\n const name = (payload.name as string) || basename(url) || key\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n try {\n if (partFile.exists) partFile.delete()\n } catch {\n /* ignore */\n }\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_DOWNLOAD_FAILED, err)\n }\n }\n\n async handleImport(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mimeFilter = payload.mimeType as string | undefined\n\n let picked: File | File[] | null = null\n try {\n picked = await File.pickFileAsync(undefined, mimeFilter)\n } catch (err) {\n // Picker dismissed / cancelled (or unavailable) → resolve to null, not an error.\n console.log(`${LOG_TAG}: blob import picker dismissed`, err)\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n const file = Array.isArray(picked) ? picked[0] : picked\n if (!file) {\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n try {\n const size = file.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n const fileName = this.makeId()\n file.copy(this.fileFor(packageName, fileName))\n const name = basename(file.uri) || key\n const mimeType = mimeFilter || file.type || inferMime(name) || OCTET\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_IMPORT_FAILED, err)\n }\n }\n\n // ---- read ----------------------------------------------------------------\n\n handleGet(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n if (!meta || !this.fileFor(packageName, meta.fileName).exists) {\n if (meta) this.dropMeta(packageName, meta) // reconcile dangling meta\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n this.hooks.sendResult(packageName, requestId, true, this.toBlobMeta(packageName, meta))\n }\n\n handleList(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const blobs = this.allMeta(packageName)\n .filter((m) => this.fileFor(packageName, m.fileName).exists)\n .sort((a, b) => b.createdAt - a.createdAt)\n .map((m) => this.toBlobMeta(packageName, m))\n this.hooks.sendResult(packageName, requestId, true, {blobs})\n }\n\n handleUsage(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const metas = this.allMeta(packageName)\n this.hooks.sendResult(packageName, requestId, true, {\n bytes: metas.reduce((s, m) => s + (m.bytes || 0), 0),\n count: metas.length,\n quotaBytes: BLOB_QUOTA_BYTES,\n })\n }\n\n handleDelete(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const meta = this.readMeta(packageName, payload.key as string)\n if (meta) this.dropMeta(packageName, meta)\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n handleClear(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n try {\n // Abort any in-flight uploads / open readers first so nothing keeps writing\n // to a .part file in the directory we're about to delete.\n this.closeAppHandles(packageName)\n for (const m of this.allMeta(packageName)) mmkvStorage.remove(this.metaKey(packageName, m.key))\n const dir = this.dirFor(packageName)\n try {\n if (dir.exists) dir.delete()\n } catch {\n /* best-effort */\n }\n this.usageCache.set(this.currentIdentity(packageName).scope, 0)\n this.hooks.sendResult(packageName, requestId, true)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleOpenRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n try {\n const handle = file.open()\n const handleId = `r_${this.makeId()}`\n this.readers.set(handleId, {packageName, handle, remaining: meta.bytes})\n this.hooks.sendResult(packageName, requestId, true, {handle: handleId, meta: this.toBlobMeta(packageName, meta)})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (!reader || reader.packageName !== packageName) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: \"Unknown blob read handle\",\n })\n return\n }\n try {\n const want = Math.max(0, Math.min(Number(payload.maxBytes) || 1024 * 1024, reader.remaining))\n const bytes = want > 0 ? reader.handle.readBytes(want) : new Uint8Array(0)\n reader.remaining -= bytes.length\n const done = reader.remaining <= 0\n const base64 = bytes.length\n ? Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(\"base64\")\n : \"\"\n if (done) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true, {base64, done})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleCloseRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (reader && reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- share ---------------------------------------------------------------\n\n async handleShare(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n // The on-disk blob name is a generated id (mime extension attached at\n // commit; legacy blobs may lack it). react-native-share derives the shared\n // file's name + extension from the URL's path (its `filename` option only\n // applies to base64/data payloads, not file:// URLs), so sharing `file.uri`\n // directly would hand the recipient a machine-named file. Copy to a temp\n // file that carries the real display name + extension, share that, then\n // clean it up.\n const shareName = shareFileName(meta)\n // Copy into a per-share unique subdir so two concurrent shares that resolve\n // to the same display name can't clobber each other's temp file while\n // Share.open still references it. The file keeps `shareName` as its basename\n // so the OS share sheet shows the right name + extension.\n let tempDir: Directory | null = null\n try {\n tempDir = new Directory(Paths.cache, SHARE_DIR_NAME, this.makeId())\n tempDir.create({intermediates: true})\n const temp = new File(tempDir, shareName)\n file.copy(temp)\n await Share.open({\n url: temp.uri,\n type: meta.mimeType || OCTET,\n filename: shareName,\n })\n this.hooks.sendResult(packageName, requestId, true, {success: true})\n } catch (error: any) {\n if (error?.message?.includes(\"User did not share\")) {\n this.hooks.sendResult(packageName, requestId, true, {success: false, cancelled: true})\n } else {\n console.error(`${LOG_TAG}: blob share error:`, error)\n this.hooks.sendResult(packageName, requestId, true, {success: false})\n }\n } finally {\n if (tempDir) {\n try {\n if (tempDir.exists) tempDir.delete()\n } catch {\n /* ignore */\n }\n }\n }\n }\n\n // ---- lifecycle / cleanup -------------------------------------------------\n\n /** Called from LocalMiniappRuntime.unregisterApp — drop this app's in-flight state. */\n onAppGone(packageName: string): void {\n this.closeAppHandles(packageName)\n }\n\n /** Abort in-flight uploads + close open read handles for an app (no-op if none). */\n private closeAppHandles(packageName: string): void {\n for (const [k, up] of this.uploads) {\n if (up.packageName === packageName) {\n this.discardUpload(up)\n this.uploads.delete(k)\n }\n }\n for (const [k, reader] of this.readers) {\n if (reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(k)\n }\n }\n }\n\n private discardUpload(up: ActiveUpload): void {\n try {\n up.handle.close()\n } catch {\n /* ignore */\n }\n try {\n if (up.partFile.exists) up.partFile.delete()\n } catch {\n /* ignore */\n }\n }\n\n private dropMeta(packageName: string, meta: StoredBlobMeta): void {\n this.deleteFileQuiet(packageName, meta.fileName)\n mmkvStorage.remove(this.metaKey(packageName, meta.key))\n this.bumpUsage(packageName, -(meta.bytes || 0))\n }\n\n private deleteFileQuiet(packageName: string, fileName: string): void {\n try {\n const f = this.fileFor(packageName, fileName)\n if (f.exists) f.delete()\n } catch {\n /* ignore */\n }\n }\n\n private fail(packageName: string, requestId: string | undefined, code: MiniappErrorCode, err: unknown): void {\n console.error(`${LOG_TAG}: blob error [${code}]:`, err)\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code,\n message: err instanceof Error ? err.message : \"Blob error\",\n })\n }\n}\n\nconst OCTET = \"application/octet-stream\"\n\n/** Last path segment of a URL/URI, query stripped + percent-decoded. */\nfunction basename(uri: string): string {\n const noQuery = uri.split(\"?\")[0].split(\"#\")[0]\n const seg = noQuery.substring(noQuery.lastIndexOf(\"/\") + 1)\n try {\n return decodeURIComponent(seg)\n } catch {\n return seg\n }\n}\n\n/** Best-effort MIME from a filename extension. Returns undefined when unknown. */\nfunction inferMime(name: string): string | undefined {\n const dot = name.lastIndexOf(\".\")\n if (dot < 0) return undefined\n const ext = name.slice(dot + 1).toLowerCase()\n const map: Record<string, string> = {\n pdf: \"application/pdf\",\n epub: \"application/epub+zip\",\n zip: \"application/zip\",\n json: \"application/json\",\n txt: \"text/plain\",\n csv: \"text/csv\",\n html: \"text/html\",\n mp4: \"video/mp4\",\n mov: \"video/quicktime\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n m4a: \"audio/mp4\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n }\n return map[ext]\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudAudioSubscriptionSync.d.ts","sourceRoot":"","sources":["../../src/services/CloudAudioSubscriptionSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IAEhB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"CloudAudioSubscriptionSync.d.ts","sourceRoot":"","sources":["../../src/services/CloudAudioSubscriptionSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IAEhB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAoB/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAKjC"}
|