Four-cut cluster opening the Favorites refactor. 1018 → 643 LOC
(−375).
TopFavoriteArtists — TopFavoriteArtistsRow (the horizontal-scroll
section with chevron nav buttons and resize-driven scroll-state)
plus the private TopFavoriteArtistCard with the cached avatar
image and selected-outline styling. Exports the
TopFavoriteArtist row-data shape.
RadioFavorites — RadioStationRow (same horizontal-scroll pattern
as the artists row) plus the private RadioFavCard with cover or
Cast-icon fallback, live-radio badge overlay when active, and an
unfavorite heart button.
useFavoritesData — owns the four data states (albums, artists,
songs, radioStations) + loading + the load-on-mount effect (calls
getStarred + reads radio favorites from localStorage + fetches
matching stations). Computes topFavoriteArtists memo (counts
favorited songs by artist, top 12). Exports unfavoriteStation
(removes from state + persists to localStorage).
useFavoritesSongFiltering — owns the filtering pipeline (drops
unfavorited, applies artist / genre / year-range filters) and
the three-state sort (asc → desc → reset). Returns
filteredSongs / visibleSongs plus handleSortClick /
getSortIndicator. Hook file uses .tsx because getSortIndicator
returns ArrowUp / ArrowDown JSX.
Favorites drops the inline definitions plus the now-unused direct
imports (getInternetRadioStations, getStarred, buildCoverArtUrl /
coverArtCacheKey, useAuthStore, Users / ArrowUp / ArrowDown
icons). Pure code move otherwise.