From 251788d799c721b18520e92140972976ba3cc032 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Fri, 16 Jan 2026 12:16:02 +0530 Subject: [PATCH] fix(05-03): extract backing tracks from session response to Redux PROBLEM: - mixerHelper.backingTracks was always empty/null - Backing track not appearing in session screen - useSessionWebSocket had MIXER_CHANGES callback that never fired ROOT CAUSE: - MIXER_CHANGES WebSocket message doesn't exist on server - Backing track data comes from REST API /api/sessions/:id response - Session data stored in activeSessionSlice but never extracted to mediaSlice - useMixerHelper reads from mediaSlice.backingTracks which was never populated SOLUTION: - Import mediaSlice actions (setBackingTracks, setJamTracks, setRecordedTracks) in useSessionModel - Update updateSessionInfo() to extract backing tracks from session.participants[].backing_tracks - Dispatch extracted arrays to Redux mediaSlice when session updates - Also extract jamTracks and recordedTracks for consistency DATA FLOW: 1. User opens backing track via jamClient.SessionOpenBackingTrackFile() 2. Server updates session state 3. Server sends TRACKS_CHANGED WebSocket message 4. Client calls refreshCurrentSession() -> REST API /api/sessions/:id 5. Response includes participants with backing_tracks (containing mixers) 6. updateSessionInfo() extracts backing tracks and dispatches to Redux 7. useMixerHelper reads from mediaSlice.backingTracks 8. Components access via mixerHelper.backingTracks Co-Authored-By: Claude Sonnet 4.5 --- jam-ui/src/hooks/useSessionModel.js | 35 ++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/jam-ui/src/hooks/useSessionModel.js b/jam-ui/src/hooks/useSessionModel.js index c7e9c581e..b8f5763f3 100644 --- a/jam-ui/src/hooks/useSessionModel.js +++ b/jam-ui/src/hooks/useSessionModel.js @@ -10,6 +10,11 @@ import { setSessionId, updateSessionData } from '../store/features/activeSessionSlice'; +import { + setBackingTracks, + setJamTracks, + setRecordedTracks +} from '../store/features/mediaSlice'; import useGearUtils from './useGearUtils'; import useTrackHelpers from './useTrackHelpers'; import useRecordingHelpers from './useRecordingHelpers'; @@ -675,13 +680,41 @@ export default function useSessionModel(app, server, sessionScreen) { // sendClientParticipantChanges logic would go here updateCurrentSession(response); + + // Extract and dispatch media arrays to Redux + // Extract backing tracks from participants + let extractedBackingTracks = []; + if (response.participants) { + response.participants.forEach((participant) => { + if (participant.backing_tracks && participant.backing_tracks.length > 0) { + extractedBackingTracks = participant.backing_tracks; + } + }); + } + dispatch(setBackingTracks(extractedBackingTracks)); + console.log('[useSessionModel] Extracted backing tracks:', extractedBackingTracks); + + // Extract jam tracks + const extractedJamTracks = response.jam_track && response.jam_track.tracks + ? response.jam_track.tracks.filter(track => track.track_type === 'Track') + : []; + dispatch(setJamTracks(extractedJamTracks)); + console.log('[useSessionModel] Extracted jam tracks:', extractedJamTracks); + + // Extract recorded tracks + const extractedRecordedTracks = response.claimed_recording && response.claimed_recording.recording + ? response.claimed_recording.recording.recorded_tracks || [] + : []; + dispatch(setRecordedTracks(extractedRecordedTracks)); + console.log('[useSessionModel] Extracted recorded tracks:', extractedRecordedTracks); + if (callback) { callback(); } } else { logger.info("ignoring refresh because we already have current: " + currentTrackChanges + ", seen: " + response.track_changes_counter); } - }, [currentTrackChanges, updateCurrentSession]); + }, [currentTrackChanges, updateCurrentSession, dispatch]); // Refresh current session REST call const refreshCurrentSessionRest = useCallback(async (callback, force) => {