zebra-report: tap-anywhere-to-resume on mobile autoplay block
When mobile Firefox/Safari blocks audio.play() on auto-enrolled DJ streams, queue the elements and retry on the first pointerdown/ touchstart anywhere on the page. WebRTC stays unmuted as fallback so the listener isn't silent in the meantime.
This commit is contained in:
parent
e3363d9cf1
commit
393b81fb23
1 changed files with 42 additions and 3 deletions
|
|
@ -4050,6 +4050,33 @@ const streamAudio = new Map(); // uuid -> <audio> pulling stream
|
|||
function streamUrlFor(pubHex){
|
||||
return SFU_BASE + '/stream?room=' + encodeURIComponent(roomID) + '&pub=' + pubHex;
|
||||
}
|
||||
/* Tap-to-resume queue: when mobile Firefox/Safari blocks autoplay
|
||||
* (auto-enrolment runs too far away from the entry-button gesture
|
||||
* for the activation window to still be alive), we stash the audio
|
||||
* element here and retry its play() on the first user touch anywhere
|
||||
* on the page. One global listener handles every queued stream at
|
||||
* once. Idempotent install. */
|
||||
const pendingAutoplay = new Set();
|
||||
let tapResumeInstalled = false;
|
||||
function installTapResume(){
|
||||
if (tapResumeInstalled) return;
|
||||
tapResumeInstalled = true;
|
||||
const retry = () => {
|
||||
if (!pendingAutoplay.size) return;
|
||||
for (const a of [...pendingAutoplay]){
|
||||
const p = a.play();
|
||||
if (p && p.then) p.then(() => pendingAutoplay.delete(a)).catch(()=>{});
|
||||
else pendingAutoplay.delete(a);
|
||||
}
|
||||
if (!pendingAutoplay.size){
|
||||
document.removeEventListener('pointerdown', retry);
|
||||
document.removeEventListener('touchstart', retry);
|
||||
tapResumeInstalled = false;
|
||||
}
|
||||
};
|
||||
document.addEventListener('pointerdown', retry, { passive: true });
|
||||
document.addEventListener('touchstart', retry, { passive: true });
|
||||
}
|
||||
async function startStream(uuid, pubHex){
|
||||
/* DON'T mute the WebRTC audio yet — if the fresh <audio>'s autoplay
|
||||
* is blocked (common on mobile after the entry gesture's grace has
|
||||
|
|
@ -4106,7 +4133,19 @@ async function startStream(uuid, pubHex){
|
|||
const p = a.play();
|
||||
if (p && p.then){
|
||||
p.then(() => logLine('', 'stream on for '+pubHex.slice(0,12)+' — DJ mode (~2s delay, glitch-free)'))
|
||||
.catch(e => unmuteWebRtcOnFail('autoplay blocked: '+e.message));
|
||||
.catch(e => {
|
||||
/* mobile Firefox / Safari block autoplay when the gesture
|
||||
* activation window has expired between entry-click and
|
||||
* auto-enrolment. Don't permanently fall back to WebRTC —
|
||||
* queue this element for tap-to-resume so the next tap
|
||||
* anywhere on the page retries play(). */
|
||||
pendingAutoplay.add(a);
|
||||
installTapResume();
|
||||
logLine('', 'stream for '+pubHex.slice(0,12)+' — tap anywhere to start ('+e.message+')');
|
||||
/* Keep WebRTC audible as the fallback while waiting for a tap. */
|
||||
const w = remoteAudio.get(uuid);
|
||||
if (w) try { w.muted = false; } catch(_){}
|
||||
});
|
||||
} else {
|
||||
logLine('', 'stream on for '+pubHex.slice(0,12)+' — DJ mode (~2s delay, glitch-free)');
|
||||
}
|
||||
|
|
@ -4780,8 +4819,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-04</span><br>
|
||||
md5 <span class="stamp-md5">a0d7d8646e0dcec5b7563cc20ee69ade</span><br>
|
||||
sha256 <span class="stamp-sha">712548a89b0e0ebfa299b91a360ef0a75128e5f35d17b2ffd7519bf0ff4423fa</span><br>
|
||||
md5 <span class="stamp-md5">988fb9812616b4cbd5c7f1073f3e4d01</span><br>
|
||||
sha256 <span class="stamp-sha">7b9cc2c6cdab3bba55beb73b6afa413b784743b986294b3ad4e043f31c553e3f</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