refactor(player): E.5 — extract playback-URL routing into module (#568)

Three file-private helpers + their shared module-scoped track id move
into src/store/playbackUrlRouting.ts: recordEnginePlayUrl,
playbackSourceHintForResolvedUrl, shouldRebindPlaybackToHotCache. The
`lastOpenedWithHttpTrackId` mutable goes with them — only those three
read it. No external callers, no re-exports needed.

Adds 12 focused tests covering the source-kind classifier
(stream / hot / offline), the rebind decision across stream:-prefix
forms, the empty-serverId / un-recorded edge cases, and the
test-only reset helper.

playerStore 3490 → 3470 LOC.
This commit is contained in:
Frank Stellmacher
2026-05-12 12:07:30 +02:00
committed by GitHub
parent 5b89051817
commit b68bddd034
3 changed files with 155 additions and 25 deletions
+5 -25
View File
@@ -39,6 +39,11 @@ import {
subscribePlaybackProgress,
type PlaybackProgressSnapshot,
} from './playbackProgress';
import {
playbackSourceHintForResolvedUrl,
recordEnginePlayUrl,
shouldRebindPlaybackToHotCache,
} from './playbackUrlRouting';
// Re-export the playback-progress public surface so existing call sites
// (PlayerBar, FullscreenPlayer, WaveformSeek, LyricsPane, MobilePlayerView,
@@ -1034,31 +1039,6 @@ async function promoteCompletedStreamToHotCache(track: Track, serverId: string,
}
}
/**
* Tracks the **actual** `audio_play` URL family: `getPlaybackSourceKind()` can
* report `hot` for RAM preload or disk index while the engine still uses HTTP.
* Rebind-to-local seeks need this, not the UI hint alone.
*/
let lastOpenedWithHttpTrackId: string | null = null;
function recordEnginePlayUrl(trackId: string, url: string): void {
lastOpenedWithHttpTrackId = url.startsWith('psysonic-local://') ? null : trackId;
}
/** Matches `playTrack` / PlayerBar: stream vs hot-cache vs offline file from resolved `audio_play` URL. */
function playbackSourceHintForResolvedUrl(trackId: string, serverId: string, url: string): PlaybackSourceKind {
if (!url.startsWith('psysonic-local://')) return 'stream';
return useOfflineStore.getState().getLocalUrl(trackId, serverId) ? 'offline' : 'hot';
}
function shouldRebindPlaybackToHotCache(trackId: string, serverId: string): boolean {
if (!serverId) return false;
if (!lastOpenedWithHttpTrackId || !sameQueueTrackId(lastOpenedWithHttpTrackId, trackId)) {
return false;
}
return resolvePlaybackUrl(trackId, serverId).startsWith('psysonic-local://');
}
// Track ID that has already been sent to audio_chain_preload (gapless chain).
let gaplessPreloadingId: string | null = null;
// Track ID that has already been sent to audio_preload (byte pre-download).