@mentra/bluetooth-sdk 3.2.0-dev.168 → 3.2.0-dev.174
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 +32 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +4 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +63 -7
- package/android/src/main/java/com/mentra/bluetoothsdk/GeneratedReleaseMetadata.kt +5 -5
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +5 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +7 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/DashboardContentFormatterTest.kt +22 -0
- package/build/BluetoothSdk.types.d.ts +2 -0
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +1 -0
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/generated/releaseMetadata.js +5 -5
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +5 -1
- package/ios/Source/BluetoothSdkDefaults.swift +1 -1
- package/ios/Source/DeviceManager.swift +155 -87
- package/ios/Source/GeneratedReleaseMetadata.swift +5 -5
- package/ios/Source/MentraBluetoothSDK.swift +5 -0
- package/ios/Source/requests/DisplayRequests.swift +8 -0
- package/ios/Tests/DashboardContentFormatterTests.swift +18 -0
- package/ios/Tests/DashboardRenderingTests.swift +168 -0
- package/package.json +1 -1
- package/scripts/public-dashboard-content-api.test.mjs +74 -0
- package/src/BluetoothSdk.types.ts +2 -0
- package/src/_private/BluetoothSdkModule.ts +1 -0
- package/src/generated/releaseMetadata.ts +5 -5
- package/src/index.ts +1 -0
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import PrivateBluetoothSdkModule from \"./_private/BluetoothSdkModule\"\nimport type {\n BluetoothSdkEventListener,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule,\n PublicBluetoothStatus,\n PublicGlassesStatus,\n VideoRecordingDefaults,\n} from \"./BluetoothSdk.types\"\nimport {getReleaseChangelogs} from \"./changelogs\"\n\nconst PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([\n \"log\",\n \"device_discovered\",\n \"default_device_changed\",\n \"glasses_not_ready\",\n \"button_press\",\n \"touch_event\",\n \"accel_event\",\n \"head_up\",\n \"voice_activity_detection_status\",\n \"speaking_status\",\n \"battery_status\",\n \"local_transcription\",\n \"wifi_status_change\",\n \"wifi_scan_result\",\n \"hotspot_status_change\",\n \"hotspot_error\",\n \"photo_response\",\n \"photo_status\",\n \"camera_status\",\n \"video_recording_status\",\n \"media_success\",\n \"media_error\",\n \"gallery_status\",\n \"compatible_glasses_search_stop\",\n \"swipe_volume_status\",\n \"switch_status\",\n \"rgb_led_control_response\",\n \"settings_ack\",\n \"pair_failure\",\n \"pairing_info\",\n \"entering_pairing_mode\",\n \"owner_replaced\",\n \"audio_pairing_needed\",\n \"audio_connected\",\n \"audio_disconnected\",\n \"mic_pcm\",\n \"mic_lc3\",\n \"mic_health\",\n \"stream_status\",\n \"mtk_update_complete\",\n \"glasses_session_changed\",\n \"ota_start_ack\",\n \"ota_status\",\n \"ar99_ota_status\",\n \"version_info\",\n \"extraction_progress\",\n])\n\nconst addListener: BluetoothSdkPublicModule[\"addListener\"] = (eventName, listener) => {\n if (!PUBLIC_EVENT_NAMES.has(eventName)) {\n throw new Error(`Unsupported BluetoothSdk event \"${eventName}\". Use @mentra/bluetooth-sdk/react for status state.`)\n }\n return PrivateBluetoothSdkModule.addListener(eventName, listener as BluetoothSdkEventListener<BluetoothSdkEventName>)\n}\n\nconst startOtaUpdate: BluetoothSdkPublicModule[\"startOtaUpdate\"] = (otaVersionUrl) => {\n return PrivateBluetoothSdkModule.startOtaUpdate(otaVersionUrl)\n}\n\nconst queryOtaStatus: BluetoothSdkPublicModule[\"queryOtaStatus\"] = () => {\n return PrivateBluetoothSdkModule.sendOtaQueryStatus()\n}\n\nconst bindPublicMethod = <K extends keyof BluetoothSdkPublicModule>(name: K): BluetoothSdkPublicModule[K] => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>)[name]\n if (typeof method === \"function\") {\n return method.bind(PrivateBluetoothSdkModule) as BluetoothSdkPublicModule[K]\n }\n\n return (async () => {\n throw new Error(`BluetoothSdk.${String(name)} is not available in this native build. Rebuild the app.`)\n }) as unknown as BluetoothSdkPublicModule[K]\n}\n\nexport const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({\n addListener,\n getGlassesStatus: bindPublicMethod(\"getGlassesStatus\"),\n getBluetoothStatus: bindPublicMethod(\"getBluetoothStatus\"),\n subscribeGlassesStatus: (listener: (changed: Partial<PublicGlassesStatus>) => void) =>\n PrivateBluetoothSdkModule.onGlassesStatus(listener),\n subscribeBluetoothStatus: (listener: (changed: Partial<PublicBluetoothStatus>) => void) =>\n PrivateBluetoothSdkModule.onBluetoothStatus(listener),\n getDefaultDevice: bindPublicMethod(\"getDefaultDevice\"),\n setDefaultDevice: bindPublicMethod(\"setDefaultDevice\"),\n clearDefaultDevice: bindPublicMethod(\"clearDefaultDevice\"),\n startScan: bindPublicMethod(\"startScan\"),\n stopScan: bindPublicMethod(\"stopScan\"),\n scan: bindPublicMethod(\"scan\") as BluetoothSdkPublicModule[\"scan\"],\n connect: bindPublicMethod(\"connect\"),\n connectDefault: bindPublicMethod(\"connectDefault\"),\n cancelConnectionAttempt: bindPublicMethod(\"cancelConnectionAttempt\"),\n disconnect: bindPublicMethod(\"disconnect\"),\n forget: bindPublicMethod(\"forget\"),\n displayText: bindPublicMethod(\"displayText\"),\n clearDisplay: bindPublicMethod(\"clearDisplay\"),\n showDashboard: bindPublicMethod(\"showDashboard\"),\n setDashboardPosition: bindPublicMethod(\"setDashboardPosition\"),\n setHeadUpAngle: bindPublicMethod(\"setHeadUpAngle\"),\n setImuEnabled: bindPublicMethod(\"setImuEnabled\"),\n setScreenDisabled: bindPublicMethod(\"setScreenDisabled\"),\n ping: bindPublicMethod(\"ping\"),\n requestWifiScan: bindPublicMethod(\"requestWifiScan\"),\n sendWifiCredentials: bindPublicMethod(\"sendWifiCredentials\"),\n forgetWifiNetwork: bindPublicMethod(\"forgetWifiNetwork\"),\n setHotspotState: bindPublicMethod(\"setHotspotState\"),\n setSystemTime: bindPublicMethod(\"setSystemTime\"),\n setWifiAdbState: bindPublicMethod(\"setWifiAdbState\"),\n setGalleryModeEnabled: bindPublicMethod(\"setGalleryModeEnabled\"),\n setVoiceActivityDetectionEnabled: bindPublicMethod(\"setVoiceActivityDetectionEnabled\"),\n setLoudnessGateEnabled: bindPublicMethod(\"setLoudnessGateEnabled\"),\n /**\n * @deprecated Sticky action-button photo presets are deprecated. Prefer per-request\n * `requestPhoto(...)` options (e.g. `mode: \"text\"` for text sensor size/crop, or explicit per-shot\n * fields). Still functional until removed in a future release.\n */\n setPhotoCaptureDefaults: bindPublicMethod(\"setPhotoCaptureDefaults\"),\n setVideoRecordingDefaults: ({width, height, fps}: VideoRecordingDefaults) => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>).setVideoRecordingDefaults\n if (typeof method !== \"function\") {\n return Promise.reject(\n new Error(\"BluetoothSdk.setVideoRecordingDefaults is not available in this native build. Rebuild the app.\"),\n )\n }\n return PrivateBluetoothSdkModule.setVideoRecordingDefaults(width, height, fps)\n },\n setMaxVideoRecordingDuration: bindPublicMethod(\"setMaxVideoRecordingDuration\"),\n setCameraFov: bindPublicMethod(\"setCameraFov\"),\n setLegacyCameraFov: bindPublicMethod(\"setLegacyCameraFov\"),\n setCameraFovOverride: bindPublicMethod(\"setCameraFovOverride\"),\n releaseCameraFovOverride: bindPublicMethod(\"releaseCameraFovOverride\"),\n setCameraTuningConfig: bindPublicMethod(\"setCameraTuningConfig\"),\n queryGalleryStatus: bindPublicMethod(\"queryGalleryStatus\"),\n requestPhoto: bindPublicMethod(\"requestPhoto\"),\n warmUpCamera: bindPublicMethod(\"warmUpCamera\"),\n stopCameraWarmUp: bindPublicMethod(\"stopCameraWarmUp\"),\n startVideoRecording: bindPublicMethod(\"startVideoRecording\"),\n stopVideoRecording: bindPublicMethod(\"stopVideoRecording\"),\n queryVideoRecordingStatus: bindPublicMethod(\"queryVideoRecordingStatus\"),\n startStream: bindPublicMethod(\"startStream\"),\n stopStream: bindPublicMethod(\"stopStream\"),\n setMicState: bindPublicMethod(\"setMicState\"),\n setPreferredMic: bindPublicMethod(\"setPreferredMic\"),\n setOwnAppAudioPlaying: bindPublicMethod(\"setOwnAppAudioPlaying\"),\n getGlassesMediaVolume: bindPublicMethod(\"getGlassesMediaVolume\"),\n setGlassesMediaVolume: bindPublicMethod(\"setGlassesMediaVolume\"),\n rgbLedControl: bindPublicMethod(\"rgbLedControl\"),\n requestVersionInfo: bindPublicMethod(\"requestVersionInfo\"),\n setOtaVersionUrl: bindPublicMethod(\"setOtaVersionUrl\"),\n getOtaVersionUrl: bindPublicMethod(\"getOtaVersionUrl\"),\n checkForOtaUpdate: bindPublicMethod(\"checkForOtaUpdate\"),\n getReleaseChangelogs,\n startOtaUpdate,\n queryOtaStatus,\n startAr99OtaFromFile: bindPublicMethod(\"startAr99OtaFromFile\"),\n cancelAr99Ota: bindPublicMethod(\"cancelAr99Ota\"),\n sendAr99FactoryReset: bindPublicMethod(\"sendAr99FactoryReset\"),\n buildAr99OtaSignature: bindPublicMethod(\"buildAr99OtaSignature\"),\n setSttModelDetails: bindPublicMethod(\"setSttModelDetails\"),\n getSttModelPath: bindPublicMethod(\"getSttModelPath\"),\n checkSttModelAvailable: bindPublicMethod(\"checkSttModelAvailable\"),\n validateSttModel: bindPublicMethod(\"validateSttModel\"),\n extractTarBz2: bindPublicMethod(\"extractTarBz2\"),\n restartTranscriber: bindPublicMethod(\"restartTranscriber\"),\n setTtsModelDetails: bindPublicMethod(\"setTtsModelDetails\"),\n getTtsModelPath: bindPublicMethod(\"getTtsModelPath\"),\n getTtsModelLanguage: bindPublicMethod(\"getTtsModelLanguage\"),\n checkTtsModelAvailable: bindPublicMethod(\"checkTtsModelAvailable\"),\n validateTtsModel: bindPublicMethod(\"validateTtsModel\"),\n generateTtsAudio: bindPublicMethod(\"generateTtsAudio\"),\n})\n\nexport default BluetoothSdk\n\nexport {\n CAMERA_FOV_DEFAULT,\n CAMERA_FOV_MAX,\n CAMERA_FOV_MIN,\n DeviceModels,\n isBusyGlassesConnectionStatus,\n isConnectedGlassesConnectionStatus,\n isConnectedWifiStatus,\n isEnabledHotspotStatus,\n isReadyGlassesConnectionStatus,\n} from \"./BluetoothSdk.types\"\n\nexport type {\n AccelEvent,\n Ar99OtaStatusEvent,\n AudioConnectedEvent,\n AudioDisconnectedEvent,\n AudioPairingNeededEvent,\n BatteryStatusEvent,\n BluetoothSdkEvent,\n BluetoothSdkEventListener,\n BluetoothSdkEventMap,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule as BluetoothSdkModule,\n BluetoothSdkSubscription,\n ButtonPhotoSize,\n PhotoCaptureDefaults,\n ButtonPressEvent,\n CameraFovPreset,\n CameraFovRequest,\n CameraFovResult,\n CameraRoiPosition,\n CompatibleGlassesSearchStopEvent,\n ConnectOptions,\n ConnectedGlassesConnectionStatus,\n ConnectedWifiStatus,\n Device,\n DeviceModel,\n EnabledHotspotStatus,\n GalleryStatusEvent,\n GlassesConnectionStatus,\n GlassesMediaVolumeGetResult,\n GlassesMediaVolumeSetResult,\n GlassesNotReadyEvent,\n HeadUpEvent,\n HotspotErrorEvent,\n HotspotStatus,\n HotspotStatusChangeEvent,\n GlassesSessionChangedEvent,\n KeepAliveAckEvent,\n LocalTranscriptionEvent,\n LogEvent,\n MicLc3Event,\n MicHealthEvent,\n MicMode,\n MicPcmEvent,\n MicPreference,\n OtaStartAckEvent,\n OtaProgress,\n OtaProgressStatus,\n OtaStage,\n OtaStatus,\n OtaStatusEvent,\n OtaQueryResult,\n OtaUpdateInfo,\n ReleaseChangelog,\n MtkUpdateCompleteEvent,\n PairFailureEvent,\n PairingInfoEvent,\n EnteringPairingModeEvent,\n OwnerReplacedEvent,\n PhotoCaptureMetadata,\n PhotoResolvedConfig,\n PhotoCompression,\n PhotoFpsRange,\n PhotoMeteredPreview,\n PhotoMode,\n PublicBluetoothStatus,\n PublicGlassesStatus,\n PhotoTransferMethod,\n PhotoResponseEvent,\n PhotoRequestedCaptureConfig,\n PhotoRequestParams,\n PhotoSize,\n PhotoStatusEvent,\n PhotoStatusState,\n PhotoSuccessResponseEvent,\n RgbLedAction,\n RgbLedColor,\n RgbLedControlResponseEvent,\n RgbLedControlSuccessResponseEvent,\n ScanModelOptions,\n ScanOptions,\n ScanResultsCallback,\n SpeakingStatusEvent,\n SettingsAckEvent,\n SettingsAckSetting,\n SettingsAckSuccessEvent,\n SettingsAckSuccessStatus,\n SettingsAckStatus,\n StreamAudioConfig,\n StreamResolvedConfig,\n StreamStartRequest,\n StreamStatusEvent,\n StreamStatusLifecycleState,\n StreamStatusReconnectState,\n StreamStatusState,\n StreamVideoConfig,\n SwipeVolumeStatusEvent,\n SwitchStatusEvent,\n TouchEvent,\n VideoRecordingDefaults,\n VideoRecordingStartedStatusEvent,\n VideoRecordingStatusEvent,\n VideoRecordingStatusState,\n VideoRecordingStoppedStatusEvent,\n VideoRecordingSuccessStatusEvent,\n VersionInfoEvent,\n VersionInfoResult,\n WifiScanResultEvent,\n VoiceActivityDetectionStatusEvent,\n WifiSearchResult,\n WifiStatus,\n WifiStatusChangeEvent,\n} from \"./BluetoothSdk.types\"\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import PrivateBluetoothSdkModule from \"./_private/BluetoothSdkModule\"\nimport type {\n BluetoothSdkEventListener,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule,\n PublicBluetoothStatus,\n PublicGlassesStatus,\n VideoRecordingDefaults,\n} from \"./BluetoothSdk.types\"\nimport {getReleaseChangelogs} from \"./changelogs\"\n\nconst PUBLIC_EVENT_NAMES = new Set<BluetoothSdkEventName>([\n \"log\",\n \"device_discovered\",\n \"default_device_changed\",\n \"glasses_not_ready\",\n \"button_press\",\n \"touch_event\",\n \"accel_event\",\n \"head_up\",\n \"voice_activity_detection_status\",\n \"speaking_status\",\n \"battery_status\",\n \"local_transcription\",\n \"wifi_status_change\",\n \"wifi_scan_result\",\n \"hotspot_status_change\",\n \"hotspot_error\",\n \"photo_response\",\n \"photo_status\",\n \"camera_status\",\n \"video_recording_status\",\n \"media_success\",\n \"media_error\",\n \"gallery_status\",\n \"compatible_glasses_search_stop\",\n \"swipe_volume_status\",\n \"switch_status\",\n \"rgb_led_control_response\",\n \"settings_ack\",\n \"pair_failure\",\n \"pairing_info\",\n \"entering_pairing_mode\",\n \"owner_replaced\",\n \"audio_pairing_needed\",\n \"audio_connected\",\n \"audio_disconnected\",\n \"mic_pcm\",\n \"mic_lc3\",\n \"mic_health\",\n \"stream_status\",\n \"mtk_update_complete\",\n \"glasses_session_changed\",\n \"ota_start_ack\",\n \"ota_status\",\n \"ar99_ota_status\",\n \"version_info\",\n \"extraction_progress\",\n])\n\nconst addListener: BluetoothSdkPublicModule[\"addListener\"] = (eventName, listener) => {\n if (!PUBLIC_EVENT_NAMES.has(eventName)) {\n throw new Error(`Unsupported BluetoothSdk event \"${eventName}\". Use @mentra/bluetooth-sdk/react for status state.`)\n }\n return PrivateBluetoothSdkModule.addListener(eventName, listener as BluetoothSdkEventListener<BluetoothSdkEventName>)\n}\n\nconst startOtaUpdate: BluetoothSdkPublicModule[\"startOtaUpdate\"] = (otaVersionUrl) => {\n return PrivateBluetoothSdkModule.startOtaUpdate(otaVersionUrl)\n}\n\nconst queryOtaStatus: BluetoothSdkPublicModule[\"queryOtaStatus\"] = () => {\n return PrivateBluetoothSdkModule.sendOtaQueryStatus()\n}\n\nconst bindPublicMethod = <K extends keyof BluetoothSdkPublicModule>(name: K): BluetoothSdkPublicModule[K] => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>)[name]\n if (typeof method === \"function\") {\n return method.bind(PrivateBluetoothSdkModule) as BluetoothSdkPublicModule[K]\n }\n\n return (async () => {\n throw new Error(`BluetoothSdk.${String(name)} is not available in this native build. Rebuild the app.`)\n }) as unknown as BluetoothSdkPublicModule[K]\n}\n\nexport const BluetoothSdk: BluetoothSdkPublicModule = Object.freeze({\n addListener,\n getGlassesStatus: bindPublicMethod(\"getGlassesStatus\"),\n getBluetoothStatus: bindPublicMethod(\"getBluetoothStatus\"),\n subscribeGlassesStatus: (listener: (changed: Partial<PublicGlassesStatus>) => void) =>\n PrivateBluetoothSdkModule.onGlassesStatus(listener),\n subscribeBluetoothStatus: (listener: (changed: Partial<PublicBluetoothStatus>) => void) =>\n PrivateBluetoothSdkModule.onBluetoothStatus(listener),\n getDefaultDevice: bindPublicMethod(\"getDefaultDevice\"),\n setDefaultDevice: bindPublicMethod(\"setDefaultDevice\"),\n clearDefaultDevice: bindPublicMethod(\"clearDefaultDevice\"),\n startScan: bindPublicMethod(\"startScan\"),\n stopScan: bindPublicMethod(\"stopScan\"),\n scan: bindPublicMethod(\"scan\") as BluetoothSdkPublicModule[\"scan\"],\n connect: bindPublicMethod(\"connect\"),\n connectDefault: bindPublicMethod(\"connectDefault\"),\n cancelConnectionAttempt: bindPublicMethod(\"cancelConnectionAttempt\"),\n disconnect: bindPublicMethod(\"disconnect\"),\n forget: bindPublicMethod(\"forget\"),\n displayText: bindPublicMethod(\"displayText\"),\n clearDisplay: bindPublicMethod(\"clearDisplay\"),\n setDashboardContent: bindPublicMethod(\"setDashboardContent\"),\n showDashboard: bindPublicMethod(\"showDashboard\"),\n setDashboardPosition: bindPublicMethod(\"setDashboardPosition\"),\n setHeadUpAngle: bindPublicMethod(\"setHeadUpAngle\"),\n setImuEnabled: bindPublicMethod(\"setImuEnabled\"),\n setScreenDisabled: bindPublicMethod(\"setScreenDisabled\"),\n ping: bindPublicMethod(\"ping\"),\n requestWifiScan: bindPublicMethod(\"requestWifiScan\"),\n sendWifiCredentials: bindPublicMethod(\"sendWifiCredentials\"),\n forgetWifiNetwork: bindPublicMethod(\"forgetWifiNetwork\"),\n setHotspotState: bindPublicMethod(\"setHotspotState\"),\n setSystemTime: bindPublicMethod(\"setSystemTime\"),\n setWifiAdbState: bindPublicMethod(\"setWifiAdbState\"),\n setGalleryModeEnabled: bindPublicMethod(\"setGalleryModeEnabled\"),\n setVoiceActivityDetectionEnabled: bindPublicMethod(\"setVoiceActivityDetectionEnabled\"),\n setLoudnessGateEnabled: bindPublicMethod(\"setLoudnessGateEnabled\"),\n /**\n * @deprecated Sticky action-button photo presets are deprecated. Prefer per-request\n * `requestPhoto(...)` options (e.g. `mode: \"text\"` for text sensor size/crop, or explicit per-shot\n * fields). Still functional until removed in a future release.\n */\n setPhotoCaptureDefaults: bindPublicMethod(\"setPhotoCaptureDefaults\"),\n setVideoRecordingDefaults: ({width, height, fps}: VideoRecordingDefaults) => {\n const method = (PrivateBluetoothSdkModule as unknown as Record<string, unknown>).setVideoRecordingDefaults\n if (typeof method !== \"function\") {\n return Promise.reject(\n new Error(\"BluetoothSdk.setVideoRecordingDefaults is not available in this native build. Rebuild the app.\"),\n )\n }\n return PrivateBluetoothSdkModule.setVideoRecordingDefaults(width, height, fps)\n },\n setMaxVideoRecordingDuration: bindPublicMethod(\"setMaxVideoRecordingDuration\"),\n setCameraFov: bindPublicMethod(\"setCameraFov\"),\n setLegacyCameraFov: bindPublicMethod(\"setLegacyCameraFov\"),\n setCameraFovOverride: bindPublicMethod(\"setCameraFovOverride\"),\n releaseCameraFovOverride: bindPublicMethod(\"releaseCameraFovOverride\"),\n setCameraTuningConfig: bindPublicMethod(\"setCameraTuningConfig\"),\n queryGalleryStatus: bindPublicMethod(\"queryGalleryStatus\"),\n requestPhoto: bindPublicMethod(\"requestPhoto\"),\n warmUpCamera: bindPublicMethod(\"warmUpCamera\"),\n stopCameraWarmUp: bindPublicMethod(\"stopCameraWarmUp\"),\n startVideoRecording: bindPublicMethod(\"startVideoRecording\"),\n stopVideoRecording: bindPublicMethod(\"stopVideoRecording\"),\n queryVideoRecordingStatus: bindPublicMethod(\"queryVideoRecordingStatus\"),\n startStream: bindPublicMethod(\"startStream\"),\n stopStream: bindPublicMethod(\"stopStream\"),\n setMicState: bindPublicMethod(\"setMicState\"),\n setPreferredMic: bindPublicMethod(\"setPreferredMic\"),\n setOwnAppAudioPlaying: bindPublicMethod(\"setOwnAppAudioPlaying\"),\n getGlassesMediaVolume: bindPublicMethod(\"getGlassesMediaVolume\"),\n setGlassesMediaVolume: bindPublicMethod(\"setGlassesMediaVolume\"),\n rgbLedControl: bindPublicMethod(\"rgbLedControl\"),\n requestVersionInfo: bindPublicMethod(\"requestVersionInfo\"),\n setOtaVersionUrl: bindPublicMethod(\"setOtaVersionUrl\"),\n getOtaVersionUrl: bindPublicMethod(\"getOtaVersionUrl\"),\n checkForOtaUpdate: bindPublicMethod(\"checkForOtaUpdate\"),\n getReleaseChangelogs,\n startOtaUpdate,\n queryOtaStatus,\n startAr99OtaFromFile: bindPublicMethod(\"startAr99OtaFromFile\"),\n cancelAr99Ota: bindPublicMethod(\"cancelAr99Ota\"),\n sendAr99FactoryReset: bindPublicMethod(\"sendAr99FactoryReset\"),\n buildAr99OtaSignature: bindPublicMethod(\"buildAr99OtaSignature\"),\n setSttModelDetails: bindPublicMethod(\"setSttModelDetails\"),\n getSttModelPath: bindPublicMethod(\"getSttModelPath\"),\n checkSttModelAvailable: bindPublicMethod(\"checkSttModelAvailable\"),\n validateSttModel: bindPublicMethod(\"validateSttModel\"),\n extractTarBz2: bindPublicMethod(\"extractTarBz2\"),\n restartTranscriber: bindPublicMethod(\"restartTranscriber\"),\n setTtsModelDetails: bindPublicMethod(\"setTtsModelDetails\"),\n getTtsModelPath: bindPublicMethod(\"getTtsModelPath\"),\n getTtsModelLanguage: bindPublicMethod(\"getTtsModelLanguage\"),\n checkTtsModelAvailable: bindPublicMethod(\"checkTtsModelAvailable\"),\n validateTtsModel: bindPublicMethod(\"validateTtsModel\"),\n generateTtsAudio: bindPublicMethod(\"generateTtsAudio\"),\n})\n\nexport default BluetoothSdk\n\nexport {\n CAMERA_FOV_DEFAULT,\n CAMERA_FOV_MAX,\n CAMERA_FOV_MIN,\n DeviceModels,\n isBusyGlassesConnectionStatus,\n isConnectedGlassesConnectionStatus,\n isConnectedWifiStatus,\n isEnabledHotspotStatus,\n isReadyGlassesConnectionStatus,\n} from \"./BluetoothSdk.types\"\n\nexport type {\n AccelEvent,\n Ar99OtaStatusEvent,\n AudioConnectedEvent,\n AudioDisconnectedEvent,\n AudioPairingNeededEvent,\n BatteryStatusEvent,\n BluetoothSdkEvent,\n BluetoothSdkEventListener,\n BluetoothSdkEventMap,\n BluetoothSdkEventName,\n BluetoothSdkPublicModule as BluetoothSdkModule,\n BluetoothSdkSubscription,\n ButtonPhotoSize,\n PhotoCaptureDefaults,\n ButtonPressEvent,\n CameraFovPreset,\n CameraFovRequest,\n CameraFovResult,\n CameraRoiPosition,\n CompatibleGlassesSearchStopEvent,\n ConnectOptions,\n ConnectedGlassesConnectionStatus,\n ConnectedWifiStatus,\n Device,\n DeviceModel,\n EnabledHotspotStatus,\n GalleryStatusEvent,\n GlassesConnectionStatus,\n GlassesMediaVolumeGetResult,\n GlassesMediaVolumeSetResult,\n GlassesNotReadyEvent,\n HeadUpEvent,\n HotspotErrorEvent,\n HotspotStatus,\n HotspotStatusChangeEvent,\n GlassesSessionChangedEvent,\n KeepAliveAckEvent,\n LocalTranscriptionEvent,\n LogEvent,\n MicLc3Event,\n MicHealthEvent,\n MicMode,\n MicPcmEvent,\n MicPreference,\n OtaStartAckEvent,\n OtaProgress,\n OtaProgressStatus,\n OtaStage,\n OtaStatus,\n OtaStatusEvent,\n OtaQueryResult,\n OtaUpdateInfo,\n ReleaseChangelog,\n MtkUpdateCompleteEvent,\n PairFailureEvent,\n PairingInfoEvent,\n EnteringPairingModeEvent,\n OwnerReplacedEvent,\n PhotoCaptureMetadata,\n PhotoResolvedConfig,\n PhotoCompression,\n PhotoFpsRange,\n PhotoMeteredPreview,\n PhotoMode,\n PublicBluetoothStatus,\n PublicGlassesStatus,\n PhotoTransferMethod,\n PhotoResponseEvent,\n PhotoRequestedCaptureConfig,\n PhotoRequestParams,\n PhotoSize,\n PhotoStatusEvent,\n PhotoStatusState,\n PhotoSuccessResponseEvent,\n RgbLedAction,\n RgbLedColor,\n RgbLedControlResponseEvent,\n RgbLedControlSuccessResponseEvent,\n ScanModelOptions,\n ScanOptions,\n ScanResultsCallback,\n SpeakingStatusEvent,\n SettingsAckEvent,\n SettingsAckSetting,\n SettingsAckSuccessEvent,\n SettingsAckSuccessStatus,\n SettingsAckStatus,\n StreamAudioConfig,\n StreamResolvedConfig,\n StreamStartRequest,\n StreamStatusEvent,\n StreamStatusLifecycleState,\n StreamStatusReconnectState,\n StreamStatusState,\n StreamVideoConfig,\n SwipeVolumeStatusEvent,\n SwitchStatusEvent,\n TouchEvent,\n VideoRecordingDefaults,\n VideoRecordingStartedStatusEvent,\n VideoRecordingStatusEvent,\n VideoRecordingStatusState,\n VideoRecordingStoppedStatusEvent,\n VideoRecordingSuccessStatusEvent,\n VersionInfoEvent,\n VersionInfoResult,\n WifiScanResultEvent,\n VoiceActivityDetectionStatusEvent,\n WifiSearchResult,\n WifiStatus,\n WifiStatusChangeEvent,\n} from \"./BluetoothSdk.types\"\n"]}
|
|
@@ -135,6 +135,11 @@ public class BluetoothSdkModule: Module, MentraBluetoothSDKDelegate {
|
|
|
135
135
|
try? await sdk.displayText(text, x: x ?? 0, y: y ?? 0, size: size ?? 24)
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
AsyncFunction("setDashboardContent") { (content: String) in
|
|
139
|
+
let sdk = await MainActor.run { self.bluetoothSdk() }
|
|
140
|
+
await sdk.setDashboardContent(content)
|
|
141
|
+
}
|
|
142
|
+
|
|
138
143
|
// MARK: - Connection Commands
|
|
139
144
|
|
|
140
145
|
AsyncFunction("connectDefault") {
|
|
@@ -937,4 +942,3 @@ private extension ConnectOptions {
|
|
|
937
942
|
}
|
|
938
943
|
|
|
939
944
|
|
|
940
|
-
|
|
@@ -11,7 +11,7 @@ enum BluetoothSdkDefaults {
|
|
|
11
11
|
static let voiceActivityDetectionEnabled = false
|
|
12
12
|
static let loudnessGateEnabled = false
|
|
13
13
|
private static let infoSdkVersionKey = "MentraBluetoothSdkVersion"
|
|
14
|
-
private static let swiftPackageSdkVersion = "3.2.0-dev.
|
|
14
|
+
private static let swiftPackageSdkVersion = "3.2.0-dev.174"
|
|
15
15
|
private static let swiftPackageSdkVersionPlaceholder = "__MENTRA" + "_BLUETOOTH_SDK_VERSION__"
|
|
16
16
|
|
|
17
17
|
private static func normalizedSdkVersion(_ value: String?) -> String? {
|
|
@@ -337,7 +337,7 @@ struct ViewState {
|
|
|
337
337
|
),
|
|
338
338
|
ViewState(
|
|
339
339
|
topText: " ", bottomText: " ", title: " ", layoutType: "text_wall",
|
|
340
|
-
text:
|
|
340
|
+
text: DashboardContentFormatter.template(for: "")
|
|
341
341
|
),
|
|
342
342
|
ViewState(
|
|
343
343
|
topText: " ", bottomText: " ", title: " ", layoutType: "text_wall", text: "",
|
|
@@ -345,7 +345,7 @@ struct ViewState {
|
|
|
345
345
|
),
|
|
346
346
|
ViewState(
|
|
347
347
|
topText: " ", bottomText: " ", title: " ", layoutType: "text_wall",
|
|
348
|
-
text:
|
|
348
|
+
text: DashboardContentFormatter.template(for: ""), data: nil,
|
|
349
349
|
animationData: nil
|
|
350
350
|
),
|
|
351
351
|
]
|
|
@@ -355,6 +355,12 @@ struct ViewState {
|
|
|
355
355
|
// sentinel so sendCurrentState routes here. Holding the WHOLE frame keeps
|
|
356
356
|
// native re-dispatch coherent (dashboard exit re-applies a complete scene).
|
|
357
357
|
var sceneStates: [SceneFrame?] = [nil, nil]
|
|
358
|
+
private var dashboardSceneCleanupPending = false
|
|
359
|
+
private var dashboardSceneCleanupTask: Task<Void, Never>?
|
|
360
|
+
private var pendingDashboardSceneElementIds = Set<String>()
|
|
361
|
+
private var dashboardSceneCleanupDeferred: Bool {
|
|
362
|
+
dashboardSceneCleanupPending || dashboardSceneCleanupTask != nil
|
|
363
|
+
}
|
|
358
364
|
|
|
359
365
|
override init() {
|
|
360
366
|
Bridge.log("MAN: init()")
|
|
@@ -762,86 +768,76 @@ struct ViewState {
|
|
|
762
768
|
}
|
|
763
769
|
}
|
|
764
770
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
771
|
+
@discardableResult
|
|
772
|
+
func sendCurrentState() -> Task<Void, Never> {
|
|
773
|
+
Task { await renderCurrentState() }
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
private func renderCurrentState() async {
|
|
777
|
+
guard !screenDisabled, sgc?.fullyBooted == true,
|
|
778
|
+
sgc?.type.contains(DeviceTypes.SIMULATED) == false else { return }
|
|
779
|
+
|
|
780
|
+
await clearPendingDashboardSceneElements(for: headUp && contextualDashboard ? 1 : 0)
|
|
781
|
+
|
|
782
|
+
// Cleanup can suspend. Select the visible slot and its contents only
|
|
783
|
+
// after it finishes, including any head movement or display update.
|
|
784
|
+
guard !screenDisabled, sgc?.fullyBooted == true,
|
|
785
|
+
sgc?.type.contains(DeviceTypes.SIMULATED) == false else { return }
|
|
786
|
+
let currentStateIndex = headUp && contextualDashboard ? 1 : 0
|
|
787
|
+
let currentViewState = viewStates[currentStateIndex]
|
|
788
|
+
|
|
789
|
+
// cancel any pending clear display work item:
|
|
790
|
+
sendStateWorkItem?.cancel()
|
|
791
|
+
|
|
792
|
+
let layoutType = currentViewState.layoutType
|
|
793
|
+
switch layoutType {
|
|
794
|
+
case "text_wall":
|
|
795
|
+
let text = parsePlaceholders(currentViewState.text)
|
|
796
|
+
await sgc?.sendTextWall(text)
|
|
797
|
+
case "double_text_wall":
|
|
798
|
+
let topText = parsePlaceholders(currentViewState.topText)
|
|
799
|
+
let bottomText = parsePlaceholders(currentViewState.bottomText)
|
|
800
|
+
await sgc?.sendDoubleTextWall(topText, bottomText)
|
|
801
|
+
case "reference_card":
|
|
802
|
+
let title = parsePlaceholders(currentViewState.title)
|
|
803
|
+
let text = parsePlaceholders(currentViewState.text)
|
|
804
|
+
await sgc?.sendTextWall(title + "\n\n" + text)
|
|
805
|
+
case "bitmap_view":
|
|
806
|
+
// Bridge.log("MAN: Processing bitmap_view layout")
|
|
807
|
+
guard let data = currentViewState.data else {
|
|
808
|
+
Bridge.log("MAN: ERROR: bitmap_view missing data field")
|
|
788
809
|
return
|
|
789
810
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
await sgc?.
|
|
815
|
-
base64ImageData: data,
|
|
816
|
-
x: currentViewState.bmpX,
|
|
817
|
-
y: currentViewState.bmpY,
|
|
818
|
-
width: currentViewState.bmpWidth,
|
|
819
|
-
height: currentViewState.bmpHeight
|
|
820
|
-
)
|
|
821
|
-
case "positioned_text":
|
|
822
|
-
let text = parsePlaceholders(currentViewState.text)
|
|
823
|
-
Bridge.log(
|
|
824
|
-
"MAN: positioned_text -> text='\(text)' rect=\(currentViewState.bmpX ?? 0),\(currentViewState.bmpY ?? 0) \(currentViewState.bmpWidth ?? 576)x\(currentViewState.bmpHeight ?? 288)"
|
|
825
|
-
)
|
|
826
|
-
await sgc?.sendPositionedText(
|
|
827
|
-
text,
|
|
828
|
-
x: currentViewState.bmpX ?? 0,
|
|
829
|
-
y: currentViewState.bmpY ?? 0,
|
|
830
|
-
width: currentViewState.bmpWidth ?? 576,
|
|
831
|
-
height: currentViewState.bmpHeight ?? 288,
|
|
832
|
-
borderWidth: currentViewState.borderWidth ?? 0,
|
|
833
|
-
borderRadius: currentViewState.borderRadius ?? 0
|
|
834
|
-
)
|
|
835
|
-
case "scene":
|
|
836
|
-
let sceneIndex = (headUp && self.contextualDashboard) ? 1 : 0
|
|
837
|
-
if let frame = self.sceneStates[sceneIndex] {
|
|
838
|
-
await sgc?.applySceneFrame(frame)
|
|
839
|
-
}
|
|
840
|
-
case "clear_view":
|
|
841
|
-
sgc?.clearDisplay()
|
|
842
|
-
default:
|
|
843
|
-
Bridge.log("UNHANDLED LAYOUT_TYPE \(layoutType)")
|
|
811
|
+
// Bridge.log("MAN: Processing bitmap_view with base64 data, length: \(data.count)")
|
|
812
|
+
await sgc?.displayBitmap(
|
|
813
|
+
base64ImageData: data,
|
|
814
|
+
x: currentViewState.bmpX,
|
|
815
|
+
y: currentViewState.bmpY,
|
|
816
|
+
width: currentViewState.bmpWidth,
|
|
817
|
+
height: currentViewState.bmpHeight
|
|
818
|
+
)
|
|
819
|
+
case "positioned_text":
|
|
820
|
+
let text = parsePlaceholders(currentViewState.text)
|
|
821
|
+
Bridge.log(
|
|
822
|
+
"MAN: positioned_text -> text='\(text)' rect=\(currentViewState.bmpX ?? 0),\(currentViewState.bmpY ?? 0) \(currentViewState.bmpWidth ?? 576)x\(currentViewState.bmpHeight ?? 288)"
|
|
823
|
+
)
|
|
824
|
+
await sgc?.sendPositionedText(
|
|
825
|
+
text,
|
|
826
|
+
x: currentViewState.bmpX ?? 0,
|
|
827
|
+
y: currentViewState.bmpY ?? 0,
|
|
828
|
+
width: currentViewState.bmpWidth ?? 576,
|
|
829
|
+
height: currentViewState.bmpHeight ?? 288,
|
|
830
|
+
borderWidth: currentViewState.borderWidth ?? 0,
|
|
831
|
+
borderRadius: currentViewState.borderRadius ?? 0
|
|
832
|
+
)
|
|
833
|
+
case "scene":
|
|
834
|
+
if let frame = sceneStates[currentStateIndex] {
|
|
835
|
+
await sgc?.applySceneFrame(frame)
|
|
844
836
|
}
|
|
837
|
+
case "clear_view":
|
|
838
|
+
sgc?.clearDisplay()
|
|
839
|
+
default:
|
|
840
|
+
Bridge.log("UNHANDLED LAYOUT_TYPE \(layoutType)")
|
|
845
841
|
}
|
|
846
842
|
}
|
|
847
843
|
|
|
@@ -1196,6 +1192,58 @@ struct ViewState {
|
|
|
1196
1192
|
Task { await sgc?.sendTextWall(text) }
|
|
1197
1193
|
}
|
|
1198
1194
|
|
|
1195
|
+
func setDashboardContent(_ content: String) async {
|
|
1196
|
+
let nextState = ViewState(
|
|
1197
|
+
topText: " ", bottomText: " ", title: " ", layoutType: "text_wall",
|
|
1198
|
+
text: DashboardContentFormatter.template(for: content), data: nil, animationData: nil
|
|
1199
|
+
)
|
|
1200
|
+
let previousScene = sceneStates[1]
|
|
1201
|
+
let currentState = viewStates[1]
|
|
1202
|
+
if previousScene == nil,
|
|
1203
|
+
currentState.layoutType == nextState.layoutType,
|
|
1204
|
+
currentState.text == nextState.text,
|
|
1205
|
+
currentState.topText == nextState.topText,
|
|
1206
|
+
currentState.bottomText == nextState.bottomText,
|
|
1207
|
+
currentState.title == nextState.title,
|
|
1208
|
+
currentState.data == nextState.data
|
|
1209
|
+
{
|
|
1210
|
+
return
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
if let previousScene {
|
|
1214
|
+
dashboardSceneCleanupPending = true
|
|
1215
|
+
pendingDashboardSceneElementIds.formUnion(previousScene.elements.map(\.id))
|
|
1216
|
+
}
|
|
1217
|
+
sceneStates[1] = nil
|
|
1218
|
+
viewStates[1] = nextState
|
|
1219
|
+
|
|
1220
|
+
if headUp && contextualDashboard {
|
|
1221
|
+
await renderCurrentState()
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
private func clearPendingDashboardSceneElements(for stateIndex: Int) async {
|
|
1226
|
+
// Share cleanup until it has fully finished; consuming the pending IDs
|
|
1227
|
+
// must not let a second renderer paint while the first is still clearing.
|
|
1228
|
+
if let cleanup = dashboardSceneCleanupTask {
|
|
1229
|
+
await cleanup.value
|
|
1230
|
+
return
|
|
1231
|
+
}
|
|
1232
|
+
guard stateIndex == 1, dashboardSceneCleanupPending else { return }
|
|
1233
|
+
|
|
1234
|
+
let cleanup = Task<Void, Never> {
|
|
1235
|
+
while self.dashboardSceneCleanupPending {
|
|
1236
|
+
self.dashboardSceneCleanupPending = false
|
|
1237
|
+
let elementIds = Array(self.pendingDashboardSceneElementIds)
|
|
1238
|
+
self.pendingDashboardSceneElementIds.removeAll()
|
|
1239
|
+
await self.sgc?.clearSceneElements(elementIds)
|
|
1240
|
+
}
|
|
1241
|
+
self.dashboardSceneCleanupTask = nil
|
|
1242
|
+
}
|
|
1243
|
+
dashboardSceneCleanupTask = cleanup
|
|
1244
|
+
await cleanup.value
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1199
1247
|
func displayEvent(_ event: [String: Any]) {
|
|
1200
1248
|
guard let view = event["view"] as? String else {
|
|
1201
1249
|
Bridge.log("MAN: invalid view")
|
|
@@ -1232,7 +1280,10 @@ struct ViewState {
|
|
|
1232
1280
|
// wipes everything anyway.
|
|
1233
1281
|
if let prevFrame = sceneStates[stateIndex] {
|
|
1234
1282
|
sceneStates[stateIndex] = nil
|
|
1235
|
-
if
|
|
1283
|
+
if stateIndex == 1, dashboardSceneCleanupDeferred {
|
|
1284
|
+
dashboardSceneCleanupPending = true
|
|
1285
|
+
pendingDashboardSceneElementIds.formUnion(prevFrame.elements.map(\.id))
|
|
1286
|
+
} else if layoutType != "clear_view" {
|
|
1236
1287
|
let ids = prevFrame.elements.map(\.id)
|
|
1237
1288
|
Task { [weak self] in
|
|
1238
1289
|
await self?.sgc?.clearSceneElements(ids)
|
|
@@ -1325,7 +1376,12 @@ struct ViewState {
|
|
|
1325
1376
|
// clearDisplay is the per-device "wipe what's there" (blank-in-place
|
|
1326
1377
|
// on G2 - no page rebuild).
|
|
1327
1378
|
let prevLegacyType = viewStates[stateIndex].layoutType
|
|
1328
|
-
|
|
1379
|
+
let cleanupDeferred = stateIndex == 1 && dashboardSceneCleanupDeferred
|
|
1380
|
+
if !cleanupDeferred,
|
|
1381
|
+
!prevLegacyType.isEmpty,
|
|
1382
|
+
prevLegacyType != "clear_view",
|
|
1383
|
+
prevLegacyType != "scene"
|
|
1384
|
+
{
|
|
1329
1385
|
sgc?.clearDisplay()
|
|
1330
1386
|
}
|
|
1331
1387
|
} else if let prevFrame, prevFrame.appId != frame.appId {
|
|
@@ -1334,9 +1390,14 @@ struct ViewState {
|
|
|
1334
1390
|
// glasses. Sweep the old app's elements (SGC registries still map
|
|
1335
1391
|
// them), then paint the new frame from scratch. The boot message
|
|
1336
1392
|
// interposes between apps in practice, so this isn't visible.
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1393
|
+
if stateIndex == 1, dashboardSceneCleanupDeferred {
|
|
1394
|
+
dashboardSceneCleanupPending = true
|
|
1395
|
+
pendingDashboardSceneElementIds.formUnion(prevFrame.elements.map(\.id))
|
|
1396
|
+
} else {
|
|
1397
|
+
let ids = prevFrame.elements.map(\.id)
|
|
1398
|
+
Task { [weak self] in
|
|
1399
|
+
await self?.sgc?.clearSceneElements(ids)
|
|
1400
|
+
}
|
|
1340
1401
|
}
|
|
1341
1402
|
frame = frame.asReplay()
|
|
1342
1403
|
}
|
|
@@ -1352,12 +1413,12 @@ struct ViewState {
|
|
|
1352
1413
|
|
|
1353
1414
|
let hUp = headUp && contextualDashboard
|
|
1354
1415
|
if (stateIndex == 0 && !hUp) || (stateIndex == 1 && hUp) {
|
|
1355
|
-
dispatchSceneFrame(frame)
|
|
1416
|
+
dispatchSceneFrame(frame, stateIndex: stateIndex)
|
|
1356
1417
|
}
|
|
1357
1418
|
}
|
|
1358
1419
|
|
|
1359
1420
|
/// Guarded scene dispatch - mirrors sendCurrentState's send conditions.
|
|
1360
|
-
private func dispatchSceneFrame(_ frame: SceneFrame) {
|
|
1421
|
+
private func dispatchSceneFrame(_ frame: SceneFrame, stateIndex: Int) {
|
|
1361
1422
|
if screenDisabled { return }
|
|
1362
1423
|
if sgc?.type.contains(DeviceTypes.SIMULATED) ?? true { return }
|
|
1363
1424
|
guard sgc?.fullyBooted == true else {
|
|
@@ -1365,7 +1426,14 @@ struct ViewState {
|
|
|
1365
1426
|
return
|
|
1366
1427
|
}
|
|
1367
1428
|
Task { [weak self] in
|
|
1368
|
-
|
|
1429
|
+
guard let self else { return }
|
|
1430
|
+
if dashboardSceneCleanupTask != nil ||
|
|
1431
|
+
(stateIndex == 1 && dashboardSceneCleanupPending)
|
|
1432
|
+
{
|
|
1433
|
+
await renderCurrentState()
|
|
1434
|
+
} else {
|
|
1435
|
+
await sgc?.applySceneFrame(frame)
|
|
1436
|
+
}
|
|
1369
1437
|
}
|
|
1370
1438
|
}
|
|
1371
1439
|
|
|
@@ -3,9 +3,9 @@ import Foundation
|
|
|
3
3
|
/// Generated by release CI. Do not edit in a release checkout.
|
|
4
4
|
enum GeneratedReleaseMetadata {
|
|
5
5
|
static let familyBaseVersion = "3.2.0"
|
|
6
|
-
static let releaseIdentity = "3.2.0-dev.
|
|
7
|
-
static let releaseSetId = "mentra-3.2.0-dev.
|
|
8
|
-
static let sourceCommit = "
|
|
9
|
-
static let otaManifestUrl = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.
|
|
10
|
-
static let otaManifestSha256 = "
|
|
6
|
+
static let releaseIdentity = "3.2.0-dev.174"
|
|
7
|
+
static let releaseSetId = "mentra-3.2.0-dev.174"
|
|
8
|
+
static let sourceCommit = "f81a22e61cce70842fc7df5d611b33995f516b78"
|
|
9
|
+
static let otaManifestUrl = "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.2.0/mentra-live-ota-3.2.0-dev.174.json"
|
|
10
|
+
static let otaManifestSha256 = "f97e5acc0c793025b271450b85468b4dc1417ce315075dcee2b6e5efd21e0337"
|
|
11
11
|
}
|
|
@@ -472,6 +472,11 @@ public final class MentraBluetoothSDK {
|
|
|
472
472
|
DeviceManager.shared.sgc?.clearDisplay()
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
+
/// Sets session-only content shown below the standard dashboard status header.
|
|
476
|
+
public func setDashboardContent(_ content: String) async {
|
|
477
|
+
await DeviceManager.shared.setDashboardContent(content)
|
|
478
|
+
}
|
|
479
|
+
|
|
475
480
|
public func showDashboard() {
|
|
476
481
|
DeviceManager.shared.showDashboard()
|
|
477
482
|
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
|
+
enum DashboardContentFormatter {
|
|
4
|
+
static let statusHeader = "$TIME12$ $DATE$ $GBATT$ $CONNECTION_STATUS$"
|
|
5
|
+
|
|
6
|
+
static func template(for content: String) -> String {
|
|
7
|
+
content.isEmpty ? statusHeader : statusHeader + "\n\n" + content
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
public struct DisplayTextRequest {
|
|
4
12
|
public let text: String
|
|
5
13
|
public let x: Int
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
@testable import MentraBluetoothSDK
|
|
2
|
+
import XCTest
|
|
3
|
+
|
|
4
|
+
final class DashboardContentFormatterTests: XCTestCase {
|
|
5
|
+
func testEmptyContentReturnsStatusHeaderOnly() {
|
|
6
|
+
XCTAssertEqual(
|
|
7
|
+
DashboardContentFormatter.template(for: ""),
|
|
8
|
+
"$TIME12$ $DATE$ $GBATT$ $CONNECTION_STATUS$"
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
func testNonEmptyContentIsAppendedExactlyAfterBlankLine() {
|
|
13
|
+
XCTAssertEqual(
|
|
14
|
+
DashboardContentFormatter.template(for: " Next meeting\nRoom 2 "),
|
|
15
|
+
"$TIME12$ $DATE$ $GBATT$ $CONNECTION_STATUS$\n\n Next meeting\nRoom 2 "
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
}
|