mirror of
https://github.com/Boof2015/astra-mobile.git
synced 2026-08-18 19:54:26 +02:00
fix repeating end of queue bug
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user