mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
feat(queue): addNext inserts a song to play right after current
Splices into currentIndex+1 and shifts both playedIndices and the history back-stack to keep references valid. Falls through to plain push when nothing is playing so the idle-bot "add → start playing" flow is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
30fd8a19b8
commit
11c6a3f51b
2 files changed
+102
No files matched your search
@@ -386,4 +386,78 @@ describe("PlayQueue", () => {
|
|||||||
expect(count).toBe(50);
|
expect(count).toBe(50);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("addNext", () => {
|
||||||
|
it("appends when queue is empty (no current)", () => {
|
||||||
|
queue.addNext(makeSong("a"));
|
||||||
|
expect(queue.size()).toBe(1);
|
||||||
|
expect(queue.list()[0].id).toBe("a");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("appends when nothing is currently playing (currentIndex < 0)", () => {
|
||||||
|
queue.add(makeSong("a"));
|
||||||
|
queue.add(makeSong("b"));
|
||||||
|
// No play() yet → currentIndex still -1
|
||||||
|
queue.addNext(makeSong("c"));
|
||||||
|
expect(queue.list().map((s) => s.id)).toEqual(["a", "b", "c"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("inserts at currentIndex+1 mid-queue", () => {
|
||||||
|
queue.add(makeSong("a"));
|
||||||
|
queue.add(makeSong("b"));
|
||||||
|
queue.add(makeSong("c"));
|
||||||
|
queue.add(makeSong("d"));
|
||||||
|
queue.play(); // current = 0 (a)
|
||||||
|
queue.next(); // current = 1 (b)
|
||||||
|
queue.addNext(makeSong("x"));
|
||||||
|
expect(queue.list().map((s) => s.id)).toEqual(["a", "b", "x", "c", "d"]);
|
||||||
|
expect(queue.current()?.id).toBe("b"); // current unchanged
|
||||||
|
});
|
||||||
|
|
||||||
|
it("makes the inserted song play next when next() is called", () => {
|
||||||
|
queue.setMode(PlayMode.Sequential);
|
||||||
|
queue.add(makeSong("a"));
|
||||||
|
queue.add(makeSong("b"));
|
||||||
|
queue.play(); // current = 0 (a)
|
||||||
|
queue.addNext(makeSong("x"));
|
||||||
|
expect(queue.next()?.id).toBe("x");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shifts playedIndices entries > currentIndex by +1", () => {
|
||||||
|
queue.setMode(PlayMode.Random);
|
||||||
|
queue.add(makeSong("a"));
|
||||||
|
queue.add(makeSong("b"));
|
||||||
|
queue.add(makeSong("c"));
|
||||||
|
queue.add(makeSong("d"));
|
||||||
|
queue.playAt(2); // current = 2 (c), played = {2}
|
||||||
|
queue.playAt(3); // current = 3 (d), played = {2, 3}
|
||||||
|
queue.playAt(2); // current = 2 (c), played = {2, 3}
|
||||||
|
// Now insert after c — d's index 3 should become 4
|
||||||
|
queue.addNext(makeSong("x"));
|
||||||
|
expect(queue.list().map((s) => s.id)).toEqual(["a", "b", "c", "x", "d"]);
|
||||||
|
// After addNext: currentIndex still 2; played should be {2, 4}
|
||||||
|
// (the previously-played 'd' is now at index 4)
|
||||||
|
// Verify by removing 'x' (index 3) — d should remain played at index 3
|
||||||
|
queue.remove(3);
|
||||||
|
expect(queue.list().map((s) => s.id)).toEqual(["a", "b", "c", "d"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shifts history entries > currentIndex by +1", () => {
|
||||||
|
queue.setMode(PlayMode.Random);
|
||||||
|
queue.add(makeSong("a"));
|
||||||
|
queue.add(makeSong("b"));
|
||||||
|
queue.add(makeSong("c"));
|
||||||
|
queue.add(makeSong("d"));
|
||||||
|
queue.playAt(0); // current = 0
|
||||||
|
queue.playAt(3); // current = 3 (d), history = [0]
|
||||||
|
queue.playAt(1); // current = 1 (b), history = [0, 3]
|
||||||
|
queue.addNext(makeSong("x"));
|
||||||
|
// Insert at index 2 → entries > 1 shift +1 → history becomes [0, 4]
|
||||||
|
// queue: [a, b, x, c, d]; d is now at index 4
|
||||||
|
// prev → pop 4 → song at index 4 = d
|
||||||
|
expect(queue.prev()?.id).toBe("d");
|
||||||
|
// prev again → pop 0 → song at index 0 = a
|
||||||
|
expect(queue.prev()?.id).toBe("a");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -40,6 +40,34 @@ export class PlayQueue {
|
|||||||
this.songs.push(...songs);
|
this.songs.push(...songs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a song to play immediately after the current one. Falls
|
||||||
|
* through to plain push when nothing is playing yet (currentIndex < 0
|
||||||
|
* or queue empty), so the existing "add → idle bot starts playing"
|
||||||
|
* flow continues to work.
|
||||||
|
*
|
||||||
|
* Shifts playedIndices and history entries > currentIndex by +1 so
|
||||||
|
* their references stay valid after the splice.
|
||||||
|
*/
|
||||||
|
addNext(song: QueuedSong): void {
|
||||||
|
if (this.currentIndex < 0 || this.songs.length === 0) {
|
||||||
|
this.songs.push(song);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const insertAt = this.currentIndex + 1;
|
||||||
|
this.songs.splice(insertAt, 0, song);
|
||||||
|
|
||||||
|
const shifted = new Set<number>();
|
||||||
|
for (const i of this.playedIndices) {
|
||||||
|
shifted.add(i > this.currentIndex ? i + 1 : i);
|
||||||
|
}
|
||||||
|
this.playedIndices = shifted;
|
||||||
|
|
||||||
|
this.history = this.history.map((i) =>
|
||||||
|
i > this.currentIndex ? i + 1 : i,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
remove(index: number): QueuedSong | null {
|
remove(index: number): QueuedSong | null {
|
||||||
if (index < 0 || index >= this.songs.length) return null;
|
if (index < 0 || index >= this.songs.length) return null;
|
||||||
const [removed] = this.songs.splice(index, 1);
|
const [removed] = this.songs.splice(index, 1);
|
||||||
|
|||||||
Reference in new issue
Block a user