import React, { memo } from 'react'; import { useTranslation } from 'react-i18next'; import { Headphones, Heart, MicVocal, Music, Star } from 'lucide-react'; import type { LastfmArtistStats, LastfmTrackInfo } from '../../api/lastfm'; import LastfmIcon from '../LastfmIcon'; import { formatTime } from '../../utils/nowPlayingHelpers'; interface HeroProps { track: { title: string; artist: string; album: string; year?: number; duration: number; suffix?: string; bitRate?: number; samplingRate?: number; bitDepth?: number; artistId?: string; albumId?: string; id: string; userRating?: number; }; genre?: string; playCount?: number; userRatingOverride?: number; lfmTrack: LastfmTrackInfo | null; lfmArtist: LastfmArtistStats | null; starred: boolean; lfmLoved: boolean; lfmLoveEnabled: boolean; activeLyricsTab: boolean; coverUrl: string; onNavigate: (path: string) => void; onToggleStar: () => void; onToggleLfmLove: () => void; onOpenLyrics: () => void; } function renderStars(rating?: number) { if (!rating) return null; return (
{[1, 2, 3, 4, 5].map(i => ( ))}
); } const Hero = memo(function Hero({ track, genre, playCount, userRatingOverride, lfmTrack, lfmArtist, starred, lfmLoved, lfmLoveEnabled, activeLyricsTab, coverUrl, onNavigate, onToggleStar, onToggleLfmLove, onOpenLyrics }: HeroProps) { const { t } = useTranslation(); const rating = userRatingOverride ?? track.userRating; const hiRes = (track.bitDepth && track.bitDepth > 16) || (track.samplingRate && track.samplingRate > 48000); const releaseAge = track.year ? new Date().getFullYear() - track.year : 0; return (
{coverUrl ? :
}
{track.title}
track.artistId && onNavigate(`/artist/${track.artistId}`)} style={{ cursor: track.artistId ? 'pointer' : 'default' }}> {track.artist} · track.albumId && onNavigate(`/album/${track.albumId}`)} style={{ cursor: track.albumId ? 'pointer' : 'default' }}> {track.album} {track.year && <>·{track.year}} {releaseAge > 0 && ( <>· {t('nowPlaying.releasedYearsAgo', { count: releaseAge, defaultValue: '{{count}} years ago' })} )}
{genre && {genre}} {track.suffix && {track.suffix.toUpperCase()}} {track.bitRate && {track.bitRate} kbps} {track.samplingRate && {(track.samplingRate / 1000).toFixed(1)} kHz} {track.bitDepth && {track.bitDepth}-bit} {hiRes && Hi-Res} {track.duration > 0 && {formatTime(track.duration)}}
{lfmLoveEnabled && ( )} {rating && renderStars(rating)}
{(playCount != null && playCount > 0) && (
{t('nowPlaying.playsCount', { count: playCount, defaultValue: '{{count}} plays' })}
)} {(lfmTrack || lfmArtist) && (
Last.fm
{lfmTrack && (
{t('nowPlaying.thisTrack', 'This track')} {t('nowPlaying.listenersN', { n: lfmTrack.listeners.toLocaleString(), defaultValue: '{{n}} listeners' })} · {t('nowPlaying.scrobblesN', { n: lfmTrack.playcount.toLocaleString(), defaultValue: '{{n}} scrobbles' })} {lfmTrack.userPlaycount != null && ( <> · {t('nowPlaying.playsByYouN', { n: lfmTrack.userPlaycount.toLocaleString(), defaultValue: 'played {{n}}× by you' })} )}
)} {lfmArtist && (
{t('nowPlaying.thisArtist', 'This artist')} {t('nowPlaying.listenersN', { n: lfmArtist.listeners.toLocaleString(), defaultValue: '{{n}} listeners' })} · {t('nowPlaying.scrobblesN', { n: lfmArtist.playcount.toLocaleString(), defaultValue: '{{n}} scrobbles' })} {lfmArtist.userPlaycount != null && ( <> · {t('nowPlaying.playsByYouN', { n: lfmArtist.userPlaycount.toLocaleString(), defaultValue: 'played {{n}}× by you' })} )}
)}
)}
); }); export default Hero;