docs(26): create phase plan for JamTrack Polish
Phase 26: JamTrack Polish - 2 plan(s) in 2 wave(s) - Wave 1: 26-01 (UI fixes - sizing, navigation) - Wave 2: 26-02 (state/callback fixes - cleanup, deferred rendering) - Ready for execution Requirements covered: - JT-01: Defer UI rendering until track ready - JT-02: Fix WindowPortal sizing (460x350) - JT-03: Implement create custom mix navigation - JT-04: Add callback cleanup for jamTrackDownload* globals Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
eab0b0d19a
commit
48c9bf8313
|
|
@ -31,10 +31,11 @@ v1.6 addresses usability issues reported in three media features: JamTrack (load
|
|||
2. JamTrack player fits properly in popup window without scrollbars
|
||||
3. "Create custom mix" button opens JamTrack editor in new tab
|
||||
4. No console warnings about leaked callbacks when closing JamTrack or navigating away
|
||||
**Plans**: TBD
|
||||
**Plans**: 2 plans
|
||||
|
||||
Plans:
|
||||
- [ ] 26-01: TBD
|
||||
- [ ] 26-01-PLAN.md - Fix window sizing and create custom mix navigation
|
||||
- [ ] 26-02-PLAN.md - Add callback cleanup and defer controls rendering
|
||||
|
||||
### Phase 27: Backing Track Sync
|
||||
**Goal**: Backing Track appears in session screen when opened
|
||||
|
|
@ -67,7 +68,7 @@ Plans:
|
|||
|
||||
| Phase | Milestone | Plans Complete | Status | Completed |
|
||||
|-------|-----------|----------------|--------|-----------|
|
||||
| 26. JamTrack Polish | v1.6 | 0/TBD | Not started | - |
|
||||
| 26. JamTrack Polish | v1.6 | 0/2 | Planned | - |
|
||||
| 27. Backing Track Sync | v1.6 | 0/TBD | Not started | - |
|
||||
| 28. Metronome Responsiveness | v1.6 | 0/TBD | Not started | - |
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
phase: 26-jamtrack-polish
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- jam-ui/src/components/client/JKSessionScreen.js
|
||||
- jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
autonomous: true
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "JamTrack player fits properly in popup window without scrollbars"
|
||||
- "Create custom mix button opens JamTrack editor in new tab"
|
||||
artifacts:
|
||||
- path: "jam-ui/src/components/client/JKSessionScreen.js"
|
||||
provides: "Corrected WindowPortal dimensions for JamTrack player"
|
||||
contains: "width=460,height=350"
|
||||
- path: "jam-ui/src/components/client/JKSessionJamTrackPlayer.js"
|
||||
provides: "Working create custom mix navigation"
|
||||
contains: "window.open"
|
||||
key_links:
|
||||
- from: "JKSessionJamTrackPlayer.js"
|
||||
to: "/jamtracks/{id}"
|
||||
via: "window.open on create custom mix click"
|
||||
pattern: "window\\.open.*jamtracks"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Fix JamTrack player window sizing and implement "create custom mix" navigation.
|
||||
|
||||
Purpose: Address two visual/navigation bugs that impact user experience - popup window has scrollbars due to oversized dimensions, and "create custom mix" button does nothing.
|
||||
Output: JamTrack player that fits its popup window and allows users to create custom mixes via the JamTrack editor.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/Users/nuwan/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/Users/nuwan/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@jam-ui/src/components/client/JKSessionScreen.js
|
||||
@jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Fix WindowPortal sizing for JamTrack player</name>
|
||||
<files>jam-ui/src/components/client/JKSessionScreen.js</files>
|
||||
<action>
|
||||
Find the WindowPortal for JamTrack player (around line 1750) with `windowFeatures="width=600,height=500..."`.
|
||||
|
||||
Change the dimensions to `width=460,height=350` to properly fit the player content (which is 420px wide with 20px padding on each side).
|
||||
|
||||
Before:
|
||||
```
|
||||
windowFeatures="width=600,height=500,left=200,top=200,menubar=no,toolbar=no,status=no,scrollbars=yes,resizable=yes,location=no, addressbar=no"
|
||||
```
|
||||
|
||||
After:
|
||||
```
|
||||
windowFeatures="width=460,height=350,left=200,top=200,menubar=no,toolbar=no,status=no,scrollbars=no,resizable=yes,location=no,addressbar=no"
|
||||
```
|
||||
|
||||
Note: Also change `scrollbars=yes` to `scrollbars=no` since the window should now fit content without scrolling.
|
||||
</action>
|
||||
<verify>
|
||||
Grep for the updated window dimensions:
|
||||
```bash
|
||||
grep -n "width=460,height=350" jam-ui/src/components/client/JKSessionScreen.js
|
||||
```
|
||||
Should find the JamTrack WindowPortal with the new dimensions.
|
||||
</verify>
|
||||
<done>WindowPortal for JamTrack player uses width=460, height=350 with scrollbars=no</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Implement "create custom mix" navigation</name>
|
||||
<files>jam-ui/src/components/client/JKSessionJamTrackPlayer.js</files>
|
||||
<action>
|
||||
Find the "create custom mix" link (around line 851-861) which currently has:
|
||||
```jsx
|
||||
onClick={() => console.log('TODO: Open custom mix creator')}
|
||||
```
|
||||
|
||||
Replace with proper navigation that opens the JamTrack editor in a new tab:
|
||||
```jsx
|
||||
onClick={() => window.open(`/jamtracks/${jamTrack?.id}`, '_blank', 'noopener,noreferrer')}
|
||||
```
|
||||
|
||||
The JamTrack editor route at `/jamtracks/{id}` already exists in the application and provides the full stem mixing interface.
|
||||
|
||||
Note: Use `noopener,noreferrer` for security best practices when opening external windows.
|
||||
</action>
|
||||
<verify>
|
||||
Grep for the window.open implementation:
|
||||
```bash
|
||||
grep -n "window.open.*jamtracks" jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
```
|
||||
Should find the onClick handler with proper navigation.
|
||||
</verify>
|
||||
<done>Clicking "create custom mix" opens /jamtracks/{id} in a new browser tab</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. Build check: `cd jam-ui && npm run build` completes without errors
|
||||
2. Code verification:
|
||||
- JKSessionScreen.js has `width=460,height=350` for JamTrack WindowPortal
|
||||
- JKSessionJamTrackPlayer.js has `window.open` for create custom mix link
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- JamTrack player WindowPortal uses correct dimensions (460x350)
|
||||
- "Create custom mix" link navigates to /jamtracks/{id} in new tab
|
||||
- No regressions in existing functionality
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/26-jamtrack-polish/26-01-SUMMARY.md`
|
||||
</output>
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
---
|
||||
phase: 26-jamtrack-polish
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["26-01"]
|
||||
files_modified:
|
||||
- jam-ui/src/store/features/mediaSlice.js
|
||||
- jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
autonomous: true
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "No console warnings about leaked callbacks when closing JamTrack"
|
||||
- "User sees loading indicator while backend processes track (not premature controls)"
|
||||
artifacts:
|
||||
- path: "jam-ui/src/store/features/mediaSlice.js"
|
||||
provides: "Callback cleanup function for jamTrackDownload* globals"
|
||||
contains: "cleanupJamTrackCallbacks"
|
||||
- path: "jam-ui/src/components/client/JKSessionJamTrackPlayer.js"
|
||||
provides: "Callback cleanup on unmount and deferred controls rendering"
|
||||
contains: "cleanupJamTrackCallbacks"
|
||||
key_links:
|
||||
- from: "JKSessionJamTrackPlayer.js"
|
||||
to: "mediaSlice.js"
|
||||
via: "dispatch(cleanupJamTrackCallbacks()) in useEffect cleanup"
|
||||
pattern: "cleanupJamTrackCallbacks"
|
||||
- from: "JKSessionJamTrackPlayer.js render"
|
||||
to: "downloadState.state"
|
||||
via: "conditional rendering of controls"
|
||||
pattern: "downloadState\\.state.*synchronized"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add callback cleanup for JamTrack download globals and defer player controls rendering until track is ready.
|
||||
|
||||
Purpose: Prevent memory leaks from orphaned window callbacks when closing JamTrack, and fix the UX issue where player controls appear before the track is actually ready to play.
|
||||
Output: Clean callback lifecycle and proper loading state management for JamTrack player.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/Users/nuwan/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/Users/nuwan/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/26-jamtrack-polish/26-01-SUMMARY.md
|
||||
@jam-ui/src/store/features/mediaSlice.js
|
||||
@jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
@jam-ui/src/hooks/useRecordingHelpers.js (lines 465-498 for cleanup pattern)
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add callback cleanup action to mediaSlice</name>
|
||||
<files>jam-ui/src/store/features/mediaSlice.js</files>
|
||||
<action>
|
||||
The downloadJamTrack thunk (lines 234-244) sets window globals but never cleans them up:
|
||||
- window.jamTrackDownloadProgress
|
||||
- window.jamTrackDownloadSuccess
|
||||
- window.jamTrackDownloadFail
|
||||
|
||||
Add a new action to clean up these callbacks. Add this after the existing slice actions (around line 400-450 where other actions are defined):
|
||||
|
||||
```javascript
|
||||
// Add to slice actions or as a standalone function
|
||||
export const cleanupJamTrackCallbacks = () => {
|
||||
// Clean up global callbacks set during download
|
||||
if (typeof window !== 'undefined') {
|
||||
delete window.jamTrackDownloadProgress;
|
||||
delete window.jamTrackDownloadSuccess;
|
||||
delete window.jamTrackDownloadFail;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
This follows the same pattern used in useRecordingHelpers.js (lines 488-496) for cleaning up window.JK callbacks.
|
||||
|
||||
Note: This is a simple function, not a thunk, since it doesn't need dispatch or getState.
|
||||
</action>
|
||||
<verify>
|
||||
Grep for the cleanup function:
|
||||
```bash
|
||||
grep -n "cleanupJamTrackCallbacks" jam-ui/src/store/features/mediaSlice.js
|
||||
```
|
||||
Should find the export and implementation.
|
||||
</verify>
|
||||
<done>mediaSlice exports cleanupJamTrackCallbacks function that removes window.jamTrackDownload* globals</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Call cleanup on unmount and defer controls rendering</name>
|
||||
<files>jam-ui/src/components/client/JKSessionJamTrackPlayer.js</files>
|
||||
<action>
|
||||
Two changes needed:
|
||||
|
||||
**1. Import and call cleanup on unmount:**
|
||||
|
||||
Add to imports (around line 4-9):
|
||||
```javascript
|
||||
import {
|
||||
loadJamTrack,
|
||||
checkJamTrackSync,
|
||||
closeJamTrack,
|
||||
setJamTrackState,
|
||||
setDownloadState,
|
||||
cleanupJamTrackCallbacks // Add this
|
||||
} from '../../store/features/mediaSlice';
|
||||
```
|
||||
|
||||
Update the cleanup useEffect (around lines 163-172) to also call cleanup:
|
||||
```javascript
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
mountedRef.current = false;
|
||||
|
||||
if (fqIdRef.current && jamClient) {
|
||||
dispatch(closeJamTrack({ fqId: fqIdRef.current, jamClient }));
|
||||
dispatch(clearOpenJamTrack());
|
||||
}
|
||||
|
||||
// Clean up download callbacks
|
||||
cleanupJamTrackCallbacks();
|
||||
};
|
||||
}, [dispatch, jamClient]);
|
||||
```
|
||||
|
||||
**2. Defer controls rendering until track is ready:**
|
||||
|
||||
Find the Controls Section (around line 720) and wrap it in a condition that checks if the track is ready:
|
||||
|
||||
```jsx
|
||||
{/* Controls Section - only show when not in loading/download states */}
|
||||
{(downloadState.state === 'idle' || downloadState.state === 'synchronized') && !isLoadingSync && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
||||
{/* ... existing controls ... */}
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
This ensures the playback controls only appear when:
|
||||
- downloadState is 'idle' (local file already synced) OR 'synchronized' (download complete)
|
||||
- AND not in initial loading state
|
||||
|
||||
The download progress UI (lines 593-711) already shows during download states, so this creates proper UX flow: loading -> download progress -> controls appear.
|
||||
</action>
|
||||
<verify>
|
||||
```bash
|
||||
# Check cleanup is imported and called
|
||||
grep -n "cleanupJamTrackCallbacks" jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
|
||||
# Check conditional rendering is in place
|
||||
grep -n "downloadState.state.*synchronized" jam-ui/src/components/client/JKSessionJamTrackPlayer.js
|
||||
```
|
||||
Both should return matches.
|
||||
</verify>
|
||||
<done>JKSessionJamTrackPlayer calls cleanupJamTrackCallbacks on unmount and only renders controls when track is ready</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Build verification and manual test notes</name>
|
||||
<files>None (verification only)</files>
|
||||
<action>
|
||||
Run build to verify no syntax errors:
|
||||
```bash
|
||||
cd jam-ui && npm run build
|
||||
```
|
||||
|
||||
Document manual test steps for verification:
|
||||
1. Open a JamTrack that needs downloading
|
||||
2. Observe: Loading indicator shown, controls hidden
|
||||
3. Wait for download to complete
|
||||
4. Observe: Controls appear after download
|
||||
5. Close JamTrack window
|
||||
6. Open browser console, verify no warnings about leaked callbacks
|
||||
7. Verify no "state update on unmounted component" warnings
|
||||
</action>
|
||||
<verify>
|
||||
Build command exits with code 0 and no TypeScript/compilation errors.
|
||||
</verify>
|
||||
<done>Build passes with no errors, manual test steps documented</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. Build check: `cd jam-ui && npm run build` completes without errors
|
||||
2. Code verification:
|
||||
- mediaSlice.js exports cleanupJamTrackCallbacks
|
||||
- JKSessionJamTrackPlayer.js imports and calls cleanupJamTrackCallbacks in cleanup
|
||||
- JKSessionJamTrackPlayer.js conditionally renders controls based on downloadState
|
||||
3. No eslint errors in modified files
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- cleanupJamTrackCallbacks function exists and is exported from mediaSlice
|
||||
- JKSessionJamTrackPlayer calls cleanup function on unmount
|
||||
- Player controls only render when downloadState is 'idle' or 'synchronized'
|
||||
- Build passes with no errors
|
||||
- No console warnings about leaked callbacks or unmounted component updates
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/26-jamtrack-polish/26-02-SUMMARY.md`
|
||||
</output>
|
||||
Loading…
Reference in New Issue