fix: paused track resumed on any page click (unlock listener overrode pause)

The AudioContext autoplay-unlock listener (pointerdown → ctx.resume()) was
persistent, so every click anywhere resumed the context — including after a
deliberate pause (pause = ctx.suspend()). Result: pause, click back on the page,
and the track resumed from its position while React's `playing` stayed false, so
the button showed "paused" and it took two clicks to actually stop it.

The gesture only needs to unlock the context ONCE; sticky activation lets
engine.play() resume it thereafter. Make the listener { once: true } so it can't
fight an intentional pause.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 12:44:25 +00:00
co-authored by Claude Opus 4.8
parent f0d475ea2e
commit 597675d6a0
@@ -106,9 +106,11 @@ export const MusicPlayerHost = () => {
});
engineRef.current = engine;
engine.setVolume(muted ? 0 : volume);
// Resume the AudioContext on the first user gesture (browser autoplay policy).
// Satisfy the browser autoplay policy ONCE, on the first user gesture — after that, sticky activation
// lets engine.play() resume the context on its own. It MUST be once-only: a persistent listener would
// resume the context on every click, overriding a deliberate pause (pause = ctx.suspend()).
const unlock = () => engine.unlock();
document.addEventListener('pointerdown', unlock);
document.addEventListener('pointerdown', unlock, { once: true });
return () => {
document.removeEventListener('pointerdown', unlock);
engine.destroy();