Extract getCardImageUrl and remove duplicate hook

This commit is contained in:
Bill Thornton
2026-03-19 14:33:23 -04:00
parent c740f24405
commit 8924ea487d
5 changed files with 193 additions and 469 deletions
+13 -8
View File
@@ -2,6 +2,7 @@ import classNames from 'classnames';
import layoutManager from 'components/layoutManager';
import { ItemAction } from 'constants/itemAction';
import { useApi } from 'hooks/useApi';
import { ItemKind } from 'types/base/models/item-kind';
import { ItemMediaKind } from 'types/base/models/item-media-kind';
import type { ItemDto } from 'types/base/models/item-dto';
@@ -9,11 +10,11 @@ import type { CardOptions } from 'types/cardOptions';
import { CardShape } from 'utils/card';
import { getDataAttributes } from 'utils/items';
import useCardImageUrl from './useCardImageUrl';
import {
resolveAction,
resolveMixedShapeByAspectRatio
} from '../cardBuilderUtils';
import { getCardImageUrl } from '../utils/url';
interface UseCardProps {
item: ItemDto;
@@ -21,6 +22,7 @@ interface UseCardProps {
}
function useCard({ item, cardOptions }: UseCardProps) {
const { api } = useApi();
const action = resolveAction({
defaultAction: cardOptions.action ?? ItemAction.Link,
isFolder: item.IsFolder ?? false,
@@ -33,15 +35,18 @@ function useCard({ item, cardOptions }: UseCardProps) {
shape = resolveMixedShapeByAspectRatio(item.PrimaryImageAspectRatio);
}
const imgInfo = useCardImageUrl({
const {
imgUrl,
blurhash,
forceName,
coverImage
} = getCardImageUrl({
api,
item: item.ProgramInfo ?? item,
cardOptions,
options: cardOptions,
shape
});
const imgUrl = imgInfo.imgUrl;
const blurhash = imgInfo.blurhash ?? undefined;
const forceName = imgInfo.forceName;
const coveredImage = cardOptions.coverImage ?? imgInfo.coverImage;
const coveredImage = cardOptions.coverImage ?? coverImage;
const overlayText = cardOptions.overlayText;
const nameWithPrefix = item.SortName ?? item.Name ?? '';
@@ -112,7 +117,7 @@ function useCard({ item, cardOptions }: UseCardProps) {
className: cardBoxClass,
shape,
imgUrl,
blurhash,
blurhash: blurhash ?? undefined,
forceName,
coveredImage,
overlayText
@@ -1,300 +0,0 @@
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
import { getImageApi } from '@jellyfin/sdk/lib/utils/api/image-api';
import { useApi } from 'hooks/useApi';
import { getDesiredAspect } from '../cardBuilderUtils';
import { CardShape } from 'utils/card';
import { ItemKind } from 'types/base/models/item-kind';
import { ItemMediaKind } from 'types/base/models/item-media-kind';
import type { NullableNumber, NullableString } from 'types/base/common/shared/types';
import type { ItemDto } from 'types/base/models/item-dto';
import type { CardOptions } from 'types/cardOptions';
function getPreferThumbInfo(item: ItemDto, cardOptions: CardOptions) {
let imgType;
let itemId;
let imgTag;
let forceName = false;
if (item.ImageTags?.Thumb) {
imgType = ImageType.Thumb;
imgTag = item.ImageTags.Thumb;
itemId = item.Id;
} else if (item.SeriesThumbImageTag && cardOptions.inheritThumb !== false) {
imgType = ImageType.Thumb;
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (
item.ParentThumbItemId
&& cardOptions.inheritThumb !== false
&& item.MediaType !== ItemMediaKind.Photo
) {
imgType = ImageType.Thumb;
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (item.BackdropImageTags?.length) {
imgType = ImageType.Backdrop;
imgTag = item.BackdropImageTags[0];
itemId = item.Id;
forceName = true;
} else if (
item.ParentBackdropImageTags?.length
&& cardOptions.inheritThumb !== false
) {
imgType = ImageType.Backdrop;
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
}
return {
itemId: itemId,
imgTag: imgTag,
imgType: imgType,
forceName: forceName
};
}
function getPreferLogoInfo(item: ItemDto) {
let imgType;
let itemId;
let imgTag;
if (item.ImageTags?.Logo) {
imgType = ImageType.Logo;
imgTag = item.ImageTags.Logo;
itemId = item.Id;
} else if (item.ParentLogoImageTag && item.ParentLogoItemId) {
imgType = ImageType.Logo;
imgTag = item.ParentLogoImageTag;
itemId = item.ParentLogoItemId;
}
return {
itemId: itemId,
imgTag: imgTag,
imgType: imgType
};
}
function getCalculatedHeight(
itemWidth: NullableNumber,
itemPrimaryImageAspectRatio: NullableNumber
) {
if (itemWidth && itemPrimaryImageAspectRatio) {
return Math.round(itemWidth / itemPrimaryImageAspectRatio);
}
}
function isForceName(cardOptions: CardOptions) {
return !!(cardOptions.preferThumb && cardOptions.showTitle !== false);
}
function isCoverImage(
itemPrimaryImageAspectRatio: NullableNumber,
uiAspect: NullableNumber
) {
if (itemPrimaryImageAspectRatio && uiAspect) {
return Math.abs(itemPrimaryImageAspectRatio - uiAspect) / uiAspect <= 0.2;
}
return false;
}
function shouldShowPreferBanner(
imageTagsBanner: NullableString,
cardOptions: CardOptions,
shape: CardShape | undefined
): boolean {
return (
(cardOptions.preferBanner || shape === CardShape.Banner)
&& Boolean(imageTagsBanner)
);
}
function shouldShowPreferDisc(
imageTagsDisc: string | null | undefined,
cardOptions: CardOptions
): boolean {
return cardOptions.preferDisc === true && Boolean(imageTagsDisc);
}
function shouldShowImageTagsPrimary(item: ItemDto): boolean {
return (
Boolean(item.ImageTags?.Primary) && (item.Type !== ItemKind.Episode || item.ChildCount !== 0)
);
}
function shouldShowImageTagsThumb(item: ItemDto): boolean {
return item.Type === ItemKind.Season && Boolean(item.ImageTags?.Thumb);
}
function shouldShowSeriesThumbImageTag(
itemSeriesThumbImageTag: NullableString,
cardOptions: CardOptions
): boolean {
return (
Boolean(itemSeriesThumbImageTag) && cardOptions.inheritThumb !== false
);
}
function shouldShowParentThumbImageTag(
itemParentThumbItemId: NullableString,
cardOptions: CardOptions
): boolean {
return (
Boolean(itemParentThumbItemId) && Boolean(cardOptions.inheritThumb)
);
}
function shouldShowAlbumPrimaryImageTag(item: ItemDto): boolean {
return Boolean(item.AlbumId) && Boolean(item.AlbumPrimaryImageTag);
}
function shouldShowPreferThumb(itemType: ItemKind, cardOptions: CardOptions): boolean {
return Boolean(cardOptions.preferThumb) && !(itemType === ItemKind.Program || itemType === ItemKind.Episode);
}
function getCardImageInfo(
item: ItemDto,
cardOptions: CardOptions,
shape: CardShape | undefined
) {
const width = cardOptions.width;
let height;
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
let forceName = false;
let imgTag;
let coverImage = false;
const uiAspect = getDesiredAspect(shape);
let imgType;
let itemId;
if (shouldShowPreferThumb(item.Type, cardOptions)) {
const preferThumbInfo = getPreferThumbInfo(item, cardOptions);
imgType = preferThumbInfo.imgType;
imgTag = preferThumbInfo.imgTag;
itemId = preferThumbInfo.itemId;
forceName = preferThumbInfo.forceName;
} else if (shouldShowPreferBanner(item.ImageTags?.Banner, cardOptions, shape)) {
imgType = ImageType.Banner;
imgTag = item.ImageTags?.Banner;
itemId = item.Id;
} else if (shouldShowPreferDisc(item.ImageTags?.Disc, cardOptions)) {
imgType = ImageType.Disc;
imgTag = item.ImageTags?.Disc;
itemId = item.Id;
} else if (cardOptions.preferLogo) {
const preferLogoInfo = getPreferLogoInfo(item);
imgType = preferLogoInfo.imgType;
imgTag = preferLogoInfo.imgType;
itemId = preferLogoInfo.itemId;
} else if (shouldShowParentThumbImageTag(item.ParentThumbItemId, cardOptions)) {
imgType = ImageType.Thumb;
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (shouldShowImageTagsPrimary(item)) {
imgType = ImageType.Primary;
imgTag = item.ImageTags?.Primary;
itemId = item.Id;
height = getCalculatedHeight(width, primaryImageAspectRatio);
forceName = isForceName(cardOptions);
coverImage = isCoverImage(primaryImageAspectRatio, uiAspect);
} else if (item.SeriesPrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.PrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.PrimaryImageTag;
itemId = item.PrimaryImageItemId;
height = getCalculatedHeight(width, primaryImageAspectRatio);
forceName = isForceName(cardOptions);
coverImage = isCoverImage(primaryImageAspectRatio, uiAspect);
} else if (item.ParentPrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
} else if (shouldShowAlbumPrimaryImageTag(item)) {
imgType = ImageType.Primary;
imgTag = item.AlbumPrimaryImageTag;
itemId = item.AlbumId;
height = getCalculatedHeight(width, primaryImageAspectRatio);
forceName = isForceName(cardOptions);
coverImage = isCoverImage(primaryImageAspectRatio, uiAspect);
} else if (shouldShowImageTagsThumb(item)) {
imgType = ImageType.Thumb;
imgTag = item.ImageTags?.Thumb;
itemId = item.Id;
} else if (item.BackdropImageTags?.length) {
imgType = ImageType.Backdrop;
imgTag = item.BackdropImageTags[0];
itemId = item.Id;
} else if (shouldShowSeriesThumbImageTag(item.SeriesThumbImageTag, cardOptions)) {
imgType = ImageType.Thumb;
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (
item.ParentBackdropImageTags?.length
&& cardOptions.inheritThumb !== false
) {
imgType = ImageType.Backdrop;
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
}
return {
imgType,
imgTag,
itemId,
width,
height,
forceName,
coverImage
};
}
interface UseCardImageUrlProps {
item: ItemDto;
cardOptions: CardOptions;
shape: CardShape | undefined;
}
function useCardImageUrl({ item, cardOptions, shape }: UseCardImageUrlProps) {
const { api } = useApi();
const imgInfo = getCardImageInfo(item, cardOptions, shape);
let width = imgInfo.width;
let height = imgInfo.height;
const imgTag = imgInfo.imgTag;
const imgType = imgInfo.imgType;
const itemId = imgInfo.itemId;
const ratio = window.devicePixelRatio || 1;
let imgUrl;
let blurhash;
if (api && imgTag && imgType && itemId) {
if (width) {
width = Math.round(width * ratio);
}
if (height) {
height = Math.round(height * ratio);
}
imgUrl = getImageApi(api).getItemImageUrlById(itemId, imgType, {
quality: 96,
fillWidth: width,
fillHeight: height,
tag: imgTag
});
blurhash = item?.ImageBlurHashes?.[imgType]?.[imgTag];
}
return {
imgUrl: imgUrl,
blurhash: blurhash,
forceName: imgInfo.forceName,
coverImage: imgInfo.coverImage
};
}
export default useCardImageUrl;
+3 -157
View File
@@ -16,6 +16,7 @@ import globalize from 'lib/globalize';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import { getBackdropShape, getPortraitShape, getSquareShape } from 'utils/card';
import { getItemTypeIcon, getLibraryIcon } from 'utils/image';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import focusManager from '../focusManager';
import imageLoader from '../images/imageLoader';
@@ -41,6 +42,7 @@ import {
resolveCardImageContainerCssClasses,
resolveMixedShapeByAspectRatio
} from './cardBuilderUtils';
import { getCardImageUrl } from './utils/url';
const enableFocusTransform = !browser.slow && !browser.edge;
@@ -251,162 +253,6 @@ function buildCardsHtmlInternal(items, options) {
return html;
}
/**
* @typedef {Object} CardImageUrl
* @property {string} imgUrl - Image URL.
* @property {string} blurhash - Image blurhash.
* @property {boolean} forceName - Force name.
* @property {boolean} coverImage - Use cover style.
*/
/** Get the URL of the card's image.
* @param {Object} item - Item for which to generate a card.
* @param {Object} apiClient - API client object.
* @param {Object} options - Options of the card.
* @param {string} shape - Shape of the desired image.
* @returns {CardImageUrl} Object representing the URL of the card's image.
*/
export function getCardImageUrl(item, apiClient, options, shape) {
item = item.ProgramInfo || item;
const width = options.width;
let height = null;
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
let forceName = false;
let imgUrl = null;
let imgTag = null;
let coverImage = false;
const uiAspect = getDesiredAspect(shape);
let imgType = null;
let itemId = null;
/* eslint-disable sonarjs/no-duplicated-branches */
if (options.preferThumb && item.ImageTags?.Thumb) {
imgType = 'Thumb';
imgTag = item.ImageTags.Thumb;
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags?.Banner) {
imgType = 'Banner';
imgTag = item.ImageTags.Banner;
} else if (options.preferDisc && item.ImageTags?.Disc) {
imgType = 'Disc';
imgTag = item.ImageTags.Disc;
} else if (options.preferLogo && item.ImageTags?.Logo) {
imgType = 'Logo';
imgTag = item.ImageTags.Logo;
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
imgType = 'Logo';
imgTag = item.ParentLogoImageTag;
itemId = item.ParentLogoItemId;
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgType = 'Thumb';
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
imgType = 'Thumb';
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (options.preferThumb && item.BackdropImageTags?.length) {
imgType = 'Backdrop';
imgTag = item.BackdropImageTags[0];
forceName = true;
} else if (options.preferThumb && item.ParentBackdropImageTags?.length && options.inheritThumb !== false && item.Type === 'Episode') {
imgType = 'Backdrop';
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
} else if (item.ImageTags?.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) {
imgType = 'Primary';
imgTag = item.ImageTags.Primary;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
if (options.preferThumb && options.showTitle !== false) {
forceName = true;
}
if (primaryImageAspectRatio && uiAspect) {
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
} else if (item.SeriesPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.PrimaryImageTag) {
imgType = 'Primary';
imgTag = item.PrimaryImageTag;
itemId = item.PrimaryImageItemId;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
if (options.preferThumb && options.showTitle !== false) {
forceName = true;
}
if (primaryImageAspectRatio && uiAspect) {
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
} else if (item.ParentPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.AlbumPrimaryImageTag;
itemId = item.AlbumId;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
if (primaryImageAspectRatio && uiAspect) {
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
} else if (item.Type === 'Season' && item.ImageTags?.Thumb) {
imgType = 'Thumb';
imgTag = item.ImageTags.Thumb;
} else if (item.BackdropImageTags?.length) {
imgType = 'Backdrop';
imgTag = item.BackdropImageTags[0];
} else if (item.ImageTags?.Thumb) {
imgType = 'Thumb';
imgTag = item.ImageTags.Thumb;
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgType = 'Thumb';
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
imgType = 'Thumb';
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (item.ParentBackdropImageTags?.length && options.inheritThumb !== false) {
imgType = 'Backdrop';
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
}
/* eslint-enable sonarjs/no-duplicated-branches */
if (!itemId) {
itemId = item.Id;
}
if (imgTag && imgType) {
// TODO: This place is a mess. Could do with a good spring cleaning.
if (!height && width && uiAspect) {
height = width / uiAspect;
}
imgUrl = apiClient.getScaledImageUrl(itemId, {
type: imgType,
fillHeight: height,
fillWidth: width,
quality: 96,
tag: imgTag
});
}
const blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {};
return {
imgUrl: imgUrl,
blurhash: blurHashes[imgType]?.[imgTag],
forceName: forceName,
coverImage: coverImage
};
}
/**
* Generates the HTML markup for a card's text.
* @param {Array} lines - Array containing the text lines.
@@ -900,7 +746,7 @@ function buildCard(index, item, apiClient, options) {
// TODO move card creation code to Card component
const imgInfo = getCardImageUrl(item, apiClient, options, shape);
const imgInfo = getCardImageUrl({ api: toApi(apiClient), item, options, shape });
const imgUrl = imgInfo.imgUrl;
const blurhash = imgInfo.blurhash;
const forceName = imgInfo.forceName;
+6 -4
View File
@@ -4,8 +4,10 @@ import type { ApiClient } from 'jellyfin-apiclient';
import type { CardOptions } from 'types/cardOptions';
import { CardShape } from 'utils/card';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import { getCardImageUrl, getDefaultText } from './cardBuilder';
import { getDefaultText } from './cardBuilder';
import { getCardImageUrl } from './utils/url';
/**
* Builds an html string for a basic image only card.
@@ -28,12 +30,12 @@ export function buildCardImage(
}
}
const image = getCardImageUrl(
const image = getCardImageUrl({
api: toApi(apiClient),
item,
apiClient,
options,
shape
);
});
if (!image) return '';
+171
View File
@@ -0,0 +1,171 @@
import { Api } from '@jellyfin/sdk';
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
import { getImageApi } from '@jellyfin/sdk/lib/utils/api/image-api';
import { ItemDto } from 'types/base/models/item-dto';
import { CardOptions } from 'types/cardOptions';
import { CardShape } from 'utils/card';
import { getDesiredAspect } from '../cardBuilderUtils';
interface CardImageUrlParams {
api?: Api;
item: ItemDto;
options: CardOptions;
shape?: CardShape;
}
// eslint-disable-next-line sonarjs/cognitive-complexity
export function getCardImageUrl({
api,
item,
options,
shape
}: CardImageUrlParams) {
if (!api) {
throw new Error('API instance is required to get card image URL');
}
item = item.ProgramInfo || item;
const width = options.width;
let height: number | undefined;
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
let forceName = false;
let imgUrl: string | undefined;
let imgTag = null;
let coverImage = false;
const uiAspect = getDesiredAspect(shape);
let imgType: ImageType | undefined;
let itemId = null;
/* eslint-disable sonarjs/no-duplicated-branches */
if (options.preferThumb && item.ImageTags?.Thumb) {
imgType = ImageType.Thumb;
imgTag = item.ImageTags.Thumb;
} else if ((options.preferBanner || shape === CardShape.Banner) && item.ImageTags?.Banner) {
imgType = ImageType.Banner;
imgTag = item.ImageTags.Banner;
} else if (options.preferDisc && item.ImageTags?.Disc) {
imgType = ImageType.Disc;
imgTag = item.ImageTags.Disc;
} else if (options.preferLogo && item.ImageTags?.Logo) {
imgType = ImageType.Logo;
imgTag = item.ImageTags.Logo;
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
imgType = ImageType.Logo;
imgTag = item.ParentLogoImageTag;
itemId = item.ParentLogoItemId;
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgType = ImageType.Thumb;
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
imgType = ImageType.Thumb;
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (options.preferThumb && item.BackdropImageTags?.length) {
imgType = ImageType.Backdrop;
imgTag = item.BackdropImageTags[0];
forceName = true;
} else if (options.preferThumb && item.ParentBackdropImageTags?.length && options.inheritThumb !== false && item.Type === 'Episode') {
imgType = ImageType.Backdrop;
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
} else if (item.ImageTags?.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) {
imgType = ImageType.Primary;
imgTag = item.ImageTags.Primary;
height = width && primaryImageAspectRatio ? (width / primaryImageAspectRatio) : undefined;
if (options.preferThumb && options.showTitle !== false) {
forceName = true;
}
if (primaryImageAspectRatio && uiAspect) {
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
} else if (item.SeriesPrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.PrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.PrimaryImageTag;
itemId = item.PrimaryImageItemId;
height = width && primaryImageAspectRatio ? (width / primaryImageAspectRatio) : undefined;
if (options.preferThumb && options.showTitle !== false) {
forceName = true;
}
if (primaryImageAspectRatio && uiAspect) {
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
} else if (item.ParentPrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
imgType = ImageType.Primary;
imgTag = item.AlbumPrimaryImageTag;
itemId = item.AlbumId;
height = width && primaryImageAspectRatio ? (width / primaryImageAspectRatio) : undefined;
if (primaryImageAspectRatio && uiAspect) {
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
} else if (item.Type === 'Season' && item.ImageTags?.Thumb) {
imgType = ImageType.Thumb;
imgTag = item.ImageTags.Thumb;
} else if (item.BackdropImageTags?.length) {
imgType = ImageType.Backdrop;
imgTag = item.BackdropImageTags[0];
} else if (item.ImageTags?.Thumb) {
imgType = ImageType.Thumb;
imgTag = item.ImageTags.Thumb;
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgType = ImageType.Thumb;
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
imgType = ImageType.Thumb;
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (item.ParentBackdropImageTags?.length && options.inheritThumb !== false) {
imgType = ImageType.Backdrop;
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
}
/* eslint-enable sonarjs/no-duplicated-branches */
if (!itemId) {
itemId = item.Id;
}
if (itemId && imgTag && imgType) {
if (!height && width && uiAspect) {
height = width / uiAspect;
}
imgUrl = getImageApi(api).getItemImageUrlById(
itemId,
imgType,
{
// Dimensions must be rounded or the API will reject the request
fillHeight: height ? Math.round(height) : undefined,
fillWidth: width ? Math.round(width) : undefined,
quality: 96,
tag: imgTag
}
);
}
const blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {};
return {
imgUrl,
blurhash: (imgType && imgTag) ? blurHashes[imgType]?.[imgTag] : undefined,
forceName,
coverImage
};
}