zebra-spaces: don't let an old camera/screen/game track's removal evict the new tile
On publisher republish (cohost hard refresh → same pubkey + kind → SFU supplants), the OLD track sees mute → ended on the subscriber side and its watchVideoTrackForRemoval closure called removeXTile(pubHex). But by then the NEW track had already populated the same tile entry — so the old watcher tore down the live tile. Net effect: other peers saw the cohost's camera flash on and disappear (the local preview kept rendering because that path is independent of SFU subscribe). Each removeFn now checks the streams store still maps pubHex to the stream it was registered against; if not (the new track replaced it), the old watcher is a no-op.
This commit is contained in:
parent
438e886627
commit
3041a1391a
1 changed files with 19 additions and 11 deletions
|
|
@ -2204,25 +2204,33 @@ async function sfuSubscribe(){
|
|||
logLine('', 'sfu ontrack: kind=' + kind + ' pub=' + pubHex +
|
||||
' track=' + ev.track.kind + ' mute=' + ev.track.muted + ' state=' + ev.track.readyState);
|
||||
}
|
||||
/* Stream-identity guard on removeFn: when a publisher supplants
|
||||
* themselves (typical: hard refresh — new SFU peer_id same pubkey +
|
||||
* kind), the OLD track's mute → ended → removeFn would tear down the
|
||||
* tile that the NEW track just installed. Only remove if the stream
|
||||
* we registered against is still the one in the store for this pub. */
|
||||
if (kind === 'screen'){
|
||||
screenStreams.set(pubHex, ev.streams[0]);
|
||||
renderScreenTile(pubHex, ev.streams[0]);
|
||||
watchVideoTrackForRemoval(ev.track, () => removeScreenTile(pubHex));
|
||||
const s = ev.streams[0];
|
||||
screenStreams.set(pubHex, s);
|
||||
renderScreenTile(pubHex, s);
|
||||
watchVideoTrackForRemoval(ev.track, () => { if (screenStreams.get(pubHex) === s) removeScreenTile(pubHex); });
|
||||
return;
|
||||
}
|
||||
if (kind === 'camera'){
|
||||
cameraStreams.set(pubHex, ev.streams[0]);
|
||||
renderCameraTile(pubHex, ev.streams[0]);
|
||||
watchVideoTrackForRemoval(ev.track, () => removeCameraTile(pubHex));
|
||||
const s = ev.streams[0];
|
||||
cameraStreams.set(pubHex, s);
|
||||
renderCameraTile(pubHex, s);
|
||||
watchVideoTrackForRemoval(ev.track, () => { if (cameraStreams.get(pubHex) === s) removeCameraTile(pubHex); });
|
||||
return;
|
||||
}
|
||||
if (kind === 'game'){
|
||||
/* a publisher is sharing their gameplay (Region-Capture cropped
|
||||
* iframe). Route to its own TILE_KIND so it coexists with a
|
||||
* normal screen-share from the same person. */
|
||||
gameStreams.set(pubHex, ev.streams[0]);
|
||||
renderVideoTile('gameshare', pubHex, ev.streams[0]);
|
||||
watchVideoTrackForRemoval(ev.track, () => removeVideoTile('gameshare', pubHex));
|
||||
const s = ev.streams[0];
|
||||
gameStreams.set(pubHex, s);
|
||||
renderVideoTile('gameshare', pubHex, s);
|
||||
watchVideoTrackForRemoval(ev.track, () => { if (gameStreams.get(pubHex) === s) removeVideoTile('gameshare', pubHex); });
|
||||
return;
|
||||
}
|
||||
if (kind !== 'mic'){
|
||||
|
|
@ -3595,8 +3603,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
|
|||
|
||||
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-02</span><br>
|
||||
md5 <span class="stamp-md5">d4513db08ec37ff2a55a1cf91cf300da</span><br>
|
||||
sha256 <span class="stamp-sha">da7da34bdf1b955af557df99a2bfd701ea2ab734c00dee9776f250fccddfcf4d</span><br>
|
||||
md5 <span class="stamp-md5">9874964f15f679f199a10f6b652d6ca4</span><br>
|
||||
sha256 <span class="stamp-sha">322d72414d2e6cb89de6e8ee961f312fffdea9e539d77650efa6d9ec1844be77</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue