perf(player): debounce localStorage persistence
Wrap save() in a 300ms debounce to prevent rapid serialization when multiple state changes fire in quick succession (e.g. removing several items or adjusting volume).
This commit is contained in:
@@ -26,6 +26,9 @@ class PlayerStore {
|
|||||||
isMuted = $state(false);
|
isMuted = $state(false);
|
||||||
uiOpen = $state(false); // Mobile UI state
|
uiOpen = $state(false); // Mobile UI state
|
||||||
|
|
||||||
|
// Debounce timer for save()
|
||||||
|
private _saveTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
// O(1) index: track.id → index in queue
|
// O(1) index: track.id → index in queue
|
||||||
private idToIndex = $derived.by(() => {
|
private idToIndex = $derived.by(() => {
|
||||||
const map = new Map<number, number>();
|
const map = new Map<number, number>();
|
||||||
@@ -99,6 +102,7 @@ class PlayerStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
|
// Read snapshots synchronously so $effect tracks reactive deps
|
||||||
const data: PlayerState = {
|
const data: PlayerState = {
|
||||||
queue: $state.snapshot(this.queue),
|
queue: $state.snapshot(this.queue),
|
||||||
currentId: $state.snapshot(this.currentId),
|
currentId: $state.snapshot(this.currentId),
|
||||||
@@ -109,7 +113,11 @@ class PlayerStore {
|
|||||||
volume: $state.snapshot(this.volume),
|
volume: $state.snapshot(this.volume),
|
||||||
isMuted: $state.snapshot(this.isMuted),
|
isMuted: $state.snapshot(this.isMuted),
|
||||||
};
|
};
|
||||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
// Debounce only the serialization + write
|
||||||
|
if (this._saveTimer) clearTimeout(this._saveTimer);
|
||||||
|
this._saveTimer = setTimeout(() => {
|
||||||
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
||||||
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|||||||
Reference in New Issue
Block a user