feat: implement playArtist function to play all albums by an artist and update QueuePage layout

This commit is contained in:
2025-06-20 00:42:03 +00:00
committed by GitHub
parent 8dfb4b34e5
commit e02ca64d17
3 changed files with 57 additions and 17 deletions

View File

@@ -21,7 +21,7 @@ export default function ArtistPage() {
const [artist, setArtist] = useState<Artist | null>(null);
const [isPlayingArtist, setIsPlayingArtist] = useState(false);
const { getArtist, starItem, unstarItem } = useNavidrome();
const { addArtistToQueue, playAlbum, clearQueue } = useAudioPlayer();
const { playArtist } = useAudioPlayer();
const { toast } = useToast();
const api = getNavidromeAPI();
@@ -65,19 +65,7 @@ export default function ArtistPage() {
setIsPlayingArtist(true);
try {
// Clear current queue and add all artist albums
clearQueue();
await addArtistToQueue(artist.id);
// Start playing the first album if we have any
if (artistAlbums.length > 0) {
await playAlbum(artistAlbums[0].id);
}
toast({
title: "Playing Artist",
description: `Now playing all albums by ${artist.name}`,
});
await playArtist(artist.id);
} catch (error) {
console.error('Failed to play artist:', error);
toast({

View File

@@ -36,6 +36,7 @@ interface AudioPlayerContextProps {
shuffle: boolean;
toggleShuffle: () => void;
shuffleAllAlbums: () => Promise<void>;
playArtist: (artistId: string) => Promise<void>;
}
const AudioPlayerContext = createContext<AudioPlayerContextProps | undefined>(undefined);
@@ -420,6 +421,55 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
}
}, [api, songToTrack, toast]);
const playArtist = useCallback(async (artistId: string) => {
setIsLoading(true);
try {
const { artist, albums } = await api.getArtist(artistId);
let allTracks: Track[] = [];
// Collect all tracks from all albums
for (const album of albums) {
const { songs } = await api.getAlbum(album.id);
const tracks = songs.map(songToTrack);
allTracks = allTracks.concat(tracks);
}
if (allTracks.length > 0) {
if (shuffle) {
// If shuffle is enabled, shuffle all tracks
const shuffledTracks = [...allTracks];
// Fisher-Yates shuffle algorithm
for (let i = shuffledTracks.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledTracks[i], shuffledTracks[j]] = [shuffledTracks[j], shuffledTracks[i]];
}
// Play the first shuffled track and set the rest as queue
playTrack(shuffledTracks[0]);
setQueue(shuffledTracks.slice(1));
} else {
// Normal order: play first track and set the rest as queue
playTrack(allTracks[0]);
setQueue(allTracks.slice(1));
}
}
toast({
title: "Playing Artist",
description: `Now playing all albums by "${artist.name}"${shuffle ? ' (shuffled)' : ''}`,
});
} catch (error) {
console.error('Failed to play artist:', error);
toast({
variant: "destructive",
title: "Error",
description: "Failed to play artist albums",
});
} finally {
setIsLoading(false);
}
}, [api, songToTrack, toast, shuffle, playTrack]);
const contextValue = useMemo(() => ({
currentTrack,
playTrack,
@@ -437,7 +487,8 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
skipToTrackInQueue,
shuffle,
toggleShuffle,
shuffleAllAlbums
shuffleAllAlbums,
playArtist
}), [
currentTrack,
queue,
@@ -455,7 +506,8 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
skipToTrackInQueue,
shuffle,
toggleShuffle,
shuffleAllAlbums
shuffleAllAlbums,
playArtist
]);
return (

View File

@@ -19,7 +19,7 @@ const QueuePage: React.FC = () => {
};
return (
<div className="h-full px-4 py-6 lg:px-8">
<div className="h-full px-4 py-6 lg:px-8 pb-24">
<div className="space-y-6">
{/* Header */}
<div className="flex items-center justify-between">