From 165d85759df2fbebbfd33b5e5500cca5b4374018 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Thu, 4 Jun 2026 11:53:17 -0400 Subject: [PATCH] =?UTF-8?q?zebra-spaces:=20UA-gated=20auto-rejoin=20?= =?UTF-8?q?=E2=80=94=20mobile=20pre-fills=20code=20+=20waits=20for=20tap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Desktop keeps the zero-click auto-rejoin convenience. Mobile (Android / iOS) pre-fills the rendezvous code and surfaces 'click enter to resume — CODE' as a status, requiring one tap to land in the space. Why mobile-only block: Firefox Android (and likely iOS Safari) needs primeAudioOnGesture's silent-oscillator wake to actually start the AudioContext render thread, and primeAudioOnGesture only runs inside the btn-enter click handler. An auto-rejoin that bypasses the click leaves audioCtx suspended → listener MediaStreamSource attaches to a dead destination → silence. Confirmed today by fox via the ctxState=suspended telemetry on the phone. This is the same trade fox originally took in 12df78a but scoped better: desktop got the auto-rejoin restored in f388d64 because they don't need the audio gesture, and now mobile pays one tap to keep listener audio working. --- web/zebra-spaces.html | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/web/zebra-spaces.html b/web/zebra-spaces.html index f057f04..7bf089e 100644 --- a/web/zebra-spaces.html +++ b/web/zebra-spaces.html @@ -5283,6 +5283,25 @@ $('btn-copy-share').addEventListener('click', async () => { return; } $('rdv-code').value = saved; + /* Auto-rejoin without a user gesture works on desktop (browsers + * grant audio engagement after first interaction with the origin) + * but breaks mobile listener audio: Firefox Android requires the + * silent-oscillator wake in primeAudioOnGesture to actually start + * the AudioContext render thread, and primeAudioOnGesture only + * runs inside the btn-enter click handler. Auto-rejoin that + * bypasses the click → audioCtx stays suspended → MediaStream- + * Source attaches silently → no audio. + * + * UA-gated: desktop preserves the zero-click rejoin convenience; + * mobile pre-fills the code + asks for one tap on enter so the + * gesture window opens and audio actually plays. Fox 2026-06-04 + * chose this trade after the AudioContext-suspended telemetry. */ + const isMobile = /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent); + if (isMobile){ + logLine('', 'last space: '+saved+' — click enter to resume (mobile needs gesture for audio)'); + setStatus('click enter to resume — '+saved, 'warn'); + return; + } logLine('', 'auto-rejoining last space …'); setTimeout(() => { joinSpace().catch(e => logLine('err', 'auto-rejoin failed: ' + e.message)); }, 100); })(); @@ -5356,8 +5375,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');