import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto'; import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind'; import type { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto'; import escapeHtml from 'escape-html'; import type { ApiClient } from 'jellyfin-apiclient'; import layoutManager from 'components/layoutManager'; import { appRouter } from 'components/router/appRouter'; import globalize from 'scripts/globalize'; import ServerConnections from 'components/ServerConnections'; import cardBuilder from 'components/cardbuilder/cardBuilder'; import { getBackdropShape, getPortraitShape, getSquareShape } from 'utils/card'; import type { SectionContainerElement, SectionOptions } from './section'; function getFetchLatestItemsFn( serverId: string, parentId: string | undefined, collectionType: string | null | undefined, { enableOverflow }: SectionOptions ) { return function () { const apiClient = ServerConnections.getApiClient(serverId); let limit = 16; if (enableOverflow) { if (collectionType === 'music') { limit = 30; } } else if (collectionType === 'tvshows') { limit = 5; } else if (collectionType === 'music') { limit = 9; } else { limit = 8; } const options = { Limit: limit, Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path', ImageTypeLimit: 1, EnableImageTypes: 'Primary,Backdrop,Thumb', ParentId: parentId }; return apiClient.getLatestItems(options); }; } function getLatestItemsHtmlFn( itemType: BaseItemKind | undefined, viewType: string | null | undefined, { enableOverflow }: SectionOptions ) { return function (items: BaseItemDto[]) { const cardLayout = false; let shape; if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') { shape = getPortraitShape(enableOverflow); } else if (viewType === 'music' || viewType === 'homevideos') { shape = getSquareShape(enableOverflow); } else { shape = getBackdropShape(enableOverflow); } return cardBuilder.getCardsHtml({ items: items, shape: shape, preferThumb: viewType !== 'movies' && viewType !== 'tvshows' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null, showUnplayedIndicator: false, showChildCountIndicator: true, context: 'home', overlayText: false, centerText: !cardLayout, overlayPlayButton: viewType !== 'photos', allowBottomPadding: !enableOverflow && !cardLayout, cardLayout: cardLayout, showTitle: viewType !== 'photos', showYear: viewType === 'movies' || viewType === 'tvshows' || !viewType, showParentTitle: viewType === 'music' || viewType === 'tvshows' || !viewType || (cardLayout && (viewType === 'tvshows')), lines: 2 }); }; } function renderLatestSection( elem: HTMLElement, apiClient: ApiClient, user: UserDto, parent: BaseItemDto, options: SectionOptions ) { let html = ''; html += '
'; if (!layoutManager.tv) { html += ''; html += '

'; html += globalize.translate('LatestFromLibrary', escapeHtml(parent.Name)); html += '

'; html += ''; html += '
'; } else { html += '

' + globalize.translate('LatestFromLibrary', escapeHtml(parent.Name)) + '

'; } html += '
'; if (options.enableOverflow) { html += '
'; html += '
'; } else { html += '
'; } if (options.enableOverflow) { html += '
'; } html += '
'; elem.innerHTML = html; const itemsContainer: SectionContainerElement | null = elem.querySelector('.itemsContainer'); if (!itemsContainer) return; itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType, options); itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType, options); itemsContainer.parentContainer = elem; } export function loadRecentlyAdded( elem: HTMLElement, apiClient: ApiClient, user: UserDto, userViews: BaseItemDto[], options: SectionOptions ) { elem.classList.remove('verticalSection'); const excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels']; const userExcludeItems = user.Configuration?.LatestItemsExcludes ?? []; userViews.forEach(item => { if (!item.Id || userExcludeItems.indexOf(item.Id) !== -1) { return; } if (!item.CollectionType || excludeViewTypes.indexOf(item.CollectionType) !== -1) { return; } const frag = document.createElement('div'); frag.classList.add('verticalSection'); frag.classList.add('hide'); elem.appendChild(frag); renderLatestSection(frag, apiClient, user, item, options); }); }