Files
Psychotoxical-psysonic/src/features/queue/hooks/useQueueTracks.ts
T
Psychotoxical 9058abd340 refactor(lib): extract Track/QueueItemRef domain model to lib/media/trackTypes
Track is the app's normalized song model and QueueItemRef its thin queue
identity -- consumed app-wide (queue, cover, context menus, sharing, lucky-mix,
library browse), not a playback-internal detail. They lived in
features/playback/store/playerStoreTypes, forcing ~115 core/feature files to
reach into the playback feature for the central media type.

Move the two interfaces to lib/media/trackTypes; playerStoreTypes keeps
PlayerState and now imports them from lib. 115 importers repointed (mixed
'PlayerState, Track' lines split so PlayerState stays). Pure type move (erased at
runtime). tsc 0, lint 0.
2026-06-30 17:16:56 +02:00

39 lines
1.6 KiB
TypeScript

import { useMemo, useSyncExternalStore } from 'react';
import { usePlayerStore } from '@/features/playback/store/playerStore';
import type { QueueItemRef, Track } from '@/lib/media/trackTypes';
import { resolveQueueTrack } from '@/features/playback/store/queueTrackView';
import {
getQueueResolverVersion,
subscribeQueueResolver,
} from '@/features/playback/store/queueTrackResolver';
/**
* Stable queue selectors (queue thin-state). The store is refs-canonical now:
* full `Track`s come from the resolver cache (placeholder until a fetch lands),
* with session star/rating overrides (F4) merged on read via resolveQueueTrack.
*/
/** The track at a queue index, or null. */
export function useQueueTrackAt(idx: number): Track | null {
const ref = usePlayerStore(s => s.queueItems[idx] ?? null);
const starredOverrides = usePlayerStore(s => s.starredOverrides);
const userRatingOverrides = usePlayerStore(s => s.userRatingOverrides);
const version = useSyncExternalStore(subscribeQueueResolver, getQueueResolverVersion);
return useMemo(() => {
if (!ref) return null;
return resolveQueueTrack(ref);
// version drives re-resolution as the cache fills; overrides drive the merge.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ref, starredOverrides, userRatingOverrides, version]);
}
/** The currently playing track, or null. */
export function useCurrentTrack(): Track | null {
return usePlayerStore(s => s.currentTrack);
}
/** The whole queue as thin refs (the canonical list). */
export function useQueueItems(): QueueItemRef[] {
return usePlayerStore(s => s.queueItems);
}