modify id to index map imperatively
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user