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