From acb8b0af3a9a1437902b0105bb100867272cc5c8 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Wed, 14 Jan 2026 16:48:53 +0530 Subject: [PATCH] fix(03-03): resolve end-of-track and popup mode issues Issue 1 - End of track playback: - When track ends, call SessionStopPlay() and reset position to 0 - Ensures clean state for next playback - Fixes "3 click" bug when restarting after track ends Issue 2 & 3 - Volume and loop not working in popup mode: - Add getBackingTrackPath() helper to handle both formats - In popup mode, backingTrack is a string (path) - In modal mode, backingTrack is an object with .path property - Update handleLoopChange to use helper - Fixes "No backing track available" error Co-Authored-By: Claude Sonnet 4.5 --- .../client/JKSessionBackingTrackPlayer.js | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js b/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js index 9ca7015ee..fb44e9232 100644 --- a/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js +++ b/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js @@ -172,7 +172,14 @@ const JKSessionBackingTrackPlayer = ({ // Check if track reached the end if (validPosition >= validDuration && validDuration > 0) { + // Stop playback and reset to beginning for clean state + await jamClient.SessionStopPlay(); setIsPlaying(false); + setCurrentPositionMs(0); + setCurrentTime('0:00'); + // Exit early - don't update position to end + consecutivePollingErrorsRef.current = 0; + return; } // Only update state if values actually changed (lazy updates) @@ -374,18 +381,19 @@ const JKSessionBackingTrackPlayer = ({ // Set loop state using SessionSetBackingTrackFileLoop // This requires the file path and loop boolean - if (!backingTrack || !backingTrack.path) { + const trackPath = getBackingTrackPath(backingTrack); + if (!trackPath) { handleError('playback', 'No backing track available for loop change', null); setIsLooping(previousLoop); // Revert checkbox return; } - await jamClient.SessionSetBackingTrackFileLoop(backingTrack.path, shouldLoop); + await jamClient.SessionSetBackingTrackFileLoop(trackPath, shouldLoop); } catch (error) { handleError('playback', 'Failed to toggle loop', error); setIsLooping(previousLoop); // Revert checkbox on error } - }, [isLooping, jamClient, backingTrack, handleError]); + }, [isLooping, jamClient, backingTrack, handleError, getBackingTrackPath]); /* * UAT-003 Fix: Seek while paused limitation workaround @@ -460,18 +468,30 @@ const JKSessionBackingTrackPlayer = ({ } }, [handleStop, closeMedia, isPopup, onClose]); + // Helper to get backing track path (handles both string and object formats) + const getBackingTrackPath = useCallback((backingTrack) => { + if (!backingTrack) return null; + // If backingTrack is a string, it's the path itself (popup mode) + if (typeof backingTrack === 'string') return backingTrack; + // If it's an object, extract the path property (modal mode) + return backingTrack.path || null; + }, []); + const getFileName = useCallback((backingTrack) => { if (!backingTrack) return 'Unknown File'; - // Extract filename from path or use provided name - if (backingTrack.path) { - return backingTrack.path.split('/').pop().split('\\').pop(); + // Get the path first + const path = getBackingTrackPath(backingTrack); + if (path) { + return path.split('/').pop().split('\\').pop(); } - if (backingTrack.name) { + + // Fallback to name if it's an object + if (typeof backingTrack === 'object' && backingTrack.name) { return backingTrack.name; } return 'Audio File'; - }, []); + }, [getBackingTrackPath]);