From 063233f53c8abac66774722564bc5a7e0863bf11 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Wed, 3 Jun 2026 12:14:45 -0400 Subject: [PATCH] zebra-spaces: new promotions start muted by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Listener -> speaker/cohost/host transition is a fresh mic grab — no hot-mic surprise. Set muted=true + persist to sessionStorage BEFORE ensureMicAndUI runs, so applyMuteState picks it up cleanly when the mic track is acquired. User can click 'unmute' when ready. Doesn't affect bless-reclaim rejoin (welcome path), where the user's previously-saved mute state is restored — they come back in the same mute state they last chose. --- web/zebra-spaces.html | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/web/zebra-spaces.html b/web/zebra-spaces.html index baa49b4..ca8b7b2 100644 --- a/web/zebra-spaces.html +++ b/web/zebra-spaces.html @@ -3229,6 +3229,14 @@ async function onRoleChanged(prev, next){ inRoleTransition = true; try { if (!canSpeak(prev) && canSpeak(next)){ + /* Listener -> speaker (or cohost/host) is a brand-new mic grab. + * Default to MUTED so the user doesn't broadcast whatever was + * happening in their room when they accepted. They can click + * 'unmute' when they're ready. ensureMicAndUI() reads the + * sessionStorage value via applyMuteState, so set it BEFORE + * the acquire. */ + muted = true; + try { sessionStorage.setItem(MUTE_STATE_KEY, '1'); } catch(_){} await ensureMicAndUI(); for (const [uuid, mm] of members){ if (uuid === myUUID) continue; @@ -3898,8 +3906,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');