diff --git a/web/zebra-spaces.html b/web/zebra-spaces.html index 6a64d39..c33b982 100644 --- a/web/zebra-spaces.html +++ b/web/zebra-spaces.html @@ -2902,9 +2902,11 @@ function stopMeter(uuid){ meterCtl.delete(uuid); } * autoplay policy is satisfied. Each tone uses a short exponential * fade-out to avoid click artifacts. * - * Tones are skipped if the page is hidden (background tab) — the - * idea is to notify the LIVE user, not interrupt them when they - * stepped away. + * Tones play even when the tab is in the background — the doorman / + * mod use case wants to know a guest just arrived without having to + * watch the tab. Browsers throttle some background work but Web + * Audio scheduling is preserved as long as the AudioContext was + * created after a user gesture (the 'enter' click counts). * ================================================================== */ let _toneCtx = null; function _toneCtxGet(){ @@ -2913,8 +2915,12 @@ function _toneCtxGet(){ return _toneCtx; } function playToneBlip(freq, durationMs, type){ - if (typeof document !== 'undefined' && document.hidden) return; const ctx = _toneCtxGet(); if (!ctx) return; + /* if the user gesture was throttled (some mobile browsers suspend + * the context on tab hide), nudge it back to running before + * scheduling — resume() on a suspended context restarts the + * timeline so the tone actually fires. */ + if (ctx.state === 'suspended'){ try { ctx.resume(); } catch(_){} } try { const t0 = ctx.currentTime; const osc = ctx.createOscillator(); @@ -4091,8 +4097,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');