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:
@@ -1,4 +1,4 @@
|
||||
import React, { MouseEventHandler, useCallback, useMemo, useState } from 'react';
|
||||
import React, { MouseEventHandler, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Icon,
|
||||
@@ -64,6 +64,16 @@ export function CallSoundboard({ callEmbed }: CallSoundboardProps) {
|
||||
const [playingKey, setPlayingKey] = useState<string>(); // host-side spam guard
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
// C-L6: the play() flow schedules a 30s safety timeout that clears playingKey;
|
||||
// guard those setState calls against the component unmounting first.
|
||||
const mountedRef = useRef(true);
|
||||
useEffect(
|
||||
() => () => {
|
||||
mountedRef.current = false;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const groups = useMemo(
|
||||
() =>
|
||||
packs
|
||||
@@ -86,7 +96,10 @@ export function CallSoundboard({ callEmbed }: CallSoundboardProps) {
|
||||
if (playingKey) return; // one at a time (fork also enforces this)
|
||||
setPlayingKey(flat.key);
|
||||
setError(undefined);
|
||||
const done = () => setPlayingKey((k) => (k === flat.key ? undefined : k));
|
||||
const done = () => {
|
||||
if (!mountedRef.current) return;
|
||||
setPlayingKey((k) => (k === flat.key ? undefined : k));
|
||||
};
|
||||
try {
|
||||
const url = await resolveClipObjectUrl(mx, flat.clip.url);
|
||||
const vol = (flat.clip.volume / 100) * master;
|
||||
|
||||
Reference in New Issue
Block a user