Skip to content

fix(player): restart on re-tap + kill loop-all Now Playing flicker - #28

Merged
EnesYilmazcode merged 2 commits into
mainfrom
claude/funny-hawking-930hed
Jul 15, 2026
Merged

EnesYilmazcode merged 2 commits into
mainfrom
claude/funny-hawking-930hed

Conversation

@EnesYilmazcode

Copy link
Copy Markdown
Owner

Fixes #9. Fixes #14.

Problem

The load effect was keyed on [index, current?.id], so:

  • Re-selecting the track already playing (same index) never reloaded — tapping a finished/playing track did nothing instead of restarting.
  • next()/prev() on a single-track loop-all queue hit the same dead end.
  • The loop-all wrap used setIndex(-1) + requestAnimationFrame(() => setIndex(0)), which made current null for a frame and flashed the Now Playing screen closed (losing lyrics scroll) every cycle.

Fix

Add a playToken nonce to the load effect's deps, bumped whenever a restart is intended:

  • playQueue bumps it → re-tapping the current track restarts it.
  • next()/prev() bump it (instead of a no-op setIndex) when the target index equals the current one (single-track loop-all). They now read index from the render closure so that case is detectable.
  • onEnded's loop-all wrap sets index 0 and bumps the token instead of the setIndex(-1) bounce — current never becomes null, so no more flicker.

Verification

Built clean; behavioral test:

Check Result
Play → seek to 5s → re-tap same track → currentTime 0.64 (restarted) ✅
Switch to a different track plays, metadata "Express Track"
page errors none ✅

The flicker fix is verified by construction (the setIndex(-1) null-frame is gone); the single-track loop-all + on-device Now Playing behavior are best confirmed on your phone.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits July 15, 2026 00:21
The load effect was keyed on [index, current?.id], so re-selecting the track
already playing (same index) never reloaded it — tapping a finished/playing
track did nothing instead of restarting. next()/prev() on a single-track
loop-all queue had the same dead-end. And the loop-all wrap used
setIndex(-1)+requestAnimationFrame(()=>setIndex(0)), which made `current` null
for a frame and flashed the Now Playing screen closed (losing lyrics scroll)
every cycle.

Add a playToken nonce to the load effect's deps and bump it whenever a restart
is intended:
- playQueue bumps it, so re-tapping the current track restarts it.
- next()/prev() bump it (instead of a no-op setIndex) when the target index
  equals the current one (single-track loop-all).
- onEnded's loop-all wrap sets index 0 and bumps the token instead of the
  setIndex(-1) bounce, so `current` never becomes null — no more flicker.

next()/prev() now read `index` from the render closure (added to deps) so the
same-index restart case is detectable.

Verified in-browser: playing a track, seeking to 5s, and re-tapping it restarts
to ~0; switching to a different track still works; no errors.

Fixes #9. Fixes #14.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkDKh1Uo1a4D7n5wCKdcKF
Review follow-up: instead of reading `index` from the closure (which could
collapse two synchronous next()/prev() calls into a single advance), special-
case only the single-track queue — where a restart needs a playToken bump
because the index can't change — and keep the functional setIndex updater for
the multi-track advance so it stays atomic. Also drops `index` from the deps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkDKh1Uo1a4D7n5wCKdcKF
@EnesYilmazcode
EnesYilmazcode merged commit 066e74c into main Jul 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants