From d4c88042e0db6a446e95590d81b2813f033f6f5c Mon Sep 17 00:00:00 2001 From: Boof2015 <75185879+Boof2015@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:30:16 -0400 Subject: [PATCH] fix queue bug --- src/components/queue/QueueTray.tsx | 22 +++++++++++++++++-- .../queue/virtualQueuePaging.test.mts | 7 ++++++ src/components/queue/virtualQueuePaging.ts | 16 ++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/components/queue/QueueTray.tsx b/src/components/queue/QueueTray.tsx index aec384c..741737a 100644 --- a/src/components/queue/QueueTray.tsx +++ b/src/components/queue/QueueTray.tsx @@ -87,6 +87,7 @@ import { QueueSheetHandle } from './QueueSheetHandle'; import { VIRTUAL_QUEUE_PAGE_SIZE, isCurrentVirtualQueueRequest, + isVirtualQueueWaitingForTracks, mergeVirtualQueueTracks, nextVirtualQueuePageStart, seedVirtualQueueTracks, @@ -390,7 +391,17 @@ export const QueueTray = memo(function QueueTray({ onClose, embedded = false }: if (embedded || listPaintedRef.current) { void loadVirtualPage(true); } else { - resetVirtualTracks(); + const state = resetVirtualTracks(); + if ( + state + && isVirtualQueueWaitingForTracks( + virtualTracksRef.current.length, + state.activePosition, + state.totalCount, + ) + ) { + void loadVirtualPage(false); + } } }, [ embedded, @@ -912,7 +923,14 @@ export const QueueTray = memo(function QueueTray({ onClose, embedded = false }: ); const queueReady = hasSnapshot; - const isLoadingQueue = !queueReady; + const isLoadingQueue = !queueReady || ( + virtualState !== null + && isVirtualQueueWaitingForTracks( + entries.length, + virtualState.activePosition, + virtualState.totalCount, + ) + ); const listExtraData = useMemo( () => ({ editMode, selectedKeys: visibleSelectedKeys, queueReady }), diff --git a/src/components/queue/virtualQueuePaging.test.mts b/src/components/queue/virtualQueuePaging.test.mts index 3073c8f..3ca1e8e 100644 --- a/src/components/queue/virtualQueuePaging.test.mts +++ b/src/components/queue/virtualQueuePaging.test.mts @@ -4,6 +4,7 @@ import { VIRTUAL_QUEUE_PAGE_SIZE, VIRTUAL_QUEUE_PREFETCH_ROWS, isCurrentVirtualQueueRequest, + isVirtualQueueWaitingForTracks, mergeVirtualQueueTracks, nextVirtualQueuePageStart, seedVirtualQueueTracks, @@ -65,6 +66,12 @@ test('stops paging at the virtual queue end', () => { assert.equal(nextVirtualQueuePageStart([], 5, 6), null); }); +test('loads an empty virtual seed immediately when tracks remain', () => { + assert.equal(isVirtualQueueWaitingForTracks(0, 5, 10), true); + assert.equal(isVirtualQueueWaitingForTracks(1, 5, 10), false); + assert.equal(isVirtualQueueWaitingForTracks(0, 9, 10), false); +}); + test('rejects stale generations and replaced playback sessions', () => { assert.equal(isCurrentVirtualQueueRequest(4, 4, 'session-a', 'session-a'), true); assert.equal(isCurrentVirtualQueueRequest(3, 4, 'session-a', 'session-a'), false); diff --git a/src/components/queue/virtualQueuePaging.ts b/src/components/queue/virtualQueuePaging.ts index bbfe1e3..6408778 100644 --- a/src/components/queue/virtualQueuePaging.ts +++ b/src/components/queue/virtualQueuePaging.ts @@ -64,6 +64,22 @@ export function nextVirtualQueuePageStart( return start < totalCount ? start : null; } +/** + * Break the empty-list mount deadlock: when the playback window has no usable + * upcoming rows but the virtual context still has tracks, paging cannot wait + * for FlashList's first paint because an empty list may never report one. + */ +export function isVirtualQueueWaitingForTracks( + visibleTrackCount: number, + activePosition: number, + totalCount: number, +): boolean { + return ( + visibleTrackCount === 0 + && nextVirtualQueuePageStart([], activePosition, totalCount) !== null + ); +} + export function shouldPrefetchVirtualQueue( lastVisibleIndex: number, loadedCount: number,