2023-10-04 23:14:14 +03:00
|
|
|
import type { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
2024-02-28 22:47:36 +03:00
|
|
|
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
2023-10-04 23:14:14 +03:00
|
|
|
import { ImageType } from '@jellyfin/sdk/lib/generated-client';
|
|
|
|
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
2024-02-28 22:47:36 +03:00
|
|
|
import React, { type FC, useCallback } from 'react';
|
2023-10-04 23:14:14 +03:00
|
|
|
import Box from '@mui/material/Box';
|
2024-01-12 21:08:06 +03:00
|
|
|
import classNames from 'classnames';
|
2023-10-04 23:14:14 +03:00
|
|
|
import { useLocalStorage } from 'hooks/useLocalStorage';
|
|
|
|
import { useGetItem, useGetItemsViewByType } from 'hooks/useFetchItems';
|
|
|
|
import { getDefaultLibraryViewSettings, getSettingsKey } from 'utils/items';
|
2024-02-28 22:47:36 +03:00
|
|
|
import { CardShape } from 'utils/card';
|
2023-10-04 23:14:14 +03:00
|
|
|
import Loading from 'components/loading/LoadingComponent';
|
|
|
|
import { playbackManager } from 'components/playback/playbackmanager';
|
2023-10-13 02:07:49 +03:00
|
|
|
import ItemsContainer from 'elements/emby-itemscontainer/ItemsContainer';
|
2023-10-04 23:14:14 +03:00
|
|
|
import AlphabetPicker from './AlphabetPicker';
|
|
|
|
import FilterButton from './filter/FilterButton';
|
|
|
|
import NewCollectionButton from './NewCollectionButton';
|
|
|
|
import Pagination from './Pagination';
|
|
|
|
import PlayAllButton from './PlayAllButton';
|
|
|
|
import QueueButton from './QueueButton';
|
|
|
|
import ShuffleButton from './ShuffleButton';
|
|
|
|
import SortButton from './SortButton';
|
|
|
|
import GridListViewButton from './GridListViewButton';
|
2024-01-31 04:33:19 +03:00
|
|
|
import NoItemsMessage from 'components/common/NoItemsMessage';
|
|
|
|
import Lists from 'components/listview/List/Lists';
|
|
|
|
import Cards from 'components/cardbuilder/Card/Cards';
|
2023-10-04 23:14:14 +03:00
|
|
|
import { LibraryTab } from 'types/libraryTab';
|
2024-02-28 22:47:36 +03:00
|
|
|
import { type LibraryViewSettings, type ParentId, ViewMode } from 'types/library';
|
2024-01-31 04:33:19 +03:00
|
|
|
import type { CardOptions } from 'types/cardOptions';
|
|
|
|
import type { ListOptions } from 'types/listOptions';
|
2023-10-04 23:14:14 +03:00
|
|
|
|
|
|
|
interface ItemsViewProps {
|
|
|
|
viewType: LibraryTab;
|
|
|
|
parentId: ParentId;
|
|
|
|
itemType: BaseItemKind[];
|
|
|
|
collectionType?: CollectionType;
|
2024-01-12 21:08:06 +03:00
|
|
|
isPaginationEnabled?: boolean;
|
2023-10-04 23:14:14 +03:00
|
|
|
isBtnPlayAllEnabled?: boolean;
|
|
|
|
isBtnQueueEnabled?: boolean;
|
|
|
|
isBtnShuffleEnabled?: boolean;
|
|
|
|
isBtnSortEnabled?: boolean;
|
|
|
|
isBtnFilterEnabled?: boolean;
|
|
|
|
isBtnNewCollectionEnabled?: boolean;
|
|
|
|
isBtnGridListEnabled?: boolean;
|
|
|
|
isAlphabetPickerEnabled?: boolean;
|
|
|
|
noItemsMessage: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ItemsView: FC<ItemsViewProps> = ({
|
|
|
|
viewType,
|
|
|
|
parentId,
|
|
|
|
collectionType,
|
2024-01-12 21:08:06 +03:00
|
|
|
isPaginationEnabled = true,
|
2023-10-04 23:14:14 +03:00
|
|
|
isBtnPlayAllEnabled = false,
|
|
|
|
isBtnQueueEnabled = false,
|
|
|
|
isBtnShuffleEnabled = false,
|
|
|
|
isBtnSortEnabled = true,
|
|
|
|
isBtnFilterEnabled = true,
|
|
|
|
isBtnNewCollectionEnabled = false,
|
|
|
|
isBtnGridListEnabled = true,
|
|
|
|
isAlphabetPickerEnabled = true,
|
|
|
|
itemType,
|
|
|
|
noItemsMessage
|
|
|
|
}) => {
|
|
|
|
const [libraryViewSettings, setLibraryViewSettings] =
|
|
|
|
useLocalStorage<LibraryViewSettings>(
|
|
|
|
getSettingsKey(viewType, parentId),
|
|
|
|
getDefaultLibraryViewSettings(viewType)
|
|
|
|
);
|
|
|
|
|
|
|
|
const {
|
|
|
|
isLoading,
|
|
|
|
data: itemsResult,
|
2023-10-13 02:07:49 +03:00
|
|
|
isPreviousData,
|
|
|
|
refetch
|
2023-10-04 23:14:14 +03:00
|
|
|
} = useGetItemsViewByType(
|
|
|
|
viewType,
|
|
|
|
parentId,
|
|
|
|
itemType,
|
|
|
|
libraryViewSettings
|
|
|
|
);
|
|
|
|
const { data: item } = useGetItem(parentId);
|
|
|
|
|
2023-10-28 22:10:46 +03:00
|
|
|
const getListOptions = useCallback(() => {
|
|
|
|
const listOptions: ListOptions = {
|
|
|
|
items: itemsResult?.Items ?? [],
|
|
|
|
context: collectionType
|
|
|
|
};
|
|
|
|
|
|
|
|
if (viewType === LibraryTab.Songs) {
|
|
|
|
listOptions.showParentTitle = true;
|
|
|
|
listOptions.action = 'playallfromhere';
|
|
|
|
listOptions.smallIcon = true;
|
|
|
|
listOptions.artist = true;
|
|
|
|
listOptions.addToListButton = true;
|
|
|
|
} else if (viewType === LibraryTab.Albums) {
|
|
|
|
listOptions.sortBy = libraryViewSettings.SortBy;
|
|
|
|
listOptions.addToListButton = true;
|
|
|
|
} else if (viewType === LibraryTab.Episodes) {
|
|
|
|
listOptions.showParentTitle = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return listOptions;
|
|
|
|
}, [itemsResult?.Items, collectionType, viewType, libraryViewSettings.SortBy]);
|
|
|
|
|
2023-10-04 23:14:14 +03:00
|
|
|
const getCardOptions = useCallback(() => {
|
|
|
|
let shape;
|
|
|
|
let preferThumb;
|
|
|
|
let preferDisc;
|
|
|
|
let preferLogo;
|
|
|
|
|
|
|
|
if (libraryViewSettings.ImageType === ImageType.Banner) {
|
2024-02-28 22:47:36 +03:00
|
|
|
shape = CardShape.Banner;
|
2023-10-04 23:14:14 +03:00
|
|
|
} else if (libraryViewSettings.ImageType === ImageType.Disc) {
|
2024-02-28 22:47:36 +03:00
|
|
|
shape = CardShape.Square;
|
2023-10-04 23:14:14 +03:00
|
|
|
preferDisc = true;
|
|
|
|
} else if (libraryViewSettings.ImageType === ImageType.Logo) {
|
2024-02-28 22:47:36 +03:00
|
|
|
shape = CardShape.Backdrop;
|
2023-10-04 23:14:14 +03:00
|
|
|
preferLogo = true;
|
|
|
|
} else if (libraryViewSettings.ImageType === ImageType.Thumb) {
|
2024-02-28 22:47:36 +03:00
|
|
|
shape = CardShape.Backdrop;
|
2023-10-04 23:14:14 +03:00
|
|
|
preferThumb = true;
|
|
|
|
} else {
|
2024-02-28 22:47:36 +03:00
|
|
|
shape = CardShape.Auto;
|
2023-10-04 23:14:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const cardOptions: CardOptions = {
|
|
|
|
shape: shape,
|
|
|
|
showTitle: libraryViewSettings.ShowTitle,
|
|
|
|
showYear: libraryViewSettings.ShowYear,
|
|
|
|
cardLayout: libraryViewSettings.CardLayout,
|
|
|
|
centerText: true,
|
|
|
|
context: collectionType,
|
|
|
|
coverImage: true,
|
|
|
|
preferThumb: preferThumb,
|
|
|
|
preferDisc: preferDisc,
|
|
|
|
preferLogo: preferLogo,
|
2024-01-31 04:33:19 +03:00
|
|
|
overlayText: !libraryViewSettings.ShowTitle,
|
|
|
|
imageType: libraryViewSettings.ImageType,
|
|
|
|
queryKey: ['ItemsViewByType']
|
2023-10-04 23:14:14 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
if (
|
|
|
|
viewType === LibraryTab.Songs
|
|
|
|
|| viewType === LibraryTab.Albums
|
|
|
|
|| viewType === LibraryTab.Episodes
|
|
|
|
) {
|
|
|
|
cardOptions.showParentTitle = libraryViewSettings.ShowTitle;
|
2024-01-31 04:33:19 +03:00
|
|
|
cardOptions.overlayPlayButton = true;
|
2023-10-04 23:14:14 +03:00
|
|
|
} else if (viewType === LibraryTab.Artists) {
|
2023-10-28 22:10:46 +03:00
|
|
|
cardOptions.lines = 1;
|
2024-01-12 21:08:06 +03:00
|
|
|
cardOptions.showYear = false;
|
2024-01-31 04:33:19 +03:00
|
|
|
cardOptions.overlayPlayButton = true;
|
2024-01-12 21:08:06 +03:00
|
|
|
} else if (viewType === LibraryTab.Channels) {
|
2024-02-28 22:47:36 +03:00
|
|
|
cardOptions.shape = CardShape.Square;
|
2024-01-12 21:08:06 +03:00
|
|
|
cardOptions.showDetailsMenu = true;
|
|
|
|
cardOptions.showCurrentProgram = true;
|
|
|
|
cardOptions.showCurrentProgramTime = true;
|
|
|
|
} else if (viewType === LibraryTab.SeriesTimers) {
|
2024-02-28 22:47:36 +03:00
|
|
|
cardOptions.shape = CardShape.Backdrop;
|
2024-01-12 21:08:06 +03:00
|
|
|
cardOptions.showSeriesTimerTime = true;
|
|
|
|
cardOptions.showSeriesTimerChannel = true;
|
2024-01-31 04:33:19 +03:00
|
|
|
cardOptions.overlayMoreButton = true;
|
2024-01-12 21:08:06 +03:00
|
|
|
cardOptions.lines = 3;
|
2024-01-31 04:33:19 +03:00
|
|
|
} else if (viewType === LibraryTab.Movies) {
|
|
|
|
cardOptions.overlayPlayButton = true;
|
|
|
|
} else if (viewType === LibraryTab.Series || viewType === LibraryTab.Networks) {
|
|
|
|
cardOptions.overlayMoreButton = true;
|
2023-10-04 23:14:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return cardOptions;
|
|
|
|
}, [
|
|
|
|
libraryViewSettings.ShowTitle,
|
|
|
|
libraryViewSettings.ImageType,
|
|
|
|
libraryViewSettings.ShowYear,
|
|
|
|
libraryViewSettings.CardLayout,
|
|
|
|
collectionType,
|
|
|
|
viewType
|
|
|
|
]);
|
|
|
|
|
2024-01-31 04:33:19 +03:00
|
|
|
const getItems = useCallback(() => {
|
|
|
|
if (!itemsResult?.Items?.length) {
|
|
|
|
return <NoItemsMessage noItemsMessage={noItemsMessage} />;
|
|
|
|
}
|
2023-10-04 23:14:14 +03:00
|
|
|
|
|
|
|
if (libraryViewSettings.ViewMode === ViewMode.ListView) {
|
2024-01-31 04:33:19 +03:00
|
|
|
return (
|
|
|
|
<Lists
|
|
|
|
items={itemsResult?.Items ?? []}
|
|
|
|
listOptions={getListOptions()}
|
|
|
|
/>
|
2023-10-04 23:14:14 +03:00
|
|
|
);
|
|
|
|
}
|
2024-01-31 04:33:19 +03:00
|
|
|
return (
|
|
|
|
<Cards
|
|
|
|
items={itemsResult?.Items ?? []}
|
|
|
|
cardOptions={getCardOptions()}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}, [
|
|
|
|
libraryViewSettings.ViewMode,
|
|
|
|
itemsResult?.Items,
|
|
|
|
getListOptions,
|
|
|
|
getCardOptions,
|
|
|
|
noItemsMessage
|
|
|
|
]);
|
2023-10-04 23:14:14 +03:00
|
|
|
|
|
|
|
const totalRecordCount = itemsResult?.TotalRecordCount ?? 0;
|
|
|
|
const items = itemsResult?.Items ?? [];
|
|
|
|
const hasFilters = Object.values(libraryViewSettings.Filters ?? {}).some(
|
|
|
|
(filter) => !!filter
|
|
|
|
);
|
|
|
|
const hasSortName = libraryViewSettings.SortBy.includes(
|
|
|
|
ItemSortBy.SortName
|
|
|
|
);
|
|
|
|
|
2024-01-12 21:08:06 +03:00
|
|
|
const itemsContainerClass = classNames(
|
|
|
|
'centered padded-left padded-right padded-right-withalphapicker',
|
|
|
|
libraryViewSettings.ViewMode === ViewMode.ListView ?
|
|
|
|
'vertical-list' :
|
|
|
|
'vertical-wrap'
|
|
|
|
);
|
2023-10-04 23:14:14 +03:00
|
|
|
return (
|
|
|
|
<Box>
|
|
|
|
<Box className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
|
2024-01-12 21:08:06 +03:00
|
|
|
{isPaginationEnabled && (
|
|
|
|
<Pagination
|
|
|
|
totalRecordCount={totalRecordCount}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
isPreviousData={isPreviousData}
|
|
|
|
setLibraryViewSettings={setLibraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
2023-10-04 23:14:14 +03:00
|
|
|
|
|
|
|
{isBtnPlayAllEnabled && (
|
|
|
|
<PlayAllButton
|
|
|
|
item={item}
|
|
|
|
items={items}
|
|
|
|
viewType={viewType}
|
|
|
|
hasFilters={hasFilters}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{isBtnQueueEnabled
|
|
|
|
&& item
|
|
|
|
&& playbackManager.canQueue(item) && (
|
|
|
|
<QueueButton
|
|
|
|
item={item}
|
|
|
|
items={items}
|
|
|
|
hasFilters={hasFilters}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{isBtnShuffleEnabled && totalRecordCount > 1 && (
|
|
|
|
<ShuffleButton
|
|
|
|
item={item}
|
|
|
|
items={items}
|
|
|
|
viewType={viewType}
|
|
|
|
hasFilters={hasFilters}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{isBtnSortEnabled && (
|
|
|
|
<SortButton
|
|
|
|
viewType={viewType}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
setLibraryViewSettings={setLibraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{isBtnFilterEnabled && (
|
|
|
|
<FilterButton
|
|
|
|
parentId={parentId}
|
|
|
|
itemType={itemType}
|
|
|
|
viewType={viewType}
|
|
|
|
hasFilters={hasFilters}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
setLibraryViewSettings={setLibraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{isBtnNewCollectionEnabled && <NewCollectionButton />}
|
|
|
|
{isBtnGridListEnabled && (
|
|
|
|
<GridListViewButton
|
|
|
|
viewType={viewType}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
setLibraryViewSettings={setLibraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</Box>
|
|
|
|
|
|
|
|
{isAlphabetPickerEnabled && hasSortName && (
|
|
|
|
<AlphabetPicker
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
setLibraryViewSettings={setLibraryViewSettings}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{isLoading ? (
|
|
|
|
<Loading />
|
|
|
|
) : (
|
|
|
|
<ItemsContainer
|
2024-01-12 21:08:06 +03:00
|
|
|
className={itemsContainerClass}
|
2023-10-13 02:07:49 +03:00
|
|
|
parentId={parentId}
|
|
|
|
reloadItems={refetch}
|
2024-01-31 04:33:19 +03:00
|
|
|
queryKey={['ItemsViewByType']}
|
|
|
|
>
|
|
|
|
{getItems()}
|
|
|
|
</ItemsContainer>
|
2023-10-04 23:14:14 +03:00
|
|
|
)}
|
|
|
|
|
2024-01-12 21:08:06 +03:00
|
|
|
{isPaginationEnabled && (
|
|
|
|
<Box className='flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x'>
|
|
|
|
<Pagination
|
|
|
|
totalRecordCount={totalRecordCount}
|
|
|
|
libraryViewSettings={libraryViewSettings}
|
|
|
|
isPreviousData={isPreviousData}
|
|
|
|
setLibraryViewSettings={setLibraryViewSettings}
|
|
|
|
/>
|
|
|
|
</Box>
|
|
|
|
)}
|
2023-10-04 23:14:14 +03:00
|
|
|
</Box>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default ItemsView;
|