Compare commits
2
Commits
6edfe70020
...
25fa0f6ef9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25fa0f6ef9 | ||
|
|
b77720c3da |
@@ -10,7 +10,7 @@ type ThumbbarAction = { action: 'mute' | 'deafen' | 'end' };
|
||||
* P5-44 — Taskbar thumbnail toolbar (call controls). While a call is active,
|
||||
* mirrors the mic/sound state onto the native `set_thumbbar` command (three
|
||||
* Mute / Deafen / End-Call buttons on the Windows taskbar thumbnail toolbar) and
|
||||
* hides them when the call ends. Thumb-button clicks come back as the
|
||||
* hides them when the call ends. The tray icon mirrors the same state. Thumb-button clicks come back as the
|
||||
* `thumbbar-action` event and drive the real call controls. No-op in the browser.
|
||||
*/
|
||||
export function useTauriThumbbar(): void {
|
||||
@@ -25,6 +25,9 @@ export function useTauriThumbbar(): void {
|
||||
|
||||
useEffect(() => {
|
||||
invokeTauri('set_thumbbar', { active, muted, deafened });
|
||||
// [cinny-desktop #4] Same state onto the tray icon + tooltip, from the same
|
||||
// effect so the tray and the thumbbar can never disagree.
|
||||
invokeTauri('set_tray_call_state', { active, muted, deafened });
|
||||
}, [active, muted, deafened]);
|
||||
|
||||
useTauriEvent<ThumbbarAction>('thumbbar-action', ({ action }) => {
|
||||
|
||||
@@ -35,20 +35,29 @@ export const useSendClientWidgetApiAction = (api: ClientWidgetApi) => {
|
||||
const DEFAULT_CONTROL_STATE = new CallControlState(false, false, false);
|
||||
|
||||
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(() => {
|
||||
if (!control) {
|
||||
setState(DEFAULT_CONTROL_STATE);
|
||||
setEntry({ control, state: DEFAULT_CONTROL_STATE });
|
||||
return;
|
||||
}
|
||||
setState(control.getState());
|
||||
const handleUpdate = () => setState(control.getState());
|
||||
setEntry({ control, state: control.getState() });
|
||||
const handleUpdate = () => setEntry({ control, state: control.getState() });
|
||||
control.on(CallControlEvent.StateUpdate, handleUpdate);
|
||||
return () => {
|
||||
control.off(CallControlEvent.StateUpdate, handleUpdate);
|
||||
};
|
||||
}, [control]);
|
||||
|
||||
return state;
|
||||
if (entry.control !== control) return control?.getState() ?? DEFAULT_CONTROL_STATE;
|
||||
return entry.state;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user