import { useMemo } from 'react'; import { Button, DropdownMenu, getColumnDefs, GridCarousel, Text, TextTitle, VirtualTable, } from '/@/renderer/components'; import { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core'; import { Box, Group, Stack } from '@mantine/core'; import { RiArrowDownSLine, 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 { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { Play, TableColumn } from '/@/renderer/types'; import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items'; import { PlayButton, PLAY_TYPES, useCreateFavorite, useDeleteFavorite, } from '/@/renderer/features/shared'; import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query'; import { 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'; const ContentContainer = styled.div` position: relative; display: flex; flex-direction: column; gap: 3rem; max-width: 1920px; 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 itemsPerPage = cq.isXl ? 9 : cq.isLg ? 7 : cq.isMd ? 5 : cq.isSm ? 4 : 3; const detailQuery = useAlbumArtistDetail({ id: albumArtistId }); const artistDiscographyLink = `${generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_DISCOGRAPHY, { albumArtistId, })}?${createSearchParams({ artistId: albumArtistId, artistName: detailQuery?.data?.name || '', })}`; const recentAlbumsQuery = useAlbumList({ jfParams: server?.type === ServerType.JELLYFIN ? { artistIds: albumArtistId } : undefined, limit: itemsPerPage, ndParams: server?.type === ServerType.NAVIDROME ? { artist_id: albumArtistId, compilation: false } : undefined, sortBy: AlbumListSort.RELEASE_DATE, sortOrder: SortOrder.DESC, startIndex: 0, }); const topSongsQuery = useTopSongsList( { artist: detailQuery?.data?.name || '' }, { enabled: server?.type !== ServerType.JELLYFIN && !!detailQuery?.data?.name }, ); 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 = { 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 carousels = [ { data: recentAlbumsQuery?.data?.items, itemType: LibraryItem.ALBUM, loading: recentAlbumsQuery?.isLoading || recentAlbumsQuery.isFetching, pagination: { itemsPerPage, }, title: ( <> Recent albums ), uniqueId: 'recentAlbums', }, { data: detailQuery?.data?.similarArtists?.slice(0, itemsPerPage), isHidden: !detailQuery?.data?.similarArtists, itemType: LibraryItem.ALBUM_ARTIST, loading: detailQuery?.isLoading || detailQuery.isFetching, pagination: { itemsPerPage, }, 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, }, }); } else { createFavoriteMutation.mutate({ query: { id: [detailQuery.data.id], type: LibraryItem.ALBUM_ARTIST, }, }); } }; const topSongs = topSongsQuery?.data?.items?.slice(0, 10); const showBiography = detailQuery?.data?.biography !== undefined && detailQuery?.data?.biography !== null; const showTopSongs = server?.type !== ServerType.JELLYFIN && topSongsQuery?.data?.items?.length; const showGenres = detailQuery?.data?.genres?.length !== 0; const isLoading = detailQuery?.isLoading || recentAlbumsQuery?.isLoading || (server?.type === ServerType.NAVIDROME && topSongsQuery?.isLoading); if (isLoading) return ; return ( handlePlay(playButtonBehavior)} /> {PLAY_TYPES.filter((type) => type.play !== playButtonBehavior).map((type) => ( handlePlay(type.play)} > {type.label} ))} Add to playlist {showGenres && ( {detailQuery?.data?.genres?.map((genre) => ( ))} )} {showBiography ? ( About {detailQuery?.data?.name} ) : null} {showTopSongs && ( Top Songs Community User data.data.uniqueId} rowData={topSongs} rowHeight={60} rowSelection="multiple" onCellContextMenu={handleContextMenu} onRowDoubleClicked={handleRowDoubleClick} /> )} {carousels .filter((c) => !c.isHidden) .map((carousel) => ( {carousel.title} ))} ); };