From db7498ed03df0869c8f9d1ad28af5d6e41d24d62 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 22 Oct 2025 10:51:33 -0400 Subject: [PATCH 1/3] Revert "Show all album artists on cards (#6929)" This reverts commit 4f9a105921b5c1027f6098a508a12fd6c35ce26b. --- src/components/cardbuilder/cardBuilder.js | 2 +- src/components/itemHelper.js | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index c48cb82ca8..60e8ffa6fc 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -577,7 +577,7 @@ function getCardFooterText(item, apiClient, options, footerClass, progressHtml, if (flags.isOuterFooter && item.AlbumArtists?.length) { item.AlbumArtists[0].Type = 'MusicArtist'; item.AlbumArtists[0].IsFolder = true; - lines.push(getTextActionButton(item.AlbumArtists, null, serverId)); + lines.push(getTextActionButton(item.AlbumArtists[0], null, serverId)); } else { lines.push(escapeHtml(isUsingLiveTvNaming(item.Type) ? item.Name : (item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''))); } diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index 965b33da48..f21ce6e063 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -52,14 +52,6 @@ export function getDisplayName(item, options = {}) { } } - if (Array.isArray(item)) { - if (item.length > 1) { - return item.map(i => getDisplayName(i, options)).join(' / '); - } else if (item.length === 1) { - return item[0].Name; - } - } - return name; } From 6ee77f18bc36c89f83ac96ffede06f5780ae8fc0 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 22 Oct 2025 11:00:54 -0400 Subject: [PATCH 2/3] Fix card links for multiple album artists --- src/components/cardbuilder/cardBuilder.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 60e8ffa6fc..43298704db 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -575,9 +575,14 @@ function getCardFooterText(item, apiClient, options, footerClass, progressHtml, if (showOtherText) { if (options.showParentTitle && parentTitleUnderneath) { if (flags.isOuterFooter && item.AlbumArtists?.length) { - item.AlbumArtists[0].Type = 'MusicArtist'; - item.AlbumArtists[0].IsFolder = true; - lines.push(getTextActionButton(item.AlbumArtists[0], null, serverId)); + const artistText = item.AlbumArtists + .map(artist => { + artist.Type = BaseItemKind.MusicArtist; + artist.IsFolder = true; + return getTextActionButton(artist, null, serverId); + }) + .join(' / '); + lines.push(artistText); } else { lines.push(escapeHtml(isUsingLiveTvNaming(item.Type) ? item.Name : (item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''))); } From b5382f01421a6815a2460ac2c5497d9620722d8b Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 22 Oct 2025 14:59:40 -0400 Subject: [PATCH 3/3] Fix card links for multiple album artists in experimental layout --- src/components/cardbuilder/Card/CardText.tsx | 45 +++++++++++-------- src/components/cardbuilder/Card/cardHelper.ts | 28 +++++++++--- src/utils/array.ts | 8 ++++ 3 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 src/utils/array.ts diff --git a/src/components/cardbuilder/Card/CardText.tsx b/src/components/cardbuilder/Card/CardText.tsx index b1230c5ec8..ef528939ef 100644 --- a/src/components/cardbuilder/Card/CardText.tsx +++ b/src/components/cardbuilder/Card/CardText.tsx @@ -1,5 +1,8 @@ import React, { type FC } from 'react'; import Box from '@mui/material/Box'; + +import { ensureArray } from 'utils/array'; + import type { TextLine } from './cardHelper'; interface CardTextProps { @@ -7,27 +10,33 @@ interface CardTextProps { textLine: TextLine; } +const SEPARATOR = ' / '; + const CardText: FC = ({ className, textLine }) => { const { title, titleAction } = textLine; - // eslint-disable-next-line sonarjs/function-return-type - const renderCardText = () => { - if (titleAction) { - return ( - - {titleAction.title} - - ); - } else { - return title; - } - }; - return {renderCardText()}; + return ( + + {titleAction ? ( + ensureArray(titleAction).map((action, i, arr) => ( + <> + + {action.title} + + {/* If there are more items, add the separator */} + {(i < arr.length - 1) && SEPARATOR} + + )) + ) : ( + ensureArray(title).join(SEPARATOR) + )} + + ); }; export default CardText; diff --git a/src/components/cardbuilder/Card/cardHelper.ts b/src/components/cardbuilder/Card/cardHelper.ts index 070c8085df..3044105a5f 100644 --- a/src/components/cardbuilder/Card/cardHelper.ts +++ b/src/components/cardbuilder/Card/cardHelper.ts @@ -1,4 +1,5 @@ import { Api } from '@jellyfin/sdk'; +import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind'; import type { BaseItemPerson } from '@jellyfin/sdk/lib/generated-client/models/base-item-person'; import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type'; import { getImageApi } from '@jellyfin/sdk/lib/utils/api/image-api'; @@ -12,6 +13,7 @@ import { isUsingLiveTvNaming } from '../cardBuilderUtils'; import { getDataAttributes } from 'utils/items'; import { ItemKind } from 'types/base/models/item-kind'; import { ItemMediaKind } from 'types/base/models/item-media-kind'; +import { ensureArray } from 'utils/array'; import type { NullableNumber, NullableString } from 'types/base/common/shared/types'; import type { ItemDto } from 'types/base/models/item-dto'; @@ -65,8 +67,8 @@ interface TextAction { } export interface TextLine { - title?: NullableString; - titleAction?: TextAction; + title?: NullableString | string[]; + titleAction?: TextAction | TextAction[]; } export function getTextActionButton( @@ -210,9 +212,25 @@ function getParentTitle( item: ItemDto ) { if (isOuterFooter && item.AlbumArtists?.length) { - (item.AlbumArtists[0] as ItemDto).Type = ItemKind.MusicArtist; - (item.AlbumArtists[0] as ItemDto).IsFolder = true; - return getTextActionButton(item.AlbumArtists[0], null, serverId); + return item.AlbumArtists + .map(artist => { + const artistItem: ItemDto = { + ...artist, + Type: BaseItemKind.MusicArtist, + IsFolder: true + }; + return getTextActionButton(artistItem, null, serverId); + }) + .reduce((acc, line) => ({ + title: [ + ...ensureArray(acc.title), + ...ensureArray(line.title) + ], + titleAction: [ + ...ensureArray(acc.titleAction), + ...ensureArray(line.titleAction) + ] + }), {}); } else { return { title: isUsingLiveTvNaming(item.Type) ? diff --git a/src/utils/array.ts b/src/utils/array.ts new file mode 100644 index 0000000000..ca648e3514 --- /dev/null +++ b/src/utils/array.ts @@ -0,0 +1,8 @@ +/** + * Utility function that converts a value that can be a single item, array of items, null, or undefined to an array. + */ +export function ensureArray(val: T | T[] | null | undefined): T[] { + if (val == null) return []; + if (Array.isArray(val)) return val; + return [ val ]; +}