refactor(queue): persist thin QueueItemRef list (thin-state phase 1) (#858)

* refactor(queue): persist thin QueueItemRef list (thin-state phase 1)

Introduce QueueItemRef ({ serverId, trackId, autoAdded?, radioAdded?,
playNextAdded? }) and persist the whole queue as a thin queueItems list,
superseding the queueRefs id list. Dual-write: the windowed queue: Track[]
stays as the index-off fallback; the in-memory store is unchanged.

hydrateQueueFromIndex now prefers queueItems (per-item serverId) and carries
the queue-only flags onto the hydrated tracks (the index doesn't store them),
with a queueRefs fallback for stores persisted before this change.

Phase 1 of the queue thin-state plan; no store/consumer changes yet.

* test(queue): cover legacy queueRefs-only upgrade in hydrate

* docs(changelog): queue section dividers kept on index restore (#858)
This commit is contained in:
Frank Stellmacher
2026-05-22 22:43:41 +02:00
committed by GitHub
parent 06213cb5d8
commit d15e270499
6 changed files with 164 additions and 22 deletions
+21
View File
@@ -285,4 +285,25 @@ describe('partialize: localStorage queue window', () => {
expect((partial.queue as unknown[]).length).toBe(0);
expect(partial.queueIndex).toBe(0);
});
it('persists the whole queue as thin queueItems (refs + serverId + flags), not just the window', () => {
const tracks = makeTracks(600);
tracks[3].radioAdded = true;
tracks[4].autoAdded = true;
usePlayerStore.setState({ queue: tracks, queueIndex: 300, queueServerId: 's1' });
const partial = getPartialize()(usePlayerStore.getState());
const items = partial.queueItems as {
serverId: string; trackId: string; radioAdded?: boolean; autoAdded?: boolean;
}[];
// windowed `queue` is capped, but queueItems carries the WHOLE queue
expect((partial.queue as unknown[]).length).toBe(501);
expect(items.length).toBe(600);
expect(partial.queueItemsIndex).toBe(300);
expect(items[0].serverId).toBe('s1');
expect(items[3].radioAdded).toBe(true);
expect(items[4].autoAdded).toBe(true);
expect(items[0].radioAdded).toBeUndefined();
});
});