docs(1): create phase plan
Phase 1: Backing Track Playback Monitoring - 1 plan created - 3 total tasks defined - Ready for execution
This commit is contained in:
parent
19115cf121
commit
cee0bf05f5
|
|
@ -0,0 +1,215 @@
|
|||
---
|
||||
phase: 01-backing-track-playback-monitoring
|
||||
type: execute
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement real-time playback monitoring for the backing track player by adding 500ms polling of the native client and displaying current position and duration in M:SS format.
|
||||
|
||||
Purpose: Complete the player's time display functionality, matching the legacy web implementation's polling pattern while using modern React hooks. This establishes the monitoring foundation that Phase 2 (seek controls) will build upon.
|
||||
|
||||
Output: Backing track player with live-updating time displays showing current position and total duration while track plays.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@./.claude/get-shit-done/workflows/execute-phase.md
|
||||
@./.claude/get-shit-down/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/01-backing-track-playback-monitoring/1-CONTEXT.md
|
||||
@jam-ui/src/components/client/JKSessionBackingTrackPlayer.js
|
||||
|
||||
**Codebase conventions:**
|
||||
- React functional components with hooks (React 16.13.1)
|
||||
- camelCase for functions and variables
|
||||
- Single quotes for strings (Prettier enforced)
|
||||
- 2-space indentation
|
||||
|
||||
**Legacy implementation reference:**
|
||||
- web/app/assets/javascripts/playbackControls.js: 500ms polling via setTimeout (lines 301-337)
|
||||
- web/app/assets/javascripts/utils.js: prettyPrintSeconds() time formatting (lines 885-906)
|
||||
- jamClient methods: SessionCurrrentPlayPosMs(), SessionGetTracksPlayDurationMs(), isSessionTrackPlaying()
|
||||
|
||||
**Current state:**
|
||||
- JKSessionBackingTrackPlayer.js has currentTime and duration state hardcoded to "0:00" (lines 20-21)
|
||||
- Play/pause/stop controls work via jamClient (lines 34-58)
|
||||
- UI structure already in place with time displays (lines 207, 217 for popup; lines 302, 312 for modal)
|
||||
|
||||
**Vision from CONTEXT.md:**
|
||||
- Functional parity with legacy web (500ms polling, accurate time display)
|
||||
- UI layout: Current time (M:SS) on left of slider, duration (M:SS) on right
|
||||
- No padding on single-digit minutes (1:02 not 01:02)
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add formatTime utility function</name>
|
||||
<files>jam-ui/src/components/client/JKSessionBackingTrackPlayer.js</files>
|
||||
<action>Add a formatTime utility function to convert milliseconds to M:SS format (matching legacy web prettyPrintSeconds behavior). Place it inside the component before the useEffect hooks.
|
||||
|
||||
Implementation:
|
||||
- Accept milliseconds as parameter
|
||||
- Convert to seconds (Math.floor(ms / 1000))
|
||||
- Calculate minutes: Math.floor(seconds / 60)
|
||||
- Calculate remaining seconds: seconds % 60
|
||||
- Pad seconds with "0" if less than 10 (e.g., "1:05" not "1:5")
|
||||
- NO padding on minutes (single digit is fine: "1:02" not "01:02")
|
||||
- Return formatted string: `${minutes}:${seconds.toString().padStart(2, '0')}`
|
||||
|
||||
Example outputs:
|
||||
- formatTime(62000) → "1:02"
|
||||
- formatTime(313000) → "5:13"
|
||||
- formatTime(3605000) → "60:05"
|
||||
|
||||
Do NOT implement hours formatting (tracks are < 60 minutes).</action>
|
||||
<verify>Add console.log tests:
|
||||
- formatTime(62000) should output "1:02"
|
||||
- formatTime(313000) should output "5:13"
|
||||
- formatTime(0) should output "0:00"</verify>
|
||||
<done>formatTime function exists, converts milliseconds to M:SS format with proper padding (seconds only)</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add playback monitoring with 500ms polling</name>
|
||||
<files>jam-ui/src/components/client/JKSessionBackingTrackPlayer.js</files>
|
||||
<action>Add useEffect hook for playback monitoring with 500ms polling interval matching legacy web implementation (web/app/assets/javascripts/playbackControls.js lines 301-337).
|
||||
|
||||
Implementation:
|
||||
- Add useEffect that runs when isPlaying changes
|
||||
- When isPlaying is true, start polling:
|
||||
- Use setInterval (not setTimeout recursion) with 500ms interval
|
||||
- In interval callback:
|
||||
1. Check if jamClient exists (guard against undefined)
|
||||
2. Call jamClient.SessionCurrrentPlayPosMs() → current position in ms
|
||||
3. Call jamClient.SessionGetTracksPlayDurationMs() → total duration in ms
|
||||
4. Call jamClient.isSessionTrackPlaying() → boolean for playing state
|
||||
5. Update setCurrentTime(formatTime(positionMs))
|
||||
6. Update setDuration(formatTime(durationMs))
|
||||
7. Sync setIsPlaying(isPlaying) if state changed
|
||||
- When isPlaying is false, clear the interval
|
||||
- Return cleanup function that clears interval
|
||||
|
||||
Error handling:
|
||||
- Wrap jamClient calls in try/catch
|
||||
- On error, log to console but don't crash
|
||||
- Continue polling even if one poll fails
|
||||
|
||||
Dependencies: [isPlaying, jamClient, backingTrack]
|
||||
|
||||
IMPORTANT: Use setInterval (not setTimeout recursion) for consistent 500ms timing. Store intervalId in a variable to clear on cleanup.</action>
|
||||
<verify>Check console logs show:
|
||||
1. When play clicked: Polling starts, position/duration update every 500ms
|
||||
2. When pause clicked: Polling stops, interval cleared
|
||||
3. When stop clicked: Polling stops, position resets to 0:00
|
||||
4. No errors logged during playback</verify>
|
||||
<done>Playback monitoring polls jamClient every 500ms when playing, updates currentTime and duration state with formatted values, cleans up interval on pause/stop</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Initialize duration on track load</name>
|
||||
<files>jam-ui/src/components/client/JKSessionBackingTrackPlayer.js</files>
|
||||
<action>Modify the existing useEffect (lines 25-32) that runs when track opens to fetch and set initial duration immediately, not waiting for playback to start.
|
||||
|
||||
Current code:
|
||||
```javascript
|
||||
useEffect(() => {
|
||||
if (isOpen && backingTrack) {
|
||||
setIsPlaying(false);
|
||||
setCurrentTime('0:00');
|
||||
setDuration('0:00');
|
||||
}
|
||||
}, [isOpen, backingTrack]);
|
||||
```
|
||||
|
||||
Change to:
|
||||
```javascript
|
||||
useEffect(() => {
|
||||
if (isOpen && backingTrack && jamClient) {
|
||||
setIsPlaying(false);
|
||||
setCurrentTime('0:00');
|
||||
|
||||
// Fetch and set duration immediately when track loads
|
||||
try {
|
||||
const durationMs = jamClient.SessionGetTracksPlayDurationMs();
|
||||
setDuration(formatTime(durationMs));
|
||||
} catch (error) {
|
||||
console.error('Error fetching track duration:', error);
|
||||
setDuration('0:00');
|
||||
}
|
||||
}
|
||||
}, [isOpen, backingTrack, jamClient]);
|
||||
```
|
||||
|
||||
This ensures the duration appears immediately when the player opens, matching the UI in the reference screenshot where "5:13" is visible before playback starts.</action>
|
||||
<verify>Open backing track player without playing:
|
||||
- Duration displays actual track length (e.g., "5:13") immediately
|
||||
- Current time shows "0:00"
|
||||
- No errors in console</verify>
|
||||
<done>Duration fetched and displayed when track loads (before play starts), matching legacy web behavior</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Before declaring phase complete:
|
||||
- [ ] Open backing track player, verify duration shows immediately (e.g., "5:13")
|
||||
- [ ] Click play, verify current time updates every ~500ms (1:00 → 1:01 → 1:02)
|
||||
- [ ] Verify time format matches reference: M:SS (no leading zero on minutes)
|
||||
- [ ] Click pause, verify polling stops (time freezes)
|
||||
- [ ] Click play again, verify polling resumes from paused position
|
||||
- [ ] Click stop, verify time resets to "0:00"
|
||||
- [ ] Check browser console for errors (should be none)
|
||||
- [ ] Verify both modal and popup versions work identically
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- formatTime utility converts milliseconds to M:SS format correctly
|
||||
- Playback monitoring polls jamClient every 500ms when playing
|
||||
- Current time display updates smoothly during playback
|
||||
- Duration displays immediately when track loads
|
||||
- Polling stops cleanly when paused/stopped
|
||||
- No console errors during playback
|
||||
- Functional parity with legacy web monitoring behavior
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/01-backing-track-playback-monitoring/01-01-SUMMARY.md`:
|
||||
|
||||
# Phase 1 Plan 1: Backing Track Playback Monitoring Summary
|
||||
|
||||
**Real-time backing track playback monitoring with 500ms polling and M:SS time display**
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Added formatTime utility for milliseconds → M:SS conversion
|
||||
- Implemented 500ms polling with setInterval matching legacy web pattern
|
||||
- Wired up currentTime and duration displays to live jamClient data
|
||||
- Duration fetches immediately on track load (before play)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `jam-ui/src/components/client/JKSessionBackingTrackPlayer.js` - Added formatTime, polling useEffect, duration initialization
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- Used setInterval (not setTimeout recursion) for consistent 500ms timing
|
||||
- Polling runs only when isPlaying=true to avoid unnecessary jamClient calls
|
||||
- Error handling: log errors but continue polling (don't crash on transient failures)
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
(None expected - straightforward polling implementation)
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
Phase 2 (Backing Track Seek Controls) can now proceed. The monitoring useEffect will need slight modification to support seeking:
|
||||
- When user drags slider, pause polling briefly
|
||||
- After seek, resume polling from new position
|
||||
- This is handled in Phase 2, not here
|
||||
</output>
|
||||
Loading…
Reference in New Issue