diff --git a/jam-ui/src/components/client/JKSessionJamTrackPlayer.js b/jam-ui/src/components/client/JKSessionJamTrackPlayer.js index 20edd8a11..b9edf5d2b 100644 --- a/jam-ui/src/components/client/JKSessionJamTrackPlayer.js +++ b/jam-ui/src/components/client/JKSessionJamTrackPlayer.js @@ -4,7 +4,8 @@ import { loadJamTrack, checkJamTrackSync, closeJamTrack, - setJamTrackState + setJamTrackState, + setDownloadState } from '../../store/features/mediaSlice'; import { setOpenJamTrack, clearOpenJamTrack } from '../../store/features/sessionUISlice'; import { setAvailableMixdowns, setActiveMixdown } from '../../store/features/activeSessionSlice'; @@ -281,6 +282,48 @@ const JKSessionJamTrackPlayer = ({ } }, [isOperating, jamClient, jamTrack, jamTrackState, availableMixdowns, dispatch]); + // Download cancel handler + const handleCancelDownload = useCallback(async () => { + if (!jamClient || !fqIdRef.current) return; + + try { + await jamClient.JamTrackCancelDownload(fqIdRef.current); + dispatch(setDownloadState({ state: 'idle', progress: 0 })); + } catch (err) { + console.error('[JamTrack] Cancel download error:', err); + setError({ type: 'download', message: 'Failed to cancel download' }); + } + }, [jamClient, dispatch]); + + // Download retry handler + const handleRetryDownload = useCallback(async () => { + if (isOperating || !jamClient) return; + + try { + setIsOperating(true); + setError(null); + + // Clear error state + dispatch(setDownloadState({ state: 'idle', error: null })); + + // Retry load (will trigger download if not synced) + await dispatch(loadJamTrack({ + jamTrack, + mixdownId: selectedMixdownId, + autoPlay: false, + jamClient + })).unwrap(); + + } catch (err) { + console.error('[JamTrack] Retry download error:', err); + setError({ type: 'download', message: 'Retry failed' }); + } finally { + if (mountedRef.current) { + setIsOperating(false); + } + } + }, [isOperating, jamClient, jamTrack, selectedMixdownId, dispatch]); + // Helper: Format milliseconds to MM:SS const formatTime = (ms) => { if (!ms || isNaN(ms)) return '00:00'; @@ -359,9 +402,43 @@ const JKSessionJamTrackPlayer = ({ )} +{/* Download/Sync State Machine UI */} {downloadState.state !== 'idle' && downloadState.state !== 'synchronized' && ( -
Download: {downloadState.state} ({downloadState.progress}%)
+{downloadState.progress}%
+ {downloadState.totalSteps > 0 && ( +Step {downloadState.currentStep} of {downloadState.totalSteps}
+ )} + +Finalizing download...
+{downloadState.error?.message || 'Download failed'}
+ +