fix(artist): play top tracks when album list is empty (#1031)

* fix(artist): play top tracks when album list is empty on page

Top-track rows silently no-op'd when albums.length was 0 (common in
lossless artist view). Play the selected top songs immediately and only
append catalog tracks when albums are available.

* docs: note artist top tracks play fix in CHANGELOG for PR #1031
This commit is contained in:
cucadmuh
2026-06-08 13:43:49 +03:00
committed by GitHub
parent 5167d8f49e
commit 1b4fb9e9b3
5 changed files with 107 additions and 31 deletions
+9 -29
View File
@@ -3,7 +3,6 @@ import { useCoverArt } from '../cover/useCoverArt';
import { useArtistCoverRef } from '../cover/useLibraryCoverRef';
import { setRating, star, unstar } from '../api/subsonicStarRating';
import type { SubsonicArtist, SubsonicAlbum, SubsonicSong, SubsonicArtistInfo } from '../api/subsonicTypes';
import { songToTrack } from '../utils/playback/songToTrack';
import { useEffect, useState, useRef, Fragment, useMemo } from 'react';
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
import AlbumCard from '../components/AlbumCard';
@@ -30,8 +29,7 @@ import {
import { useArtistDetailData } from '../hooks/useArtistDetailData';
import { useArtistSimilarArtists } from '../hooks/useArtistSimilarArtists';
import {
fetchArtistDetailTracks,
runArtistDetailPlayAll, runArtistDetailShuffle, runArtistDetailStartRadio,
runArtistDetailPlayAll, runArtistDetailPlayTopSong, runArtistDetailShuffle, runArtistDetailStartRadio,
} from '../utils/componentHelpers/runArtistDetailPlay';
import { useOfflineBrowseContext } from '../hooks/useOfflineBrowseContext';
import { offlineActionPolicy } from '../utils/offline/offlineActionPolicy';
@@ -142,32 +140,14 @@ export default function ArtistDetail() {
return runArtistShare({ artist, t });
};
const playTopSongWithContinuation = async (startIndex: number) => {
if (!artist || albums.length === 0) return;
setPlayAllLoading(true);
try {
// Get all artist tracks ordered by album and track number
const allTracks = await fetchArtistDetailTracks(albums, activeServerId);
// Top songs from clicked index onward
const topTracksFromIndex = topSongs.slice(startIndex).map(songToTrack);
// Track IDs for deduplication
const topSongIds = new Set(topSongs.map(s => s.id));
// Filter remaining tracks to exclude top songs (prevent duplicates)
const remainingTracks = allTracks.filter(tr => !topSongIds.has(tr.id));
// Build queue: remaining top songs + rest of artist catalog
const queue = [...topTracksFromIndex, ...remainingTracks];
if (queue.length > 0) {
playTrack(queue[0], queue);
}
} finally {
setPlayAllLoading(false);
}
};
const playTopSongWithContinuation = (startIndex: number) => runArtistDetailPlayTopSong({
topSongs,
albums,
serverId: activeServerId,
startIndex,
setPlayAllLoading,
playTrack,
});
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => runArtistImageUpload({
e, artist, t, setUploading, setCoverRevision,