import { useMemo } from 'react'; import { Button, Text, TextTitle } from '/@/renderer/components'; import { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core'; import { Box, Group, Stack } from '@mantine/core'; import { RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri'; import { generatePath, useParams } from 'react-router'; import { useCurrentServer } from '/@/renderer/store'; import { createSearchParams, Link } from 'react-router-dom'; import styled from 'styled-components'; import { AppRoute } from '/@/renderer/router/routes'; import { useContainerQuery } from '/@/renderer/hooks'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { useHandleGeneralContextMenu, useHandleTableContextMenu, } from '/@/renderer/features/context-menu'; import { CardRow, Play, TableColumn } from '/@/renderer/types'; import { ARTIST_CONTEXT_MENU_ITEMS, SONG_CONTEXT_MENU_ITEMS, } from '/@/renderer/features/context-menu/context-menu-items'; import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared'; import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query'; import { Album, AlbumArtist, AlbumListSort, LibraryItem, QueueSong, ServerType, SortOrder, } from '/@/renderer/api/types'; import { usePlayQueueAdd } from '/@/renderer/features/player'; import { useAlbumArtistDetail } from '/@/renderer/features/artists/queries/album-artist-detail-query'; import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query'; import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table'; import { SwiperGridCarousel } from '/@/renderer/components/grid-carousel'; const ContentContainer = styled.div` position: relative; display: flex; flex-direction: column; gap: 3rem; padding: 1rem 2rem 5rem; overflow: hidden; .ag-theme-alpine-dark { --ag-header-background-color: rgba(0, 0, 0, 0%) !important; } .ag-header { margin-bottom: 0.5rem; } `; export const AlbumArtistDetailContent = () => { const { albumArtistId } = useParams() as { albumArtistId: string }; const cq = useContainerQuery(); const handlePlayQueueAdd = usePlayQueueAdd(); const server = useCurrentServer(); const detailQuery = useAlbumArtistDetail({ query: { id: albumArtistId }, serverId: server?.id }); const artistDiscographyLink = `${generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY, { albumArtistId, })}?${createSearchParams({ artistId: albumArtistId, artistName: detailQuery?.data?.name || '', })}`; const artistSongsLink = `${generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS, { albumArtistId, })}?${createSearchParams({ artistId: albumArtistId, artistName: detailQuery?.data?.name || '', })}`; const recentAlbumsQuery = useAlbumList({ query: { _custom: { jellyfin: { ...(server?.type === ServerType.JELLYFIN ? { ArtistIds: albumArtistId } : undefined), }, navidrome: { ...(server?.type === ServerType.NAVIDROME ? { artist_id: albumArtistId, compilation: false } : undefined), }, }, // limit: 10, sortBy: AlbumListSort.RELEASE_DATE, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }); const compilationAlbumsQuery = useAlbumList({ query: { _custom: { jellyfin: { ...(server?.type === ServerType.JELLYFIN ? { ContributingArtistIds: albumArtistId } : undefined), }, navidrome: { ...(server?.type === ServerType.NAVIDROME ? { artist_id: albumArtistId, compilation: true } : undefined), }, }, // limit: 10, sortBy: AlbumListSort.RELEASE_DATE, sortOrder: SortOrder.DESC, startIndex: 0, }, serverId: server?.id, }); const topSongsQuery = useTopSongsList({ options: { enabled: !!detailQuery?.data?.name, }, query: { artist: detailQuery?.data?.name || '', artistId: albumArtistId, }, serverId: server?.id, }); const topSongsColumnDefs: ColDef[] = useMemo( () => getColumnDefs([ { column: TableColumn.ROW_INDEX, width: 0 }, { column: TableColumn.TITLE_COMBINED, width: 0 }, { column: TableColumn.DURATION, width: 0 }, { column: TableColumn.ALBUM, width: 0 }, { column: TableColumn.YEAR, width: 0 }, { column: TableColumn.PLAY_COUNT, width: 0 }, { column: TableColumn.USER_FAVORITE, width: 0 }, ]), [], ); const cardRows: Record[] | CardRow[]> = { album: [ { property: 'name', route: { route: AppRoute.LIBRARY_ALBUMS_DETAIL, slugs: [{ idProperty: 'id', slugProperty: 'albumId' }], }, }, { arrayProperty: 'name', property: 'albumArtists', route: { route: AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, slugs: [{ idProperty: 'id', slugProperty: 'albumArtistId' }], }, }, ], albumArtist: [ { property: 'name', route: { route: AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, slugs: [{ idProperty: 'id', slugProperty: 'albumArtistId' }], }, }, ], }; const cardRoutes = { album: { route: AppRoute.LIBRARY_ALBUMS_DETAIL, slugs: [{ idProperty: 'id', slugProperty: 'albumId' }], }, albumArtist: { route: AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, slugs: [{ idProperty: 'id', slugProperty: 'albumArtistId' }], }, }; const carousels = [ { data: recentAlbumsQuery?.data?.items, isHidden: !recentAlbumsQuery?.data?.items?.length, itemType: LibraryItem.ALBUM, loading: recentAlbumsQuery?.isLoading || recentAlbumsQuery.isFetching, title: ( Recent releases ), uniqueId: 'recentReleases', }, { data: compilationAlbumsQuery?.data?.items, isHidden: !compilationAlbumsQuery?.data?.items?.length, itemType: LibraryItem.ALBUM, loading: compilationAlbumsQuery?.isLoading || compilationAlbumsQuery.isFetching, title: ( Appears on ), uniqueId: 'compilationAlbums', }, { data: detailQuery?.data?.similarArtists || [], isHidden: !detailQuery?.data?.similarArtists, itemType: LibraryItem.ALBUM_ARTIST, loading: detailQuery?.isLoading || detailQuery.isFetching, title: ( Related artists ), uniqueId: 'similarArtists', }, ]; const playButtonBehavior = usePlayButtonBehavior(); const handlePlay = async (playType?: Play) => { handlePlayQueueAdd?.({ byItemType: { id: [albumArtistId], type: LibraryItem.ALBUM_ARTIST, }, play: playType || playButtonBehavior, }); }; const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, SONG_CONTEXT_MENU_ITEMS); const handleRowDoubleClick = (e: RowDoubleClickedEvent) => { if (!e.data) return; handlePlayQueueAdd?.({ byData: [e.data], play: playButtonBehavior, }); }; const createFavoriteMutation = useCreateFavorite({}); const deleteFavoriteMutation = useDeleteFavorite({}); const handleFavorite = () => { if (!detailQuery?.data) return; if (detailQuery.data.userFavorite) { deleteFavoriteMutation.mutate({ query: { id: [detailQuery.data.id], type: LibraryItem.ALBUM_ARTIST, }, serverId: detailQuery.data.serverId, }); } else { createFavoriteMutation.mutate({ query: { id: [detailQuery.data.id], type: LibraryItem.ALBUM_ARTIST, }, serverId: detailQuery.data.serverId, }); } }; const handleGeneralContextMenu = useHandleGeneralContextMenu( LibraryItem.ALBUM_ARTIST, ARTIST_CONTEXT_MENU_ITEMS, ); const topSongs = topSongsQuery?.data?.items?.slice(0, 10); const showBiography = detailQuery?.data?.biography !== undefined && detailQuery?.data?.biography !== null; const showTopSongs = topSongsQuery?.data?.items?.length; const showGenres = detailQuery?.data?.genres ? detailQuery?.data?.genres.length !== 0 : false; const isLoading = detailQuery?.isLoading || (server?.type === ServerType.NAVIDROME && topSongsQuery?.isLoading); if (isLoading) return ; return ( handlePlay(playButtonBehavior)} /> {showGenres && ( {detailQuery?.data?.genres?.map((genre) => ( ))} )} {showBiography ? ( About {detailQuery?.data?.name} ) : null} {showTopSongs && ( Top Songs data.data.uniqueId} rowData={topSongs} rowHeight={60} rowSelection="multiple" onCellContextMenu={handleContextMenu} onRowDoubleClicked={handleRowDoubleClick} /> )} {carousels .filter((c) => !c.isHidden) .map((carousel) => ( ))} ); };