From 77b2a5401a1e36435b651fe8ff60cc1ebd8eb523 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Sun, 26 Apr 2026 01:41:25 +0200 Subject: [PATCH] fix(queue): preserve scroll context when user clicks a track in the queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Auto-scroll used to fire on every currentTrack change, including manual clicks inside the queue list itself. The clicked track would slide off screen as the list rebased onto the new "next track", which is disorienting — the user just acted on something specific and expects to keep seeing it. Set a one-shot suppression flag from the queue-item onClick handler so the immediately following auto-scroll effect skips its scrollIntoView call. Natural advance (track end, prev/next button, anything that does not originate inside the queue list) leaves the flag untouched and keeps the original "show what's coming next" behavior. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/QueuePanel.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/QueuePanel.tsx b/src/components/QueuePanel.tsx index 97140f32..b0249dd3 100644 --- a/src/components/QueuePanel.tsx +++ b/src/components/QueuePanel.tsx @@ -297,6 +297,12 @@ function QueuePanelHostOrSolo() { const enqueueAt = usePlayerStore(s => s.enqueueAt); const contextMenu = usePlayerStore(s => s.contextMenu); + // When the user picks a track *from* the queue list, suppress the + // upcoming auto-scroll so their click target stays in view instead of + // the list rebasing onto the next track. Auto-advance (natural playback) + // never sets this flag, so it keeps its original "show what's next" behavior. + const suppressNextAutoScrollRef = useRef(false); + const playbackSource = usePlayerStore(s => s.currentPlaybackSource); const crossfadeEnabled = useAuthStore(s => s.crossfadeEnabled); @@ -407,6 +413,10 @@ function QueuePanelHostOrSolo() { }, [enqueueAt]); useEffect(function queueAutoScroll() { + if (suppressNextAutoScrollRef.current) { + suppressNextAutoScrollRef.current = false; + return; + } if (!queueListRef.current || queueIndex < 0) return; if (activeTab !== 'queue') return; const songs = queueListRef.current!.querySelectorAll('[data-queue-idx]'); @@ -741,7 +751,10 @@ function QueuePanelHostOrSolo() {
playTrack(track, queue)} + onClick={() => { + suppressNextAutoScrollRef.current = true; + playTrack(track, queue); + }} onContextMenu={(e) => { e.preventDefault(); usePlayerStore.getState().openContextMenu(e.clientX, e.clientY, track, 'queue-item', idx);