fix(call): deliver incoming-call popup from any page and resolve glare server-side #117

Merged
nrupard merged 1 commit from fix/global-call-popup-and-glare into main 2026-05-15 19:14:33 +02:00
Owner

Previously the 1:1 call popup only rendered when the callee was already viewing the DM with the caller, because the call UI lived inside the DM template and call.js short-circuited when its per-DM cfg was unset. Two simultaneous invites in the same DM could also leave both peers in separate "calling" states because glare resolution relied on both clients comparing user ids, which only worked when both happened to be on the DM page at the same moment.

Lift the call root (incoming overlay + active overlay) into layout.html so the popup is reachable everywhere, expose window.__lcWS from the layout's wsOpen listener so non-DM pages can send signals, carry room/peer context on the DM-header start buttons, and serve the ICE-server config from a new /call/config endpoint instead of threading it through every page struct. Track per-DM ringing state in the Hub: the first invite wins, a second invite from the peer (glare) is dropped and the winner's invite is replayed back to the loser so their UI flips from outgoing to incoming, and terminating signals (accept/reject/cancel/hangup) plus a 60s TTL release the slot.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

Previously the 1:1 call popup only rendered when the callee was already viewing the DM with the caller, because the call UI lived inside the DM template and call.js short-circuited when its per-DM cfg was unset. Two simultaneous invites in the same DM could also leave both peers in separate "calling" states because glare resolution relied on both clients comparing user ids, which only worked when both happened to be on the DM page at the same moment. Lift the call root (incoming overlay + active overlay) into layout.html so the popup is reachable everywhere, expose window.__lcWS from the layout's wsOpen listener so non-DM pages can send signals, carry room/peer context on the DM-header start buttons, and serve the ICE-server config from a new /call/config endpoint instead of threading it through every page struct. Track per-DM ringing state in the Hub: the first invite wins, a second invite from the peer (glare) is dropped and the winner's invite is replayed back to the loser so their UI flips from outgoing to incoming, and terminating signals (accept/reject/cancel/hangup) plus a 60s TTL release the slot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(call): deliver incoming-call popup from any page and resolve glare server-side
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 4m25s
3be65e4fb8
Previously the 1:1 call popup only rendered when the callee was already viewing the DM with the caller, because the call UI lived inside the DM template and call.js short-circuited when its per-DM cfg was unset. Two simultaneous invites in the same DM could also leave both peers in separate "calling" states because glare resolution relied on both clients comparing user ids, which only worked when both happened to be on the DM page at the same moment.

Lift the call root (incoming overlay + active overlay) into layout.html so the popup is reachable everywhere, expose window.__lcWS from the layout's wsOpen listener so non-DM pages can send signals, carry room/peer context on the DM-header start buttons, and serve the ICE-server config from a new /call/config endpoint instead of threading it through every page struct. Track per-DM ringing state in the Hub: the first invite wins, a second invite from the peer (glare) is dropped and the winner's invite is replayed back to the loser so their UI flips from outgoing to incoming, and terminating signals (accept/reject/cancel/hangup) plus a 60s TTL release the slot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nrupard deleted branch fix/global-call-popup-and-glare 2026-05-15 19:14:33 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!117
No description provided.