diff --git a/jam-ui/src/components/client/JKSessionJamTrackPlayer.js b/jam-ui/src/components/client/JKSessionJamTrackPlayer.js index e5d75d7ed..c7319cba9 100644 --- a/jam-ui/src/components/client/JKSessionJamTrackPlayer.js +++ b/jam-ui/src/components/client/JKSessionJamTrackPlayer.js @@ -10,7 +10,6 @@ import { import { setOpenJamTrack, clearOpenJamTrack } from '../../store/features/sessionUISlice'; import { setAvailableMixdowns, setActiveMixdown } from '../../store/features/activeSessionSlice'; import { useJamServerContext } from '../../context/JamServerContext'; -import './JKSessionJamTrackPlayer.css'; // Error types for comprehensive error handling const ERROR_TYPES = { @@ -476,191 +475,417 @@ const JKSessionJamTrackPlayer = ({ if (!isOpen && !isPopup) return null; return ( -
+ <> + +
{/* Window Chrome */} -
-
-
-
-
+
+
+
+
+
-
+
JamTrack: {jamTrack?.name || 'Loading...'}
{/* Content Area */} -
- {/* Error Banner */} - {error && ( -
- {error.type.toUpperCase()} ERROR: -
{error.message}
-
- - {(error.type === ERROR_TYPES.NETWORK || error.type === ERROR_TYPES.DOWNLOAD || error.type === ERROR_TYPES.FILE) && ( - +
+
+ {/* Error Banner */} + {error && ( +
+
{error.type.toUpperCase()} ERROR: {error.message}
+
+ + {(error.type === ERROR_TYPES.NETWORK || error.type === ERROR_TYPES.DOWNLOAD || error.type === ERROR_TYPES.FILE) && ( + + )} +
+
+ )} + + {/* Download/Sync State Banner */} + {downloadState.state !== 'idle' && downloadState.state !== 'synchronized' && ( +
+
+ {downloadState.state === 'checking' && 'Checking sync status...'} + {downloadState.state === 'packaging' && 'Your JamTrack is currently being created in the JamKazam server'} + {downloadState.state === 'downloading' && 'Downloading JamTrack...'} + {downloadState.state === 'keying' && 'Requesting decryption keys...'} + {downloadState.state === 'error' && 'Download Failed'} +
+ + {downloadState.state === 'packaging' && ( + <> +
+ {downloadState.signing_state === 'SIGNED' && 'Package ready, starting download...'} + {downloadState.signing_state !== 'SIGNED' && downloadState.signing_state && `Status: ${downloadState.signing_state}`} + {!downloadState.signing_state && 'Preparing your JamTrack...'} +
+ {downloadState.packaging_steps > 0 && ( +
+ Step {downloadState.current_packaging_step} of {downloadState.packaging_steps} +
+ )} +
+ + )} + + {downloadState.state === 'downloading' && ( + <> + +
+ {downloadState.progress}% +
+ {downloadState.totalSteps > 0 && ( +
+ Step {downloadState.currentStep} of {downloadState.totalSteps} +
+ )} + + + )} + + {downloadState.state === 'keying' && ( + <> +
+ Finalizing download... +
+
+ + )} + + {downloadState.state === 'error' && ( + <> +
+ {downloadState.error?.message || 'Download failed'} +
+ + )}
-
- )} + )} - {/* Download/Sync State Banner */} - {downloadState.state !== 'idle' && downloadState.state !== 'synchronized' && ( -
-

- {downloadState.state === 'checking' && 'Checking sync status...'} - {downloadState.state === 'packaging' && 'Your JamTrack is currently being created in the JamKazam server'} - {downloadState.state === 'downloading' && 'Downloading JamTrack...'} - {downloadState.state === 'keying' && 'Requesting decryption keys...'} - {downloadState.state === 'error' && 'Download Failed'} -

- - {downloadState.state === 'packaging' && ( - <> -

- {downloadState.signing_state === 'SIGNED' && 'Package ready, starting download...'} - {downloadState.signing_state !== 'SIGNED' && downloadState.signing_state && `Status: ${downloadState.signing_state}`} - {!downloadState.signing_state && 'Preparing your JamTrack...'} -

- {downloadState.packaging_steps > 0 && ( -

Step {downloadState.current_packaging_step} of {downloadState.packaging_steps}

- )} -
- - )} - - {downloadState.state === 'downloading' && ( - <> - -

{downloadState.progress}%

- {downloadState.totalSteps > 0 && ( -

Step {downloadState.currentStep} of {downloadState.totalSteps}

- )} - - - )} - - {downloadState.state === 'keying' && ( - <> -

Finalizing download...

-
- - )} - - {downloadState.state === 'error' && ( - <> -

{downloadState.error?.message || 'Download failed'}

- - - )} -
- )} - - {/* Playback Controls */} -
- - - - - {/* Time Display and Scrubber */} -
- {formattedPosition} -
-
-
-
- handleSeek(parseInt(e.target.value, 10))} - disabled={isOperating || !jamTrackState.durationMs} - /> + {/* Loading indicator */} + {isLoadingSync && ( +
+ Loading track...
- {formattedDuration} + )} + + {/* Controls Section */} +
+ {/* Circular Buttons and Seek Bar */} +
+ {/* Play Button - Circular */} + + + {/* Stop Button - Circular */} + + + {/* Time and Seek Bar */} +
+ + {formattedPosition} + + handleSeek(parseInt(e.target.value, 10))} + disabled={isOperating || !jamTrackState.durationMs} + style={{ + flex: 1, + height: '4px', + borderRadius: '2px', + outline: 'none', + background: `linear-gradient(to right, #5b9bd5 0%, #5b9bd5 ${progressPercent}%, #ddd ${progressPercent}%, #ddd 100%)`, + WebkitAppearance: 'none', + cursor: (isOperating || !jamTrackState.durationMs) ? 'not-allowed' : 'pointer' + }} + /> + + {formattedDuration} + +
+
+ + {/* Mix Selector */} + {availableMixdowns.length > 0 && ( +
+
+ + Mix: + + +
+ +
+ )} +
+ + {/* Close Button */} +
+
- - {/* Mix Selector */} - {availableMixdowns.length > 0 && ( - <> -
- Mix: - -
- - - )} - - {/* Close Button */} -
+ ); };