Bug 1 — playback stops on navigation:
WaveSurfer v7 creates its <audio> element inside the container div. When
SongPage unmounts, the container is removed from the DOM, taking the audio
element with it and stopping playback. Fix: AudioService owns a persistent
hidden <audio> element on document.body and passes it to WaveSurfer via the
`media` option. WaveSurfer uses it for playback but does not destroy it on
WaveSurfer.destroy(), so audio survives any number of navigations.
Bug 2 — stale playhead/duration when opening a new song:
initialize() called destroyWaveSurfer() but never reset the store, so the
previous song's currentTime, duration, and isPlaying leaked into the new song's
load sequence. Fix: reset those three fields in the store immediately after
tearing down the old WaveSurfer instance. cleanup() also now resets duration.
Bug 3 — excessive console noise on mobile:
Remove console.warn from play() (silent return when not ready) and from
useWaveform's play() wrapper. Only console.error on actual errors remains.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
playerStore: remove currentPlayingSongId/currentPlayingBandId/setCurrentPlayingSong.
Single pair (currentSongId/currentBandId) now set exclusively when play() is
called, not when the page opens. This means MiniPlayer and sidebar links only
appear after audio has been started — correct UX for a "now playing" widget.
audioService: play() calls setCurrentSong instead of setCurrentPlayingSong;
cleanup() clears it. Remove isReadyForPlayback() and canAttemptPlayback()
aliases — all callers now use isWaveformReady() directly.
useWaveform: remove setCurrentSong call from init (store updated by play()
now); restore-playback snapshot reads currentSongId/currentBandId.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
useWaveform.ts:
- Remove requestAnimationFrame polling loop that was re-running after every
re-initialization and leaking across renders when cleanup didn't fire
- Remove local useState for isPlaying/currentTime/duration; these now come
directly from usePlayerStore selectors — WaveSurfer event handlers in
AudioService already write to the store, so no intermediate sync needed
- The useEffect is now a clean async init only; no cleanup needed (AudioService
persists intentionally across page navigations)
tests/:
- Delete 3 obsolete test files that tested removed APIs (logging system,
setupAudioContext, ensureAudioContext, initializeAudioContext)
- Add tests/audioService.test.ts: 25 tests covering initialize(), play(),
pause(), seekTo(), cleanup(), and all WaveSurfer event→store mappings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Simplified audio context access from 7 fallback methods to 2 reliable methods
- Added comprehensive test suite with 12 tests covering all scenarios
- Enhanced error handling and debugging capabilities
- Maintained full compatibility with WaveSurfer.js 7.12.5
- Build and production deployment ready
Changes:
- src/services/audioService.ts: Core implementation with simplified context access
- tests/audioService.test.ts: Comprehensive test suite
Next: Logging optimization to reduce console spam in production
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>