fix: prevent auto-connect on dm_call_accepted for non-caller instances

Three fixes for multi-instance call state consistency:

1. Client dm_call_accepted handler only auto-connects to LiveKit if
   the user was the caller (outgoingCall was set). Other instances of
   the same user just clear ringing state without connecting.

2. Server processDmCallAcceptEvent remote path skips duplicate
   broadcast when FederatedCallEntry is already active (prevents
   state conflicts from host fan-out arriving after local accept).

3. Ready payload handler clears stuck incomingCall when restoring
   an already-active call after page refresh.
This commit is contained in:
Jannis Braun
2026-04-08 12:21:27 +02:00
parent f40ea03cfb
commit 9ad240495f
2 changed files with 20 additions and 8 deletions
+9 -3
View File
@@ -322,6 +322,8 @@ function handleEvent(origin: string, event: ServerEvent): void {
const isParticipant = call.participants.includes(myId) || !!call.livekitToken;
if (call.state === 'active' && isParticipant) {
const callDmId = call.dmChannelId || call.federatedCallId || '';
// Clear any stuck ringing UI from a ringing→active transition during refresh
setIncomingCall(null);
setActiveDmCall({ dmChannelId: callDmId });
// Store federated call data if present (server already filtered to this user's token)
if (call.livekitUrl && call.livekitToken) {
@@ -797,13 +799,17 @@ function handleEvent(origin: string, event: ServerEvent): void {
}
case 'dm_call_accepted': {
const { setIncomingCall, setOutgoingCall, setActiveDmCall, connectFn, isLiveKitConnected } = useVoiceStore.getState();
const { setIncomingCall, setOutgoingCall, outgoingCall, setActiveDmCall, connectFn, isLiveKitConnected } = useVoiceStore.getState();
// Track whether WE are the caller before clearing state
const wasOutgoingCall = !!outgoingCall;
setIncomingCall(null);
setOutgoingCall(null);
const callDmId = event.dmChannelId || event.federatedCallId || '';
setActiveDmCall({ dmChannelId: callDmId });
// Only connect if not already connected (federated acceptor connects immediately in handleAccept)
if (connectFn && !isLiveKitConnected && callDmId) {
// Only auto-connect if we're the CALLER waiting for acceptance.
// The callee who accepted connects in the click handler (handleAccept).
// Other instances of the same user should NOT auto-connect.
if (connectFn && !isLiveKitConnected && wasOutgoingCall && callDmId) {
connectFn(callDmId, true).catch((err: unknown) => {
console.error('[WS] DM call connect failed:', err);
});