fix(calls): no stale "muted + deafened" render when a call starts
useCallControlState kept the previous control's state (the all-off default before a call) for one render after the control changed, until its effect caught up. The thumbbar, SMTC and tray hooks pushed that render to the OS, so every join flashed "muted + deafened" first (recorded: idle → active+muted+deafened → active). The state now remembers which control it belongs to and reads the new control directly when they differ (now: idle → active). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6edfe70020
commit
b77720c3da
@@ -35,20 +35,29 @@ export const useSendClientWidgetApiAction = (api: ClientWidgetApi) => {
|
|||||||
const DEFAULT_CONTROL_STATE = new CallControlState(false, false, false);
|
const DEFAULT_CONTROL_STATE = new CallControlState(false, false, false);
|
||||||
|
|
||||||
export const useCallControlState = (control: CallControl | undefined): CallControlState => {
|
export const useCallControlState = (control: CallControl | undefined): CallControlState => {
|
||||||
const [state, setState] = useState(control?.getState() ?? DEFAULT_CONTROL_STATE);
|
// Remember which control the stored state came from. When a call starts the
|
||||||
|
// control changes, and the effect below only catches up after a render; until
|
||||||
|
// then the old (default: all off) state would be returned for the NEW call —
|
||||||
|
// one render of "muted + deafened" that the thumbbar, SMTC and tray (#4)
|
||||||
|
// pushed to the OS as a flicker. Read the new control directly instead.
|
||||||
|
const [entry, setEntry] = useState(() => ({
|
||||||
|
control,
|
||||||
|
state: control?.getState() ?? DEFAULT_CONTROL_STATE,
|
||||||
|
}));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!control) {
|
if (!control) {
|
||||||
setState(DEFAULT_CONTROL_STATE);
|
setEntry({ control, state: DEFAULT_CONTROL_STATE });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState(control.getState());
|
setEntry({ control, state: control.getState() });
|
||||||
const handleUpdate = () => setState(control.getState());
|
const handleUpdate = () => setEntry({ control, state: control.getState() });
|
||||||
control.on(CallControlEvent.StateUpdate, handleUpdate);
|
control.on(CallControlEvent.StateUpdate, handleUpdate);
|
||||||
return () => {
|
return () => {
|
||||||
control.off(CallControlEvent.StateUpdate, handleUpdate);
|
control.off(CallControlEvent.StateUpdate, handleUpdate);
|
||||||
};
|
};
|
||||||
}, [control]);
|
}, [control]);
|
||||||
|
|
||||||
return state;
|
if (entry.control !== control) return control?.getState() ?? DEFAULT_CONTROL_STATE;
|
||||||
|
return entry.state;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user