fix: prevent skipped/duplicate songs in Random mode edge cases

Three corner cases fixed:

1. Removing the currently-playing song caused the next song in the array
   to be silently marked as "played" and skipped. Root cause: playedIndices
   was updated in next() by marking currentIndex, but after remove() shifts
   currentIndex, it pointed to the wrong song. Fix: mark songs as played
   at play-time (in play/playAt/next/prev) instead of at next-request-time.

2. Using prev() in Random mode could cause a song to play twice — the
   song navigated to via prev() was not recorded in playedIndices, so
   next() could randomly select it again. Fix: prev() now marks the
   returned song as played.

3. Switching to Random mode mid-playback could cause the current song to
   repeat because setMode() cleared playedIndices without preserving the
   currently-playing song. Fix: setMode() now re-adds currentIndex after
   clearing.

https://claude.ai/code/session_01W3ZncxL5VfdZeB4qqYWDmY
This commit is contained in:
Claude committed 2026-04-12 15:02:53 +00:00
1 parent 4eac2e4dde
commit e2b1a5e055
2 files changed
+76 -3

No files matched your search

+7 -3
View File
@@ -61,6 +61,7 @@ export class PlayQueue {
if (this.songs.length === 0) return null;
this.playedIndices.clear();
this.currentIndex = 0;
this.playedIndices.add(0);
return this.songs[0];
}
@@ -68,6 +69,7 @@ export class PlayQueue {
if (index < 0 || index >= this.songs.length) return null;
this.playedIndices.clear();
this.currentIndex = index;
this.playedIndices.add(index);
return this.songs[index];
}
@@ -86,9 +88,6 @@ export class PlayQueue {
return this.songs[this.currentIndex];
}
case PlayMode.Random: {
if (this.currentIndex >= 0) {
this.playedIndices.add(this.currentIndex);
}
const unplayed: number[] = [];
for (let i = 0; i < this.songs.length; i++) {
if (!this.playedIndices.has(i)) unplayed.push(i);
@@ -97,6 +96,7 @@ export class PlayQueue {
const nextIndex =
unplayed[Math.floor(Math.random() * unplayed.length)];
this.currentIndex = nextIndex;
this.playedIndices.add(nextIndex);
return this.songs[nextIndex];
}
case PlayMode.RandomLoop: {
@@ -124,6 +124,7 @@ export class PlayQueue {
} else {
this.currentIndex = prevIndex;
}
this.playedIndices.add(this.currentIndex);
return this.songs[this.currentIndex];
}
@@ -152,6 +153,9 @@ export class PlayQueue {
setMode(mode: PlayMode): void {
this.mode = mode;
this.playedIndices.clear();
if (this.currentIndex >= 0) {
this.playedIndices.add(this.currentIndex);
}
}
getCurrentIndex(): number {