Removed Phase 28 (Metronome Responsiveness) from v1.6 milestone.
Metronome responsiveness is satisfactory after Phase 26-27 improvements.
MET-01, MET-02 requirements moved to Out of Scope.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add media state tracking to JKSessionOpenMenu component
- Disable menu items when any media (JamTrack, Backing Track, Metronome) is open
- Show warning toast when user attempts to open another media type
- Update backing track and metronome track styling and icons
- Adjust close button styling in session screen media sections
- Handle cancelled file selection dialog for backing tracks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The stylesheet copying code was accidentally removed in aa731c96d,
causing popup windows (metronome, backing track) to render without
CSS styles. This restores the code that copies all <link> and <style>
elements from the parent window to the popup.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change play/stop icon colors from black (#000000) to blue (#2c7be5)
- Adjust JamTrack player dimensions to 420x220px
- Reduce backing track popup height from 400 to 250px
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Detect track end via position reset (>80% to <20%) since native client
auto-loops without updating isSessionTrackPlaying state
- Implement manual looping: Stop → Seek to 0 → Play when loop enabled
- Fix Close button to use onClose callback for proper WindowPortal cleanup
- Add boolean conversion for isSessionTrackPlaying (handles string/number)
- Clean up debug console.log statements
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Native client needs Stop -> Seek(0) -> Play sequence to reliably
start playback after track has finished. Previously we only did
this when "atEnd", but after track finishes and resets to 0, the
"atEnd" check is false.
Fix: Also do the full reset sequence when position is at the
beginning (< 100ms). This ensures native client is in the right
state whether starting fresh or restarting after track finished.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When track reaches end:
- UI was reset to position 0
- Native client was NOT seeked to position 0
Result: First play click failed because native client was still at end,
but UI showed position 0 so atEnd check was false and no seek was done.
Fix: Call SessionTrackSeekMs(0) when track ends, so native client
position matches UI state and next play works immediately.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Race condition: when opening backing track, the sequence was:
1. Local state set from native client (my previous fix)
2. Native callback triggers refreshCurrentSession
3. Server hasn't received sync yet, returns empty backing_tracks
4. dispatch(setBackingTracks([])) clears local data
5. Track disappears
Fix: Only dispatch setBackingTracks if server has data. When user
closes backing track, closeMedia action clears the state directly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
MediaTrackGroup is 6 (not 8) per globals.js ChannelGroupIds.
8 is StreamOutChatGroup, which is why no backing tracks were found.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After opening a backing track file via native client:
1. Call SessionGetAllControlState(true) to get track info
2. Extract backing track data (id, rid, filename, shortFilename)
3. Dispatch to both Redux slices:
- activeSessionSlice.addBackingTrack (for track sync)
- mediaSlice.setBackingTracks (for session screen UI)
Also fixes syncTracksToServer calls that incorrectly passed jamClient
object instead of server.clientId.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tasks completed: 2/2
- Use openBackingTrack action in handleBackingTrackSelected
- Add ignore flag to duration fetch useEffect
SUMMARY: .planning/phases/27-backing-track-sync/27-01-SUMMARY.md
- Add let ignore = false at start of duration fetch useEffect
- Check ignore flag after async jamClient call
- Add cleanup function that sets ignore = true
- Prevents 'state update on unmounted component' React warnings
when closing backing track popup quickly
- Add jamServer to useMediaActions by creating object from subscribe/unsubscribe
- Pass jamServer to loadJamTrackThunk so it can subscribe to packaging progress
- Improve error handling to extract message from Response objects (not just Error)
- Fixes "Failed to start packaging: undefined" error
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added loadJamTrack call in handleJamTrackSelect else branch
- When syncResult.isSynchronized is false, triggers download flow
- This transitions state through checking → packaging → downloading → keying → synchronized
- Fixes empty JamTrack player for non-synchronized tracks
- Change condition from 'idle' OR 'synchronized' to only 'synchronized'
- Controls only appear after JamTrack is synchronized with backend
- Download progress UI handles loading states appropriately
- Change condition from 'synchronized' OR 'idle' to only 'synchronized'
- Stems only appear after JamTrack is synchronized with backend
- Already-synchronized tracks show stems immediately (checkJamTrackSync returns synchronized)
- Import checkJamTrackSync from mediaSlice
- Call checkJamTrackSync BEFORE setSelectedJamTrack/setJamTrackStems
- Show different toast messages based on sync state
- This ensures downloadState transitions from 'idle' appropriately
Phase 26: JamTrack Polish
- Plan 26-03 removes 'idle' from valid render states
- Closes UAT gap: stems/controls appearing before sync
- 1 plan in wave 3, depends on 26-02
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Import and call cleanupJamTrackCallbacks in cleanup useEffect
- Wrap controls section in condition: only render when downloadState
is 'idle' or 'synchronized' and not in initial loading
- Fixes memory leak from orphaned window.jamTrackDownload* globals
- Fixes UX issue where controls appeared before track ready
- Replace TODO console.log with actual navigation
- Open JamTrack editor at /jamtracks/{id} in new tab
- Use noopener,noreferrer for security best practices
- Change window dimensions from 600x500 to 460x350
- Disable scrollbars since content now fits properly
- Player content is 420px wide + 20px padding on each side
- 3 phases: JamTrack Polish, Backing Track Sync, Metronome Responsiveness
- 8 requirements mapped to phases
- Research complete for all features
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 5 comprehensive test sections covering all memory leak scenarios
- Timer cleanup verification test
- Callback accumulation verification test
- Async operation cleanup verification test
- 15-minute modal idle stability test
- 15-minute active recording stability test
- Troubleshooting guide for each failure type
- Add ignore flag pattern to audio preference useEffect
- Add ignore flag pattern to video sources useEffect
- Guard state updates with !ignore check
- Prevents "state update on unmounted component" warnings