From 130e54cad8b83febfd0742876a1ebfcdb1e79e58 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Wed, 3 Jun 2026 12:38:57 -0400 Subject: [PATCH] =?UTF-8?q?zebra-report:=20deploy=20=E2=80=94=20drop=20til?= =?UTF-8?q?es=20of=20demoted=20peers=20immediately?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zebra-report/zebra-spaces.html | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/zebra-report/zebra-spaces.html b/zebra-report/zebra-spaces.html index 83bd378..4da0f36 100644 --- a/zebra-report/zebra-spaces.html +++ b/zebra-report/zebra-spaces.html @@ -3191,6 +3191,21 @@ async function handleSignal(raw){ if (canSpeak(myRole) && canSpeak(m.role) && !peers.has(m.uuid)){ connectToPeer(m.uuid, myUUID < m.uuid); } + /* If the role transition stripped them of the ability to + * publish (anything -> listener), their camera/screen/game + * tiles can't get fresh RTP anymore. The demoted page calls + * sfuUnpublish* on its own side which should propagate via + * SFU 'ended', but that path is unreliable (Pion may not + * fire OnConnectionStateChange immediately and SSE renego + * can race). Authoritative removal: drop tiles by pubkey + * here, the moment the role change broadcast lands. */ + if (canSpeak(prev) && !canSpeak(m.role) && subjPub){ + try { + removeScreenTile(subjPub); + removeCameraTile(subjPub); + removeVideoTile('gameshare', subjPub); + } catch(_){} + } } renderRoom(); reorderTiles(); @@ -3974,8 +3989,8 @@ logLine('', 'ready โ€” pick a handle, type a rendezvous code, enter the space');