@mentra/engine 0.1.0-dev.0 → 0.1.0-dev.1
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 +42 -1
- package/build/engine.d.ts +11 -3
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +7 -2
- 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/gallery.js +1 -1
- package/build/facades/gallery.js.map +1 -1
- package/build/facades/glasses.d.ts +1 -0
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +19 -4
- 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 +11 -2
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +19 -4
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +4 -0
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +10 -8
- 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/index.d.ts +6 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -2
- package/build/index.js.map +1 -1
- package/build/internal.d.ts +3 -2
- package/build/internal.d.ts.map +1 -1
- package/build/internal.js +2 -1
- package/build/internal.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 +33 -57
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +193 -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 +94 -14
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +574 -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 +38 -3
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +142 -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.js +2 -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 +22 -11
- 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 +15 -3
- 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/otaManifestUrl.d.ts +2 -0
- package/build/services/otaManifestUrl.d.ts.map +1 -0
- package/build/services/{asgOtaVersionUrl.js → otaManifestUrl.js} +15 -5
- 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 +1 -0
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +1 -0
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +14 -0
- package/build/types/hardware.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 +25 -15
- package/src/assets/silence.wav +0 -0
- package/src/engine.ts +7 -2
- package/src/facades/dev.ts +17 -12
- package/src/facades/gallery.ts +1 -1
- package/src/facades/glasses.ts +17 -4
- package/src/facades/glassesSettings.ts +5 -0
- package/src/facades/miniapps.ts +7 -0
- package/src/facades/ota.ts +19 -4
- package/src/facades/pairing.ts +11 -7
- package/src/facades/permissions.ts +14 -0
- package/src/facades/phoneNotifications.ts +4 -13
- package/src/index.ts +26 -2
- package/src/internal.ts +3 -1
- 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 +224 -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 +645 -143
- package/src/services/OtaService.ts +11 -5
- package/src/services/OtaUpdateCheckService.ts +180 -20
- 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 +2 -2
- package/src/services/manifestActions.ts +30 -0
- package/src/services/otaDisplayState.ts +57 -16
- package/src/services/otaInstallPolicy.ts +29 -3
- package/src/services/{asgOtaVersionUrl.ts → otaManifestUrl.ts} +16 -4
- 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 +2 -1
- package/src/types/hardware.ts +17 -0
- 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/services/asgOtaVersionUrl.d.ts +0 -2
- package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
- package/build/services/asgOtaVersionUrl.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnosticContext.js","sourceRoot":"","sources":["../../src/utils/diagnosticContext.ts"],"names":[],"mappings":"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","sourcesContent":["import NetInfo from \"@react-native-community/netinfo\"\nimport Constants from \"expo-constants\"\nimport * as Location from \"expo-location\"\nimport {Platform} from \"react-native\"\nimport type {ReportContext} from \"@mentra/cloud-client\"\n\nimport {useAppStatusStore} from \"../stores/apps\"\nimport {useConnectionStore} from \"../stores/connection\"\nimport {useCoreStore} from \"../stores/core\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {SETTINGS, useSettingsStore} from \"../stores/settings\"\n\nconst SENSITIVE_SETTINGS_KEYS = [\"core_token\", \"auth_token\", \"auth_email\"] as const\nconst SENSITIVE_GLASSES_KEYS = [\"hotspotPassword\"] as const\n\n/**\n * The glasses store keeps hotspot credentials NESTED (`hotspot: {state, ssid,\n * password, localIp}`), not just on the legacy top-level `hotspotPassword` key —\n * strip the password before the state is attached to a report.\n */\nfunction redactNestedCredentials(glasses: Record<string, unknown>): Record<string, unknown> {\n const hotspot = glasses.hotspot\n if (hotspot && typeof hotspot === \"object\" && \"password\" in hotspot) {\n const {password: _password, ...rest} = hotspot as Record<string, unknown>\n return {...glasses, hotspot: {...rest, password: \"[REDACTED]\"}}\n }\n return glasses\n}\n\nexport async function collectDiagnosticContext(extra?: Partial<ReportContext>): Promise<ReportContext> {\n const appletState = useAppStatusStore.getState()\n const settingsState = useSettingsStore.getState()\n const {setCoreInfo: _setCoreInfo, reset: _resetBluetooth, ...coreState} = useCoreStore.getState()\n const {\n setStatus: _setConnectionStatus,\n setUrl: _setConnectionUrl,\n setError: _setConnectionError,\n incrementReconnectAttempts: _incrementReconnectAttempts,\n resetReconnectAttempts: _resetReconnectAttempts,\n reset: _resetConnection,\n ...connectionState\n } = useConnectionStore.getState()\n const {\n setGlassesInfo: _setGlassesInfo,\n setBatteryInfo: _setBatteryInfo,\n setWifiInfo: _setWifiInfo,\n setHotspotInfo: _setHotspotInfo,\n setOtaUpdateAvailable: _setOtaUpdateAvailable,\n setOtaProgress: _setOtaProgress,\n setOtaInProgress: _setOtaInProgress,\n setMtkUpdatedThisSession: _setMtkUpdatedThisSession,\n clearOtaState: _clearOtaState,\n reset: _resetGlasses,\n ...glassesState\n } = useGlassesStore.getState()\n\n const filteredGlasses = redactNestedCredentials(\n Object.fromEntries(\n Object.entries(glassesState).filter(\n ([key]) => !SENSITIVE_GLASSES_KEYS.includes(key as (typeof SENSITIVE_GLASSES_KEYS)[number]),\n ),\n ),\n )\n const filteredSettings = Object.fromEntries(\n Object.entries(settingsState.settings || {}).filter(\n ([key]) => !SENSITIVE_SETTINGS_KEYS.includes(key as (typeof SENSITIVE_SETTINGS_KEYS)[number]),\n ),\n )\n\n let networkInfo: Record<string, unknown> = {type: \"unknown\", isConnected: false, isInternetReachable: false}\n try {\n const netState = await NetInfo.fetch()\n networkInfo = {\n type: netState.type,\n isConnected: netState.isConnected ?? false,\n isInternetReachable: netState.isInternetReachable ?? false,\n }\n } catch (error) {\n console.log(\"diagnosticContext: failed to get network info:\", error)\n }\n\n let locationInfo: Record<string, unknown> | undefined\n try {\n const {status} = await Location.getForegroundPermissionsAsync()\n if (status === \"granted\") {\n const location = await Location.getLastKnownPositionAsync()\n if (location) {\n locationInfo = {\n latitude: Number(location.coords.latitude.toFixed(4)),\n longitude: Number(location.coords.longitude.toFixed(4)),\n }\n try {\n const [place] = await Location.reverseGeocodeAsync({\n latitude: location.coords.latitude,\n longitude: location.coords.longitude,\n })\n if (place) {\n locationInfo.place = [place.city, place.region, place.country].filter(Boolean).join(\", \")\n }\n } catch (error) {\n console.log(\"diagnosticContext: failed to reverse geocode:\", error)\n }\n }\n }\n } catch (error) {\n console.log(\"diagnosticContext: failed to get location:\", error)\n }\n\n const offlineMode = await useSettingsStore.getState().getSetting(SETTINGS.offline_mode.key)\n const defaultWearable = await useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n const apps = appletState.apps.map((app) => ({\n packageName: app.packageName,\n name: app.name,\n running: app.running,\n loading: app.loading,\n healthy: app.healthy,\n hidden: app.hidden,\n type: app.type,\n offline: app.offline,\n local: app.local,\n }))\n\n return {\n app: {\n appVersion: process.env.EXPO_PUBLIC_MENTRAOS_VERSION || \"version\",\n buildCommit: process.env.EXPO_PUBLIC_BUILD_COMMIT || \"commit\",\n buildBranch: process.env.EXPO_PUBLIC_BUILD_BRANCH || \"branch\",\n buildTime: process.env.EXPO_PUBLIC_BUILD_TIME || \"time\",\n buildUser: process.env.EXPO_PUBLIC_BUILD_USER || \"user\",\n },\n phone: {\n deviceName: Constants.deviceName || \"deviceName\",\n osVersion: `${Platform.OS} ${Platform.Version}`,\n platform: Platform.OS,\n network: networkInfo,\n location: locationInfo,\n },\n glasses: filteredGlasses,\n runtime: {\n core: coreState,\n connection: connectionState,\n },\n apps: {\n apps,\n installed: apps.map((app) => app.packageName),\n running: apps.filter((app) => app.running).map((app) => app.packageName),\n },\n settings: {\n ...filteredSettings,\n offlineMode: !!offlineMode,\n defaultWearable,\n },\n ...extra,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"diagnosticContext.js","sourceRoot":"","sources":["../../src/utils/diagnosticContext.ts"],"names":[],"mappings":"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","sourcesContent":["import NetInfo from \"@react-native-community/netinfo\"\nimport Constants from \"expo-constants\"\nimport * as Location from \"expo-location\"\nimport {Platform} from \"react-native\"\nimport type {ReportContext} from \"@mentra/cloud-client\"\n\nimport appRegistry from \"../services/AppRegistry\"\nimport localMiniappRuntime from \"../services/LocalMiniappRuntime\"\nimport {getLastOpenTime, useAppStatusStore} from \"../stores/apps\"\nimport {useConnectionStore} from \"../stores/connection\"\nimport {useCoreStore} from \"../stores/core\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {SETTINGS, useSettingsStore} from \"../stores/settings\"\nimport {buildMiniappDiagnosticContext} from \"./miniappDiagnostics\"\n\nconst SENSITIVE_SETTINGS_KEYS = [\"core_token\", \"auth_token\", \"auth_email\"] as const\nconst SENSITIVE_GLASSES_KEYS = [\"hotspotPassword\"] as const\n\n/**\n * The glasses store keeps hotspot credentials NESTED (`hotspot: {state, ssid,\n * password, localIp}`), not just on the legacy top-level `hotspotPassword` key —\n * strip the password before the state is attached to a report.\n */\nfunction redactNestedCredentials(glasses: Record<string, unknown>): Record<string, unknown> {\n const hotspot = glasses.hotspot\n if (hotspot && typeof hotspot === \"object\" && \"password\" in hotspot) {\n const {password: _password, ...rest} = hotspot as Record<string, unknown>\n return {...glasses, hotspot: {...rest, password: \"[REDACTED]\"}}\n }\n return glasses\n}\n\nexport async function collectDiagnosticContext(extra?: Partial<ReportContext>): Promise<ReportContext> {\n const appletState = useAppStatusStore.getState()\n const settingsState = useSettingsStore.getState()\n const {setCoreInfo: _setCoreInfo, reset: _resetBluetooth, ...coreState} = useCoreStore.getState()\n const {\n setStatus: _setConnectionStatus,\n setUrl: _setConnectionUrl,\n setError: _setConnectionError,\n incrementReconnectAttempts: _incrementReconnectAttempts,\n resetReconnectAttempts: _resetReconnectAttempts,\n reset: _resetConnection,\n ...connectionState\n } = useConnectionStore.getState()\n const {\n setGlassesInfo: _setGlassesInfo,\n setBatteryInfo: _setBatteryInfo,\n setWifiInfo: _setWifiInfo,\n setHotspotInfo: _setHotspotInfo,\n setOtaUpdateAvailable: _setOtaUpdateAvailable,\n setOtaProgress: _setOtaProgress,\n setOtaInProgress: _setOtaInProgress,\n setMtkUpdatedThisSession: _setMtkUpdatedThisSession,\n clearOtaState: _clearOtaState,\n reset: _resetGlasses,\n ...glassesState\n } = useGlassesStore.getState()\n\n const filteredGlasses = redactNestedCredentials(\n Object.fromEntries(\n Object.entries(glassesState).filter(\n ([key]) => !SENSITIVE_GLASSES_KEYS.includes(key as (typeof SENSITIVE_GLASSES_KEYS)[number]),\n ),\n ),\n )\n const filteredSettings = Object.fromEntries(\n Object.entries(settingsState.settings || {}).filter(\n ([key]) => !SENSITIVE_SETTINGS_KEYS.includes(key as (typeof SENSITIVE_SETTINGS_KEYS)[number]),\n ),\n )\n\n let networkInfo: Record<string, unknown> = {type: \"unknown\", isConnected: false, isInternetReachable: false}\n try {\n const netState = await NetInfo.fetch()\n networkInfo = {\n type: netState.type,\n isConnected: netState.isConnected ?? false,\n isInternetReachable: netState.isInternetReachable ?? false,\n }\n } catch (error) {\n console.log(\"diagnosticContext: failed to get network info:\", error)\n }\n\n let locationInfo: Record<string, unknown> | undefined\n try {\n const {status} = await Location.getForegroundPermissionsAsync()\n if (status === \"granted\") {\n const location = await Location.getLastKnownPositionAsync()\n if (location) {\n locationInfo = {\n latitude: Number(location.coords.latitude.toFixed(4)),\n longitude: Number(location.coords.longitude.toFixed(4)),\n }\n try {\n const [place] = await Location.reverseGeocodeAsync({\n latitude: location.coords.latitude,\n longitude: location.coords.longitude,\n })\n if (place) {\n locationInfo.place = [place.city, place.region, place.country].filter(Boolean).join(\", \")\n }\n } catch (error) {\n console.log(\"diagnosticContext: failed to reverse geocode:\", error)\n }\n }\n }\n } catch (error) {\n console.log(\"diagnosticContext: failed to get location:\", error)\n }\n\n const offlineMode = await useSettingsStore.getState().getSetting(SETTINGS.offline_mode.key)\n const defaultWearable = await useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n const miniappRuntime = localMiniappRuntime.getDiagnosticSnapshot()\n const miniapps = buildMiniappDiagnosticContext({\n apps: appletState.apps,\n foregroundedPackage: appletState.foregroundedPackage,\n runtime: miniappRuntime,\n getLastOpenedAtMs: (app) => getLastOpenTime(app.packageName),\n getManifest: (app) =>\n app.local && app.version ? appRegistry.getMiniappManifest(app.packageName, app.version) : undefined,\n getReleaseIdentity: (app) =>\n app.local && app.version ? appRegistry.getReleaseIdentity(app.packageName, app.version) : undefined,\n })\n\n return {\n app: {\n appVersion: process.env.EXPO_PUBLIC_MENTRAOS_VERSION || \"version\",\n buildCommit: process.env.EXPO_PUBLIC_BUILD_COMMIT || \"commit\",\n buildBranch: process.env.EXPO_PUBLIC_BUILD_BRANCH || \"branch\",\n buildTime: process.env.EXPO_PUBLIC_BUILD_TIME || \"time\",\n buildUser: process.env.EXPO_PUBLIC_BUILD_USER || \"user\",\n },\n phone: {\n deviceName: Constants.deviceName || \"deviceName\",\n osVersion: `${Platform.OS} ${Platform.Version}`,\n platform: Platform.OS,\n network: networkInfo,\n location: locationInfo,\n },\n glasses: filteredGlasses,\n runtime: {\n core: coreState,\n connection: connectionState,\n miniapps: miniappRuntime,\n },\n apps: miniapps,\n settings: {\n ...filteredSettings,\n offlineMode: !!offlineMode,\n defaultWearable,\n },\n ...extra,\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hardware.d.ts","sourceRoot":"","sources":["../../../src/utils/hardware/hardware.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"hardware.d.ts","sourceRoot":"","sources":["../../../src/utils/hardware/hardware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAe,mBAAmB,EAA2D,MAAM,aAAa,CAAA;AAEpI;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,OAAO,CAAA;IACrB,eAAe,EAAE,mBAAmB,EAAE,CAAA;IACtC,eAAe,EAAE,mBAAmB,EAAE,CAAA;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAChC;;;;;OAKG;IACH,MAAM,CAAC,kBAAkB,CACvB,oBAAoB,EAAE,mBAAmB,EAAE,EAC3C,YAAY,EAAE,YAAY,GAAG,IAAI,GAChC,mBAAmB;IAkCtB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IA4CrC;;;;OAIG;IACH,MAAM,CAAC,uBAAuB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM;IAkBnE;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,EAAE;CA0BlE"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { simulatedGlasses } from "../../types";
|
|
1
|
+
import { DeviceTypes, HardwareRequirementLevel, HardwareType, simulatedGlasses } from "../../types";
|
|
3
2
|
/**
|
|
4
3
|
* Service for checking hardware compatibility between apps and glasses
|
|
5
4
|
*/
|
|
@@ -59,7 +58,12 @@ export class HardwareCompatibility {
|
|
|
59
58
|
case HardwareType.DISPLAY:
|
|
60
59
|
return capabilities.hasDisplay;
|
|
61
60
|
case HardwareType.MICROPHONE:
|
|
62
|
-
|
|
61
|
+
// MentraOS always provides an audio-input path. When the connected
|
|
62
|
+
// glasses do not have an onboard microphone, the engine falls back to
|
|
63
|
+
// the phone microphone. Keep `capabilities.hasMicrophone` reserved for
|
|
64
|
+
// physical-device/source selection; app compatibility is about whether
|
|
65
|
+
// the requested input is available to the miniapp.
|
|
66
|
+
return true;
|
|
63
67
|
case HardwareType.SPEAKER:
|
|
64
68
|
return capabilities.hasSpeaker;
|
|
65
69
|
case HardwareType.IMU:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hardware.js","sourceRoot":"","sources":["../../../src/utils/hardware/hardware.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"hardware.js","sourceRoot":"","sources":["../../../src/utils/hardware/hardware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,WAAW,EAAuB,wBAAwB,EAAE,YAAY,EAAE,gBAAgB,EAAC,MAAM,aAAa,CAAA;AAYpI;;GAEG;AACH,MAAM,OAAO,qBAAqB;IAChC;;;;;OAKG;IACH,MAAM,CAAC,kBAAkB,CACvB,oBAA2C,EAC3C,YAAiC;QAEjC,MAAM,MAAM,GAAwB;YAClC,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,EAAE;YACnB,eAAe,EAAE,EAAE;YACnB,QAAQ,EAAE,EAAE;SACb,CAAA;QAED,6EAA6E;QAC7E,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,OAAO,MAAM,CAAA;QACf,CAAC;QAED,yDAAyD;QACzD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,YAAY,GAAG,gBAAgB,CAAA;QACjC,CAAC;QAED,kCAAkC;QAClC,KAAK,MAAM,WAAW,IAAI,oBAAoB,EAAE,CAAC;YAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,IAAI,EAAE,YAAa,CAAC,CAAA;YAChF,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,IAAI,WAAW,CAAC,KAAK,KAAK,wBAAwB,CAAC,QAAQ,EAAE,CAAC;oBAC5D,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBACxC,MAAM,CAAC,YAAY,GAAG,KAAK,CAAA;gBAC7B,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,sBAAsB,CAAC,YAA0B,EAAE,YAA0B;QAC1F,IAAI,YAAY,KAAK,YAAY,CAAC,KAAK,EAAE,CAAC;YACxC,IAAI,YAAY,CAAC,SAAS,KAAK,WAAW,CAAC,IAAI,EAAE,CAAC;gBAChD,OAAO,KAAK,CAAA;YACd,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,QAAQ,YAAY,EAAE,CAAC;YACrB,KAAK,YAAY,CAAC,MAAM;gBACtB,OAAO,YAAY,CAAC,SAAS,CAAA;YAE/B,KAAK,YAAY,CAAC,OAAO;gBACvB,OAAO,YAAY,CAAC,UAAU,CAAA;YAEhC,KAAK,YAAY,CAAC,UAAU;gBAC1B,mEAAmE;gBACnE,sEAAsE;gBACtE,uEAAuE;gBACvE,uEAAuE;gBACvE,mDAAmD;gBACnD,OAAO,IAAI,CAAA;YAEb,KAAK,YAAY,CAAC,OAAO;gBACvB,OAAO,YAAY,CAAC,UAAU,CAAA;YAEhC,KAAK,YAAY,CAAC,GAAG;gBACnB,OAAO,YAAY,CAAC,MAAM,CAAA;YAE5B,KAAK,YAAY,CAAC,MAAM;gBACtB,OAAO,YAAY,CAAC,SAAS,CAAA;YAE/B,KAAK,YAAY,CAAC,KAAK;gBACrB,OAAO,YAAY,CAAC,QAAQ,CAAA;YAE9B,KAAK,YAAY,CAAC,IAAI;gBACpB,OAAO,YAAY,CAAC,OAAO,CAAA;YAE7B;gBACE,+CAA+C;gBAC/C,OAAO,KAAK,CAAA;QAChB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,uBAAuB,CAAC,MAA2B;QACxD,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtC,MAAM,gBAAgB,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAC/F,OAAO,4EAA4E,gBAAgB,EAAE,CAAA;YACvG,CAAC;YACD,OAAO,gDAAgD,CAAA;QACzD,CAAC;QAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE/F,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxC,OAAO,uBAAuB,gBAAgB,mDAAmD,CAAA;QACnG,CAAC;aAAM,CAAC;YACN,OAAO,8FAA8F,gBAAgB,EAAE,CAAA;QACzH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAA2B;QACpD,MAAM,QAAQ,GAAa,EAAE,CAAA;QAE7B,qBAAqB;QACrB,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;QAEjC,gCAAgC;QAChC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YACzC,IAAI,OAAO,GAAG,sBAAsB,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAA;YAC5D,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpB,OAAO,IAAI,KAAK,GAAG,CAAC,WAAW,EAAE,CAAA;YACnC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,CAAC;QAED,gCAAgC;QAChC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YACzC,IAAI,OAAO,GAAG,uBAAuB,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAA;YAC7D,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpB,OAAO,IAAI,KAAK,GAAG,CAAC,WAAW,EAAE,CAAA;YACnC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,CAAC;QAED,OAAO,QAAQ,CAAA;IACjB,CAAC;CACF","sourcesContent":["import {Capabilities, DeviceTypes, HardwareRequirement, HardwareRequirementLevel, HardwareType, simulatedGlasses} from \"../../types\"\n\n/**\n * Result of a hardware compatibility check\n */\nexport interface CompatibilityResult {\n isCompatible: boolean\n missingRequired: HardwareRequirement[]\n missingOptional: HardwareRequirement[]\n warnings: string[]\n}\n\n/**\n * Service for checking hardware compatibility between apps and glasses\n */\nexport class HardwareCompatibility {\n /**\n * Check if app is compatible with given device capabilities\n * @param app The app to check\n * @param capabilities The device capabilities (null if no device connected)\n * @returns Detailed compatibility result\n */\n static checkCompatibility(\n hardwareRequirements: HardwareRequirement[],\n capabilities: Capabilities | null,\n ): CompatibilityResult {\n const result: CompatibilityResult = {\n isCompatible: true,\n missingRequired: [],\n missingOptional: [],\n warnings: [],\n }\n\n // If no hardware requirements specified, app is compatible with any hardware\n if (hardwareRequirements.length === 0) {\n return result\n }\n\n // If no capabilities available assume simulated glasses:\n if (!capabilities) {\n capabilities = simulatedGlasses\n }\n\n // Check each hardware requirement\n for (const requirement of hardwareRequirements) {\n const hasHardware = this.checkHardwareAvailable(requirement.type, capabilities!)\n if (!hasHardware) {\n if (requirement.level === HardwareRequirementLevel.REQUIRED) {\n result.missingRequired.push(requirement)\n result.isCompatible = false\n } else {\n result.missingOptional.push(requirement)\n }\n }\n }\n\n return result\n }\n\n /**\n * Check if specific hardware is available in capabilities\n * @param hardwareType The type of hardware to check\n * @param capabilities The device capabilities\n * @returns true if hardware is available\n */\n private static checkHardwareAvailable(hardwareType: HardwareType, capabilities: Capabilities): boolean {\n if (hardwareType === HardwareType.EXIST) {\n if (capabilities.modelName === DeviceTypes.NONE) {\n return false\n }\n return true\n }\n\n switch (hardwareType) {\n case HardwareType.CAMERA:\n return capabilities.hasCamera\n\n case HardwareType.DISPLAY:\n return capabilities.hasDisplay\n\n case HardwareType.MICROPHONE:\n // MentraOS always provides an audio-input path. When the connected\n // glasses do not have an onboard microphone, the engine falls back to\n // the phone microphone. Keep `capabilities.hasMicrophone` reserved for\n // physical-device/source selection; app compatibility is about whether\n // the requested input is available to the miniapp.\n return true\n\n case HardwareType.SPEAKER:\n return capabilities.hasSpeaker\n\n case HardwareType.IMU:\n return capabilities.hasIMU\n\n case HardwareType.BUTTON:\n return capabilities.hasButton\n\n case HardwareType.LIGHT:\n return capabilities.hasLight\n\n case HardwareType.WIFI:\n return capabilities.hasWifi\n\n default:\n // Unknown hardware type - assume not available\n return false\n }\n }\n\n /**\n * Get human-readable compatibility message\n * @param result The compatibility check result\n * @returns User-friendly message about compatibility\n */\n static getCompatibilityMessage(result: CompatibilityResult): string {\n if (result.isCompatible) {\n if (result.missingOptional.length > 0) {\n const optionalHardware = result.missingOptional.map((req) => req.type.toLowerCase()).join(\", \")\n return `This app works with your glasses but has optional features that require: ${optionalHardware}`\n }\n return \"This app is fully compatible with your glasses\"\n }\n\n const requiredHardware = result.missingRequired.map((req) => req.type.toLowerCase()).join(\", \")\n\n if (result.missingRequired.length === 1) {\n return `This app requires a ${requiredHardware} which is not available on your connected glasses`\n } else {\n return `This app requires the following hardware which is not available on your connected glasses: ${requiredHardware}`\n }\n }\n\n /**\n * Get detailed compatibility messages including descriptions\n * @param result The compatibility check result\n * @returns Array of detailed messages\n */\n static getDetailedMessages(result: CompatibilityResult): string[] {\n const messages: string[] = []\n\n // Add warnings first\n messages.push(...result.warnings)\n\n // Add missing required hardware\n for (const req of result.missingRequired) {\n let message = `❌ Missing required ${req.type.toLowerCase()}`\n if (req.description) {\n message += `: ${req.description}`\n }\n messages.push(message)\n }\n\n // Add missing optional hardware\n for (const req of result.missingOptional) {\n let message = `⚠️ Missing optional ${req.type.toLowerCase()}`\n if (req.description) {\n message += `: ${req.description}`\n }\n messages.push(message)\n }\n\n return messages\n }\n}\n"]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ClientApp } from "../types/applet";
|
|
2
|
+
export interface MiniappManifestSnapshot {
|
|
3
|
+
packageName: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
sdkVersion?: string;
|
|
7
|
+
minHostVersion?: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
entry?: {
|
|
10
|
+
background?: string;
|
|
11
|
+
ui?: string;
|
|
12
|
+
};
|
|
13
|
+
permissions: Array<{
|
|
14
|
+
type: string;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
hardwareRequirements: Array<{
|
|
18
|
+
type: string;
|
|
19
|
+
level: string;
|
|
20
|
+
}>;
|
|
21
|
+
actionIds: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface MiniappRuntimeAppSnapshot {
|
|
24
|
+
packageName: string;
|
|
25
|
+
handshakeComplete: boolean;
|
|
26
|
+
subscriptions: string[];
|
|
27
|
+
lastMessageAgeMs: number;
|
|
28
|
+
requestedLocationRate: string | null;
|
|
29
|
+
hasActiveSpeakerStream: boolean;
|
|
30
|
+
manifest?: MiniappManifestSnapshot;
|
|
31
|
+
}
|
|
32
|
+
export interface MiniappRuntimeDiagnosticSnapshot {
|
|
33
|
+
connectedApps: MiniappRuntimeAppSnapshot[];
|
|
34
|
+
subscriptionsByStream: Record<string, string[]>;
|
|
35
|
+
resources: {
|
|
36
|
+
display: Record<string, unknown>;
|
|
37
|
+
camera: Record<string, unknown>;
|
|
38
|
+
video: Record<string, unknown>;
|
|
39
|
+
stream: Record<string, unknown>;
|
|
40
|
+
cameraFov: Record<string, unknown>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
type ManifestFallback = {
|
|
44
|
+
packageName: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
version?: string;
|
|
47
|
+
type?: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Keep the routing/build fields from miniapp.json while excluding arbitrary
|
|
51
|
+
* free-form manifest content from reports. Descriptions, URLs, and unknown
|
|
52
|
+
* extension fields are intentionally omitted.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildMiniappManifestSnapshot(raw: unknown, fallback: ManifestFallback): MiniappManifestSnapshot;
|
|
55
|
+
export declare function buildMiniappDiagnosticContext(input: {
|
|
56
|
+
apps: ClientApp[];
|
|
57
|
+
foregroundedPackage: string | null;
|
|
58
|
+
runtime: MiniappRuntimeDiagnosticSnapshot;
|
|
59
|
+
getLastOpenedAtMs: (app: ClientApp) => number;
|
|
60
|
+
getManifest: (app: ClientApp) => unknown;
|
|
61
|
+
getReleaseIdentity: (app: ClientApp) => unknown;
|
|
62
|
+
}): Record<string, unknown>;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=miniappDiagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"miniappDiagnostics.d.ts","sourceRoot":"","sources":["../../src/utils/miniappDiagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAA;AAM9C,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,EAAE,CAAC,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,WAAW,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAC,CAAC,CAAA;IACtD,oBAAoB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAA;IAC1D,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,sBAAsB,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,EAAE,uBAAuB,CAAA;CACnC;AAED,MAAM,WAAW,gCAAgC;IAC/C,aAAa,EAAE,yBAAyB,EAAE,CAAA;IAC1C,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC/C,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACnC,CAAA;CACF;AAED,KAAK,gBAAgB,GAAG;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAsDD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,GAAG,uBAAuB,CAsB9G;AAoBD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,IAAI,EAAE,SAAS,EAAE,CAAA;IACjB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,gCAAgC,CAAA;IACzC,iBAAiB,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,CAAA;IAC7C,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAA;IACxC,kBAAkB,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAA;CAChD,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoE1B"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
const MAX_DIAGNOSTIC_STRING_LENGTH = 512;
|
|
2
|
+
const MAX_DIAGNOSTIC_LIST_ITEMS = 100;
|
|
3
|
+
const MAX_RECENT_MINIAPPS = 20;
|
|
4
|
+
function boundedString(value) {
|
|
5
|
+
if (typeof value !== "string")
|
|
6
|
+
return undefined;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
if (!trimmed)
|
|
9
|
+
return undefined;
|
|
10
|
+
return trimmed.slice(0, MAX_DIAGNOSTIC_STRING_LENGTH);
|
|
11
|
+
}
|
|
12
|
+
function recordValue(value) {
|
|
13
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
14
|
+
}
|
|
15
|
+
function diagnosticPermissions(value) {
|
|
16
|
+
if (!Array.isArray(value))
|
|
17
|
+
return [];
|
|
18
|
+
const permissions = [];
|
|
19
|
+
for (const raw of value) {
|
|
20
|
+
if (typeof raw === "string") {
|
|
21
|
+
const type = boundedString(raw);
|
|
22
|
+
if (type)
|
|
23
|
+
permissions.push({ type });
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const permission = recordValue(raw);
|
|
27
|
+
const type = boundedString(permission?.type);
|
|
28
|
+
if (!type)
|
|
29
|
+
continue;
|
|
30
|
+
permissions.push({
|
|
31
|
+
type,
|
|
32
|
+
...(typeof permission?.required === "boolean" ? { required: permission.required } : {}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return permissions.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS);
|
|
36
|
+
}
|
|
37
|
+
function diagnosticHardwareRequirements(value) {
|
|
38
|
+
if (!Array.isArray(value))
|
|
39
|
+
return [];
|
|
40
|
+
const requirements = [];
|
|
41
|
+
for (const raw of value) {
|
|
42
|
+
const requirement = recordValue(raw);
|
|
43
|
+
const type = boundedString(requirement?.type);
|
|
44
|
+
const level = boundedString(requirement?.level);
|
|
45
|
+
if (type && level)
|
|
46
|
+
requirements.push({ type, level });
|
|
47
|
+
}
|
|
48
|
+
return requirements.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS);
|
|
49
|
+
}
|
|
50
|
+
function diagnosticActionIds(value) {
|
|
51
|
+
if (!Array.isArray(value))
|
|
52
|
+
return [];
|
|
53
|
+
return value
|
|
54
|
+
.map((raw) => boundedString(typeof raw === "string" ? raw : recordValue(raw)?.id))
|
|
55
|
+
.filter((id) => id !== undefined)
|
|
56
|
+
.sort()
|
|
57
|
+
.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Keep the routing/build fields from miniapp.json while excluding arbitrary
|
|
61
|
+
* free-form manifest content from reports. Descriptions, URLs, and unknown
|
|
62
|
+
* extension fields are intentionally omitted.
|
|
63
|
+
*/
|
|
64
|
+
export function buildMiniappManifestSnapshot(raw, fallback) {
|
|
65
|
+
const manifest = recordValue(raw);
|
|
66
|
+
const entry = recordValue(manifest?.entry);
|
|
67
|
+
const packageName = boundedString(manifest?.packageName) ?? boundedString(fallback.packageName) ?? "unknown";
|
|
68
|
+
const name = boundedString(manifest?.name) ?? boundedString(fallback.name);
|
|
69
|
+
const version = boundedString(manifest?.version) ?? boundedString(fallback.version);
|
|
70
|
+
const type = boundedString(manifest?.type) ?? boundedString(fallback.type);
|
|
71
|
+
const background = boundedString(entry?.background);
|
|
72
|
+
const ui = boundedString(entry?.ui);
|
|
73
|
+
return {
|
|
74
|
+
packageName,
|
|
75
|
+
...(name ? { name } : {}),
|
|
76
|
+
...(version ? { version } : {}),
|
|
77
|
+
...(boundedString(manifest?.sdkVersion) ? { sdkVersion: boundedString(manifest?.sdkVersion) } : {}),
|
|
78
|
+
...(boundedString(manifest?.minHostVersion) ? { minHostVersion: boundedString(manifest?.minHostVersion) } : {}),
|
|
79
|
+
...(type ? { type } : {}),
|
|
80
|
+
...(background || ui ? { entry: { ...(background ? { background } : {}), ...(ui ? { ui } : {}) } } : {}),
|
|
81
|
+
permissions: diagnosticPermissions(manifest?.permissions),
|
|
82
|
+
hardwareRequirements: diagnosticHardwareRequirements(manifest?.hardwareRequirements),
|
|
83
|
+
actionIds: diagnosticActionIds(manifest?.actions ?? manifest?.actionIds),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function executionMode(app) {
|
|
87
|
+
if (app.offline)
|
|
88
|
+
return "built_in";
|
|
89
|
+
if (app.isMiniappDev && app.devUrl && !app.version)
|
|
90
|
+
return "dev_server";
|
|
91
|
+
if (app.isMiniappDev)
|
|
92
|
+
return "dev_snapshot";
|
|
93
|
+
return "installed_bundle";
|
|
94
|
+
}
|
|
95
|
+
function safeReleaseIdentity(value) {
|
|
96
|
+
const identity = recordValue(value);
|
|
97
|
+
if (!identity)
|
|
98
|
+
return undefined;
|
|
99
|
+
const out = {};
|
|
100
|
+
for (const key of ["source", "releaseId", "bundleSha256", "channel"]) {
|
|
101
|
+
const field = boundedString(identity[key]);
|
|
102
|
+
if (field)
|
|
103
|
+
out[key] = field;
|
|
104
|
+
}
|
|
105
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
106
|
+
}
|
|
107
|
+
export function buildMiniappDiagnosticContext(input) {
|
|
108
|
+
const runtimeByPackage = new Map(input.runtime.connectedApps.map((app) => [app.packageName, app]));
|
|
109
|
+
const appSnapshots = input.apps.map((app) => {
|
|
110
|
+
const lastOpenedAtMs = input.getLastOpenedAtMs(app);
|
|
111
|
+
const packageName = boundedString(app.packageName) ?? "unknown";
|
|
112
|
+
return {
|
|
113
|
+
packageName,
|
|
114
|
+
name: boundedString(app.name) ?? packageName,
|
|
115
|
+
version: boundedString(app.version) ?? null,
|
|
116
|
+
executionMode: executionMode(app),
|
|
117
|
+
running: app.running,
|
|
118
|
+
foregrounded: app.packageName === input.foregroundedPackage,
|
|
119
|
+
loading: app.loading,
|
|
120
|
+
healthy: app.healthy,
|
|
121
|
+
hidden: app.hidden,
|
|
122
|
+
type: app.type,
|
|
123
|
+
offline: app.offline,
|
|
124
|
+
local: app.local,
|
|
125
|
+
lastOpenedAtMs: Number.isFinite(lastOpenedAtMs) ? lastOpenedAtMs : 0,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
const recentlyInteracted = [...appSnapshots]
|
|
129
|
+
.filter((app) => app.lastOpenedAtMs > 0)
|
|
130
|
+
.sort((a, b) => b.lastOpenedAtMs - a.lastOpenedAtMs)
|
|
131
|
+
.slice(0, MAX_RECENT_MINIAPPS)
|
|
132
|
+
.map((app) => ({ packageName: app.packageName, lastOpenedAtMs: app.lastOpenedAtMs }));
|
|
133
|
+
const runningMiniapps = input.apps
|
|
134
|
+
.filter((app) => app.running)
|
|
135
|
+
.map((app) => {
|
|
136
|
+
const runtime = runtimeByPackage.get(app.packageName);
|
|
137
|
+
const releaseIdentity = safeReleaseIdentity(input.getReleaseIdentity(app));
|
|
138
|
+
const packageName = boundedString(app.packageName) ?? "unknown";
|
|
139
|
+
const manifest = buildMiniappManifestSnapshot(input.getManifest(app) ?? runtime?.manifest, {
|
|
140
|
+
packageName,
|
|
141
|
+
name: app.name,
|
|
142
|
+
version: app.version,
|
|
143
|
+
type: app.type,
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
packageName,
|
|
147
|
+
version: boundedString(app.version) ?? manifest.version ?? null,
|
|
148
|
+
executionMode: executionMode(app),
|
|
149
|
+
foregrounded: app.packageName === input.foregroundedPackage,
|
|
150
|
+
manifest,
|
|
151
|
+
...(releaseIdentity ? { releaseIdentity } : {}),
|
|
152
|
+
runtime: runtime
|
|
153
|
+
? {
|
|
154
|
+
handshakeComplete: runtime.handshakeComplete,
|
|
155
|
+
subscriptions: runtime.subscriptions,
|
|
156
|
+
lastMessageAgeMs: runtime.lastMessageAgeMs,
|
|
157
|
+
requestedLocationRate: runtime.requestedLocationRate,
|
|
158
|
+
hasActiveSpeakerStream: runtime.hasActiveSpeakerStream,
|
|
159
|
+
}
|
|
160
|
+
: null,
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
apps: appSnapshots,
|
|
165
|
+
installed: appSnapshots.map((app) => app.packageName),
|
|
166
|
+
running: runningMiniapps.map((app) => app.packageName),
|
|
167
|
+
foregroundedPackage: boundedString(input.foregroundedPackage) ?? null,
|
|
168
|
+
mostRecentlyInteractedPackage: recentlyInteracted[0]?.packageName ?? null,
|
|
169
|
+
recentlyInteracted,
|
|
170
|
+
runningMiniapps,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=miniappDiagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"miniappDiagnostics.js","sourceRoot":"","sources":["../../src/utils/miniappDiagnostics.ts"],"names":[],"mappings":"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","sourcesContent":["import type {ClientApp} from \"../types/applet\"\n\nconst MAX_DIAGNOSTIC_STRING_LENGTH = 512\nconst MAX_DIAGNOSTIC_LIST_ITEMS = 100\nconst MAX_RECENT_MINIAPPS = 20\n\nexport interface MiniappManifestSnapshot {\n packageName: string\n name?: string\n version?: string\n sdkVersion?: string\n minHostVersion?: string\n type?: string\n entry?: {\n background?: string\n ui?: string\n }\n permissions: Array<{type: string; required?: boolean}>\n hardwareRequirements: Array<{type: string; level: string}>\n actionIds: string[]\n}\n\nexport interface MiniappRuntimeAppSnapshot {\n packageName: string\n handshakeComplete: boolean\n subscriptions: string[]\n lastMessageAgeMs: number\n requestedLocationRate: string | null\n hasActiveSpeakerStream: boolean\n manifest?: MiniappManifestSnapshot\n}\n\nexport interface MiniappRuntimeDiagnosticSnapshot {\n connectedApps: MiniappRuntimeAppSnapshot[]\n subscriptionsByStream: Record<string, string[]>\n resources: {\n display: Record<string, unknown>\n camera: Record<string, unknown>\n video: Record<string, unknown>\n stream: Record<string, unknown>\n cameraFov: Record<string, unknown>\n }\n}\n\ntype ManifestFallback = {\n packageName: string\n name?: string\n version?: string\n type?: string\n}\n\nfunction boundedString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined\n const trimmed = value.trim()\n if (!trimmed) return undefined\n return trimmed.slice(0, MAX_DIAGNOSTIC_STRING_LENGTH)\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : null\n}\n\nfunction diagnosticPermissions(value: unknown): Array<{type: string; required?: boolean}> {\n if (!Array.isArray(value)) return []\n const permissions: Array<{type: string; required?: boolean}> = []\n for (const raw of value) {\n if (typeof raw === \"string\") {\n const type = boundedString(raw)\n if (type) permissions.push({type})\n continue\n }\n const permission = recordValue(raw)\n const type = boundedString(permission?.type)\n if (!type) continue\n permissions.push({\n type,\n ...(typeof permission?.required === \"boolean\" ? {required: permission.required} : {}),\n })\n }\n return permissions.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)\n}\n\nfunction diagnosticHardwareRequirements(value: unknown): Array<{type: string; level: string}> {\n if (!Array.isArray(value)) return []\n const requirements: Array<{type: string; level: string}> = []\n for (const raw of value) {\n const requirement = recordValue(raw)\n const type = boundedString(requirement?.type)\n const level = boundedString(requirement?.level)\n if (type && level) requirements.push({type, level})\n }\n return requirements.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)\n}\n\nfunction diagnosticActionIds(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value\n .map((raw) => boundedString(typeof raw === \"string\" ? raw : recordValue(raw)?.id))\n .filter((id): id is string => id !== undefined)\n .sort()\n .slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)\n}\n\n/**\n * Keep the routing/build fields from miniapp.json while excluding arbitrary\n * free-form manifest content from reports. Descriptions, URLs, and unknown\n * extension fields are intentionally omitted.\n */\nexport function buildMiniappManifestSnapshot(raw: unknown, fallback: ManifestFallback): MiniappManifestSnapshot {\n const manifest = recordValue(raw)\n const entry = recordValue(manifest?.entry)\n const packageName = boundedString(manifest?.packageName) ?? boundedString(fallback.packageName) ?? \"unknown\"\n const name = boundedString(manifest?.name) ?? boundedString(fallback.name)\n const version = boundedString(manifest?.version) ?? boundedString(fallback.version)\n const type = boundedString(manifest?.type) ?? boundedString(fallback.type)\n const background = boundedString(entry?.background)\n const ui = boundedString(entry?.ui)\n\n return {\n packageName,\n ...(name ? {name} : {}),\n ...(version ? {version} : {}),\n ...(boundedString(manifest?.sdkVersion) ? {sdkVersion: boundedString(manifest?.sdkVersion)} : {}),\n ...(boundedString(manifest?.minHostVersion) ? {minHostVersion: boundedString(manifest?.minHostVersion)} : {}),\n ...(type ? {type} : {}),\n ...(background || ui ? {entry: {...(background ? {background} : {}), ...(ui ? {ui} : {})}} : {}),\n permissions: diagnosticPermissions(manifest?.permissions),\n hardwareRequirements: diagnosticHardwareRequirements(manifest?.hardwareRequirements),\n actionIds: diagnosticActionIds(manifest?.actions ?? manifest?.actionIds),\n }\n}\n\nfunction executionMode(app: ClientApp): \"built_in\" | \"dev_server\" | \"dev_snapshot\" | \"installed_bundle\" {\n if (app.offline) return \"built_in\"\n if (app.isMiniappDev && app.devUrl && !app.version) return \"dev_server\"\n if (app.isMiniappDev) return \"dev_snapshot\"\n return \"installed_bundle\"\n}\n\nfunction safeReleaseIdentity(value: unknown): Record<string, string> | undefined {\n const identity = recordValue(value)\n if (!identity) return undefined\n const out: Record<string, string> = {}\n for (const key of [\"source\", \"releaseId\", \"bundleSha256\", \"channel\"] as const) {\n const field = boundedString(identity[key])\n if (field) out[key] = field\n }\n return Object.keys(out).length > 0 ? out : undefined\n}\n\nexport function buildMiniappDiagnosticContext(input: {\n apps: ClientApp[]\n foregroundedPackage: string | null\n runtime: MiniappRuntimeDiagnosticSnapshot\n getLastOpenedAtMs: (app: ClientApp) => number\n getManifest: (app: ClientApp) => unknown\n getReleaseIdentity: (app: ClientApp) => unknown\n}): Record<string, unknown> {\n const runtimeByPackage = new Map(input.runtime.connectedApps.map((app) => [app.packageName, app]))\n const appSnapshots = input.apps.map((app) => {\n const lastOpenedAtMs = input.getLastOpenedAtMs(app)\n const packageName = boundedString(app.packageName) ?? \"unknown\"\n return {\n packageName,\n name: boundedString(app.name) ?? packageName,\n version: boundedString(app.version) ?? null,\n executionMode: executionMode(app),\n running: app.running,\n foregrounded: app.packageName === input.foregroundedPackage,\n loading: app.loading,\n healthy: app.healthy,\n hidden: app.hidden,\n type: app.type,\n offline: app.offline,\n local: app.local,\n lastOpenedAtMs: Number.isFinite(lastOpenedAtMs) ? lastOpenedAtMs : 0,\n }\n })\n\n const recentlyInteracted = [...appSnapshots]\n .filter((app) => app.lastOpenedAtMs > 0)\n .sort((a, b) => b.lastOpenedAtMs - a.lastOpenedAtMs)\n .slice(0, MAX_RECENT_MINIAPPS)\n .map((app) => ({packageName: app.packageName, lastOpenedAtMs: app.lastOpenedAtMs}))\n\n const runningMiniapps = input.apps\n .filter((app) => app.running)\n .map((app) => {\n const runtime = runtimeByPackage.get(app.packageName)\n const releaseIdentity = safeReleaseIdentity(input.getReleaseIdentity(app))\n const packageName = boundedString(app.packageName) ?? \"unknown\"\n const manifest = buildMiniappManifestSnapshot(input.getManifest(app) ?? runtime?.manifest, {\n packageName,\n name: app.name,\n version: app.version,\n type: app.type,\n })\n return {\n packageName,\n version: boundedString(app.version) ?? manifest.version ?? null,\n executionMode: executionMode(app),\n foregrounded: app.packageName === input.foregroundedPackage,\n manifest,\n ...(releaseIdentity ? {releaseIdentity} : {}),\n runtime: runtime\n ? {\n handshakeComplete: runtime.handshakeComplete,\n subscriptions: runtime.subscriptions,\n lastMessageAgeMs: runtime.lastMessageAgeMs,\n requestedLocationRate: runtime.requestedLocationRate,\n hasActiveSpeakerStream: runtime.hasActiveSpeakerStream,\n }\n : null,\n }\n })\n\n return {\n apps: appSnapshots,\n installed: appSnapshots.map((app) => app.packageName),\n running: runningMiniapps.map((app) => app.packageName),\n foregroundedPackage: boundedString(input.foregroundedPackage) ?? null,\n mostRecentlyInteractedPackage: recentlyInteracted[0]?.packageName ?? null,\n recentlyInteracted,\n runningMiniapps,\n }\n}\n"]}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export interface MediaLibrarySaveReceipt {
|
|
2
|
+
success: boolean;
|
|
3
|
+
platform: "ios" | "android" | "unknown";
|
|
4
|
+
uri?: string;
|
|
5
|
+
identifier?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
1
8
|
/**
|
|
2
9
|
* MediaLibraryPermissions - Handles save-only permissions for camera roll
|
|
3
10
|
*
|
|
@@ -7,6 +14,8 @@
|
|
|
7
14
|
* - Android 9-: Uses WRITE_EXTERNAL_STORAGE (legacy)
|
|
8
15
|
*/
|
|
9
16
|
export declare class MediaLibraryPermissions {
|
|
17
|
+
/** Limited iOS access cannot see historical, unselected assets for duplicate reconciliation. */
|
|
18
|
+
static hasLimitedAccess(): Promise<boolean>;
|
|
10
19
|
/**
|
|
11
20
|
* Check if we have permission to save to the camera roll
|
|
12
21
|
* Note: On Android 10+, this always returns true since no permission is needed
|
|
@@ -30,5 +39,7 @@ export declare class MediaLibraryPermissions {
|
|
|
30
39
|
* @param creationTime - Optional creation/capture time in milliseconds (Unix timestamp)
|
|
31
40
|
*/
|
|
32
41
|
static saveToLibrary(filePath: string, creationTime?: number): Promise<boolean>;
|
|
42
|
+
/** Save and return the durable MediaStore/PhotoKit identifier used as the export receipt. */
|
|
43
|
+
static saveToLibraryWithReceipt(filePath: string, creationTime?: number): Promise<MediaLibrarySaveReceipt>;
|
|
33
44
|
}
|
|
34
45
|
//# sourceMappingURL=MediaLibraryPermissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaLibraryPermissions.d.ts","sourceRoot":"","sources":["../../../src/utils/permissions/MediaLibraryPermissions.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,qBAAa,uBAAuB;IAClC;;;OAGG;WACU,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAyBhD;;;OAGG;WACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAyBlD;;;;;;;;;;;OAWG;WACU,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MediaLibraryPermissions.d.ts","sourceRoot":"","sources":["../../../src/utils/permissions/MediaLibraryPermissions.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAA;IACvC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,qBAAa,uBAAuB;IAClC,gGAAgG;WACnF,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAWjD;;;OAGG;WACU,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAyBhD;;;OAGG;WACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAyBlD;;;;;;;;;;;OAWG;WACU,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrF,6FAA6F;WAChF,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAiDjH"}
|
|
@@ -11,6 +11,19 @@ import { deriveGalleryDisplayName } from "./galleryDisplayName";
|
|
|
11
11
|
* - Android 9-: Uses WRITE_EXTERNAL_STORAGE (legacy)
|
|
12
12
|
*/
|
|
13
13
|
export class MediaLibraryPermissions {
|
|
14
|
+
/** Limited iOS access cannot see historical, unselected assets for duplicate reconciliation. */
|
|
15
|
+
static async hasLimitedAccess() {
|
|
16
|
+
if (Platform.OS !== "ios")
|
|
17
|
+
return false;
|
|
18
|
+
try {
|
|
19
|
+
return (await check(PERMISSIONS.IOS.PHOTO_LIBRARY)) === RESULTS.LIMITED;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error("[MediaLibrary] Error checking limited-library access:", error);
|
|
23
|
+
// Conservatively block legacy reconciliation when the scope cannot be verified.
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
14
27
|
/**
|
|
15
28
|
* Check if we have permission to save to the camera roll
|
|
16
29
|
* Note: On Android 10+, this always returns true since no permission is needed
|
|
@@ -78,6 +91,11 @@ export class MediaLibraryPermissions {
|
|
|
78
91
|
* @param creationTime - Optional creation/capture time in milliseconds (Unix timestamp)
|
|
79
92
|
*/
|
|
80
93
|
static async saveToLibrary(filePath, creationTime) {
|
|
94
|
+
return (await this.saveToLibraryWithReceipt(filePath, creationTime)).success;
|
|
95
|
+
}
|
|
96
|
+
/** Save and return the durable MediaStore/PhotoKit identifier used as the export receipt. */
|
|
97
|
+
static async saveToLibraryWithReceipt(filePath, creationTime) {
|
|
98
|
+
const platform = Platform.OS === "ios" || Platform.OS === "android" ? Platform.OS : "unknown";
|
|
81
99
|
try {
|
|
82
100
|
// On Android 10+, we can save without permission
|
|
83
101
|
// On iOS and older Android, check permission first
|
|
@@ -88,7 +106,7 @@ export class MediaLibraryPermissions {
|
|
|
88
106
|
const granted = await this.requestPermission();
|
|
89
107
|
if (!granted) {
|
|
90
108
|
console.warn("[MediaLibrary] No permission to save to library - photos saved to app storage only");
|
|
91
|
-
return false;
|
|
109
|
+
return { success: false, platform, error: "permission denied" };
|
|
92
110
|
}
|
|
93
111
|
}
|
|
94
112
|
}
|
|
@@ -106,16 +124,21 @@ export class MediaLibraryPermissions {
|
|
|
106
124
|
else {
|
|
107
125
|
console.log(`[MediaLibrary] Saved to camera roll: ${cleanPath}`);
|
|
108
126
|
}
|
|
109
|
-
return
|
|
127
|
+
return {
|
|
128
|
+
success: true,
|
|
129
|
+
platform,
|
|
130
|
+
uri: result.uri,
|
|
131
|
+
identifier: result.identifier,
|
|
132
|
+
};
|
|
110
133
|
}
|
|
111
134
|
else {
|
|
112
135
|
console.error(`[MediaLibrary] Failed to save to library: ${result.error}`);
|
|
113
|
-
return false;
|
|
136
|
+
return { success: false, platform, error: result.error || "native export failed" };
|
|
114
137
|
}
|
|
115
138
|
}
|
|
116
139
|
catch (error) {
|
|
117
140
|
console.error("[MediaLibrary] Error saving to library:", error);
|
|
118
|
-
return false;
|
|
141
|
+
return { success: false, platform, error: error instanceof Error ? error.message : String(error) };
|
|
119
142
|
}
|
|
120
143
|
}
|
|
121
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaLibraryPermissions.js","sourceRoot":"","sources":["../../../src/utils/permissions/MediaLibraryPermissions.ts"],"names":[],"mappings":"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","sourcesContent":["import {Platform} from \"react-native\"\nimport {check, request, PERMISSIONS, RESULTS} from \"react-native-permissions\"\n\nimport CrustModule from \"@mentra/crust\"\n\nimport {deriveGalleryDisplayName} from \"./galleryDisplayName\"\n\n/**\n * MediaLibraryPermissions - Handles save-only permissions for camera roll\n *\n * Platform behavior:\n * - iOS: Uses PHOTO_LIBRARY (read-write) so we can manage the MentraOS album\n * - Android 10+ (API 29+): No permission needed to save your own files to MediaStore\n * - Android 9-: Uses WRITE_EXTERNAL_STORAGE (legacy)\n */\nexport class MediaLibraryPermissions {\n /**\n * Check if we have permission to save to the camera roll\n * Note: On Android 10+, this always returns true since no permission is needed\n */\n static async checkPermission(): Promise<boolean> {\n try {\n if (Platform.OS === \"ios\") {\n const status = await check(PERMISSIONS.IOS.PHOTO_LIBRARY)\n return status === RESULTS.GRANTED || status === RESULTS.LIMITED\n }\n\n if (Platform.OS === \"android\") {\n // Android 10+ (API 29+): No permission needed to save your own files\n if (Platform.Version >= 29) {\n return true\n }\n // Android 9 and below: Check legacy write permission\n const status = await check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE)\n return status === RESULTS.GRANTED\n }\n\n return false\n } catch (error) {\n console.error(\"[MediaLibrary] Error checking permission:\", error)\n // On error, assume we can try (Android 10+ doesn't need permission anyway)\n return Platform.OS === \"android\" && Platform.Version >= 29\n }\n }\n\n /**\n * Request permission to save to the camera roll\n * Note: On Android 10+, this always returns true since no permission is needed\n */\n static async requestPermission(): Promise<boolean> {\n try {\n if (Platform.OS === \"ios\") {\n const status = await request(PERMISSIONS.IOS.PHOTO_LIBRARY)\n return status === RESULTS.GRANTED || status === RESULTS.LIMITED\n }\n\n if (Platform.OS === \"android\") {\n // Android 10+ (API 29+): No permission needed to save your own files\n if (Platform.Version >= 29) {\n return true\n }\n // Android 9 and below: Request legacy write permission\n const status = await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE)\n return status === RESULTS.GRANTED\n }\n\n return false\n } catch (error) {\n console.error(\"[MediaLibrary] Error requesting permission:\", error)\n // On error, assume we can try (Android 10+ doesn't need permission anyway)\n return Platform.OS === \"android\" && Platform.Version >= 29\n }\n }\n\n /**\n * Save a file to the photo library in a glasses-specific location (MentraOS album on iOS;\n * Pictures/MentraOS or Movies/MentraOS on Android 10+).\n * On Android 10+, this works without any permission.\n *\n * IMPORTANT: This method sets the DATE_TAKEN (Android) or creation date (iOS)\n * metadata to the original capture time, so gallery apps show the correct date.\n * Also saves files in chronological order for proper \"date added\" ordering.\n *\n * @param filePath - Path to the file to save\n * @param creationTime - Optional creation/capture time in milliseconds (Unix timestamp)\n */\n static async saveToLibrary(filePath: string, creationTime?: number): Promise<boolean> {\n try {\n // On Android 10+, we can save without permission\n // On iOS and older Android, check permission first\n if (!(Platform.OS === \"android\" && Platform.Version >= 29)) {\n const hasPermission = await this.checkPermission()\n if (!hasPermission) {\n // Try requesting permission one more time\n const granted = await this.requestPermission()\n if (!granted) {\n console.warn(\"[MediaLibrary] No permission to save to library - photos saved to app storage only\")\n return false\n }\n }\n }\n\n // Remove file:// prefix if present\n const cleanPath = filePath.replace(\"file://\", \"\")\n const displayName = deriveGalleryDisplayName(cleanPath)\n\n // Use native module to save with proper DATE_TAKEN / creation date metadata\n // This ensures gallery apps show the correct capture date, not the sync date\n const result = await CrustModule.saveToGalleryWithDate(cleanPath, creationTime, displayName)\n\n if (result.success) {\n if (creationTime) {\n const captureDate = new Date(creationTime)\n console.log(\n `[MediaLibrary] Saved to camera roll with DATE_TAKEN: ${cleanPath} (captured: ${captureDate.toISOString()})`,\n )\n } else {\n console.log(`[MediaLibrary] Saved to camera roll: ${cleanPath}`)\n }\n return true\n } else {\n console.error(`[MediaLibrary] Failed to save to library: ${result.error}`)\n return false\n }\n } catch (error) {\n console.error(\"[MediaLibrary] Error saving to library:\", error)\n return false\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MediaLibraryPermissions.js","sourceRoot":"","sources":["../../../src/utils/permissions/MediaLibraryPermissions.ts"],"names":[],"mappings":"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","sourcesContent":["import {Platform} from \"react-native\"\nimport {check, request, PERMISSIONS, RESULTS} from \"react-native-permissions\"\n\nimport CrustModule from \"@mentra/crust\"\n\nimport {deriveGalleryDisplayName} from \"./galleryDisplayName\"\n\nexport interface MediaLibrarySaveReceipt {\n success: boolean\n platform: \"ios\" | \"android\" | \"unknown\"\n uri?: string\n identifier?: string\n error?: string\n}\n\n/**\n * MediaLibraryPermissions - Handles save-only permissions for camera roll\n *\n * Platform behavior:\n * - iOS: Uses PHOTO_LIBRARY (read-write) so we can manage the MentraOS album\n * - Android 10+ (API 29+): No permission needed to save your own files to MediaStore\n * - Android 9-: Uses WRITE_EXTERNAL_STORAGE (legacy)\n */\nexport class MediaLibraryPermissions {\n /** Limited iOS access cannot see historical, unselected assets for duplicate reconciliation. */\n static async hasLimitedAccess(): Promise<boolean> {\n if (Platform.OS !== \"ios\") return false\n try {\n return (await check(PERMISSIONS.IOS.PHOTO_LIBRARY)) === RESULTS.LIMITED\n } catch (error) {\n console.error(\"[MediaLibrary] Error checking limited-library access:\", error)\n // Conservatively block legacy reconciliation when the scope cannot be verified.\n return true\n }\n }\n\n /**\n * Check if we have permission to save to the camera roll\n * Note: On Android 10+, this always returns true since no permission is needed\n */\n static async checkPermission(): Promise<boolean> {\n try {\n if (Platform.OS === \"ios\") {\n const status = await check(PERMISSIONS.IOS.PHOTO_LIBRARY)\n return status === RESULTS.GRANTED || status === RESULTS.LIMITED\n }\n\n if (Platform.OS === \"android\") {\n // Android 10+ (API 29+): No permission needed to save your own files\n if (Platform.Version >= 29) {\n return true\n }\n // Android 9 and below: Check legacy write permission\n const status = await check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE)\n return status === RESULTS.GRANTED\n }\n\n return false\n } catch (error) {\n console.error(\"[MediaLibrary] Error checking permission:\", error)\n // On error, assume we can try (Android 10+ doesn't need permission anyway)\n return Platform.OS === \"android\" && Platform.Version >= 29\n }\n }\n\n /**\n * Request permission to save to the camera roll\n * Note: On Android 10+, this always returns true since no permission is needed\n */\n static async requestPermission(): Promise<boolean> {\n try {\n if (Platform.OS === \"ios\") {\n const status = await request(PERMISSIONS.IOS.PHOTO_LIBRARY)\n return status === RESULTS.GRANTED || status === RESULTS.LIMITED\n }\n\n if (Platform.OS === \"android\") {\n // Android 10+ (API 29+): No permission needed to save your own files\n if (Platform.Version >= 29) {\n return true\n }\n // Android 9 and below: Request legacy write permission\n const status = await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE)\n return status === RESULTS.GRANTED\n }\n\n return false\n } catch (error) {\n console.error(\"[MediaLibrary] Error requesting permission:\", error)\n // On error, assume we can try (Android 10+ doesn't need permission anyway)\n return Platform.OS === \"android\" && Platform.Version >= 29\n }\n }\n\n /**\n * Save a file to the photo library in a glasses-specific location (MentraOS album on iOS;\n * Pictures/MentraOS or Movies/MentraOS on Android 10+).\n * On Android 10+, this works without any permission.\n *\n * IMPORTANT: This method sets the DATE_TAKEN (Android) or creation date (iOS)\n * metadata to the original capture time, so gallery apps show the correct date.\n * Also saves files in chronological order for proper \"date added\" ordering.\n *\n * @param filePath - Path to the file to save\n * @param creationTime - Optional creation/capture time in milliseconds (Unix timestamp)\n */\n static async saveToLibrary(filePath: string, creationTime?: number): Promise<boolean> {\n return (await this.saveToLibraryWithReceipt(filePath, creationTime)).success\n }\n\n /** Save and return the durable MediaStore/PhotoKit identifier used as the export receipt. */\n static async saveToLibraryWithReceipt(filePath: string, creationTime?: number): Promise<MediaLibrarySaveReceipt> {\n const platform = Platform.OS === \"ios\" || Platform.OS === \"android\" ? Platform.OS : \"unknown\"\n try {\n // On Android 10+, we can save without permission\n // On iOS and older Android, check permission first\n if (!(Platform.OS === \"android\" && Platform.Version >= 29)) {\n const hasPermission = await this.checkPermission()\n if (!hasPermission) {\n // Try requesting permission one more time\n const granted = await this.requestPermission()\n if (!granted) {\n console.warn(\"[MediaLibrary] No permission to save to library - photos saved to app storage only\")\n return {success: false, platform, error: \"permission denied\"}\n }\n }\n }\n\n // Remove file:// prefix if present\n const cleanPath = filePath.replace(\"file://\", \"\")\n const displayName = deriveGalleryDisplayName(cleanPath)\n\n // Use native module to save with proper DATE_TAKEN / creation date metadata\n // This ensures gallery apps show the correct capture date, not the sync date\n const result = await CrustModule.saveToGalleryWithDate(cleanPath, creationTime, displayName)\n\n if (result.success) {\n if (creationTime) {\n const captureDate = new Date(creationTime)\n console.log(\n `[MediaLibrary] Saved to camera roll with DATE_TAKEN: ${cleanPath} (captured: ${captureDate.toISOString()})`,\n )\n } else {\n console.log(`[MediaLibrary] Saved to camera roll: ${cleanPath}`)\n }\n return {\n success: true,\n platform,\n uri: result.uri,\n identifier: result.identifier,\n }\n } else {\n console.error(`[MediaLibrary] Failed to save to library: ${result.error}`)\n return {success: false, platform, error: result.error || \"native export failed\"}\n }\n } catch (error) {\n console.error(\"[MediaLibrary] Error saving to library:\", error)\n return {success: false, platform, error: error instanceof Error ? error.message : String(error)}\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../../src/utils/timers/timers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../../src/utils/timers/timers.ts"],"names":[],"mappings":"AAwHA,qBAAa,OAAO;IAClB,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAO/D,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAO9C,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAO9D,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAM7C;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAU/G;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAY/G"}
|