diff --git a/app/artist/[artist]/page.tsx b/app/artist/[artist]/page.tsx index f4873bc..c475db9 100644 --- a/app/artist/[artist]/page.tsx +++ b/app/artist/[artist]/page.tsx @@ -21,7 +21,7 @@ export default function ArtistPage() { const [artist, setArtist] = useState(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({ diff --git a/app/components/AudioPlayerContext.tsx b/app/components/AudioPlayerContext.tsx index 3b54100..51c8197 100644 --- a/app/components/AudioPlayerContext.tsx +++ b/app/components/AudioPlayerContext.tsx @@ -36,6 +36,7 @@ interface AudioPlayerContextProps { shuffle: boolean; toggleShuffle: () => void; shuffleAllAlbums: () => Promise; + playArtist: (artistId: string) => Promise; } const AudioPlayerContext = createContext(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 ( diff --git a/app/queue/page.tsx b/app/queue/page.tsx index 248327e..d0c8dc2 100644 --- a/app/queue/page.tsx +++ b/app/queue/page.tsx @@ -19,7 +19,7 @@ const QueuePage: React.FC = () => { }; return ( -
+
{/* Header */}