From fa3515acc9773e52049c51aafbfacd2657fc94ea Mon Sep 17 00:00:00 2001 From: Kagamine Rin Date: Fri, 29 May 2026 21:49:36 -0400 Subject: [PATCH] feat: Smart play/pause overlay on DetailPanel album art MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DetailPanel.tsx: - Added isPlaying and currentClipId props to track playback state - Added onTogglePlay prop for pausing currently-playing track - Album art click handler now smart: * If this track IS playing → pause it (onTogglePlay) * If this track is NOT playing → play it (onPlay) - Hover overlay icon adapts dynamically: * Currently playing + hover → shows PAUSE icon (⏸) * Not playing + hover → shows PLAY icon (▶) - Works for both artwork images and placeholder state App.tsx: - Passes isPlaying, currentClipId, and onTogglePlay to DetailPanel Visual states: - Different track in panel: ▶ on hover (click to play) - Same track playing: ⏸ on hover (click to pause) - Same track paused: ▶ on hover (click to resume) --- frontend/src/App.tsx | 3 ++ frontend/src/components/DetailPanel.tsx | 45 ++++++++++++++++++++----- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4f3fb13..3f496a0 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -229,12 +229,15 @@ function App() { {selectedClip && ( setSelectedClip(null)} onRename={handleRename} onDelete={handleDelete} onUploadArtwork={handleUploadArtwork} onRemoveArtwork={handleRemoveArtwork} onPlay={handlePlay} + onTogglePlay={() => setIsPlaying(!isPlaying)} /> )} diff --git a/frontend/src/components/DetailPanel.tsx b/frontend/src/components/DetailPanel.tsx index 2508095..e6d2b8c 100644 --- a/frontend/src/components/DetailPanel.tsx +++ b/frontend/src/components/DetailPanel.tsx @@ -18,12 +18,15 @@ interface Clip { interface Props { clip: Clip + isPlaying: boolean + currentClipId?: string onClose: () => void onRename: (id: string, title: string) => void onDelete: (id: string) => void onUploadArtwork: (id: string, file: File) => void onRemoveArtwork: (id: string) => void onPlay?: (clip: Clip) => void + onTogglePlay?: () => void } const modelName = (modelId: string) => { @@ -34,7 +37,7 @@ const modelName = (modelId: string) => { return names[modelId] || modelId } -export default function DetailPanel({ clip, onClose, onRename, onDelete, onUploadArtwork, onRemoveArtwork, onPlay }: Props) { +export default function DetailPanel({ clip, isPlaying, currentClipId, onClose, onRename, onDelete, onUploadArtwork, onRemoveArtwork, onPlay, onTogglePlay }: Props) { const artworkInputRef = useRef(null) const [isEditingTitle, setIsEditingTitle] = useState(false) const [editTitle, setEditTitle] = useState(clip.title || '') @@ -149,7 +152,13 @@ export default function DetailPanel({ clip, onClose, onRename, onDelete, onUploa {clip.artwork_filename ? (
onPlay?.(clip)} + onClick={() => { + if (currentClipId === clip.id && isPlaying) { + onTogglePlay?.() + } else { + onPlay?.(clip) + } + }} >
- - - + {currentClipId === clip.id && isPlaying ? ( + + + + ) : ( + + + + )}
) : (
onPlay?.(clip)} + onClick={() => { + if (currentClipId === clip.id && isPlaying) { + onTogglePlay?.() + } else { + onPlay?.(clip) + } + }} > 𝄞 No album art
- - - + {currentClipId === clip.id && isPlaying ? ( + + + + ) : ( + + + + )}
)}