'use client'; import { ScrollArea, ScrollBar } from '../components/ui/scroll-area'; import { Separator } from '../components/ui/separator'; import { Tabs, TabsContent } from '../components/ui/tabs'; import { AlbumArtwork } from './components/album-artwork'; import { useNavidrome } from './components/NavidromeContext'; import { useEffect, useState } from 'react'; import { Album } from '@/lib/navidrome'; import { useNavidromeConfig } from './components/NavidromeConfigContext'; import { useSearchParams } from 'next/navigation'; import { useAudioPlayer } from './components/AudioPlayerContext'; type TimeOfDay = 'morning' | 'afternoon' | 'evening'; export default function MusicPage() { const { albums, isLoading, api, isConnected } = useNavidrome(); const { playAlbum, playTrack, shuffle, toggleShuffle, addToQueue } = useAudioPlayer(); const searchParams = useSearchParams(); const [recentAlbums, setRecentAlbums] = useState([]); const [newestAlbums, setNewestAlbums] = useState([]); const [favoriteAlbums, setFavoriteAlbums] = useState([]); const [favoritesLoading, setFavoritesLoading] = useState(true); const [shortcutProcessed, setShortcutProcessed] = useState(false); useEffect(() => { if (albums.length > 0) { // Split albums into recent and newest for display const recent = albums.slice(0, Math.ceil(albums.length / 2)); const newest = albums.slice(Math.ceil(albums.length / 2)); setRecentAlbums(recent); setNewestAlbums(newest); } }, [albums]); useEffect(() => { const loadFavoriteAlbums = async () => { if (!api || !isConnected) return; setFavoritesLoading(true); try { const starredAlbums = await api.getAlbums('starred', 20); // Limit to 20 for homepage setFavoriteAlbums(starredAlbums); } catch (error) { console.error('Failed to load favorite albums:', error); } finally { setFavoritesLoading(false); } }; loadFavoriteAlbums(); }, [api, isConnected]); // Handle PWA shortcuts useEffect(() => { const action = searchParams.get('action'); if (!action || shortcutProcessed || !api || !isConnected) return; const handleShortcuts = async () => { try { switch (action) { case 'resume': // Try to resume from localStorage or play a recent track const lastTrack = localStorage.getItem('lastPlayedTrack'); if (lastTrack) { const trackData = JSON.parse(lastTrack); await playTrack(trackData); } else if (recentAlbums.length > 0) { // Fallback: play first track from most recent album await playAlbum(recentAlbums[0].id); } break; case 'recent': if (recentAlbums.length > 0) { // Get the 10 most recent albums and shuffle them const tenRecentAlbums = recentAlbums.slice(0, 10); const shuffledAlbums = [...tenRecentAlbums].sort(() => Math.random() - 0.5); // Enable shuffle if not already on if (!shuffle) { toggleShuffle(); } // Play first album and add remaining albums to queue await playAlbum(shuffledAlbums[0].id); // Add remaining albums to queue for (let i = 1; i < shuffledAlbums.length; i++) { try { const albumSongs = await api.getAlbumSongs(shuffledAlbums[i].id); albumSongs.forEach(song => { addToQueue({ id: song.id, name: song.title, url: api.getStreamUrl(song.id), artist: song.artist || 'Unknown Artist', artistId: song.artistId || '', album: song.album || 'Unknown Album', albumId: song.parent, duration: song.duration || 0, coverArt: song.coverArt, starred: !!song.starred }); }); } catch (error) { console.error('Failed to load album tracks:', error); } } } break; case 'shuffle-favorites': if (favoriteAlbums.length > 0) { // Shuffle all favorite albums const shuffledFavorites = [...favoriteAlbums].sort(() => Math.random() - 0.5); // Enable shuffle if not already on if (!shuffle) { toggleShuffle(); } // Play first album and add remaining albums to queue await playAlbum(shuffledFavorites[0].id); // Add remaining albums to queue for (let i = 1; i < shuffledFavorites.length; i++) { try { const albumSongs = await api.getAlbumSongs(shuffledFavorites[i].id); albumSongs.forEach(song => { addToQueue({ id: song.id, name: song.title, url: api.getStreamUrl(song.id), artist: song.artist || 'Unknown Artist', artistId: song.artistId || '', album: song.album || 'Unknown Album', albumId: song.parent, duration: song.duration || 0, coverArt: song.coverArt, starred: !!song.starred }); }); } catch (error) { console.error('Failed to load album tracks:', error); } } } break; } setShortcutProcessed(true); } catch (error) { console.error('Failed to handle PWA shortcut:', error); } }; // Delay to ensure data is loaded const timeout = setTimeout(handleShortcuts, 1000); return () => clearTimeout(timeout); }, [searchParams, api, isConnected, recentAlbums, favoriteAlbums, shortcutProcessed, playAlbum, playTrack, shuffle, toggleShuffle, addToQueue]); // Get greeting and time of day const hour = new Date().getHours(); const greeting = hour < 12 ? 'Good morning' : 'Good afternoon'; let timeOfDay: TimeOfDay; if (hour >= 5 && hour < 12) { timeOfDay = 'morning'; } else if (hour >= 12 && hour < 18) { timeOfDay = 'afternoon'; } else { timeOfDay = 'evening'; } // Try to get user name from navidrome context, fallback to 'user' let userName = ''; // If you add user info to NavidromeContext, update this logic const { config } = useNavidromeConfig(); if (config && config.username) { userName = config.username; } return (

{greeting}{userName ? `, ${userName}` : ''}!

<>

Recently Played

Albums you've listened to recently.

{isLoading ? ( // Loading skeletons Array.from({ length: 10 }).map((_, i) => (
)) ) : ( recentAlbums.map((album) => ( )) )}
{/* Favorite Albums Section */} {favoriteAlbums.length > 0 && ( <>

Favorite Albums

Your starred albums collection.

{favoritesLoading ? ( // Loading skeletons Array.from({ length: 10 }).map((_, i) => (
)) ) : ( favoriteAlbums.map((album) => ( )) )}
)}

Your Library

Albums from your music collection.

{isLoading ? ( // Loading skeletons Array.from({ length: 10 }).map((_, i) => (
)) ) : ( newestAlbums.map((album) => ( )) )}
); }