perf(player): add idToIndex Map for O(1) track lookups
Replace all linear find/findIndex/some scans with a derived Map keyed by track.id. This makes currentTrack, currentIndex, hasTrack, add, playNext, remove, and addAll all O(1) for ID lookups.
This commit is contained in:
@@ -26,16 +26,26 @@ class PlayerStore {
|
||||
isMuted = $state(false);
|
||||
uiOpen = $state(false); // Mobile UI state
|
||||
|
||||
// Derived
|
||||
currentTrack = $derived(
|
||||
this.currentId
|
||||
? (this.queue.find((t) => t.id === this.currentId) ?? null)
|
||||
: null,
|
||||
);
|
||||
// O(1) index: track.id → index in queue
|
||||
private idToIndex = $derived.by(() => {
|
||||
const map = new Map<number, number>();
|
||||
for (let i = 0; i < this.queue.length; i++) {
|
||||
map.set(this.queue[i].id, i);
|
||||
}
|
||||
return map;
|
||||
});
|
||||
|
||||
currentIndex = $derived(
|
||||
this.currentId ? this.queue.findIndex((t) => t.id === this.currentId) : -1,
|
||||
);
|
||||
// Derived
|
||||
currentTrack = $derived.by(() => {
|
||||
if (this.currentId == null) return null;
|
||||
const idx = this.idToIndex.get(this.currentId);
|
||||
return idx !== undefined ? this.queue[idx] : null;
|
||||
});
|
||||
|
||||
currentIndex = $derived.by(() => {
|
||||
if (this.currentId == null) return -1;
|
||||
return this.idToIndex.get(this.currentId) ?? -1;
|
||||
});
|
||||
|
||||
displayQueue = $derived(
|
||||
this.isShuffled
|
||||
@@ -46,7 +56,7 @@ class PlayerStore {
|
||||
);
|
||||
|
||||
hasTrack(id: number) {
|
||||
return this.queue.some((t) => t.id === id);
|
||||
return this.idToIndex.has(id);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@@ -105,9 +115,9 @@ class PlayerStore {
|
||||
// Actions
|
||||
|
||||
add(track: Track, playNow = false) {
|
||||
const existingIdx = this.queue.findIndex((t) => t.id === track.id);
|
||||
const exists = this.hasTrack(track.id);
|
||||
|
||||
if (existingIdx !== -1) {
|
||||
if (exists) {
|
||||
if (playNow) {
|
||||
this.playNext(track);
|
||||
this.playId(track.id);
|
||||
@@ -133,7 +143,7 @@ class PlayerStore {
|
||||
}
|
||||
|
||||
playNext(track: Track) {
|
||||
const existingIdx = this.queue.findIndex((t) => t.id === track.id);
|
||||
const existingIdx = this.idToIndex.get(track.id) ?? -1;
|
||||
const targetTrack = track;
|
||||
|
||||
if (existingIdx !== -1) {
|
||||
@@ -173,7 +183,7 @@ class PlayerStore {
|
||||
const newTracks: Track[] = [];
|
||||
for (const track of tracks) {
|
||||
// Check existence inline to avoid O(n) per-track via add()
|
||||
if (!this.queue.some((t) => t.id === track.id)) {
|
||||
if (!this.hasTrack(track.id)) {
|
||||
newTracks.push(track);
|
||||
}
|
||||
}
|
||||
@@ -200,8 +210,8 @@ class PlayerStore {
|
||||
}
|
||||
|
||||
remove(id: number) {
|
||||
const idx = this.queue.findIndex((t) => t.id === id);
|
||||
if (idx === -1) return;
|
||||
const idx = this.idToIndex.get(id);
|
||||
if (idx === undefined) return;
|
||||
|
||||
const wasCurrent = this.currentId === id;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user