mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
refactor(queue): track resolver + selectors (thin-state phase 2) (#859)
* refactor(queue): add queue track resolver (thin-state phase 2a) Standalone resolver: QueueItemRef → Track via index batch (library_get_tracks_batch, ≤100/call) → network getSong fallback (P8), into a bounded LRU cache. Holds raw tracks; session star/rating overrides (F4) merged on read via applyQueueOverrides. Sync getCachedTrack + subscribeQueueResolver for selectors; resolveVisibleRange prefetches a [-50, +200] window; carries queue-only flags from refs; invalidate drops entries after a sync succeeds. Not wired into the store/UI yet — phase 2b does that. * refactor(queue): extract toQueueItemRefs helper Pure helper deriving thin QueueItemRefs from a Track[] queue (per-item serverId, queue-only flags), shared by the persist partialize and the upcoming phase-2b resolver bridge. No behaviour change. * refactor(queue): resolver bridge + queue selectors (thin-state phase 2b) Seed the resolver cache from the canonical queue (queueResolverBridge, a windowed [-50, +200] seed around the current index) and add the stable queue selectors (useQueueTrackAt / useCurrentTrack / useQueueItems). Additive: the store stays queue: Track[]-canonical; consumers migrate onto the selectors in phase 3, and the selector impls move to the resolver once queue: Track[] is dropped in phase 4. No mutation or persist change — the persisted queueItems keeps its single restore role (no dual-role clash). * docs(changelog): on-demand queue track loading groundwork (#859)
This commit is contained in:
committed by
GitHub
parent
d15e270499
commit
090a31bc82
@@ -1,7 +1,8 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||
import { emitPlaybackProgress } from './playbackProgress';
|
||||
import type { PlayerState, QueueItemRef } from './playerStoreTypes';
|
||||
import type { PlayerState } from './playerStoreTypes';
|
||||
import { toQueueItemRefs } from '../utils/library/queueItemRef';
|
||||
import { readInitialQueueVisibility } from './queueVisibilityStorage';
|
||||
import { createLastfmActions } from './lastfmActions';
|
||||
import { createMiscActions } from './miscActions';
|
||||
@@ -99,13 +100,7 @@ export const usePlayerStore = create<PlayerState>()(
|
||||
// windowed `queue` above stays as the no-index fallback (queue never
|
||||
// empty when the index is off, the P6 default). Per-item serverId is
|
||||
// the playback server (single-server v1); supersedes `queueRefs`.
|
||||
queueItems: state.queue.map((t): QueueItemRef => {
|
||||
const ref: QueueItemRef = { serverId: state.queueServerId ?? '', trackId: t.id };
|
||||
if (t.autoAdded) ref.autoAdded = true;
|
||||
if (t.radioAdded) ref.radioAdded = true;
|
||||
if (t.playNextAdded) ref.playNextAdded = true;
|
||||
return ref;
|
||||
}),
|
||||
queueItems: toQueueItemRefs(state.queueServerId ?? '', state.queue),
|
||||
queueItemsIndex: qi,
|
||||
isQueueVisible: state.isQueueVisible,
|
||||
// currentTime is intentionally NOT persisted here.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Side-effect wiring (queue thin-state, phase 2b): seed the queue track
|
||||
* resolver cache with the tracks around the current index whenever the queue
|
||||
* changes. The store stays `queue: Track[]`-canonical for now — this only fills
|
||||
* the resolver cache (additive; no mutation or persist change), so the queue
|
||||
* selectors resolve without a fetch once consumers move onto them (phase 3) and
|
||||
* after `queue: Track[]` is dropped (phase 4).
|
||||
*/
|
||||
import { usePlayerStore } from './playerStore';
|
||||
import { seedQueueResolver } from '../utils/library/queueTrackResolver';
|
||||
|
||||
const SEED_BACK = 50;
|
||||
const SEED_AHEAD = 200;
|
||||
|
||||
usePlayerStore.subscribe((state, prev) => {
|
||||
if (state.queue === prev.queue && state.queueServerId === prev.queueServerId) return;
|
||||
const serverId = state.queueServerId ?? '';
|
||||
if (!serverId || state.queue.length === 0) return;
|
||||
const start = Math.max(0, state.queueIndex - SEED_BACK);
|
||||
seedQueueResolver(serverId, state.queue.slice(start, state.queueIndex + SEED_AHEAD + 1));
|
||||
});
|
||||
Reference in New Issue
Block a user