fix(calls): screen-share stage never engaged on the receiver (LC-408) #425

Merged
longjacksonle merged 1 commit from fix/lc-408-screenshare-receiver-pin into main 2026-06-21 01:44:55 +02:00

Follow-up fix to LC-408: the presenter's tile spanned correctly (after #423), but on every other participant the sharer's tile stayed small - the stage never engaged on the receiver.

Cause

The "stuck pin" fallback I added in #423: updateTileMedia cleared data-screen on any remote tile that had no live video. On the RECEIVER the voice_screen=true WS signal lands before the screen video track is live (the signal beats the media renegotiation), and updateTileMedia runs from the screen handler / ontrack / onmute during that window - so it stripped the data-screen that had just been set, and .lc-voice-grid:has([data-screen]) never matched. The presenter never hit it because it pins against its own already-live screen track. (Not the two-accounts-in-one-browser setup.)

Fix

Remove that fallback. The pin is now owned solely by the explicit voice_screen signal:

  • stop -> voice_screen=false (broadcast_to_room) reliably clears it,
  • a crashed sharer -> VoiceLeft removes the tile entirely.

The updateTileMedia(userId) nudge in the screen handler still reverts the video on stop; it just no longer touches data-screen.

Scope

Frontend only: a one-block deletion in assets/voice.js. No Rust, CSS, template, or schema change.

Tests

just check, just test, just test-saas all pass. voice.js syntax-checked.

Follow-up fix to LC-408: the presenter's tile spanned correctly (after #423), but on every other participant the sharer's tile stayed small - the stage never engaged on the receiver. ## Cause The "stuck pin" fallback I added in #423: `updateTileMedia` cleared `data-screen` on any remote tile that had no live video. On the RECEIVER the `voice_screen=true` WS signal lands *before* the screen video track is live (the signal beats the media renegotiation), and `updateTileMedia` runs from the screen handler / `ontrack` / `onmute` during that window - so it stripped the `data-screen` that had just been set, and `.lc-voice-grid:has([data-screen])` never matched. The presenter never hit it because it pins against its own already-live screen track. (Not the two-accounts-in-one-browser setup.) ## Fix Remove that fallback. The pin is now owned solely by the explicit `voice_screen` signal: - stop -> `voice_screen=false` (`broadcast_to_room`) reliably clears it, - a crashed sharer -> `VoiceLeft` removes the tile entirely. The `updateTileMedia(userId)` nudge in the screen handler still reverts the video on stop; it just no longer touches `data-screen`. ## Scope Frontend only: a one-block deletion in `assets/voice.js`. No Rust, CSS, template, or schema change. ## Tests `just check`, `just test`, `just test-saas` all pass. `voice.js` syntax-checked.
fix(calls): screen-share stage never engaged on the receiver (LC-408)
All checks were successful
check-secrets / Kingfisher (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Nosey parker (pull_request) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Kingfisher (pull_request) Successful in 5s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 3m13s
50f3e10fd4
The presenter pinned correctly but peers kept the sharer's tile small. Root cause was the LC-408 "stuck pin" fallback I added: updateTileMedia cleared data-screen on any remote tile with no live video. On the RECEIVER the voice_screen=true signal lands before the screen video track is live (the WS signal beats the media renegotiation), and updateTileMedia runs from the screen handler / ontrack / onmute during that window - so it stripped the data-screen that had just been set, and the `:has([data-screen])` stage never engaged. The presenter never hit this because it pins against its own already-live screen track.

Remove that fallback. The screen-share pin is now owned solely by the explicit voice_screen signal: voice_screen=false (broadcast_to_room) reliably clears it on stop, and a crashed sharer is cleaned up by VoiceLeft removing the tile. The remaining updateTileMedia(userId) nudge in the screen handler still reverts the video on stop; it just no longer touches data-screen.

Frontend only (voice.js); one-block deletion. No Rust/CSS/template change. just check, just test, just test-saas all pass; voice.js syntax-checked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch fix/lc-408-screenshare-receiver-pin 2026-06-21 01:44:55 +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!425
No description provided.