import { useQuery } from '@tanstack/react-query'; import { Suspense, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { createSearchParams, generatePath, Link, useParams } from 'react-router'; import styles from './album-artist-detail-content.module.css'; import { AlbumInfiniteCarousel } from '/@/renderer/features/albums/components/album-infinite-carousel'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { AlbumArtistGridCarousel } from '/@/renderer/features/artists/components/album-artist-grid-carousel'; import { ContextMenuController } from '/@/renderer/features/context-menu/context-menu-controller'; import { usePlayer } from '/@/renderer/features/player/context/player-context'; import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay'; import { PlayButton } from '/@/renderer/features/shared/components/play-button'; import { useContainerQuery } from '/@/renderer/hooks'; import { useGenreRoute } from '/@/renderer/hooks/use-genre-route'; import { AppRoute } from '/@/renderer/router/routes'; import { ArtistItem, useCurrentServer } from '/@/renderer/store'; import { useGeneralSettings, usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { sanitize } from '/@/renderer/utils/sanitize'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { Button } from '/@/shared/components/button/button'; import { Grid } from '/@/shared/components/grid/grid'; import { Group } from '/@/shared/components/group/group'; import { Spinner } from '/@/shared/components/spinner/spinner'; import { Spoiler } from '/@/shared/components/spoiler/spoiler'; import { Stack } from '/@/shared/components/stack/stack'; import { TextTitle } from '/@/shared/components/text-title/text-title'; import { AlbumArtist, AlbumListSort, LibraryItem, ServerType, SortOrder, } from '/@/shared/types/domain-types'; import { Play } from '/@/shared/types/types'; interface AlbumArtistDetailContentProps { background?: string; } export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailContentProps) => { const { t } = useTranslation(); const { artistItems, externalLinks, lastFM, musicBrainz } = useGeneralSettings(); const { albumArtistId, artistId } = useParams() as { albumArtistId?: string; artistId?: string; }; const routeId = (artistId || albumArtistId) as string; const { ref } = useContainerQuery(); const { addToQueueByFetch, setFavorite } = usePlayer(); const server = useCurrentServer(); const genrePath = useGenreRoute(); const [enabledItem, itemOrder] = useMemo(() => { const enabled: { [key in ArtistItem]?: boolean } = {}; const order: { [key in ArtistItem]?: number } = {}; for (const [idx, item] of artistItems.entries()) { enabled[item.id] = !item.disabled; order[item.id] = idx + 1; } return [enabled, order]; }, [artistItems]); const detailQuery = useQuery( artistsQueries.albumArtistDetail({ query: { id: routeId }, serverId: server?.id, }), ); const artistDiscographyLink = `${generatePath( AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY, { albumArtistId: routeId, }, )}?${createSearchParams({ artistId: routeId, artistName: detailQuery?.data?.name || '', })}`; const artistSongsLink = `${generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS, { albumArtistId: routeId, })}?${createSearchParams({ artistId: routeId, artistName: detailQuery?.data?.name || '', })}`; const topSongsQuery = useQuery( artistsQueries.topSongs({ options: { enabled: !!detailQuery?.data?.name && enabledItem.topSongs, }, query: { artist: detailQuery?.data?.name || '', artistId: routeId, }, serverId: server?.id, }), ); const carousels = useMemo(() => { return [ { isHidden: !enabledItem.recentAlbums || !routeId, itemType: LibraryItem.ALBUM, order: itemOrder.recentAlbums, query: { artistIds: routeId ? [routeId] : undefined, compilation: false, }, sortBy: AlbumListSort.RELEASE_DATE, sortOrder: SortOrder.DESC, title: ( {t('page.albumArtistDetail.recentReleases', { postProcess: 'sentenceCase', })} ), uniqueId: 'recentReleases', }, { isHidden: !enabledItem.compilations || server?.type === ServerType.SUBSONIC || !routeId, itemType: LibraryItem.ALBUM, order: itemOrder.compilations, query: { artistIds: routeId ? [routeId] : undefined, compilation: true, }, sortBy: AlbumListSort.RELEASE_DATE, sortOrder: SortOrder.DESC, title: ( {t('page.albumArtistDetail.appearsOn', { postProcess: 'sentenceCase' })} ), uniqueId: 'compilationAlbums', }, { data: (detailQuery?.data?.similarArtists || []) as AlbumArtist[], isHidden: !detailQuery?.data?.similarArtists || !enabledItem.similarArtists, itemType: LibraryItem.ALBUM_ARTIST, order: itemOrder.similarArtists, title: ( {t('page.albumArtistDetail.relatedArtists', { postProcess: 'sentenceCase', })} ), uniqueId: 'similarArtists', }, ]; }, [ artistDiscographyLink, detailQuery?.data?.similarArtists, enabledItem.compilations, enabledItem.recentAlbums, enabledItem.similarArtists, itemOrder.compilations, itemOrder.recentAlbums, itemOrder.similarArtists, routeId, server?.type, t, ]); const playButtonBehavior = usePlayButtonBehavior(); const handlePlay = async (playType?: Play) => { if (!server?.id) return; addToQueueByFetch( server.id, [routeId], albumArtistId ? LibraryItem.ALBUM_ARTIST : LibraryItem.ARTIST, playType || playButtonBehavior, ); }; const handleFavorite = () => { if (!detailQuery?.data) return; setFavorite( detailQuery.data._serverId, [detailQuery.data.id], LibraryItem.ALBUM_ARTIST, !detailQuery.data.userFavorite, ); }; const handleMoreOptions = (e: React.MouseEvent) => { if (!detailQuery?.data) return; ContextMenuController.call({ cmd: { items: [detailQuery.data], type: LibraryItem.ALBUM_ARTIST }, event: e, }); }; const albumCount = detailQuery?.data?.albumCount; const biography = useMemo(() => { const bio = detailQuery?.data?.biography; if (!bio || !enabledItem.biography) return null; return sanitize(bio); }, [detailQuery?.data?.biography, enabledItem.biography]); const showTopSongs = topSongsQuery?.data?.items?.length && enabledItem.topSongs; const showGenres = detailQuery?.data?.genres ? detailQuery?.data?.genres.length !== 0 : false; const mbzId = detailQuery?.data?.mbz; const isLoading = detailQuery?.isLoading || (server?.type === ServerType.NAVIDROME && enabledItem.topSongs && topSongsQuery?.isLoading); if (isLoading) return
; return (
handlePlay(playButtonBehavior)} /> {showGenres ? (
{detailQuery?.data?.genres?.map((genre) => ( ))}
) : null} {externalLinks && (lastFM || musicBrainz) ? (
{lastFM && ( )} {mbzId && musicBrainz ? ( ) : null}
) : null} {biography ? (
{t('page.albumArtistDetail.about', { artist: detailQuery?.data?.name, })}
) : null} {showTopSongs ? (
{t('page.albumArtistDetail.topSongs', { postProcess: 'sentenceCase', })}
) : null} {carousels .filter((c) => !c.isHidden) .map((carousel) => (
{carousel.itemType === LibraryItem.ALBUM ? ( 'query' in carousel && carousel.query && carousel.sortBy && carousel.sortOrder ? ( }> ) : null ) : carousel.itemType === LibraryItem.ALBUM_ARTIST ? ( 'data' in carousel && carousel.data ? ( ) : null ) : null}
))}
); };