Fix outgoing-call re-ring: never send the cancel push to the caller

Hanging up an UNANSWERED outgoing call re-rang the caller's own phone: the server
sent the "cancel" VoIP push to BOTH parties, and the plugin must reportNewIncomingCall
for every VoIP push (iOS rule) → a phantom ring on the caller who just hung up.
Incoming calls don't hit this (an answered call sends no cancel). Fix: DM cancel goes
only to the callee (not startedBy); group cancel skips the starter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 11:38:53 +05:30
parent 29106370fd
commit 9d0fd93d7e
+5 -2
View File
@@ -91,7 +91,7 @@ async function endGroupCallByRoom(room) {
if (call.historyId && teamId) { try { await R.scheduledMeetings.end(call.historyId, teamId); } catch (_) {} } // mark the history row past
broadcast(group, { type: 'group-call', group, active: false, room, uuid: call.uuid });
// Stop any CallKit ring on members' killed/backgrounded devices.
try { for (const mid of await R.conversations.members(group)) PUSH.sendCallCancel(mid, call.uuid); } catch (_) {}
try { for (const mid of await R.conversations.members(group)) { if (mid !== call.startedBy) PUSH.sendCallCancel(mid, call.uuid); } } catch (_) {} // not the starter — a cancel to them re-rings their own phone
}
}
@@ -153,7 +153,10 @@ async function endDmCallByRoom(room, silent) {
// Stop the CallKit ring on a device that's still RINGING (unanswered) — a killed/asleep callee has no WS
// to receive the dm-call above. For an ANSWERED call both sides are awake (the WS event ends it), and a
// cancel push would re-ring the device that just hung up — so only cancel when it was NOT answered.
if (!call.answered) { try { for (const uid of call.users) PUSH.sendCallCancel(uid, call.uuid); } catch (_) {} }
// Cancel the ring ONLY on the CALLEE's device(s) — never the caller (startedBy). The caller is placing the
// call, not ringing, so a cancel push to them made their OWN phone re-ring after they hung up an unanswered
// outgoing call (the plugin must reportNewIncomingCall for every VoIP push → a phantom ring on the caller).
if (!call.answered) { const callee = call.users.find((u) => u !== call.startedBy); if (callee) { try { PUSH.sendCallCancel(callee, call.uuid); } catch (_) {} } }
// Missed-call banner to the callee (a plain notification, like a phone's missed call) when the call ended
// UNANSWERED — timeout or the caller hung up before pickup. Skipped on decline (silent): they chose to.
if (!silent && !call.answered) {