mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +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,46 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { SubsonicSong } from '../api/subsonicTypes';
|
||||
import type { Track } from '../store/playerStoreTypes';
|
||||
import { usePlayerStore } from '../store/playerStore';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
import { getDisplayedSongs, type PlaylistSortDir, type PlaylistSortKey } from '../utils/playlistDisplayedSongs';
|
||||
|
||||
export interface PlaylistDerivedOptions {
|
||||
filterText: string;
|
||||
sortKey: PlaylistSortKey;
|
||||
sortDir: PlaylistSortDir;
|
||||
ratings: Record<string, number>;
|
||||
starredSongs: Set<string>;
|
||||
}
|
||||
|
||||
export interface PlaylistDerived {
|
||||
existingIds: Set<string>;
|
||||
tracks: Track[];
|
||||
displayedSongs: SubsonicSong[];
|
||||
displayedTracks: Track[];
|
||||
isFiltered: boolean;
|
||||
}
|
||||
|
||||
export function usePlaylistDerived(songs: SubsonicSong[], opts: PlaylistDerivedOptions): PlaylistDerived {
|
||||
const userRatingOverrides = usePlayerStore(s => s.userRatingOverrides);
|
||||
const starredOverrides = usePlayerStore(s => s.starredOverrides);
|
||||
const { filterText, sortKey, sortDir, ratings, starredSongs } = opts;
|
||||
|
||||
const existingIds = useMemo(() => new Set(songs.map(s => s.id)), [songs]);
|
||||
const tracks = useMemo(() => songs.map(songToTrack), [songs]);
|
||||
|
||||
const displayedSongs = useMemo(
|
||||
() => getDisplayedSongs(songs, {
|
||||
filterText, sortKey, sortDir,
|
||||
ratings, userRatingOverrides, starredOverrides, starredSongs,
|
||||
}),
|
||||
[songs, filterText, sortKey, sortDir, ratings, userRatingOverrides, starredOverrides, starredSongs],
|
||||
);
|
||||
const displayedTracks = useMemo(
|
||||
() => displayedSongs === songs ? tracks : displayedSongs.map(songToTrack),
|
||||
[displayedSongs, songs, tracks],
|
||||
);
|
||||
const isFiltered = displayedSongs !== songs;
|
||||
|
||||
return { existingIds, tracks, displayedSongs, displayedTracks, isFiltered };
|
||||
}
|
||||
Reference in New Issue
Block a user