From 40cb7fe9083e3be12653b08595fa0c56a29b17fb Mon Sep 17 00:00:00 2001 From: Nuwan Date: Thu, 15 Jan 2026 01:51:21 +0530 Subject: [PATCH] fix(05-jamtrack): add jamTrackData state for player props Added jamTrackData state to activeSessionSlice following the same pattern as backingTrackData. This properly separates concerns: - jamTrackData stores full player data (jamTrack, session, currentUser) - Presence of jamTrackData indicates player should be shown Changes to activeSessionSlice.js: - Add jamTrackData: null to initial state - Add setJamTrackData and clearJamTrackData reducers - Export actions and selectJamTrackData selector Changes to JKSessionScreen.js: - Import setJamTrackData, clearJamTrackData, selectJamTrackData - Remove openJamTrack usage from sessionUISlice - Update handleJamTrackSelect to dispatch setJamTrackData - Update selectors to use jamTrackData - Update render to pass jamTrackData.jamTrack to player Fixes "Cannot read properties of undefined (reading 'id')" error where jamTrack prop was undefined due to incorrect state structure. Co-Authored-By: Claude Sonnet 4.5 --- .../src/components/client/JKSessionScreen.js | 37 ++++++++++--------- .../src/store/features/activeSessionSlice.js | 14 +++++++ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/jam-ui/src/components/client/JKSessionScreen.js b/jam-ui/src/components/client/JKSessionScreen.js index d4cdf868a..b4bd2d86b 100644 --- a/jam-ui/src/components/client/JKSessionScreen.js +++ b/jam-ui/src/components/client/JKSessionScreen.js @@ -23,7 +23,7 @@ import { dkeys } from '../../helpers/utils.js'; import { getSessionHistory, getSession, joinSession as joinSessionRest, updateSessionSettings, getFriends, startRecording, stopRecording, submitSessionFeedback, getVideoConferencingRoomUrl, getJamTrack, closeJamTrack, openMetronome } from '../../helpers/rest'; // Redux imports -import { openModal, closeModal, toggleModal, selectModal, setOpenJamTrack, clearOpenJamTrack, selectOpenJamTrack } from '../../store/features/sessionUISlice'; +import { openModal, closeModal, toggleModal, selectModal } from '../../store/features/sessionUISlice'; import { selectMediaSummary } from '../../store/features/mixersSlice'; import { fetchActiveSession, @@ -38,6 +38,8 @@ import { setJamTrackStems, setBackingTrackData, clearBackingTrackData, + setJamTrackData, + clearJamTrackData, clearSession, selectActiveSession, selectJoinStatus, @@ -49,7 +51,8 @@ import { selectInSession, selectSelectedJamTrack, selectJamTrackStems, - selectBackingTrackData + selectBackingTrackData, + selectJamTrackData } from '../../store/features/activeSessionSlice'; import { CLIENT_ROLE, RECORD_TYPE_AUDIO, RECORD_TYPE_BOTH } from '../../helpers/globals'; @@ -200,13 +203,13 @@ const JKSessionScreen = () => { }, [closeMedia]); // Redux JamTrack player state (modal visibility and data) - const openJamTrack = useSelector(selectOpenJamTrack); - const showJamTrackPlayer = Boolean(openJamTrack); + const jamTrackData = useSelector(selectJamTrackData); + const showJamTrackPlayer = Boolean(jamTrackData); // Stable callback for JamTrack player popup close const handleJamTrackPlayerClose = useCallback(() => { console.log('JKSessionScreen: JamTrack Player Popup closing'); - dispatch(clearOpenJamTrack()); + dispatch(clearJamTrackData()); }, [dispatch]); // State for media controls popup (modal visibility now in Redux) @@ -860,22 +863,22 @@ const JKSessionScreen = () => { try { // Fetch jam track details with stems const response = await getJamTrack({ id: jamTrack.id }); - const jamTrackData = await response.json(); + const jamTrackWithStems = await response.json(); - console.log('Jam track data:', jamTrackData); + console.log('Jam track data:', jamTrackWithStems); // Set the selected jam track and stems (for display on session screen) - dispatch(setSelectedJamTrack(jamTrackData)); - dispatch(setJamTrackStems(jamTrackData.tracks || [])); + dispatch(setSelectedJamTrack(jamTrackWithStems)); + dispatch(setJamTrackStems(jamTrackWithStems.tracks || [])); // Open the JamTrack player popup (with full data needed for player) - dispatch(setOpenJamTrack({ - jamTrack: jamTrackData, + dispatch(setJamTrackData({ + jamTrack: jamTrackWithStems, session: currentSession, currentUser: currentUser })); - toast.success(`Loaded JamTrack: ${jamTrackData.name}`); + toast.success(`Loaded JamTrack: ${jamTrackWithStems.name}`); } catch (error) { console.error('Error loading jam track:', error); toast.error('Failed to load JamTrack'); @@ -1338,20 +1341,20 @@ const JKSessionScreen = () => { )} {/* JamTrack Player Popup */} - {showJamTrackPlayer && openJamTrack && ( + {showJamTrackPlayer && jamTrackData && ( { console.log('JKSessionScreen: JKSessionJamTrackPlayer onClose called'); - dispatch(clearOpenJamTrack()); + dispatch(clearJamTrackData()); }} /> diff --git a/jam-ui/src/store/features/activeSessionSlice.js b/jam-ui/src/store/features/activeSessionSlice.js index 576d2ef22..526c3ac4c 100644 --- a/jam-ui/src/store/features/activeSessionSlice.js +++ b/jam-ui/src/store/features/activeSessionSlice.js @@ -63,6 +63,9 @@ const initialState = { // Backing track data (for currently active backing track) backingTrackData: null, + // JamTrack data (for currently active JamTrack player) + jamTrackData: null, + // Mixdown management (Phase 5) availableMixdowns: [], // Array of mixdown objects: { id, type: 'master'|'custom-mix'|'stem', name, jamTrackId, packageId } activeMixdown: null, // Currently selected mixdown object @@ -191,6 +194,14 @@ export const activeSessionSlice = createSlice({ state.backingTrackData = null; }, + setJamTrackData: (state, action) => { + state.jamTrackData = action.payload; + }, + + clearJamTrackData: (state) => { + state.jamTrackData = null; + }, + // Recording startRecording: (state, action) => { state.recordingState.isRecording = true; @@ -307,6 +318,8 @@ export const { removeBackingTrack, setBackingTrackData, clearBackingTrackData, + setJamTrackData, + clearJamTrackData, startRecording, stopRecording, addRecordedTrack, @@ -337,6 +350,7 @@ export const selectBackingTracks = (state) => state.activeSession.backingTracks; export const selectSelectedJamTrack = (state) => state.activeSession.selectedJamTrack; export const selectJamTrackStems = (state) => state.activeSession.jamTrackStems; export const selectBackingTrackData = (state) => state.activeSession.backingTrackData; +export const selectJamTrackData = (state) => state.activeSession.jamTrackData; export const selectConnectionStatus = (state) => state.activeSession.connectionStatus; export const selectShowConnectionAlert = (state) => state.activeSession.showConnectionAlert; export const selectRecordingState = (state) => state.activeSession.recordingState;