'use client'; import { useEffect, useState } from 'react'; import { useParams } from 'next/navigation'; import Image from 'next/image'; import Link from 'next/link'; import { Playlist, Song } from '@/lib/navidrome'; import { useNavidrome } from '@/app/components/NavidromeContext'; import { useAudioPlayer } from '@/app/components/AudioPlayerContext'; import { getNavidromeAPI } from '@/lib/navidrome'; import { Play, Heart, Plus, User, Disc } from 'lucide-react'; import { Button } from '@/components/ui/button'; import Loading from "@/app/components/loading"; import { Separator } from '@/components/ui/separator'; import { ScrollArea } from '@/components/ui/scroll-area'; export default function PlaylistPage() { const { id } = useParams(); const [playlist, setPlaylist] = useState(null); const [tracklist, setTracklist] = useState([]); const [loading, setLoading] = useState(true); const { getPlaylist } = useNavidrome(); const { playTrack, addToQueue, currentTrack } = useAudioPlayer(); const api = getNavidromeAPI(); useEffect(() => { const fetchPlaylist = async () => { setLoading(true); console.log(`Fetching playlist with id: ${id}`); try { const playlistData = await getPlaylist(id as string); setPlaylist(playlistData.playlist); setTracklist(playlistData.songs); console.log(`Playlist found: ${playlistData.playlist.name}`); } catch (error) { console.error('Failed to fetch playlist:', error); } setLoading(false); }; if (id) { fetchPlaylist(); } }, [id, getPlaylist]); const handlePlayClick = (song: Song) => { if (!api) { console.error('Navidrome API not available'); return; } const track = { id: song.id, name: song.title, url: api.getStreamUrl(song.id), artist: song.artist, album: song.album, duration: song.duration, coverArt: song.coverArt ? api.getCoverArtUrl(song.coverArt, 300) : undefined, albumId: song.albumId, artistId: song.artistId, starred: !!song.starred }; playTrack(track); }; const handleAddToQueue = (song: Song) => { if (!api) { console.error('Navidrome API not available'); return; } const track = { id: song.id, name: song.title, url: api.getStreamUrl(song.id), artist: song.artist, album: song.album, duration: song.duration, coverArt: song.coverArt ? api.getCoverArtUrl(song.coverArt, 300) : undefined, albumId: song.albumId, artistId: song.artistId, starred: !!song.starred }; addToQueue(track); }; const handlePlayPlaylist = () => { if (tracklist.length === 0 || !api) { if (!api) console.error('Navidrome API not available'); return; } // Convert all songs to tracks const tracks = tracklist.map(song => ({ id: song.id, name: song.title, url: api.getStreamUrl(song.id), artist: song.artist, album: song.album, duration: song.duration, coverArt: song.coverArt ? api.getCoverArtUrl(song.coverArt, 300) : undefined, albumId: song.albumId, artistId: song.artistId, starred: !!song.starred })); // Play the first track and add the rest to queue if (tracks.length > 0) { playTrack(tracks[0], true); // Enable autoplay if (tracks.length > 1) { // Add remaining tracks to queue tracks.slice(1).forEach(track => addToQueue(track)); } } }; const isCurrentlyPlaying = (song: Song): boolean => { return currentTrack?.id === song.id; }; const formatDuration = (duration: number): string => { const minutes = Math.floor(duration / 60); const seconds = duration % 60; return `${minutes}:${seconds.toString().padStart(2, '0')}`; }; if (loading) { return ; } if (!playlist) { return (

Playlist not found

The playlist you're looking for doesn't exist.

); } // Get playlist cover art URL with fallback const playlistCoverUrl = playlist.coverArt && api ? api.getCoverArtUrl(playlist.coverArt, 300) : '/default-user.jpg'; return (
{playlist.name}

{playlist.name}

{playlist.comment && (

{playlist.comment}

)}

{playlist.songCount} songs • Duration: {formatDuration(playlist.duration || 0)}

{playlist.public !== undefined && (

{playlist.public ? 'Public' : 'Private'} playlist

)}
{tracklist.length === 0 ? (

This playlist is empty.

) : (
{tracklist.map((song, index) => (
handlePlayClick(song)} > {/* Track Number / Play Indicator */}
{isCurrentlyPlaying(song) ? (
) : ( <> {index + 1} )}
{/* Album Art */}
{song.album}
{/* Song Info */}

{song.title}

e.stopPropagation()} > {song.artist}
{song.album && (
e.stopPropagation()} > {song.album}
)}
{/* Duration */}
{formatDuration(song.duration)}
{/* Actions */}
))}
)}
); }