Skip to content

fix(nowplaying): cover leaves with the track, not lingering/expanding on pause#53

Open
gyng wants to merge 1 commit into
mainfrom
fix/nowplaying-cover-track-loss
Open

fix(nowplaying): cover leaves with the track, not lingering/expanding on pause#53
gyng wants to merge 1 commit into
mainfrom
fix/nowplaying-cover-track-loss

Conversation

@gyng

@gyng gyng commented Jun 25, 2026

Copy link
Copy Markdown
Owner

What

Fixes the now-playing widget where, on pause, the album cover expands to fill the box for a moment before disappearing (reported as "the track text disappears, then the cover").

Root cause

The title/artist are derived straight from props, so they vanish the instant a session loses its media. The cover, however, lives in React state and was held by the crossfade's no-art grace (NO_ART_GRACE_MS = 1200) whenever the art URL was absent — including when there was no current track at all (a player that tears down / recreates its SMTC session on pause, so the prior track can't be carried forward). With the title/artist rows gone, the flex: 1 cover stack grew to fill the freed space and lingered up to ~1.2s before fading.

Fix

Tie the cover's lifecycle to whether there's a current track:

  • Effect — drop the layers immediately when there is no media (!hasSession || !hasMediaRef.current), not only when there's no session. The no-art grace below now only ever bridges a genuine art-lag (a track is present, its cover just hasn't arrived).
  • Render — gate the cover stack on hasMedia, so the cover leaves in the same commit as the title (no transient expand frame).

The idle label (text with no session) and track-to-track crossfade are unchanged.

Test

Adds a failing-first test in NowPlaying.test.tsx using a present session with last_media_update: null. It reproduced the bug (cover held: expected 1 to be 0) and is green after the fix. Existing grace/crossfade tests still pass.

Verification

  • npm run check ✓ · npm run lint ✓ (Prettier + ESLint, 0 warnings) · full unit suite 269 files
  • Pure frontend change — no Rust/bridge touched.
  • Note: a live repro depends on the player actually dropping its SMTC session on pause (browser media tabs do; Spotify/foobar2000 usually keep it and just dim). The unit test pins the path deterministically regardless.

Heads-up for review: NowPlaying.tsx renders as a binary diff on GitHub because the file contains two pre-existing \0 delimiters in trackKey (${source}\0${title}\0${artist}) — unrelated to this change.

🤖 Generated with Claude Code

… on pause

When a session lost its current track (media gone while the session stayed
selected — e.g. a player that tears down/recreates its SMTC session on pause),
the title cleared instantly (it is prop-derived) while the album cover stayed up
on the crossfade's no-art grace (NO_ART_GRACE_MS), growing to fill the box the
title/artist had vacated before finally fading — the reported "cover expands for
a short while then disappears".

Tie the cover's lifecycle to whether there is a current track: drop the layers at
once when there is no media (not only when there is no session), and gate the
cover stack on `hasMedia` so it leaves in the same commit as the title. The
no-art grace now only bridges a genuine art-lag (media present, art not yet
arrived); the idle `label` and track-to-track crossfade are unchanged.

Adds a failing-first test (a present session with null media) that reproduced the
lingering cover (was: 1 layer held; now: 0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant