fix(call): Wave-1 audit fixes (calls host side)
- C-H1: forceState only on FIRST join; on EC reconnect re-arm the fork handlers (resendForkState — deafen+quality only) instead of clobbering live mic/video/ deafen back to the join-time snapshot. - C-H2: AFK auto-mute reads the fork's io.lotus.call_state VAD of the LOCAL published track instead of getUserMedia on the browser DEFAULT mic (which could measure silence while the user spoke on another device → auto-mute an active speaker). Fails safe (never mutes) when call_state is null OR empty. - C-H3: control observer re-binds after EC re-renders (body subtree:true + 100ms debounce) with an early-return so unchanged state doesn't re-render. - C-M3 setQuality join-gated; C-M4 hangup 4s fallback dispose (idempotent); C-M5 PTT no longer silently un-deafens; C-M6 screenshare-audio mute resets on stop; C-L4 deafen key works in the iframe; C-L6 setState-after-unmount guards. Reviewed (C-H2 [] fail-safe + C-H3 re-render guard applied). tsc/eslint/prettier clean, build OK, 677 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -413,6 +413,16 @@ function IncomingCallListener({ callEmbed, joined }: IncomingCallListenerProps)
|
||||
const dm = callInfo ? directs.has(callInfo.room.roomId) : false;
|
||||
const startCall = useCallStart(dm);
|
||||
|
||||
// C-L6: handleTimelineEvent awaits decryption before calling setState; guard
|
||||
// against the component unmounting during that await.
|
||||
const mountedRef = useRef(true);
|
||||
useEffect(
|
||||
() => () => {
|
||||
mountedRef.current = false;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleTimelineEvent: EventTimelineSetHandlerMap[RoomEvent.Timeline] = useCallback(
|
||||
async (event, room, toStartOfTimeline, removed, data) => {
|
||||
// only process rtc notification reference events.
|
||||
@@ -427,6 +437,9 @@ function IncomingCallListener({ callEmbed, joined }: IncomingCallListenerProps)
|
||||
await event.getDecryptionPromise();
|
||||
}
|
||||
|
||||
// C-L6: bail if we unmounted while awaiting decryption above.
|
||||
if (!mountedRef.current) return;
|
||||
|
||||
// Caller-side: a participant declined a call we're hosting in this room.
|
||||
// Without this the caller's UI keeps "ringing" until the notification
|
||||
// lifetime expires, with no indication the callee said no.
|
||||
|
||||
Reference in New Issue
Block a user