jellyfish-web/src/components/common/GenresItemsContainer.tsx

160 lines
6.2 KiB
TypeScript
Raw Normal View History

2022-08-06 02:38:27 +03:00
import '../../elements/emby-button/emby-button';
import '../../elements/emby-itemscontainer/emby-itemscontainer';
import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client';
2022-08-06 02:38:27 +03:00
import escapeHTML from 'escape-html';
2022-10-02 19:07:42 +03:00
import React, { FC, useCallback, useEffect, useRef } from 'react';
2022-08-06 01:36:13 +03:00
2022-10-27 00:59:46 +03:00
import { appRouter } from '../appRouter';
import cardBuilder from '../cardbuilder/cardBuilder';
import layoutManager from '../layoutManager';
import lazyLoader from '../lazyLoader/lazyLoaderIntersectionObserver';
2022-08-06 02:38:27 +03:00
import globalize from '../../scripts/globalize';
2022-08-06 01:36:13 +03:00
2022-10-14 02:07:54 +03:00
interface GenresItemsContainerProps {
2022-08-06 01:36:13 +03:00
topParentId?: string | null;
getCurrentViewStyle: () => string;
itemsResult?: BaseItemDtoQueryResult;
}
2022-10-14 02:07:54 +03:00
const GenresItemsContainer: FC<GenresItemsContainerProps> = ({ topParentId, getCurrentViewStyle, itemsResult = {} }) => {
2022-08-06 01:36:13 +03:00
const element = useRef<HTMLDivElement>(null);
const enableScrollX = useCallback(() => {
return !layoutManager.desktop;
}, []);
const getPortraitShape = useCallback(() => {
return enableScrollX() ? 'overflowPortrait' : 'portrait';
}, [enableScrollX]);
const getThumbShape = useCallback(() => {
return enableScrollX() ? 'overflowBackdrop' : 'backdrop';
}, [enableScrollX]);
const fillItemsContainer = useCallback((entry) => {
const elem = entry.target;
const id = elem.getAttribute('data-id');
const viewStyle = getCurrentViewStyle();
let limit = viewStyle == 'Thumb' || viewStyle == 'ThumbCard' ? 5 : 9;
if (enableScrollX()) {
limit = 10;
}
const enableImageTypes = viewStyle == 'Thumb' || viewStyle == 'ThumbCard' ? 'Primary,Backdrop,Thumb' : 'Primary';
const query = {
SortBy: 'Random',
SortOrder: 'Ascending',
IncludeItemTypes: 'Movie',
Recursive: true,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: enableImageTypes,
Limit: limit,
GenreIds: id,
EnableTotalRecordCount: false,
ParentId: topParentId
};
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
const items = result.Items || [];
if (viewStyle == 'Thumb') {
cardBuilder.buildCards(items, {
itemsContainer: elem,
shape: getThumbShape(),
preferThumb: true,
showTitle: true,
scalable: true,
centerText: true,
overlayMoreButton: true,
allowBottomPadding: false
});
} else if (viewStyle == 'ThumbCard') {
cardBuilder.buildCards(items, {
itemsContainer: elem,
shape: getThumbShape(),
preferThumb: true,
showTitle: true,
scalable: true,
centerText: false,
cardLayout: true,
showYear: true
});
} else if (viewStyle == 'PosterCard') {
cardBuilder.buildCards(items, {
itemsContainer: elem,
shape: getPortraitShape(),
showTitle: true,
scalable: true,
centerText: false,
cardLayout: true,
showYear: true
});
} else if (viewStyle == 'Poster') {
cardBuilder.buildCards(items, {
itemsContainer: elem,
shape: getPortraitShape(),
scalable: true,
overlayMoreButton: true,
allowBottomPadding: true,
showTitle: true,
centerText: true,
showYear: true
});
}
});
}, [enableScrollX, getCurrentViewStyle, getPortraitShape, getThumbShape, topParentId]);
useEffect(() => {
const elem = element.current?.querySelector('#items') as HTMLDivElement;
let html = '';
const items = itemsResult.Items || [];
for (let i = 0, length = items.length; i < length; i++) {
const item = items[i];
html += '<div class="verticalSection">';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item, {
context: 'movies',
parentId: topParentId
}) + '" class="more button-flat button-flat-mini sectionTitleTextButton btnMoreFromGenre' + item.Id + '">';
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += escapeHTML(item.Name);
html += '</h2>';
html += '<span class="material-icons chevron_right" aria-hidden="true"></span>';
html += '</a>';
html += '</div>';
if (enableScrollX()) {
2022-08-21 03:09:22 +03:00
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x lazy" data-id="' + item.Id + '">';
2022-08-06 01:36:13 +03:00
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap lazy padded-left padded-right" data-id="' + item.Id + '">';
}
html += '</div>';
html += '</div>';
}
if (!itemsResult.Items?.length) {
html = '';
html += '<div class="noItemsMessage centerMessage">';
html += '<h1>' + globalize.translate('MessageNothingHere') + '</h1>';
html += '<p>' + globalize.translate('MessageNoGenresAvailable') + '</p>';
html += '</div>';
}
elem.innerHTML = html;
lazyLoader.lazyChildren(elem, fillItemsContainer);
2022-08-06 03:06:41 +03:00
}, [getCurrentViewStyle, itemsResult.Items, fillItemsContainer, topParentId, enableScrollX]);
2022-08-06 01:36:13 +03:00
return (
<div ref={element}>
<div id='items'/>
2022-08-06 01:36:13 +03:00
</div>
);
};
export default GenresItemsContainer;