modify id to index map imperatively

This commit is contained in:
2026-02-11 23:18:41 -08:00
parent 6fca5bae39
commit 3944cf6ff4

View File

@@ -29,14 +29,17 @@ class PlayerStore {
// Debounce timer for save()
private _saveTimer: ReturnType<typeof setTimeout> | null = null;
// O(1) index: track.id → index in queue
private idToIndex = $derived.by(() => {
// O(1) index: track.id → index in queue (maintained imperatively)
private idToIndex = $state(new Map<number, number>());
/** Rebuild the full index from the queue array. */
private rebuildIndex() {
const map = new Map<number, number>();
for (let i = 0; i < this.queue.length; i++) {
map.set(this.queue[i].id, i);
}
return map;
});
this.idToIndex = map;
}
// Derived
currentTrack = $derived.by(() => {
@@ -52,9 +55,7 @@ class PlayerStore {
displayQueue = $derived(
this.isShuffled
? this.shuffledIndices
.map((i) => this.queue[i])
.filter((t) => t !== undefined)
? this.shuffledIndices.map((i) => this.queue[i])
: this.queue,
);
@@ -80,6 +81,7 @@ class PlayerStore {
if (state.volume !== undefined) this.volume = state.volume;
if (state.isMuted !== undefined) this.isMuted = state.isMuted;
if (state.minimized !== undefined) this.uiOpen = !state.minimized;
this.rebuildIndex();
}
load() {
@@ -95,6 +97,7 @@ class PlayerStore {
this.repeatMode = data.repeatMode || "off";
this.volume = data.volume ?? 1;
this.isMuted = data.isMuted || false;
this.rebuildIndex();
}
} catch (e) {
console.error("Failed to load player state", e);
@@ -139,6 +142,7 @@ class PlayerStore {
} else {
// Add to end
this.queue.push(track);
this.idToIndex.set(track.id, this.queue.length - 1);
if (this.isShuffled) {
this.shuffledIndices.push(this.queue.length - 1);
@@ -166,6 +170,8 @@ class PlayerStore {
const insertIdx = currentIdx === -1 ? 0 : currentIdx + 1;
this.queue.splice(insertIdx, 0, targetTrack);
// Rebuild index — splice shifts everything after insertIdx
this.rebuildIndex();
if (this.isShuffled) {
// Shift indices that are >= insertIdx because we inserted a new item
@@ -199,6 +205,10 @@ class PlayerStore {
const startIdx = this.queue.length;
this.queue.push(...newTracks);
// Only index the newly added tracks
for (let i = 0; i < newTracks.length; i++) {
this.idToIndex.set(newTracks[i].id, startIdx + i);
}
if (this.isShuffled) {
const newIndices = newTracks.map((_, i) => startIdx + i);
@@ -224,6 +234,8 @@ class PlayerStore {
const wasCurrent = this.currentId === id;
this.queue.splice(idx, 1);
// Rebuild index — splice shifts everything after idx
this.rebuildIndex();
if (wasCurrent) {
this.currentId = null; // Or auto-advance?
@@ -240,6 +252,7 @@ class PlayerStore {
clearQueue() {
this.queue = [];
this.idToIndex = new Map();
this.currentId = null;
this.shuffledIndices = [];
this.history = [];
@@ -271,6 +284,7 @@ class PlayerStore {
const [item] = q.splice(fromIdx, 1);
q.splice(toIdx, 0, item);
this.queue = q;
this.rebuildIndex();
}
}