Commit Graph

8352 Commits

Author SHA1 Message Date
Nuwan 58e96cd965 docs: complete v1.7 milestone with Phases 28-30
v1.7 Performance Optimization shipped with 3 stable phases:
- Phase 28: VU Meter Optimization (external store + RAF)
- Phase 29: Context Optimization (memoized providers)
- Phase 30: Component Memoization (React.memo wrappers)

Phases 31-32 permanently reverted:
- Selector composition with shallowEqual blocked main thread
- State update changes caused VU/slider unresponsiveness

Results: Page freezes eliminated, VU meters smooth, sliders responsive.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-06 09:56:04 +05:30
Nuwan 9a3f4e3f1a docs: update STATE.md after Phase 31-32 revert
Phases 31-32 caused VU meter and volume slider performance regression:
- VU meters animated slowly
- Volume sliders unresponsive when dragged

Reverted to Phase 30 state. Phases 28-30 optimizations remain stable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-06 09:53:26 +05:30
Nuwan c13bc73806 revert(31,32): restore pre-optimization state to fix VU/slider perf
Phase 31 selector optimization and Phase 32 state update changes
caused VU meters to animate slowly and volume sliders to be
unresponsive. Reverted all affected files to pre-Phase-31 state.

Files reverted:
- useMixerHelper.js: back to individual selectors (no shallowEqual)
- mixersSlice.js: removed composed selectors
- JKSessionScreen.js: pre-Phase-32 state
- useSessionModel.js: pre-Phase-32 debounce changes

Performance issues resolved:
- VU meter animations now smooth
- Volume sliders respond immediately

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-06 09:52:28 +05:30
Nuwan be7b219525 perf(32-02): fix categorization running on every property change
- Create stable masterMixerIds key that only changes on add/remove
- Remove console.log statements causing performance overhead
- Remove expensive mixerArraysEqual string comparisons
- Categorization now only runs when mixers added/removed, not on
  volume/pan changes

Fixes sluggish VU meters and slow volume slider response.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-06 09:11:51 +05:30
Nuwan 9a49d3a423 fix(32-01): remove fetchFriends from deps to fix TDZ error
Original code had empty deps []. Function defined below, runs once on mount.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:42:02 +05:30
Nuwan c4ec621a08 fix(32-01): remove joinSession from deps to fix TDZ error
Original code didn't include joinSession in useEffect deps.
Function is defined after useEffect and accessed via closure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:41:11 +05:30
Nuwan 98163c2acb fix(32-01): remove guardOnJoinSession from deps to fix TDZ error
Original code didn't include guardOnJoinSession in useEffect deps.
Function is defined after useEffect and accessed via closure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:40:29 +05:30
Nuwan a839cd9d9d fix(32-01): apply minimal trackChanges debounce fix
Replace useCallback(debounce()) with useDebounceCallback for stable timer.
Minimal change - only import and trackChanges handler modified.
Original dependency arrays preserved to avoid initialization order issues.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:37:30 +05:30
Nuwan cc9f4ace8d fix(32-01): restore empty dependency array for refreshCurrentSession
Original code used [] deps - functions accessed via closure are stable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:36:28 +05:30
Nuwan e9a6e6f8bc fix(32-01): restore original joinSession dependency array
Revert to minimal [currentSessionIdRef] deps to avoid temporal dead zone
errors. Other functions are stable refs or callbacks defined earlier.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:35:00 +05:30
Nuwan 742ced69e0 fix(32-01): resolve refreshCurrentSession initialization order
Use ref pattern to access refreshCurrentSession in joinSession callback
to avoid "Cannot access before initialization" temporal dead zone error

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:18:32 +05:30
Nuwan 14e9834f72 fix(32-03): correct video icon import path
Change from non-existent icons8-video-call-50.png to existing video.svg

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 22:15:13 +05:30
Nuwan f4740436b7 chore(32-04): audit useState and add render counter
- Audited all 14 remaining useState declarations
- Documented decisions for each state variable
- Confirmed videoLoading/resyncLoading removed in Plan 03
- Identified 3 leave modal states as future colocation candidates
- Added temporary render counter for Phase 32 verification
- Counter logs only in development mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 19:43:28 +05:30
Nuwan 03f8ecda95 docs(32-03): complete loading state colocation plan
Tasks completed: 3/3
- Create JKResyncButton component
- Create JKVideoButton component
- Refactor JKSessionScreen to use extracted components

SUMMARY: .planning/phases/32-state-update-optimization/32-03-SUMMARY.md
2026-03-05 19:41:10 +05:30
Nuwan f5bd1b1cd5 refactor(32-03): use JKResyncButton and JKVideoButton in JKSessionScreen
- Replaced inline video button with JKVideoButton component
- Replaced inline resync button with JKResyncButton component
- Removed videoLoading and resyncLoading state from parent
- Removed handleVideoClick and handleResync functions
- Removed unused videoIcon and resyncIcon imports
- Loading state changes no longer trigger parent re-renders
2026-03-05 19:39:56 +05:30
Nuwan 98e5a5ac15 docs(32-01): complete redundant operations fix plan
Tasks completed: 3/3
- Create useDebounceCallback hook
- Consolidate track sync to single debounced call
- Fix trackChanges debounce in useSessionModel

SUMMARY: .planning/phases/32-state-update-optimization/32-01-SUMMARY.md
2026-03-05 19:38:57 +05:30
Nuwan 3000de6695 docs(32-02): complete mixer categorization optimization plan
Tasks completed: 3/3
- Task 1: Add mixer array comparison helper
- Task 2: Add prevCategoriesRef to track dispatched values
- Task 3: Add conditional dispatch to categorization

SUMMARY: .planning/phases/32-state-update-optimization/32-02-SUMMARY.md
2026-03-05 19:38:14 +05:30
Nuwan 2075989409 feat(32-03): create JKVideoButton with colocated loading state
- Extracted video button from JKSessionScreen
- Local loading state prevents parent re-renders
- memo() wrapper for render optimization
- Preserves 10-second loading timeout behavior
- Handles permission checks via canVideo prop
2026-03-05 19:37:51 +05:30
Nuwan e35bed21e3 feat(32-03): create JKResyncButton with colocated loading state
- Extracted resync button from JKSessionScreen
- Local loading state prevents parent re-renders
- memo() wrapper for render optimization
- Preserves original error handling logic
2026-03-05 19:37:34 +05:30
Nuwan f0ddd9d7c7 feat(32-01): fix trackChanges debounce stability
- Replace useCallback(debounce()) with useDebounceCallback hook
- Timer no longer resets when currentTrackChanges or refreshCurrentSession change
- Callback always reads fresh state values via ref closure (fixes STATE-02)
- Remove lodash debounce import (no longer needed)
- Fixes debounce timer reset on dependency changes
2026-03-05 19:37:18 +05:30
Nuwan d53603cd08 feat(32-02): add conditional dispatch to mixer categorization
- Replace unconditional dispatches with mixerArraysEqual checks
- Only dispatch when category content actually changes
- Update prevCategoriesRef after each dispatch
- Add console logs for debugging dispatch decisions
- Run prettier to fix formatting
2026-03-05 19:36:57 +05:30
Nuwan de5b331e07 feat(32-01): consolidate track sync to single debounced call
- Replace triple setTimeout pattern (1s, 1.4s, 6s) with single 1.5s debounced call
- Eliminates redundant API calls on session join (STATE-01)
- Uses useMemo to create stable debounced function
- Debounce delay of 1.5s covers mixer initialization window
- Cleanup via cancel() on unmount
2026-03-05 19:36:27 +05:30
Nuwan f7f6f10d6d feat(32-02): add prevCategoriesRef to track dispatched values
- Add useRef to track previous category values
- Prevents circular updates by using ref instead of selectors
- Stores last dispatched values for comparison
2026-03-05 19:36:17 +05:30
Nuwan 10a1eb6577 feat(32-02): add mixer array comparison helper
- Add mixerArraysEqual helper to compare mixer arrays by ID
- Compares master.id + personal.id to create unique pair key
- Used to prevent unnecessary Redux dispatches when categorizing mixers
2026-03-05 19:36:04 +05:30
Nuwan 1a42be980c feat(32-01): create useDebounceCallback hook
- Implements ref-based debounce pattern for stable timers
- Solves stale closure problem with debounced callbacks
- useRef stores latest callback, useMemo creates debounce once
- Cleanup on unmount via useEffect return
- Exports both named and default for flexibility
2026-03-05 19:35:23 +05:30
Nuwan 173cf5e94d docs(32): create phase plan
Phase 32: State Update Optimization
- 4 plan(s) in 2 wave(s)
- 3 parallel in wave 1, 1 sequential in wave 2
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 19:28:11 +05:30
Nuwan ae583e7bc7 docs(32): research state update optimization phase domain
Phase 32: State Update Optimization
- Debounce patterns for track sync consolidation documented
- Ref-based closure pattern for stable debounce identified
- State colocation principles for button loading states
- Content comparison before Redux dispatch patterns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 19:22:50 +05:30
Nuwan af9b467546 docs(31): complete selector-optimization phase
- Phase 31 verified: 3/3 must-haves passed
- SEL-01, SEL-02, SEL-03 requirements marked complete
- 13/19 v1.7 requirements now complete (68%)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 19:15:38 +05:30
Nuwan 20ab1fd86a docs(31-01): complete selector optimization plan
Tasks completed: 2/2
- Create composed selectors in mixersSlice.js
- Refactor useMixerHelper to use composed selectors

SUMMARY: .planning/phases/31-selector-optimization/31-01-SUMMARY.md
2026-03-05 19:12:03 +05:30
Nuwan 43b99c549d feat(31-01): refactor useMixerHelper to use composed selectors
- Replace 21 individual useSelector calls with 6 composed selectors
- Import shallowEqual from react-redux for object comparison
- Import composed selectors (selectCoreMixerState, selectTrackMixerState, etc.)
- Remove 16 individual selector imports no longer needed
- Destructure composed results for backward compatibility
- Total useSelector calls reduced from 28 to 13

Performance: Single mixer field change now triggers 6 selector runs
instead of 21, with shallowEqual preventing unnecessary re-renders
when composed object contents haven't changed.
2026-03-05 19:10:24 +05:30
Nuwan 0630ebdd3f feat(31-01): add composed memoized selectors to mixersSlice
- Add createSelector import from @reduxjs/toolkit
- Add selectCoreMixerState (chatMixer, broadcastMixer, recordingMixer)
- Add selectTrackMixerState (5 track mixer arrays)
- Add selectMixerLookupTables (allMixers, mixersByResourceId, mixersByTrackId)
- Add selectMasterPersonalMixers (masterMixers, personalMixers)
- Add selectMixerMetadata (metronome, settings, mediaSummary, noAudioUsers, etc)
- Add selectSimulatedCategoryMixers (simulatedMusic, simulatedChat)

These composed selectors memoize grouped state objects, reducing
selector overhead from 18+ individual subscriptions to 6 memoized selectors.
2026-03-05 19:08:46 +05:30
Nuwan 3a9df2bef8 fix(31): revise plan based on checker feedback
- Updated must_haves.truths to clarify that grouping state IS derived data
- Made Task 2 verification precise: exactly 13 useSelector calls expected
- Added verification that old individual selectors (lines 72-92) are removed
- Changed vague 'around 9-12' to exact count verification
2026-03-05 18:59:34 +05:30
Nuwan 249cf75ec6 docs(31): create phase plan
Phase 31: Selector Optimization
- 1 plan in 1 wave
- Fully autonomous (no checkpoints)
- Ready for execution
2026-03-05 18:56:14 +05:30
Nuwan bb0019c941 docs(31): research selector optimization phase domain
Phase 31: Selector Optimization
- Standard stack identified (createSelector, shallowEqual in Redux Toolkit)
- Architecture patterns documented (composed selectors, memoization)
- Pitfalls catalogued (reference equality, over-subscription, cache thrashing)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 18:53:42 +05:30
Nuwan 773382d4f7 docs(30): complete component memoization phase
- JKSessionAudioInputs wrapped with React.memo
- JKSessionRemoteTracks wrapped with React.memo
- MEMO-01 through MEMO-04 requirements satisfied
- Phase goal verified: child components skip re-renders when props unchanged

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 18:44:15 +05:30
Nuwan 2a06f8bc1e docs(30-01): complete memoize container components plan
Tasks completed: 2/2
- Task 1: Wrap JKSessionAudioInputs with React.memo
- Task 2: Wrap JKSessionRemoteTracks with React.memo

SUMMARY: .planning/phases/30-component-memoization/30-01-SUMMARY.md
2026-03-05 18:40:31 +05:30
Nuwan a26f755912 refactor(30-01): wrap JKSessionRemoteTracks with React.memo
- Add memo to React imports (with useMemo)
- Wrap component with memo(function JKSessionRemoteTracks)
- Add displayName for React DevTools
- Prevents unnecessary re-renders when mixerHelper and sessionModel props unchanged
2026-03-05 18:39:02 +05:30
Nuwan 4dea95e855 refactor(30-01): wrap JKSessionAudioInputs with React.memo
- Add memo to React import
- Wrap component with memo(function JKSessionAudioInputs)
- Add displayName for React DevTools
- Prevents unnecessary re-renders when parent re-renders with same props
2026-03-05 18:38:32 +05:30
Nuwan 35997b407a fix(29): correct memo syntax in JKSessionBackingTrack and JKSessionMyTrack
Remove invalid arrow function syntax from memo-wrapped named functions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 18:34:06 +05:30
Nuwan 4fb81ea93e docs(30): create phase plan
Phase 30: Component Memoization
- 1 plan in 1 wave
- Wrap JKSessionAudioInputs with React.memo
- Wrap JKSessionRemoteTracks with React.memo
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 18:27:26 +05:30
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