import React, { useState, useEffect, useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { MediaList } from '../components/MediaList'; import { LazyDiscoverySection } from '../components/LazyDiscoverySection'; import { Loader } from '../components/Loader'; import { PullToRefreshWrapper } from '../components/PullToRefreshWrapper'; import { useSocket } from '../hooks/useSocket'; import { useOptimizedDiscovery } from '../hooks/useOptimizedDiscovery'; import { useDownloadContext } from '../context/DownloadContext/DownloadContext'; import { MediaItem } from '../api/jellyfin'; import { toast } from 'sonner'; import { Music, Heart, Star, TrendingUp, Radio, Disc3, RotateCcw } from 'lucide-react'; import './Discover.css'; import '../styles/discoveryOptimization.css'; interface GenreSection { genre: string; title: string; tracks: MediaItem[]; } type TabType = 'all' | 'made-for-you' | 'new-releases' | 'trending' | 'genres' | 'albums'; interface Tab { id: TabType; label: string; icon: React.ComponentType<{ size?: number; className?: string }>; } const TABS: Tab[] = [ { id: 'all', label: 'All', icon: Music }, { id: 'made-for-you', label: 'Made for You', icon: Heart }, { id: 'new-releases', label: 'New Releases', icon: Star }, { id: 'trending', label: 'Trending', icon: TrendingUp }, { id: 'genres', label: 'Genres', icon: Radio }, { id: 'albums', label: 'Albums', icon: Disc3 } ]; export const DiscoverOptimized: React.FC = () => { const { discoveryData, loading, error, refresh, hasContent } = useOptimizedDiscovery(); const [activeTab, setActiveTab] = useState('all'); const [downloadStatus, setDownloadStatus] = useState<{ [key: string]: any }>({}); const navigate = useNavigate(); const { socket } = useSocket(); const { downloads, updateDownloadStatus } = useDownloadContext(); // Universal download handler for Discover page items const handleDiscoverDownload = useCallback((item: MediaItem) => { if (!socket) { toast.error('Not connected to the server.'); return; } const spotifyId = (item as any).SpotifyId; if (!spotifyId) { toast.error('Invalid item - missing Spotify ID.'); return; } console.log('🔽 Starting optimized download for:', item.Name, 'Spotify ID:', spotifyId); // Handle album downloads if (item.Type === 'MusicAlbum' || (item as any).MediaType === 'Album') { socket.emit('download_spotify_album', { albumId: spotifyId, albumName: item.Name }); toast.info(`Started downloading album "${item.Name}"`); return; } // Handle track downloads toast.info(`Downloading ${item.Name}...`); socket.emit('download_spotify', { spotifyId: spotifyId, trackName: item.Name, artistName: item.AlbumArtist || item.Artists?.[0] || 'Unknown Artist' }); // Update local download status for immediate UI feedback const backendKey = `spotify_${spotifyId}`; const downloadInfo = { status: 'Queued...', progress: 0, id: backendKey, name: item.Name }; setDownloadStatus((prevStatus: any) => ({ ...prevStatus, [spotifyId]: downloadInfo, [backendKey]: downloadInfo })); // Also update the DownloadContext immediately for UI feedback if (updateDownloadStatus) { updateDownloadStatus(backendKey, 'accepted', 0); } }, [socket, updateDownloadStatus]); // Transform discovery items to include download status and Spotify metadata const transformDiscoverItems = useCallback((items: MediaItem[]) => { return items.map(item => { const spotifyId = (item as any).SpotifyId || (item as any).spotify_id; // Get download status from either local state or context const localStatus = downloadStatus[spotifyId]; const contextStatus = downloads[spotifyId]; // Determine offline state based on download status let offlineState = 'none'; let downloadProgress = 0; if (localStatus || contextStatus) { const activeStatus = localStatus || contextStatus; if (activeStatus.status === 'completed' || activeStatus.status === 'finished') { offlineState = 'downloaded'; } else if (activeStatus.status === 'downloading' || activeStatus.status === 'accepted' || activeStatus.status === 'Queued...') { offlineState = 'downloading'; downloadProgress = activeStatus.progress || 0; } } return { ...item, SpotifyId: spotifyId, SpotifyUrl: (item as any).SpotifyUrl || (item as any).spotify_url, SpotifyImage: (item as any).SpotifyImage || (item as any).spotify_image, offlineState, downloadProgress } as MediaItem; }); }, [downloadStatus, downloads]); // Socket event handlers for download progress useEffect(() => { if (!socket) return; const handleDownloadUpdate = (data: any) => { console.log('🔄 Optimized download update received:', data); if (data.history && Array.isArray(data.history)) { const newStatus: { [key: string]: any } = {}; data.history.forEach((download: any) => { const key = download.id || download.spotify_id; if (key) { newStatus[key] = { status: download.status, progress: download.progress || 0, id: key, name: download.name || download.track_name }; } }); setDownloadStatus((prevStatus: any) => ({ ...prevStatus, ...newStatus })); } }; socket.on('update_status', handleDownloadUpdate); return () => { socket.off('update_status', handleDownloadUpdate); }; }, [socket]); if (loading) { return ( refresh()}>
); } if (error) { return ( refresh()}>

Failed to load discovery content

{error}

); } if (!hasContent) { return ( refresh()}>

No recommendations available

Start listening to music to get personalized recommendations!

); } // Render tab content based on active tab const renderTabContent = () => { switch (activeTab) { case 'all': return renderAllContent(); case 'made-for-you': return renderMadeForYouContent(); case 'new-releases': return renderNewReleasesContent(); case 'trending': return renderTrendingContent(); case 'genres': return renderGenresContent(); case 'albums': return renderAlbumsContent(); default: return renderAllContent(); } }; const renderAllContent = () => { return (
{/* Made for You Section - Lazy Loaded */} {discoveryData.for_you && discoveryData.for_you.tracks && discoveryData.for_you.tracks.length > 0 && ( navigate('/section/for-you?limit=100')} initialLoadCount={12} /> )} {/* New Releases Section - Lazy Loaded */} {discoveryData.new_releases && discoveryData.new_releases.tracks.length > 0 && ( navigate('/section/new-releases?limit=100')} initialLoadCount={12} /> )} {/* Trending Section - Lazy Loaded */} {discoveryData.trending && discoveryData.trending.tracks.length > 0 && ( navigate('/section/trending?limit=100')} initialLoadCount={12} /> )} {/* Trending Albums Section - Lazy Loaded */} {discoveryData.trending_albums && discoveryData.trending_albums.albums.length > 0 && ( navigate('/section/trending-albums?limit=100')} initialLoadCount={8} /> )} {/* New Albums Section - Lazy Loaded */} {discoveryData.new_albums && discoveryData.new_albums.albums.length > 0 && ( navigate('/section/new-albums?limit=100')} initialLoadCount={8} /> )} {/* Genre Sections - Optimized with limit */} {discoveryData.genres && discoveryData.genres.length > 0 && ( <>
Explore by Genre
Discover new music across different genres
navigate('/section/trending-albums?limit=100')}> See more (100)
{discoveryData.genres.slice(0, 3).map((genreSection: GenreSection, index: number) => ( navigate(`/section/genre-${encodeURIComponent(genreSection.genre)}?limit=100`)} initialLoadCount={8} /> ))} )}
); }; const renderMadeForYouContent = () => { if (!discoveryData.for_you || !discoveryData.for_you.tracks || discoveryData.for_you.tracks.length === 0) { return (

No personalized recommendations yet

Start listening to music to get recommendations based on your taste and current song!

); } return (

{discoveryData.for_you.title}

{discoveryData.for_you.description}

navigate('/section/for-you?limit=100')}> See all 100 recommendations
); }; const renderNewReleasesContent = () => { if (!discoveryData.new_releases || !discoveryData.new_releases.tracks || discoveryData.new_releases.tracks.length === 0) { return (

No new releases available

Check back later for the latest music releases!

); } return (

{discoveryData.new_releases.title}

{discoveryData.new_releases.description}

navigate('/section/new-releases?limit=100')}> See all 100 new releases
); }; const renderTrendingContent = () => { if (!discoveryData.trending || discoveryData.trending.tracks.length === 0) { return (

No trending tracks available

Check back later for trending music!

); } return (

{discoveryData.trending.title}

{discoveryData.trending.description}

navigate('/section/trending?limit=100')}> See all 100 trending tracks
); }; const renderGenresContent = () => { if (!discoveryData.genres || discoveryData.genres.length === 0) { return (

No genre recommendations available

Check back later for genre-based recommendations!

); } return (

Explore by Genre

Discover new music across different genres

{discoveryData.genres.map((genreSection: GenreSection, index: number) => ( { console.log(`Navigating to genre section: ${genreSection.genre}`); navigate(`/section/genre-${encodeURIComponent(genreSection.genre)}?limit=50`); }} initialLoadCount={8} /> ))}
); }; const renderAlbumsContent = () => { const hasAlbums = (discoveryData.trending_albums?.albums.length || 0) > 0 || (discoveryData.new_albums?.albums.length || 0) > 0; if (!hasAlbums) { return (

No album recommendations available

Check back later for album recommendations!

); } return (

Album Discoveries

Explore trending and new album releases

{/* Trending Albums - Lazy Loaded */} {discoveryData.trending_albums && discoveryData.trending_albums.albums.length > 0 && ( navigate('/section/trending-albums?limit=100')} initialLoadCount={8} /> )} {/* New Albums - Lazy Loaded */} {discoveryData.new_albums && discoveryData.new_albums.albums.length > 0 && ( navigate('/section/new-albums?limit=100')} initialLoadCount={8} /> )}
); }; return ( refresh()}>
{/* Tab Navigation */}
{TABS.map((tab) => { const Icon = tab.icon; return ( ); })}
{/* Tab Content */}
{renderTabContent()}
); };