feat(album): single cover on album detail, track-number rows
Docker Build & Publish / build (push) Has been cancelled
Docker Build & Publish / push (push) Has been cancelled
Docker Build & Publish / Prune old image versions (push) Has been cancelled

Album detail header falls back to a track's cover when the album
record itself has none, and each track row hides its per-track art in
favour of a large album-position number, since the header already
shows the album's cover once.
This commit is contained in:
Senko-san
2026-06-13 17:51:55 +03:00
parent f5767ff55e
commit df8c67b368
2 changed files with 46 additions and 15 deletions
+11 -4
View File
@@ -9,16 +9,17 @@ import { TrackRow } from '../../components/track/TrackRow';
import { LoadingSkeleton } from '../../components/common/LoadingSkeleton';
import { ErrorState } from '../../components/common/ErrorState';
import { EmptyState } from '../../components/common/EmptyState';
import { useAppDispatch } from '../../hooks/useAppDispatch';
import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch';
import { setQueue } from '../../store/slices/queue';
import { formatDuration } from '../../lib/format';
import { getCoverUrl } from '../../api/endpoints/streaming';
import { getCoverUrl, getTrackCoverUrl } from '../../api/endpoints/streaming';
export function AlbumDetailPage() {
const { t } = useTranslation();
const { albumId } = useParams<{ albumId: string }>();
const navigate = useNavigate();
const dispatch = useAppDispatch();
const token = useAppSelector((s) => s.auth.accessToken);
const albumQuery = useGetAlbumQuery(albumId ?? '', { skip: !albumId });
const tracksQuery = useGetAlbumTracksQuery(albumId ?? '', { skip: !albumId });
@@ -42,7 +43,13 @@ export function AlbumDetailPage() {
const album = albumQuery.data;
const tracks = tracksQuery.data ?? [];
const artUrl = getCoverUrl(album?.artUrl);
// The album record itself carries no cover; fall back to a track's cover.
const coverTrack = tracks.find((t) => t.hasCover);
const artUrl =
getCoverUrl(album?.artUrl) ??
(token && coverTrack
? getTrackCoverUrl(coverTrack.id, token, true)
: undefined);
const handlePlayAll = () => {
if (!tracks.length || !album) return;
@@ -178,7 +185,7 @@ export function AlbumDetailPage() {
/>
)}
{tracks.map((track, i) => (
<TrackRow key={track.id} track={track} index={i} />
<TrackRow key={track.id} track={track} index={i} hideArt />
))}
</ScrollArea>
</div>