Commit Graph

8312 Commits

Author SHA1 Message Date
Nuwan 125a7cdcc2 docs(30): research component memoization phase domain
Phase 30: Component Memoization
- React.memo API and patterns for React 16.13.1
- Prop stability requirements documented
- Integration with Phase 29 context memoization
- Common pitfalls: inline props, children, context
- Verification with React DevTools Profiler
- DisplayName for debugging best practices

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 18:25:04 +05:30
Nuwan cb73b3dcdd fix(29): correct memo syntax in JKSessionMetronome
Remove invalid arrow function syntax from memo-wrapped named function.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 18:11:16 +05:30
Nuwan af1c06302a docs(29): complete Context Optimization phase
Phase 29 verified and complete:
- MixersContext.Provider value memoized with useMemo
- VuContext separated from MixerConfigContext (Phase 28)
- 6 context consumers wrapped with React.memo
- useMixerHelper.getMixer stabilized with useCallback

Requirements satisfied: CTX-01, CTX-02, CTX-03

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 17:59:02 +05:30
Nuwan db1033a5c6 docs(29-01): complete context optimization plan 01
Tasks completed: 4/4
- Task 1a: Stabilize useMixerHelper function references
- Task 1b: Memoize MixersContext provider value
- Task 2: Memoize VuContext and GlobalContext provider values
- Task 3: Wrap context consumers with React.memo

SUMMARY: .planning/phases/29-context-optimization/29-01-SUMMARY.md

Accomplishments:
- Memoized all 3 context providers (MixersContext, VuContext, GlobalContext)
- Stabilized getMixer and dependent function references
- Wrapped 6 consumer components with React.memo
- Eliminated cascading re-renders from context value changes

Requirements completed:
- CTX-00: useMixerHelper.getMixer wrapped with useCallback
- CTX-01: MixersContext.Provider value is memoized
- CTX-03: Context consumers only re-render when data changes

Performance impact:
- Volume slider changes no longer re-render VU meters
- VU updates no longer re-render volume sliders
- Context consumers only re-render when their specific data changes
2026-03-05 17:54:56 +05:30
Nuwan b27ea854f4 refactor(29-01): wrap context consumers with React.memo
Components wrapped:
- SessionTrackGain: volume slider
- JKSessionMyTrack: local track display
- JKSessionVolumeModal: volume popup
- JKSessionPanModal: pan control popup
- JKSessionBackingTrack: backing track display
- JKSessionMetronome: metronome controls

Each component:
- Wrapped with memo(function ComponentName(...))
- Added displayName for debugging
- Preserved PropTypes

React.memo prevents re-renders when props haven't changed.
Combined with memoized context values, this eliminates
unnecessary re-renders across the component tree.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 17:53:34 +05:30
Nuwan 566a53fb2b refactor(29-01): memoize VuContext and GlobalContext provider values
VuContext:
- Wrap combined value object with useMemo
- vuStore is stable module reference (not a dependency)
- Depends on vuHelpers

GlobalContext:
- Wrap provider value with useMemo
- Dependencies: all state and callback values
- useState setters are stable (not dependencies)

Both contexts now only update consumers when actual data changes,
preventing unnecessary re-renders across the component tree.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 17:52:15 +05:30
Nuwan 6b5b0990bb refactor(29-01): memoize MixersContext provider value
- Add useMemo wrapper around mixerHelper value
- Prevents new object creation on every render
- Depends on stable mixerHelper (from Task 1a)
- Context consumers now only re-render when data actually changes

This eliminates cascading re-renders when unrelated state updates occur.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 17:51:46 +05:30
Nuwan d008fe977c refactor(29-01): stabilize useMixerHelper function references
- Wrap getMixer with useCallback to ensure stable reference
- Prevents cascade of function recreations on every render
- Dependencies: mixMode (selector value)
- Uses allMixersRef.current (ref, not dependency)

This stabilization is prerequisite for effective context memoization.
All dependent functions (fillTrackVolumeObject, mute, faderChanged, etc.)
now automatically stabilize because their getMixer dependency is stable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 17:51:31 +05:30
Nuwan 468860d54f fix(29): revise plan based on checker feedback
- Split Task 1 into Task 1a (stabilize useMixerHelper) and Task 1b (memoize MixersContext)
- Add useMixerHelper.js to files_modified
- Add getMixer useCallback wrapping as prerequisite for context memoization
- Add key_link verifying useMixerHelper -> MixersContext wiring
- Add CTX-00 success criterion for getMixer stabilization

Issues addressed:
- task_completeness: Task 1 now includes getMixer useCallback wrapping
- key_links_planned: Added verification for useMixerHelper stabilization
2026-03-05 17:22:30 +05:30
Nuwan c595d5334e docs(29): create phase plan
Phase 29: Context Optimization
- 1 plan in 1 wave
- Memoize MixersContext, VuContext, GlobalContext providers
- Wrap 6 consumer components with React.memo
- Ready for execution
2026-03-05 17:18:20 +05:30
Nuwan ceec2342fe docs(29): research context optimization phase domain
Phase 29: Context Optimization
- Standard stack identified (useMemo, useCallback, memo built-ins)
- Architecture patterns documented (memoized provider values)
- Pitfalls catalogued (stale closures, missing dependencies)
2026-03-05 17:15:44 +05:30
Nuwan 393bdfe057 docs(28): complete VU Meter Optimization phase
Phase 28 verified and approved:
- VU data flows through external store (vuStore.js)
- VU components use refs for direct DOM updates
- React DevTools shows 0 re-renders from VU updates
- Session screen remains responsive

Requirements satisfied: VU-01, VU-02, VU-03

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 16:53:43 +05:30
Nuwan 6b6aeb1017 docs(28-02): complete Wire Components to External Store plan
Tasks completed: 4/4
- Update useMixerStore to route VU data to external store
- Simplify useVuHelpers and VuContext
- Rewrite SessionTrackVU with direct DOM updates
- Human verification (approved)

Additional fix:
- getLevelSnapshot now checks pendingUpdates for immediate access

SUMMARY: .planning/phases/28-vu-meter-optimization/28-02-SUMMARY.md
2026-03-05 15:18:31 +05:30
Nuwan a1d24fe385 fix(28-02): check pendingUpdates in getLevelSnapshot
The vuStore RAF loop only runs with subscribers, but SessionTrackVU
uses direct polling without subscribing. Changed getLevelSnapshot to
check pendingUpdates first for immediate access to latest VU data.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 15:03:28 +05:30
Nuwan a020e27260 refactor(28-02): rewrite SessionTrackVU with direct DOM updates
- Remove useVuContext - directly import vuStore
- Remove VuMeter component usage - render lights directly
- Add RAF loop polling vuStore.getLevelSnapshot at ~60fps
- Store light element refs for direct className assignment
- Wrap with React.memo to prevent parent re-renders
- Zero React re-renders for VU visual updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:26:16 +05:30
Nuwan f8214854d9 refactor(28-02): simplify VU helpers to use external store
- Remove useState from useVuHelpers (no React state for VU data)
- Remove updateVuState, removeVuState, updateVU3 functions
- Remove VuMeterComponent (replaced by direct DOM in SessionTrackVU)
- Expose vuStore methods via return object
- VuContext provides vuStore reference to consumers
- Keep legacy renderVU/updateVU for backward compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:25:48 +05:30
Nuwan 96d8f97175 refactor(28-02): route VU data to external store
- Import vuStore in useMixerStore.js
- Replace mixerHelper.updateVU call with vuStore.updateLevel
- VU data now flows to external store instead of React state
- Native bridge still calls at 50-70/sec but updates are buffered

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:25:08 +05:30
Nuwan 344ef27ae0 docs(28-01): complete External VU Store Infrastructure plan
Tasks completed: 2/2
- Install useSyncExternalStore shim and create external VU store
- Create useVuStore React hooks

SUMMARY: .planning/phases/28-vu-meter-optimization/28-01-SUMMARY.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:22:13 +05:30
Nuwan 834472127d feat(28-01): create useVuStore React hooks
- Add useAllVuLevels hook for subscribing to all VU levels
- Add useVuLevel hook for efficient single-mixer subscription
- Use useSyncExternalStore shim for React 16 compatibility
- Memoize getSnapshot callback to avoid unnecessary resubscription

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:20:26 +05:30
Nuwan 5da85c1e79 feat(28-01): create external VU store with RAF batching
- Install use-sync-external-store shim for React 16 compatibility
- Create vuStore.js with external state management
- Implement RAF batching loop to limit updates to 60fps
- Add updateLevel, removeLevel, getSnapshot, getLevelSnapshot, subscribe, reset methods
- Store VU data outside React to avoid reconciliation overhead

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:19:41 +05:30
Nuwan 9c9e118a6e docs(28): create phase plan
Phase 28: VU Meter Optimization
- 2 plan(s) in 2 wave(s)
- 1 parallel (wave 1), 1 sequential (wave 2)
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:09:26 +05:30
Nuwan e8c5a213c6 docs(28): research VU meter optimization phase domain
Phase 28: VU Meter Optimization
- Standard stack identified (use-sync-external-store shim, requestAnimationFrame)
- Architecture patterns documented (external store, direct DOM updates with refs)
- Pitfalls catalogued (getSnapshot object creation, rAF cleanup, layout thrashing)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 20:05:08 +05:30
Nuwan 9174d161c6 docs: start milestone v1.7 Performance Optimization
Goals:
- Eliminate page freezes from excessive React re-renders
- Optimize VU meter updates (50-70/sec → batched RAF)
- Prevent cascading re-renders with memoization
- Apply React best practices for granular updates

Phases:
28. VU Meter Optimization
29. Context Optimization
30. Component Memoization
31. Selector Optimization
32. State Update Optimization

19 requirements across 5 phases.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 19:57:32 +05:30
Nuwan 4c4ee9253b chore: complete v1.6 milestone
Archived:
- milestones/v1.6-ROADMAP.md
- milestones/v1.6-REQUIREMENTS.md

Deleted (fresh for next milestone):
- ROADMAP.md
- REQUIREMENTS.md

Updated:
- MILESTONES.md (new entry)
- PROJECT.md (requirements → Validated)
- STATE.md (reset for next milestone)

v1.6 Media Features Polish shipped:
- JamTrack loading sequence, sizing, navigation fixed
- Backing track sync to session screen
- Prevent multiple media players simultaneously
- 2 phases, 5 plans, 7 days

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-03 16:33:44 +05:30
Nuwan 51f7cb105a docs(v1.6): descope Phase 28 - metronome responsiveness satisfactory
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>
2026-03-03 16:31:17 +05:30
Nuwan 388dfe16f8 fix: prevent opening multiple media players simultaneously
- 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>
2026-03-03 16:08:41 +05:30
Nuwan fd8900c15b media players related updates 2026-03-03 09:47:59 +05:30
Nuwan eb65785e3d fix(27): restore stylesheet copying to popup windows
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>
2026-03-02 19:17:26 +05:30
Nuwan 3da5f8938e docs(27): add debug notes and verification documentation
- Add jamtrack stems debug notes
- Add phase 26 verification v2 documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-02 19:04:42 +05:30
Nuwan b674a7e1b8 style(27): update media player icons and popup dimensions
- 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>
2026-03-02 19:03:31 +05:30
Nuwan 5349dc0d63 fix(27): fix backing track player end detection, loop, and close
- 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>
2026-03-02 19:01:47 +05:30
Nuwan 79ddf613f9 fix(27): do full reset sequence when playing from beginning
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>
2026-03-02 13:39:15 +05:30
Nuwan fe589f4ac2 fix(27): seek native client to start when backing track ends
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>
2026-03-02 13:28:58 +05:30
Nuwan d59fdae944 fix(27): prevent session refresh from clearing local backing tracks
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>
2026-03-01 23:53:45 +05:30
Nuwan c0c6e33863 fix(27): correct MediaTrackGroup ID from 8 to 6
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>
2026-03-01 20:15:26 +05:30
Nuwan 2ea18d59ea fix(27): populate backing track Redux state from native client
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>
2026-02-27 01:00:54 +05:30
Nuwan e35163ec84 docs(27): complete Backing Track Sync phase
- Phase 27 verified: 2/2 must-haves confirmed
- BT-01: openBackingTrack action enables session screen sync
- BT-02: ignore flag prevents unmount warnings
- ROADMAP.md, STATE.md, REQUIREMENTS.md updated

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-26 17:25:08 +05:30
Nuwan 748e01f60a docs(27-01): complete backing track sync plan
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
2026-02-26 17:21:22 +05:30
Nuwan bba12ac905 fix(27-01): add ignore flag to prevent unmount state updates
- 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
2026-02-26 17:20:35 +05:30
Nuwan d958b26008 feat(27-01): use openBackingTrack action for session screen sync
- Replace direct jamClient.SessionOpenBackingTrackFile() call with
  openBackingTrack() action from useMediaActions
- This enables backing track sync to session screen via:
  1. jamClient call (via thunk)
  2. Redux mediaSummary.backingTrackOpen state update
  3. syncTracksToServer call for server-side sync
2026-02-26 17:20:28 +05:30
Nuwan c7f6480137 docs(27): create phase plan for backing track sync
Phase 27: Backing Track Sync
- 1 plan in 1 wave
- 2 tasks (both auto)
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-26 16:55:35 +05:30
Nuwan 12ce12420f docs(27): research backing track sync domain
Phase 27: Backing Track Sync
- Standard stack identified (existing React/Redux patterns)
- Architecture patterns documented (openBackingTrack action, ignore flag)
- Pitfalls catalogued (bypassing Redux, race conditions)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-26 16:53:05 +05:30
Nuwan 3d847ece7f fix(26): pass jamServer to loadJamTrack and improve error handling
- 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>
2026-02-26 11:52:53 +05:30
Nuwan e4300aecb4 docs(26): complete JamTrack Polish phase with gap closure round 2 2026-02-25 23:51:01 +05:30
Nuwan 5a7f29e3e6 fix(26): orchestrator corrections - update planning docs 2026-02-25 23:47:07 +05:30
Nuwan 38aacb49a5 docs(26-04): complete trigger download flow plan
Tasks completed: 2/2
- Task 1: Call loadJamTrack when track is not synchronized
- Task 2: Build verification (syntax validated via Babel parser)

SUMMARY: .planning/phases/26-jamtrack-polish/26-04-SUMMARY.md
2026-02-25 23:46:46 +05:30
Nuwan 6d92e93a63 feat(26-04): call loadJamTrack when track is not synchronized
- 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
2026-02-25 23:44:45 +05:30
Nuwan 6423df4b7b docs(26): complete JamTrack Polish phase with gap closure 2026-02-25 23:24:34 +05:30
Nuwan b52e822bf7 fix(26-03): restore JamTrack popup window dimensions to 460x350 2026-02-25 23:21:15 +05:30
Nuwan 4e5192d52f docs(26-03): complete JamTrack stems/controls render timing fix
Tasks completed: 4/4
- Task 1: Call checkJamTrackSync in handleJamTrackSelect
- Task 2: Remove 'idle' from stems render condition
- Task 3: Remove 'idle' from controls render condition
- Task 4: Build verification

SUMMARY: .planning/phases/26-jamtrack-polish/26-03-SUMMARY.md
2026-02-25 23:17:32 +05:30