mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
refactor(playlist): G.69 — extract runPlaylistLoad + usePlaylistPreview + usePlaylistBulkPlayCallbacks + usePlaylistDerived (cluster) (#636)
Four-cut cluster pulling the remaining handler bodies + memo island
out of PlaylistDetail.tsx. 507 → 437 LOC (−70).
runPlaylistLoad — async fetch + populate flow that the load
useEffect drives: getPlaylist → filterSongsToActiveLibrary →
setPlaylist + setSongs + setCustomCoverId from playlist.coverArt +
rebuild ratings + starredSongs from each song's stored userRating /
starred flag. Takes the six setters as deps. Page keeps the
useEffect that calls it on id / lastModified change.
usePlaylistPreview — startPreview callback (dispatches into
previewStore with the 'suggestions' source) plus the unmount-time
stopPreview cleanup. Returns just { startPreview }. No props
needed.
usePlaylistBulkPlayCallbacks — wraps playPlaylistAll /
shufflePlaylistAll / enqueuePlaylistAll utilities behind three
useCallback handles with the right deps array. Takes
{ songsLength, id, tracks, touchPlaylist, playTrack, enqueue }.
usePlaylistDerived — existingIds, tracks (songToTrack), sorted +
filtered displayedSongs via getDisplayedSongs, displayedTracks (with
the cheap aliasing optimization when displayedSongs === songs),
isFiltered. Subscribes to playerStore's userRatingOverrides +
starredOverrides directly so the page no longer threads them through
the memo deps.
PlaylistDetail drops these direct imports — they followed the new
modules: getPlaylist, filterSongsToActiveLibrary, songToTrack,
useMemo, getDisplayedSongs (now type-only),
playPlaylistAll/shuffle/enqueue from playlistBulkPlayActions.
Pure code move otherwise.
This commit is contained in:
committed by
GitHub
parent
d08875dc70
commit
16ee1ea373
@@ -0,0 +1,38 @@
|
||||
import type React from 'react';
|
||||
import { getPlaylist } from '../api/subsonicPlaylists';
|
||||
import { filterSongsToActiveLibrary } from '../api/subsonicLibrary';
|
||||
import type { SubsonicPlaylist, SubsonicSong } from '../api/subsonicTypes';
|
||||
|
||||
export interface RunPlaylistLoadDeps {
|
||||
id: string;
|
||||
setLoading: (v: boolean) => void;
|
||||
setPlaylist: React.Dispatch<React.SetStateAction<SubsonicPlaylist | null>>;
|
||||
setSongs: React.Dispatch<React.SetStateAction<SubsonicSong[]>>;
|
||||
setCustomCoverId: React.Dispatch<React.SetStateAction<string | null>>;
|
||||
setRatings: React.Dispatch<React.SetStateAction<Record<string, number>>>;
|
||||
setStarredSongs: React.Dispatch<React.SetStateAction<Set<string>>>;
|
||||
}
|
||||
|
||||
export async function runPlaylistLoad(deps: RunPlaylistLoadDeps): Promise<void> {
|
||||
const { id, setLoading, setPlaylist, setSongs, setCustomCoverId, setRatings, setStarredSongs } = deps;
|
||||
setLoading(true);
|
||||
try {
|
||||
const { playlist, songs } = await getPlaylist(id);
|
||||
const filteredSongs = await filterSongsToActiveLibrary(songs);
|
||||
setPlaylist(playlist);
|
||||
setSongs(filteredSongs);
|
||||
if (playlist.coverArt) setCustomCoverId(playlist.coverArt);
|
||||
const init: Record<string, number> = {};
|
||||
const starred = new Set<string>();
|
||||
filteredSongs.forEach(s => {
|
||||
if (s.userRating) init[s.id] = s.userRating;
|
||||
if (s.starred) starred.add(s.id);
|
||||
});
|
||||
setRatings(init);
|
||||
setStarredSongs(starred);
|
||||
} catch {
|
||||
// intentional swallow; load failure leaves loading false + playlist null
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user