fix(artist): align top-track covers with album grid cover path (#886)

* fix(artist): align top-track covers with album grid cover path

Top tracks now resolve album.id + album.coverArt like AlbumCard, use
the same useAlbumCoverRef/CoverArtImage dense pipeline, and batch-warm
covers on page load instead of a custom sparse resolver.

* docs: CHANGELOG and credits for PR #886 artist top-track covers

* fix(artist): match All Albums cover warm tier and prefetch on detail page

Warm top-track and discography covers at dense grid tier (140px) instead of
32px thumb tier so disk peek hits cached WebP. Register high-priority dense
prefetch like All Albums and ensure top-track cells at high priority so dense
defer-until-visible does not stall visible thumbs.

* fix(artist): satisfy tsc for top-track cover warm helpers

Use optional coverArt access in pushAlbumWarmRow and align album pick
types with topSongAlbumForCover (id + name + coverArt).
This commit is contained in:
cucadmuh
2026-05-28 22:47:38 +03:00
committed by GitHub
parent 455aec4def
commit 8443b3d4be
8 changed files with 189 additions and 42 deletions
+24 -14
View File
@@ -44,8 +44,10 @@ import ArtistDetailSimilarArtists from '../components/artistDetail/ArtistDetailS
import ArtistCard from '../components/nowPlaying/ArtistCard';
import LosslessModeBanner from '../components/LosslessModeBanner';
import { usePerfProbeFlags } from '../utils/perf/perfFlags';
import { albumGridWarmCovers } from '../cover/layoutSizes';
import { rememberAlbumDistinctDiscCovers } from '../cover/ref';
import { albumGridWarmCovers, COVER_DENSE_GRID_MIN_CELL_CSS_PX, GRID_COVER_WARM_LIMIT } from '../cover/layoutSizes';
import { artistDetailCoverWarmAlbums } from '../components/artistDetail/topSongAlbumForCover';
import { useLibraryCoverPrefetch } from '../cover/useLibraryCoverPrefetch';
import { useWarmGridCovers } from '../hooks/useWarmGridCovers';
import { VirtualCardGrid } from '../components/VirtualCardGrid';
import { LOSSLESS_MODE_QUERY } from '../utils/library/losslessMode';
import { sortArtistAlbumsByYear } from '../utils/library/sortArtistAlbums';
@@ -215,18 +217,26 @@ export default function ArtistDetail() {
setHeaderCoverFailed(false);
}, [coverId, coverRevision, id]);
useEffect(() => {
const byAlbum = new Map<string, SubsonicSong[]>();
for (const song of topSongs) {
const albumId = song.albumId?.trim();
if (!albumId) continue;
if (!byAlbum.has(albumId)) byAlbum.set(albumId, []);
byAlbum.get(albumId)!.push(song);
}
for (const [albumId, songs] of byAlbum) {
rememberAlbumDistinctDiscCovers(albumId, songs);
}
}, [topSongs]);
const artistCoverWarmAlbums = useMemo(
() => artistDetailCoverWarmAlbums(topSongs, albums, GRID_COVER_WARM_LIMIT),
[topSongs, albums],
);
useWarmGridCovers(artistCoverWarmAlbums, COVER_DENSE_GRID_MIN_CELL_CSS_PX, {
enabled: artistCoverWarmAlbums.length > 0,
limit: GRID_COVER_WARM_LIMIT,
surface: 'dense',
});
useLibraryCoverPrefetch(
[
{
albums: artistCoverWarmAlbums.slice(0, 24),
limit: 24,
priority: 'high',
surface: 'dense',
},
],
[artistCoverWarmAlbums],
);
if (loading) {
return (