* refactor(album-detail): extract sanitizeFilename + useAlbumDetailData
Move sanitizeFilename into utils/albumDetailHelpers.ts. Pull the album +
related-albums fetch and the starred state seeds (isStarred,
starredSongs) into hooks/useAlbumDetailData.ts.
AlbumDetail.tsx: 511 → 483 LOC.
* refactor(album-detail): extract useAlbumOfflineState hook
Move the four primitive-selector offline status reads (cache map +
job-status filters + progress totals) into hooks/useAlbumOfflineState.ts.
Keeps the re-render minimisation comment with the code that needs it.
AlbumDetail.tsx: 483 → 461 LOC.
* refactor(album-detail): extract useAlbumDetailSort hook
Pull sortKey/Dir/clickCount state, the 3-click natural-reset cycle in
handleSort, and the displayedSongs memo (filter + sort comparator) into
hooks/useAlbumDetailSort.ts. Rating comparator keeps the same priority
chain as the row renderer.
AlbumDetail.tsx: 461 → 414 LOC.
* refactor(album-detail): extract AlbumDetailToolbar subcomponent
Pull the search input + bulk-action cluster (selection count, add-to-
playlist popover, clear-selection button) into
components/albumDetail/AlbumDetailToolbar.tsx. Parent retains showPlPicker
to coordinate the popover close with selection clears.
AlbumDetail.tsx: 414 → 369 LOC.