fix(web): make the Frutiger Aero soundtrack start on the first switch and skip tracks that never begin playing
This commit is contained in:
parent
8f8a54cf18
commit
2d4a42bcef
5 changed files with 208 additions and 105 deletions
23
AGENTS.md
23
AGENTS.md
|
|
@ -186,15 +186,20 @@ Themes: `web` = default frosted-glass website (sidebar + content, light/dark),
|
|||
random track from the *Frutiger Aero* SoundCloud playlist (a hidden SoundCloud
|
||||
iframe driven through their widget API: it picks a random index from `getSounds`
|
||||
and re-randomises on every `PLAY` event so the set never plays in order; the chip
|
||||
label is synced from `getCurrentSound`, not from what we asked for). Two
|
||||
SoundCloud quirks are handled there: entries from `getSounds` can arrive
|
||||
not-yet-hydrated (no `title`/`user`) and are still perfectly playable, so the
|
||||
random pick filters on `playable !== false` *only* — `playable: false` means the
|
||||
uploader left "Enable app playback" off, and SoundCloud refuses to stream those
|
||||
to a third-party app at all (picking one just leaves the player silent); and the
|
||||
widget API drives the iframe over `postMessage`, so every call is gated behind
|
||||
an `alive()` check — React detaches the iframe *before* the effect cleanup runs,
|
||||
and an unguarded `pause()` there throws `Cannot read properties of null (reading
|
||||
label is synced from `getCurrentSound` on PLAY, not from what we asked for).
|
||||
SoundCloud's widget is quirky and `AeroMusic.tsx` works around all of it: the
|
||||
Widget API script is loaded *before* the player iframe is mounted, because
|
||||
creating the iframe first lets the widget boot and fire READY before we can
|
||||
bind to it, which leaves the first switch silent (later switches are fine, as
|
||||
the script is cached by then); `playable` is only trusted once the whole set is
|
||||
described, because SoundCloud sends the set in stages and every entry claims
|
||||
`playable: true` until then (`playable: false` means the uploader left "Enable
|
||||
app playback" off, so a third-party app can't stream it at all) — and since even
|
||||
that flag still lies, playback is *verified*: a track that is still `paused`
|
||||
once we have started it is rejected and another is picked; and every widget call
|
||||
goes through an `alive()` check, because the API drives the iframe over
|
||||
`postMessage` and React detaches the iframe *before* the effect cleanup runs —
|
||||
an unguarded `pause()` there throws `Cannot read properties of null (reading
|
||||
'postMessage')`, which unmounts the whole page. The two remaining feature panels (`.web-split`) stretch
|
||||
to equal height and share a fixed `16 / 10` `.fw` window (the `FeatureWindow`
|
||||
component) — decorative, **asset-free CSS mock-ups** rather than screenshots:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue