fix(queue): restore playedIndices clear in playAt; test HISTORY_LIMIT

Code review of 390d3fa flagged that dropping playedIndices.clear() from
playAt is an unnecessary behavior change. The two operations (push
history, reset random pool) are not in tension — restoring the clear
preserves the original 'explicit pick restarts shuffle' semantic that
Random mode users rely on, while still tracking the prev-history stack.

Also add a regression test that the 50-entry HISTORY_LIMIT cap works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
saopig1andClaude Opus 4.7 committed 2026-05-06 16:32:23 +08:00
1 parent 390d3fa782
commit 30fd8a19b8
2 files changed
+26

No files matched your search

+22
View File
@@ -363,5 +363,27 @@ describe("PlayQueue", () => {
queue.prev(); // pops 0, history: [] queue.prev(); // pops 0, history: []
expect(queue.prev()).toBeNull(); // no fallback target in random mode expect(queue.prev()).toBeNull(); // no fallback target in random mode
}); });
it("caps history at HISTORY_LIMIT (50) entries, dropping oldest", () => {
queue.setMode(PlayMode.Random);
// Build a queue large enough to overflow HISTORY_LIMIT
for (let i = 0; i < 60; i++) queue.add(makeSong(`s${i}`));
// Walk through 60 explicit picks → 59 pushes to history
// (playAt pushes the previous currentIndex; first call has -1
// which pushHistory rejects). After 60 playAts, history holds
// the last 50 of those 59 entries.
for (let i = 0; i < 60; i++) queue.playAt(i);
// Walk back through history. The first prev returns whatever the
// 50th-most-recent push was (= index 9, since pushes 0..58 happened
// and the oldest 9 fell off). We can verify by counting prevs that
// succeed before history exhausts and prev returns null in random.
let count = 0;
while (queue.prev() !== null) {
count++;
if (count > 100) break; // safety
}
expect(count).toBe(50);
});
}); });
}); });
+4
View File
@@ -86,6 +86,10 @@ export class PlayQueue {
playAt(index: number): QueuedSong | null { playAt(index: number): QueuedSong | null {
if (index < 0 || index >= this.songs.length) return null; if (index < 0 || index >= this.songs.length) return null;
this.pushHistory(this.currentIndex); this.pushHistory(this.currentIndex);
// Reset the Random-mode "unplayed" pool — explicit picks restart
// shuffle from this point. History tracking is independent and
// unaffected by this clear.
this.playedIndices.clear();
this.currentIndex = index; this.currentIndex = index;
this.playedIndices.add(index); this.playedIndices.add(index);
return this.songs[index]; return this.songs[index];