refactor(camera): unify toggle paths through handleCameraAction
- Voice-bar and mobile camera buttons now use the canonical handler (fixes mobile no-op and voice-bar wrong-preset bugs) - Remove dead useLiveKit.toggleCamera - Add _intentionalCameraOff flag with mark/consume helpers
This commit is contained in:
@@ -6,6 +6,25 @@ import { getChannelOrigin } from '../stores/spaceStore';
|
||||
import { broadcastVoiceStatus, broadcastDeafenViaLiveKit } from './voice';
|
||||
import { CAMERA_PRESET, startScreenShare, stopScreenShare } from './screenShare';
|
||||
|
||||
/**
|
||||
* One-shot flag used to distinguish user-initiated camera-off from unexpected
|
||||
* track-end events (hardware unplug, OS permission revoke). Set right before
|
||||
* `setCameraEnabled(false)` in any deliberate disable path; consumed-and-cleared
|
||||
* by the camera-track `ended` handler in useLiveKit. Module-level by design:
|
||||
* never persisted, never on the store, single producer + single consumer.
|
||||
*/
|
||||
let _intentionalCameraOff = false;
|
||||
|
||||
export function markIntentionalCameraOff(): void {
|
||||
_intentionalCameraOff = true;
|
||||
}
|
||||
|
||||
export function consumeIntentionalCameraOff(): boolean {
|
||||
const v = _intentionalCameraOff;
|
||||
_intentionalCameraOff = false;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle mute. Respects space-mute/deafen guards.
|
||||
* Extracted from VoiceControlBar so keybinds and buttons share the same logic.
|
||||
@@ -31,7 +50,8 @@ export function handleDeafenAction(isSpaceDeafened: boolean): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle camera. Requires LiveKit room.
|
||||
* Toggle camera. Requires LiveKit room. Sole canonical camera-toggle path —
|
||||
* the voice-bar button, mobile button, and keybind all funnel through here.
|
||||
*/
|
||||
export async function handleCameraAction(): Promise<void> {
|
||||
const room = getActiveRoom();
|
||||
@@ -40,8 +60,9 @@ export async function handleCameraAction(): Promise<void> {
|
||||
try {
|
||||
const willEnable = !isCameraOn;
|
||||
if (willEnable) {
|
||||
await room.localParticipant.setCameraEnabled(true,
|
||||
{ resolution: CAMERA_PRESET.resolution },
|
||||
await room.localParticipant.setCameraEnabled(
|
||||
true,
|
||||
{ resolution: CAMERA_PRESET.resolution, frameRate: CAMERA_PRESET.encoding.maxFramerate },
|
||||
{
|
||||
videoCodec: CAMERA_PRESET.codec,
|
||||
videoEncoding: CAMERA_PRESET.encoding,
|
||||
@@ -49,6 +70,9 @@ export async function handleCameraAction(): Promise<void> {
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Mark this disable as intentional so the track-`ended` handler skips
|
||||
// its unplug/permission-revoke probe + toast.
|
||||
markIntentionalCameraOff();
|
||||
await room.localParticipant.setCameraEnabled(false);
|
||||
}
|
||||
useVoiceStore.getState().toggleCamera();
|
||||
|
||||
Reference in New Issue
Block a user