From 5b1c847e5772a428d7ba87bc89815693862790d5 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Wed, 8 Apr 2026 14:49:29 +0200 Subject: [PATCH] fix: exclude acting user from federated call end/reject broadcast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sendToFederatedCallUsers sent dm_call_ended/rejected back to the user who initiated the action. They already disconnected in their click handler — the redundant event triggered disconnectFn() again, causing connect and disconnect sounds to play simultaneously. Added excludeUserId parameter to sendToFederatedCallUsers, used in handleDmCallEnd and handleDmCallReject Path 2. --- packages/server/src/ws/events.ts | 7 +++++-- packages/server/src/ws/handler.ts | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/server/src/ws/events.ts b/packages/server/src/ws/events.ts index cebcffb0..ab8a7cba 100644 --- a/packages/server/src/ws/events.ts +++ b/packages/server/src/ws/events.ts @@ -1589,11 +1589,12 @@ function handleDmCallReject(event: Record, userId: string): voi : undefined; if (fedCall) { + // Exclude the rejecting user — they already handled their own state connectionManager.sendToFederatedCallUsers(fedCall.federatedId, { type: 'dm_call_rejected', dmChannelId: fedCall.dmChannelId, federatedCallId: fedCall.federatedId, - } as ServerEvent); + } as ServerEvent, userId); connectionManager.clearFederatedCall(fedCall.federatedId); const db = getDb(); @@ -1660,11 +1661,13 @@ function handleDmCallEnd(event: Record, userId: string): void { : undefined; if (fedCall) { + // Exclude the user who ended the call — they already disconnected in their click handler. + // Sending dm_call_ended back to them causes redundant disconnectFn() and double sounds. connectionManager.sendToFederatedCallUsers(fedCall.federatedId, { type: 'dm_call_ended', dmChannelId: fedCall.dmChannelId, federatedCallId: fedCall.federatedId, - } as ServerEvent); + } as ServerEvent, userId); connectionManager.clearFederatedCall(fedCall.federatedId); const db = getDb(); diff --git a/packages/server/src/ws/handler.ts b/packages/server/src/ws/handler.ts index 6955a939..93d503ce 100644 --- a/packages/server/src/ws/handler.ts +++ b/packages/server/src/ws/handler.ts @@ -758,11 +758,13 @@ class ConnectionManager { * ALWAYS uses ringedUserIds, never sendToDmMembers — sendToDmMembers would * also reach the caller's replicated stub, causing cross-instance event contamination * (the caller's multi-instance WS gets dm_call_accepted with the wrong dmChannelId). */ - sendToFederatedCallUsers(federatedId: string, event: ServerEvent): void { + sendToFederatedCallUsers(federatedId: string, event: ServerEvent, excludeUserId?: string): void { const call = this.federatedCalls.get(federatedId); if (!call) return; for (const uid of call.ringedUserIds) { - this.sendToUser(uid, event); + if (uid !== excludeUserId) { + this.sendToUser(uid, event); + } } }