feat(camera): handle camera-track end with branched toast (unplug vs permission revoke)

LocalTrackPublished registers a one-shot onended on the camera track's
MediaStreamTrack. The handler:
  - skips when consumeIntentionalCameraOff() flag is set (user-initiated)
  - re-probes getUserMedia to distinguish NotAllowedError (permission
    revoked) from NotFoundError (disconnected) from other errors
  - tears down camera state via the unified path

Also reset _intentionalCameraOff in voiceActions if setCameraEnabled(false)
rejects, so a failed disable doesn't poison the next genuine unplug.
This commit is contained in:
Jannis Braun
2026-04-27 20:29:32 +02:00
parent e8534339fb
commit 786823946a
2 changed files with 58 additions and 5 deletions
+8 -1
View File
@@ -80,7 +80,14 @@ export async function handleCameraAction(): Promise<void> {
// Mark this disable as intentional so the track-`ended` handler skips
// its unplug/permission-revoke probe + toast.
markIntentionalCameraOff();
await room.localParticipant.setCameraEnabled(false);
try {
await room.localParticipant.setCameraEnabled(false);
} catch (err) {
// Disable rejected — consume the flag so it doesn't poison the
// next genuine unplug. Re-throw to the outer catch for logging.
consumeIntentionalCameraOff();
throw err;
}
}
useVoiceStore.getState().toggleCamera();
broadcastVoiceStatus();