fix repeating end of queue bug

This commit is contained in:
Boof2015
2026-07-24 02:26:36 -04:00
parent a10ecf4a0f
commit 031db907ae
4 changed files with 72 additions and 21 deletions
+32 -13
View File
@@ -76,6 +76,15 @@ export interface PlaybackStartOptions {
source: PlaybackSource;
}
function toVirtualRntpTrack(
item: DbTrack & { queuePosition: number },
): RntpTrack {
return {
...toRntpTrack(dbTrackToTrack(item)),
astraQueuePosition: item.queuePosition,
};
}
const NEXT_REPEAT: Record<RepeatModeStr, RepeatModeStr> = {
none: 'all',
all: 'one',
@@ -337,7 +346,7 @@ export function restoreVirtualPlaybackContext(
restorePlaybackSession(null);
return;
}
const queueTracks = tracks.map(toRntpTrack);
const queueTracks = window.items.map(toVirtualRntpTrack);
const activeIndex = Math.max(
0,
Math.min(queueTracks.length - 1, window.activePosition - window.windowStart),
@@ -426,7 +435,7 @@ async function startVirtualWindow(
shuffle: boolean,
): Promise<void> {
const tracks = window.items.map(dbTrackToTrack);
const queueTracks = tracks.map(toRntpTrack);
const queueTracks = window.items.map(toVirtualRntpTrack);
const startIndex = Math.max(
0,
Math.min(queueTracks.length - 1, window.activePosition - window.windowStart),
@@ -496,14 +505,22 @@ async function replenishVirtualContext(): Promise<void> {
100,
);
if (virtualContext !== context || next.items.length === 0) return;
const additions = next.items.map(dbTrackToTrack).map(toRntpTrack);
const additions = next.items
.filter((item) => (
item.queuePosition >= context.loadedEnd &&
item.queuePosition < context.totalCount
))
.map(toVirtualRntpTrack);
if (additions.length === 0) return;
const nextLoadedEnd = Number(additions[additions.length - 1].astraQueuePosition) + 1;
if (!Number.isFinite(nextLoadedEnd) || nextLoadedEnd <= context.loadedEnd) return;
const before = useQueueStore.getState();
await appendUpcomingChunked(additions, before.tracks.length);
useQueueStore.getState().setSnapshot(
[...before.tracks, ...additions],
localIndex,
);
context.loadedEnd = next.items[next.items.length - 1].queuePosition + 1;
context.loadedEnd = Math.min(context.totalCount, nextLoadedEnd);
}
/** Returns a bounded page from the native virtual queue, or null for ordinary queues. */
@@ -519,14 +536,17 @@ export async function getVirtualQueuePage(
Math.max(1, Math.min(100, limit)),
);
if (virtualContext !== context) return null;
const boundedStart = Math.max(0, start);
return {
items: window.items.map((item) => ({
track: {
...toRntpTrack(dbTrackToTrack(item)),
astraQueuePosition: item.queuePosition,
},
queuePosition: item.queuePosition,
})),
items: window.items
.filter((item) => (
item.queuePosition >= boundedStart &&
item.queuePosition < window.totalCount
))
.map((item) => ({
track: toVirtualRntpTrack(item),
queuePosition: item.queuePosition,
})),
activePosition: window.activePosition,
totalCount: window.totalCount,
};
@@ -599,8 +619,7 @@ async function mutateVirtualQueue(
const boundedActive = Math.max(0, activeLocal);
const upcoming = window.items
.filter((item) => item.queuePosition > window.activePosition)
.map(dbTrackToTrack)
.map(toRntpTrack);
.map(toVirtualRntpTrack);
const before = useQueueStore.getState();
const prefix = before.tracks.slice(0, boundedActive + 1);
+18 -5
View File
@@ -212,7 +212,6 @@ export const QueueTray = memo(function QueueTray({ onClose, embedded = false }:
const loadVirtualPage = useCallback(async (reset: boolean) => {
const state = getVirtualQueueState();
if (!state || (!reset && virtualLoading.current)) return;
virtualLoading.current = true;
const generation = reset ? ++virtualLoadGeneration.current : virtualLoadGeneration.current;
const existing = reset ? [] : virtualTracksRef.current;
const lastPosition = existing.length > 0
@@ -221,6 +220,15 @@ export const QueueTray = memo(function QueueTray({ onClose, embedded = false }:
const start = typeof lastPosition === 'number'
? lastPosition + 1
: state.activePosition + 1;
if (start >= state.totalCount) {
if (reset) {
virtualLoading.current = false;
virtualTracksRef.current = [];
setVirtualTracks([]);
}
return;
}
virtualLoading.current = true;
try {
const page = await getVirtualQueuePage(start, 100);
if (
@@ -228,10 +236,15 @@ export const QueueTray = memo(function QueueTray({ onClose, embedded = false }:
generation !== virtualLoadGeneration.current ||
getVirtualQueueState()?.sessionId !== state.sessionId
) return;
const next = reset ? page.items.map((item) => item.track) : [
...existing,
...page.items.map((item) => item.track),
];
const existingPositions = new Set(
existing.map((track) => track.astraQueuePosition).filter(
(position): position is number => typeof position === 'number'
)
);
const incoming = page.items
.filter((item) => item.queuePosition >= start && !existingPositions.has(item.queuePosition))
.map((item) => item.track);
const next = reset ? incoming : [...existing, ...incoming];
// Keep no more than five tray pages in JS.
const bounded = next.slice(-500);
virtualTracksRef.current = bounded;