import React, { useMemo, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { useAlbumDetailBack } from '../../hooks/useAlbumDetailBack'; import { ArrowLeft, Camera, Check, ExternalLink, HardDriveDownload, Heart, Loader2, Play, Radio, Share2, Shuffle, Users, } from 'lucide-react'; import type { SubsonicAlbum, SubsonicArtist, SubsonicArtistInfo } from '../../api/subsonicTypes'; import { useOfflineStore } from '../../store/offlineStore'; import { useAuthStore } from '../../store/authStore'; import { useArtistOfflineState } from '../../hooks/useArtistOfflineState'; import { useIsMobile } from '../../hooks/useIsMobile'; import { ArtistHeroCover } from '../../cover/artistHero'; import { useCoverLightboxSrc } from '../../cover/lightbox'; import type { CoverArtRef } from '../../cover/types'; import LastfmIcon from '../LastfmIcon'; import StarRating from '../StarRating'; import { tooltipAttrs } from '../tooltipAttrs'; import { offlineActionPolicy, type OfflineActionPolicy } from '../../utils/offline/offlineActionPolicy'; interface Props { artist: SubsonicArtist; id: string | undefined; albums: SubsonicAlbum[]; info: SubsonicArtistInfo | null; isStarred: boolean; artistEntityRating: number; handleArtistEntityRating: (rating: number) => Promise; toggleStar: () => Promise; handlePlayAll: () => void; handleShuffle: () => void; handleStartRadio: () => void; handleShareArtist: () => void; handleImageUpload: (e: React.ChangeEvent) => Promise; playAllLoading: boolean; radioLoading: boolean; uploading: boolean; openedLink: string | null; openLink: (url: string, key: string) => void; coverId: string; coverRef: CoverArtRef | null; coverRevision: number; headerCoverFailed: boolean; setHeaderCoverFailed: React.Dispatch>; actionPolicy?: OfflineActionPolicy; } export default function ArtistDetailHero({ artist, id, albums, info, isStarred, artistEntityRating, handleArtistEntityRating, toggleStar, handlePlayAll, handleShuffle, handleStartRadio, handleShareArtist, handleImageUpload, playAllLoading, radioLoading, uploading, openedLink, openLink, coverId, coverRef, coverRevision, headerCoverFailed, setHeaderCoverFailed, actionPolicy, }: Props) { const policy = actionPolicy ?? offlineActionPolicy('artistDetail', false); const { t } = useTranslation(); const goBack = useAlbumDetailBack(); const isMobile = useIsMobile(); const imageInputRef = useRef(null); const downloadArtist = useOfflineStore(s => s.downloadArtist); const activeServerId = useAuthStore(s => s.activeServerId) ?? ''; const artistAlbumIds = useMemo(() => albums.map(a => a.id), [albums]); const { status: artistOfflineStatus, progress: artistOfflineProgress } = useArtistOfflineState( id ?? '', activeServerId, artistAlbumIds, ); const entityRatingSupportByServer = useAuthStore(s => s.entityRatingSupportByServer); const artistEntityRatingSupport = entityRatingSupportByServer[activeServerId] ?? 'unknown'; const { open: openLightbox, lightbox } = useCoverLightboxSrc(coverRef, { alt: artist.name }); const wikiUrl = `https://en.wikipedia.org/wiki/${encodeURIComponent(artist.name)}`; return ( <> {lightbox}
{coverId ? ( ) : ( )} {/* Upload overlay */}
{ e.stopPropagation(); imageInputRef.current?.click(); }} > {uploading ? : }

{artist.name}

{t('artistDetail.albumCount_other', { count: artist.albumCount ?? 0 })}
{t('entityRating.artistShort')}
{(info?.lastFmUrl || artist.name) && (
{info?.lastFmUrl && ( )}
)} {policy.canFavorite && ( )}
{albums.length > 0 && ( <> )} {id && artist && ( )} {policy.canCacheDiscography && albums.length > 0 && ( )}
); }