mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
f41005682d
The queue-resolver family (queueTrackResolver, queueRestore, queueItemRef, queueTrackView) runtime-imports usePlayerStore / playerStoreTypes — it is the playback engine's thin-state queue subsystem, not shared library infra. It sat in utils/library only because it queries the local index. Co-locate into features/playback/store so those edges become intra-feature; its remaining deps (advancedSearchLocal, libraryReady, serverLookup, serverIndexKey, authStore) are plain core/infra (feature -> infra, no inversion). Removes 4 of the 6 store/utils -> feature runtime inversions that blocked the utils/library -> lib move. 8 files moved, 46 consumers rewritten. tsc 0, lint 0, targeted suites green.
76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
import type { QueueItemRef, Track } from '@/features/playback/store/playerStoreTypes';
|
|
import { getQueueTracksView } from '@/features/playback/store/queueTrackView';
|
|
import { scheduleHotCachePrefetchForTrack } from '@/hotCachePrefetch';
|
|
import { getPlaybackCacheServerKey } from '@/features/playback/utils/playback/playbackServer';
|
|
import { useAuthStore } from '@/store/authStore';
|
|
import { bumpPlayGeneration, getPlayGeneration } from '@/features/playback/store/engineState';
|
|
import { engineLoadTrackAtPosition } from '@/features/playback/store/engineLoadTrackAtPosition';
|
|
import { emitPlaybackProgress } from '@/features/playback/store/playbackProgress';
|
|
import { promoteCompletedStreamToHotCache } from '@/features/playback/store/promoteStreamCache';
|
|
import { usePlayerStore } from '@/features/playback/store/playerStore';
|
|
import { setSeekFallbackVisualTarget } from '@/features/playback/store/seekFallbackState';
|
|
|
|
/** Push restored position into the store + progress channel so the seekbar paints immediately. */
|
|
export function applyRestoredPlaybackVisual(track: Track, atSeconds: number): void {
|
|
const dur = track.duration > 0 ? track.duration : 0;
|
|
const seconds = Math.max(0, atSeconds);
|
|
const progress = dur > 0 ? Math.min(1, seconds / dur) : 0;
|
|
usePlayerStore.setState({ currentTime: seconds, progress, buffered: 0 });
|
|
emitPlaybackProgress({
|
|
currentTime: seconds,
|
|
progress,
|
|
buffered: 0,
|
|
buffering: false,
|
|
});
|
|
if (seconds > 0.05) {
|
|
setSeekFallbackVisualTarget({
|
|
trackId: track.id,
|
|
seconds,
|
|
setAtMs: Date.now(),
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* After `getPlayQueue` restores a paused session: show the saved seek position,
|
|
* prefetch bytes for the current track, and load the engine paused at that spot
|
|
* so the next Play is a warm `audio_resume`.
|
|
*/
|
|
export function preparePausedRestoreOnStartup(
|
|
track: Track,
|
|
queueItems: QueueItemRef[],
|
|
queueIndex: number,
|
|
atSeconds: number,
|
|
): void {
|
|
const player = usePlayerStore.getState();
|
|
if (player.isPlaying || player.currentRadio) return;
|
|
|
|
applyRestoredPlaybackVisual(track, atSeconds);
|
|
scheduleHotCachePrefetchForTrack(track, getPlaybackCacheServerKey());
|
|
|
|
const generation = bumpPlayGeneration();
|
|
void (async () => {
|
|
const auth = useAuthStore.getState();
|
|
const promoteSid = getPlaybackCacheServerKey();
|
|
if (auth.hotCacheEnabled && promoteSid) {
|
|
await promoteCompletedStreamToHotCache(
|
|
track,
|
|
promoteSid,
|
|
auth.hotCacheDownloadDir || null,
|
|
);
|
|
}
|
|
if (getPlayGeneration() !== generation) return;
|
|
if (usePlayerStore.getState().isPlaying) return;
|
|
|
|
const queue = getQueueTracksView(queueItems, [track]);
|
|
engineLoadTrackAtPosition({
|
|
generation,
|
|
track,
|
|
queue,
|
|
queueIndex,
|
|
atSeconds,
|
|
wantPlaying: false,
|
|
});
|
|
})();
|
|
}
|