Files
pig/apps
karti b63ed0181f
CI / verify (push) Successful in 3m20s
CI / publish (push) Has been skipped
Fix the music never starting in Safari
It played in Chrome and was silent on every Apple device. Two false signals,
compounding.

Neither the play() promise nor a synchronous `paused` check tells you whether
audio is playing. Chrome REJECTS the promise when autoplay is blocked, which is
the behaviour the obvious implementation is written against. WebKit RESOLVES
it, reports `paused === false` for an instant, and quietly pauses the element a
moment later. So the code concluded it had started, faded the volume up on a
silent element, and — because it thought it had succeeded — never armed the
gesture listener that was the entire fallback. Music could then never start at
all, no matter how many times the visitor clicked.

Traced by hooking HTMLMediaElement.prototype.play and addEventListener before
the app booted: exactly one play() call, "resolved paused=false", and no
pointerdown listener ever registered on window.

Two changes. Playing state is now driven by the element's own `playing` and
`pause` events, which are the only honest source. And the gesture listener is
armed UNCONDITIONALLY rather than only on a detected failure — play() on an
already-playing element is a no-op, so the redundant case costs nothing and the
broken case is fixed. The listeners are capture-phase so a component calling
stopPropagation cannot swallow them, and cover touchend and keydown as well.

Verified 12/12: Chrome and WebKit x desktop and iPhone x /, /learn and /margin
all reach t>2.5s at volume 0.14, and mute still fades and persists in both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 20:12:43 -07:00
..