From 3944cf6ff4a64c5c8b7f4c07e3b7c690dbabc0a8 Mon Sep 17 00:00:00 2001 From: Yuri Tatishchev Date: Wed, 11 Feb 2026 23:18:41 -0800 Subject: [PATCH] modify id to index map imperatively --- src/lib/player/store.svelte.ts | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/lib/player/store.svelte.ts b/src/lib/player/store.svelte.ts index b66ec1b..ee6092b 100644 --- a/src/lib/player/store.svelte.ts +++ b/src/lib/player/store.svelte.ts @@ -29,14 +29,17 @@ class PlayerStore { // Debounce timer for save() private _saveTimer: ReturnType | 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()); + + /** Rebuild the full index from the queue array. */ + private rebuildIndex() { const map = new Map(); 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(); } }