"use client" import type React from "react" import { useEffect, useState } from "react" import { Loader2, AlertCircle } from "lucide-react" import { PiMusicNotesFill } from "react-icons/pi"; import { FaBluetoothB } from "react-icons/fa6"; import { IoBatteryFullSharp } from "react-icons/io5" import { IoIosPlay } from "react-icons/io" import { TbDiscOff } from "react-icons/tb" import { Progress } from "@/components/ui/progress" import Link from "@/components/objects/Link" import ScrollTxt from "@/components/objects/MusicText" import { connectSocket, disconnectSocket } from "@/lib/socket" interface LastFmResponse { album?: { image?: Array<{ size: string; '#text': string }> } track?: { album?: { image?: Array<{ size: string; '#text': string }> } } } interface NowPlayingData { track_name?: string artist_name?: string release_name?: string mbid?: string coverArt?: string | null lastFmData?: LastFmResponse status: 'loading' | 'partial' | 'complete' | 'error' message?: string } const NowPlaying: React.FC = () => { const [nowPlaying, setNowPlaying] = useState({ status: 'loading' }) const [currentTime, setCurrentTime] = useState(new Date()) const [volume, setVolume] = useState(25) const [screenOn, setScreenOn] = useState(true) const [progressSteps, setProgressSteps] = useState({ current: 0, total: 3 }) useEffect(() => { const socket = connectSocket() socket.on('connect', () => { console.log('Connected to server') socket.emit('requestNowPlaying') socket.emit('startAutoRefresh') }) socket.on('disconnect', () => { console.log('[i] Disconnected from server') }) socket.on('nowPlaying', (data: NowPlayingData) => { console.log('Received now playing data:', data) setNowPlaying(prevState => ({ ...prevState, ...data })) if (data.status === 'loading') { setProgressSteps({ current: 1, total: 3 }) } else if (data.status === 'partial') { setProgressSteps({ current: 2, total: 3 }) } else if (data.status === 'complete') { setProgressSteps({ current: 3, total: 3 }) } }) socket.on('connect_error', (error) => { console.error('[!] Connection error:', error) setNowPlaying({ status: 'error', message: 'Connection failed' }) }) return () => { socket.off('connect') socket.off('disconnect') socket.off('nowPlaying') socket.off('connect_error') disconnectSocket() } }, []) useEffect(() => { const timer = setInterval(() => { setCurrentTime(new Date()) }, 1000) return () => clearInterval(timer) }, []) const formatTime = (date: Date) => { return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }) } const renderScreenContent = () => { if (nowPlaying.status === 'loading') { return (
{nowPlaying.message || 'Connecting...'}
0 ? (progressSteps.current * 100) / progressSteps.total : 0} className="h-1" />
) } if (nowPlaying.status === 'error') { return (
{nowPlaying.message || 'Error loading data'}
) } if (!nowPlaying.track_name) { return (
Nothing playing
Check my ListenBrainz
) } // normal state return ( <>
{nowPlaying.release_name && }
{/* Album art */}
{nowPlaying.status === 'partial' && !nowPlaying.coverArt ? (
Fetching Album Art
) : nowPlaying.coverArt ? ( // eslint-disable-next-line @next/next/no-img-element {nowPlaying.track_name ) : (
)}
) } return (
{/* Volume buttons */}
setVolume(v => Math.min(100, v + 5))}>
{/* up */}
{/* play/pause */}
setVolume(v => Math.max(0, v - 5))}>
{/* down */}
{/* Top power button */}
setScreenOn(prev => !prev)}>
{/* White bezel (fuses screen+home btn) */}
{/* Virtual screen */}
{screenOn && (
{formatTime(currentTime)}
)} {screenOn ? renderScreenContent() : (
)} {/* Player controls and seekbar */} {screenOn && nowPlaying.track_name && (
setVolume(Number(e.target.value))} className="absolute top-0 left-0 w-full h-full opacity-0 cursor-pointer" />
)}
{/* Home button */}
) } export default NowPlaying