From 3db229ef6876fbeb6175cab11181967fbd5de724 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 27 Dec 2025 01:13:28 -0800 Subject: [PATCH] re-add similar artists carousel to artist page --- .../grid-carousel/grid-carousel-v2.tsx | 84 ++++++---- .../grid-carousel/grid-carousel.module.css | 13 ++ .../album-artist-detail-content.module.css | 13 +- .../album-artist-detail-content.tsx | 146 ++++++++++++++---- src/renderer/store/settings.store.ts | 1 - 5 files changed, 194 insertions(+), 63 deletions(-) diff --git a/src/renderer/components/grid-carousel/grid-carousel-v2.tsx b/src/renderer/components/grid-carousel/grid-carousel-v2.tsx index 56a31c0ba..eba2cc639 100644 --- a/src/renderer/components/grid-carousel/grid-carousel-v2.tsx +++ b/src/renderer/components/grid-carousel/grid-carousel-v2.tsx @@ -157,45 +157,65 @@ function BaseGridCarousel(props: GridCarouselProps) { {cq.isCalculated && ( <>
- - - {typeof title === 'string' ? ( + {typeof title === 'string' ? ( + + {title} - ) : ( - title - )} - {enableRefresh && onRefresh && ( + {enableRefresh && onRefresh && ( + + )} + + - )} + + - - - - - + ) : ( +
+
{title}
+ + + + +
+ )}
- - - - {t('page.albumArtistDetail.topSongs', { - postProcess: 'sentenceCase', - })} - +
+ + {t('page.albumArtistDetail.topSongs', { + postProcess: 'sentenceCase', + })} + +
+
+
); } @@ -268,13 +273,14 @@ const AlbumArtistMetadataTopSongs = ({ return (
- - - - {t('page.albumArtistDetail.topSongs', { - postProcess: 'sentenceCase', - })} - +
+ + {t('page.albumArtistDetail.topSongs', { + postProcess: 'sentenceCase', + })} + +
+
+
>; + routeId: string; +} + +const AlbumArtistMetadataSimilarArtists = ({ + detailQuery, + routeId, +}: AlbumArtistMetadataSimilarArtistsProps) => { + const { t } = useTranslation(); + const server = useCurrentServer(); + const serverId = useCurrentServerId(); + + const similarArtists = useMemo(() => { + const relatedArtists = detailQuery.data?.similarArtists; + if (!relatedArtists || relatedArtists.length === 0) { + return []; + } + + return relatedArtists.map( + (relatedArtist: RelatedArtist): AlbumArtist => ({ + _itemType: LibraryItem.ALBUM_ARTIST, + _serverId: serverId || '', + _serverType: (server?.type as ServerType) || ServerType.JELLYFIN, + albumCount: null, + biography: null, + duration: null, + genres: [], + id: relatedArtist.id, + imageId: relatedArtist.imageId, + imageUrl: relatedArtist.imageUrl, + lastPlayedAt: null, + mbz: null, + name: relatedArtist.name, + playCount: null, + similarArtists: null, + songCount: null, + userFavorite: false, + userRating: null, + }), + ); + }, [detailQuery.data?.similarArtists, server?.type, serverId]); + + const carouselTitle = useMemo( + () => ( +
+ + {t('page.albumArtistDetail.relatedArtists', { + postProcess: 'sentenceCase', + })} + +
+
+
+
+ ), + [t], + ); + + if (similarArtists.length === 0) { + return null; + } + + return ( + + ); +}; + export const AlbumArtistDetailContent = () => { const { artistItems, externalLinks, lastFM, musicBrainz } = useGeneralSettings(); const { albumArtistId, artistId } = useParams() as { @@ -493,7 +572,7 @@ export const AlbumArtistDetailContent = () => { artistDiscographyLink={artistDiscographyLink} artistSongsLink={artistSongsLink} /> - + {showGenres && ( @@ -521,6 +600,14 @@ export const AlbumArtistDetailContent = () => { + {enabledItem.similarArtists && ( + + + + )} {enabledItem.topSongs && ( { />
- {releaseTypeEntries.map(({ albums, displayName, releaseType }) => ( - - ))} + {cq.isCalculated && + releaseTypeEntries.map(({ albums, displayName, releaseType }) => ( + + ))}
); diff --git a/src/renderer/store/settings.store.ts b/src/renderer/store/settings.store.ts index 9a0e7c38f..6fd970fe0 100644 --- a/src/renderer/store/settings.store.ts +++ b/src/renderer/store/settings.store.ts @@ -578,7 +578,6 @@ export const SettingsStateSchema = ValidationSettingsStateSchema.merge( export enum ArtistItem { BIOGRAPHY = 'biography', - COMPILATIONS = 'compilations', RECENT_ALBUMS = 'recentAlbums', SIMILAR_ARTISTS = 'similarArtists', TOP_SONGS = 'topSongs',