mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Use enums CardShape & BaseItemKind,
Use type import for react FC, Remove escapeHTML Co-authored-by: Bill Thornton <thornbill@users.noreply.github.com>
This commit is contained in:
parent
11d013b07e
commit
8cbddba8fd
18 changed files with 102 additions and 82 deletions
|
@ -1,18 +1,17 @@
|
||||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
|
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
|
||||||
|
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
||||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
||||||
import { SortOrder } from '@jellyfin/sdk/lib/generated-client/models/sort-order';
|
import { SortOrder } from '@jellyfin/sdk/lib/generated-client/models/sort-order';
|
||||||
import escapeHTML from 'escape-html';
|
import React, { type FC } from 'react';
|
||||||
import React, { FC } from 'react';
|
|
||||||
|
|
||||||
import { useGetItems } from 'hooks/useFetchItems';
|
import { useGetItems } from 'hooks/useFetchItems';
|
||||||
import Loading from 'components/loading/LoadingComponent';
|
import Loading from 'components/loading/LoadingComponent';
|
||||||
import { appRouter } from 'components/router/appRouter';
|
import { appRouter } from 'components/router/appRouter';
|
||||||
import SectionContainer from './SectionContainer';
|
import SectionContainer from './SectionContainer';
|
||||||
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
import { CardShape } from 'utils/card';
|
||||||
import { ParentId } from 'types/library';
|
import type { ParentId } from 'types/library';
|
||||||
|
|
||||||
interface GenresSectionContainerProps {
|
interface GenresSectionContainerProps {
|
||||||
parentId: ParentId;
|
parentId: ParentId;
|
||||||
|
@ -60,7 +59,7 @@ const GenresSectionContainer: FC<GenresSectionContainerProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return <SectionContainer
|
return <SectionContainer
|
||||||
sectionTitle={escapeHTML(genre.Name)}
|
sectionTitle={genre.Name || ''}
|
||||||
items={itemsResult?.Items || []}
|
items={itemsResult?.Items || []}
|
||||||
url={getRouteUrl(genre)}
|
url={getRouteUrl(genre)}
|
||||||
cardOptions={{
|
cardOptions={{
|
||||||
|
@ -69,7 +68,7 @@ const GenresSectionContainer: FC<GenresSectionContainerProps> = ({
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
centerText: true,
|
centerText: true,
|
||||||
cardLayout: false,
|
cardLayout: false,
|
||||||
shape: collectionType === CollectionType.Music ? 'overflowSquare' : 'overflowPortrait',
|
shape: collectionType === CollectionType.Music ? CardShape.SquareOverflow : CardShape.PortraitOverflow,
|
||||||
showParentTitle: collectionType === CollectionType.Music,
|
showParentTitle: collectionType === CollectionType.Music,
|
||||||
showYear: collectionType !== CollectionType.Music
|
showYear: collectionType !== CollectionType.Music
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import type { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
import type { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
|
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
||||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client';
|
import { ImageType } from '@jellyfin/sdk/lib/generated-client';
|
||||||
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
||||||
import React, { FC, useCallback } from 'react';
|
import React, { type FC, useCallback } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useLocalStorage } from 'hooks/useLocalStorage';
|
import { useLocalStorage } from 'hooks/useLocalStorage';
|
||||||
import { useGetItem, useGetItemsViewByType } from 'hooks/useFetchItems';
|
import { useGetItem, useGetItemsViewByType } from 'hooks/useFetchItems';
|
||||||
import { getDefaultLibraryViewSettings, getSettingsKey } from 'utils/items';
|
import { getDefaultLibraryViewSettings, getSettingsKey } from 'utils/items';
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import Loading from 'components/loading/LoadingComponent';
|
import Loading from 'components/loading/LoadingComponent';
|
||||||
import { playbackManager } from 'components/playback/playbackmanager';
|
import { playbackManager } from 'components/playback/playbackmanager';
|
||||||
import ItemsContainer from 'elements/emby-itemscontainer/ItemsContainer';
|
import ItemsContainer from 'elements/emby-itemscontainer/ItemsContainer';
|
||||||
|
@ -22,10 +24,8 @@ import GridListViewButton from './GridListViewButton';
|
||||||
import NoItemsMessage from 'components/common/NoItemsMessage';
|
import NoItemsMessage from 'components/common/NoItemsMessage';
|
||||||
import Lists from 'components/listview/List/Lists';
|
import Lists from 'components/listview/List/Lists';
|
||||||
import Cards from 'components/cardbuilder/Card/Cards';
|
import Cards from 'components/cardbuilder/Card/Cards';
|
||||||
import { type LibraryViewSettings, type ParentId, ViewMode } from 'types/library';
|
|
||||||
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
|
||||||
import { LibraryTab } from 'types/libraryTab';
|
import { LibraryTab } from 'types/libraryTab';
|
||||||
|
import { type LibraryViewSettings, type ParentId, ViewMode } from 'types/library';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
import type { ListOptions } from 'types/listOptions';
|
import type { ListOptions } from 'types/listOptions';
|
||||||
|
|
||||||
|
@ -110,18 +110,18 @@ const ItemsView: FC<ItemsViewProps> = ({
|
||||||
let preferLogo;
|
let preferLogo;
|
||||||
|
|
||||||
if (libraryViewSettings.ImageType === ImageType.Banner) {
|
if (libraryViewSettings.ImageType === ImageType.Banner) {
|
||||||
shape = 'banner';
|
shape = CardShape.Banner;
|
||||||
} else if (libraryViewSettings.ImageType === ImageType.Disc) {
|
} else if (libraryViewSettings.ImageType === ImageType.Disc) {
|
||||||
shape = 'square';
|
shape = CardShape.Square;
|
||||||
preferDisc = true;
|
preferDisc = true;
|
||||||
} else if (libraryViewSettings.ImageType === ImageType.Logo) {
|
} else if (libraryViewSettings.ImageType === ImageType.Logo) {
|
||||||
shape = 'backdrop';
|
shape = CardShape.Backdrop;
|
||||||
preferLogo = true;
|
preferLogo = true;
|
||||||
} else if (libraryViewSettings.ImageType === ImageType.Thumb) {
|
} else if (libraryViewSettings.ImageType === ImageType.Thumb) {
|
||||||
shape = 'backdrop';
|
shape = CardShape.Backdrop;
|
||||||
preferThumb = true;
|
preferThumb = true;
|
||||||
} else {
|
} else {
|
||||||
shape = 'auto';
|
shape = CardShape.Auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardOptions: CardOptions = {
|
const cardOptions: CardOptions = {
|
||||||
|
@ -152,12 +152,12 @@ const ItemsView: FC<ItemsViewProps> = ({
|
||||||
cardOptions.showYear = false;
|
cardOptions.showYear = false;
|
||||||
cardOptions.overlayPlayButton = true;
|
cardOptions.overlayPlayButton = true;
|
||||||
} else if (viewType === LibraryTab.Channels) {
|
} else if (viewType === LibraryTab.Channels) {
|
||||||
cardOptions.shape = 'square';
|
cardOptions.shape = CardShape.Square;
|
||||||
cardOptions.showDetailsMenu = true;
|
cardOptions.showDetailsMenu = true;
|
||||||
cardOptions.showCurrentProgram = true;
|
cardOptions.showCurrentProgram = true;
|
||||||
cardOptions.showCurrentProgramTime = true;
|
cardOptions.showCurrentProgramTime = true;
|
||||||
} else if (viewType === LibraryTab.SeriesTimers) {
|
} else if (viewType === LibraryTab.SeriesTimers) {
|
||||||
cardOptions.shape = 'backdrop';
|
cardOptions.shape = CardShape.Backdrop;
|
||||||
cardOptions.showSeriesTimerTime = true;
|
cardOptions.showSeriesTimerTime = true;
|
||||||
cardOptions.showSeriesTimerChannel = true;
|
cardOptions.showSeriesTimerChannel = true;
|
||||||
cardOptions.overlayMoreButton = true;
|
cardOptions.overlayMoreButton = true;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import React, { FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import { useGetProgramsSectionsWithItems, useGetTimers } from 'hooks/useFetchItems';
|
import { useGetProgramsSectionsWithItems, useGetTimers } from 'hooks/useFetchItems';
|
||||||
import { appRouter } from 'components/router/appRouter';
|
import { appRouter } from 'components/router/appRouter';
|
||||||
import globalize from 'scripts/globalize';
|
import globalize from 'scripts/globalize';
|
||||||
import Loading from 'components/loading/LoadingComponent';
|
import Loading from 'components/loading/LoadingComponent';
|
||||||
import SectionContainer from './SectionContainer';
|
import SectionContainer from './SectionContainer';
|
||||||
import { ParentId } from 'types/library';
|
import { CardShape } from 'utils/card';
|
||||||
import { Section, SectionType } from 'types/sections';
|
import type { ParentId } from 'types/library';
|
||||||
|
import type { Section, SectionType } from 'types/sections';
|
||||||
|
|
||||||
interface ProgramsSectionViewProps {
|
interface ProgramsSectionViewProps {
|
||||||
parentId: ParentId;
|
parentId: ParentId;
|
||||||
|
@ -76,7 +77,7 @@ const ProgramsSectionView: FC<ProgramsSectionViewProps> = ({
|
||||||
items={group.timerInfo ?? []}
|
items={group.timerInfo ?? []}
|
||||||
cardOptions={{
|
cardOptions={{
|
||||||
queryKey: ['Timers'],
|
queryKey: ['Timers'],
|
||||||
shape: 'overflowBackdrop',
|
shape: CardShape.BackdropOverflow,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showParentTitleOrTitle: true,
|
showParentTitleOrTitle: true,
|
||||||
showAirTime: true,
|
showAirTime: true,
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import {
|
import {
|
||||||
RecommendationDto,
|
type RecommendationDto,
|
||||||
RecommendationType
|
RecommendationType
|
||||||
} from '@jellyfin/sdk/lib/generated-client';
|
} from '@jellyfin/sdk/lib/generated-client';
|
||||||
import React, { FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import escapeHTML from 'escape-html';
|
|
||||||
import {
|
import {
|
||||||
useGetMovieRecommendations,
|
useGetMovieRecommendations,
|
||||||
useGetSuggestionSectionsWithItems
|
useGetSuggestionSectionsWithItems
|
||||||
|
@ -12,8 +11,9 @@ import { appRouter } from 'components/router/appRouter';
|
||||||
import globalize from 'scripts/globalize';
|
import globalize from 'scripts/globalize';
|
||||||
import Loading from 'components/loading/LoadingComponent';
|
import Loading from 'components/loading/LoadingComponent';
|
||||||
import SectionContainer from './SectionContainer';
|
import SectionContainer from './SectionContainer';
|
||||||
import { ParentId } from 'types/library';
|
import { CardShape } from 'utils/card';
|
||||||
import { Section, SectionType } from 'types/sections';
|
import type { ParentId } from 'types/library';
|
||||||
|
import type { Section, SectionType } from 'types/sections';
|
||||||
|
|
||||||
interface SuggestionsSectionViewProps {
|
interface SuggestionsSectionViewProps {
|
||||||
parentId: ParentId;
|
parentId: ParentId;
|
||||||
|
@ -89,7 +89,7 @@ const SuggestionsSectionView: FC<SuggestionsSectionViewProps> = ({
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return escapeHTML(title);
|
return title;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -119,7 +119,7 @@ const SuggestionsSectionView: FC<SuggestionsSectionViewProps> = ({
|
||||||
items={recommendation.Items ?? []}
|
items={recommendation.Items ?? []}
|
||||||
cardOptions={{
|
cardOptions={{
|
||||||
queryKey: ['MovieRecommendations'],
|
queryKey: ['MovieRecommendations'],
|
||||||
shape: 'overflowPortrait',
|
shape: CardShape.PortraitOverflow,
|
||||||
showYear: true,
|
showYear: true,
|
||||||
scalable: true,
|
scalable: true,
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import React, { FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { useGetGroupsUpcomingEpisodes } from 'hooks/useFetchItems';
|
import { useGetGroupsUpcomingEpisodes } from 'hooks/useFetchItems';
|
||||||
import Loading from 'components/loading/LoadingComponent';
|
import Loading from 'components/loading/LoadingComponent';
|
||||||
import globalize from 'scripts/globalize';
|
import globalize from 'scripts/globalize';
|
||||||
import SectionContainer from './SectionContainer';
|
import SectionContainer from './SectionContainer';
|
||||||
import { LibraryViewProps } from 'types/library';
|
import { CardShape } from 'utils/card';
|
||||||
|
import type { LibraryViewProps } from 'types/library';
|
||||||
|
|
||||||
const UpcomingView: FC<LibraryViewProps> = ({ parentId }) => {
|
const UpcomingView: FC<LibraryViewProps> = ({ parentId }) => {
|
||||||
const { isLoading, data: groupsUpcomingEpisodes } = useGetGroupsUpcomingEpisodes(parentId);
|
const { isLoading, data: groupsUpcomingEpisodes } = useGetGroupsUpcomingEpisodes(parentId);
|
||||||
|
@ -29,7 +30,7 @@ const UpcomingView: FC<LibraryViewProps> = ({ parentId }) => {
|
||||||
sectionTitle={group.name}
|
sectionTitle={group.name}
|
||||||
items={group.items ?? []}
|
items={group.items ?? []}
|
||||||
cardOptions={{
|
cardOptions={{
|
||||||
shape: 'overflowBackdrop',
|
shape: CardShape.BackdropOverflow,
|
||||||
showLocationTypeIndicator: false,
|
showLocationTypeIndicator: false,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import CardOverlayButtons from './CardOverlayButtons';
|
||||||
import CardHoverMenu from './CardHoverMenu';
|
import CardHoverMenu from './CardHoverMenu';
|
||||||
import CardOuterFooter from './CardOuterFooter';
|
import CardOuterFooter from './CardOuterFooter';
|
||||||
import CardContent from './CardContent';
|
import CardContent from './CardContent';
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import type { ItemDto } from 'types/itemDto';
|
import type { ItemDto } from 'types/itemDto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ interface CardBoxProps {
|
||||||
item: ItemDto;
|
item: ItemDto;
|
||||||
cardOptions: CardOptions;
|
cardOptions: CardOptions;
|
||||||
className: string;
|
className: string;
|
||||||
shape: string | null | undefined;
|
shape: CardShape | undefined;
|
||||||
imgUrl: string | undefined;
|
imgUrl: string | undefined;
|
||||||
blurhash: string | undefined;
|
blurhash: string | undefined;
|
||||||
forceName: boolean;
|
forceName: boolean;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
import React, { type FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -32,7 +33,7 @@ const CardImageContainer: FC<CardImageContainerProps> = ({
|
||||||
const cardImageClass = classNames(
|
const cardImageClass = classNames(
|
||||||
'cardImageContainer',
|
'cardImageContainer',
|
||||||
{ coveredImage: coveredImage },
|
{ coveredImage: coveredImage },
|
||||||
{ 'coveredImage-contain': coveredImage && item.Type === 'TvChannel' }
|
{ 'coveredImage-contain': coveredImage && item.Type === BaseItemKind.TvChannel }
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -52,7 +53,7 @@ const CardImageContainer: FC<CardImageContainerProps> = ({
|
||||||
indicator.getChildCountIndicator() :
|
indicator.getChildCountIndicator() :
|
||||||
indicator.getPlayedIndicator()}
|
indicator.getPlayedIndicator()}
|
||||||
|
|
||||||
{(item.Type === 'CollectionFolder'
|
{(item.Type === BaseItemKind.CollectionFolder
|
||||||
|| item.CollectionType)
|
|| item.CollectionType)
|
||||||
&& item.RefreshProgress && (
|
&& item.RefreshProgress && (
|
||||||
<RefreshIndicator item={item} />
|
<RefreshIndicator item={item} />
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
|
import { LocationType } from '@jellyfin/sdk/lib/generated-client/models/location-type';
|
||||||
import React, { type FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import ButtonGroup from '@mui/material/ButtonGroup';
|
import ButtonGroup from '@mui/material/ButtonGroup';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -15,10 +17,10 @@ const sholudShowOverlayPlayButton = (
|
||||||
return (
|
return (
|
||||||
overlayPlayButton
|
overlayPlayButton
|
||||||
&& !item.IsPlaceHolder
|
&& !item.IsPlaceHolder
|
||||||
&& (item.LocationType !== 'Virtual'
|
&& (item.LocationType !== LocationType.Virtual
|
||||||
|| !item.MediaType
|
|| !item.MediaType
|
||||||
|| item.Type === 'Program')
|
|| item.Type === BaseItemKind.Program)
|
||||||
&& item.Type !== 'Person'
|
&& item.Type !== BaseItemKind.Person
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import useCardImageUrl from './useCardImageUrl';
|
import useCardImageUrl from './useCardImageUrl';
|
||||||
import {
|
import {
|
||||||
|
@ -5,6 +6,7 @@ import {
|
||||||
resolveMixedShapeByAspectRatio
|
resolveMixedShapeByAspectRatio
|
||||||
} from '../cardBuilderUtils';
|
} from '../cardBuilderUtils';
|
||||||
import { getDataAttributes } from 'utils/items';
|
import { getDataAttributes } from 'utils/items';
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import layoutManager from 'components/layoutManager';
|
import layoutManager from 'components/layoutManager';
|
||||||
|
|
||||||
import type { ItemDto } from 'types/itemDto';
|
import type { ItemDto } from 'types/itemDto';
|
||||||
|
@ -24,7 +26,7 @@ function useCard({ item, cardOptions }: UseCardProps) {
|
||||||
|
|
||||||
let shape = cardOptions.shape;
|
let shape = cardOptions.shape;
|
||||||
|
|
||||||
if (shape === 'mixed') {
|
if (shape === CardShape.Mixed) {
|
||||||
shape = resolveMixedShapeByAspectRatio(item.PrimaryImageAspectRatio);
|
shape = resolveMixedShapeByAspectRatio(item.PrimaryImageAspectRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +84,9 @@ function useCard({ item, cardOptions }: UseCardProps) {
|
||||||
{ groupedCard: cardOptions.showChildCountIndicator && item.ChildCount },
|
{ groupedCard: cardOptions.showChildCountIndicator && item.ChildCount },
|
||||||
{
|
{
|
||||||
'card-withuserdata':
|
'card-withuserdata':
|
||||||
item.Type !== 'MusicAlbum'
|
item.Type !== BaseItemKind.MusicAlbum
|
||||||
&& item.Type !== 'MusicArtist'
|
&& item.Type !== BaseItemKind.MusicArtist
|
||||||
&& item.Type !== 'Audio'
|
&& item.Type !== BaseItemKind.Audio
|
||||||
},
|
},
|
||||||
{ itemAction: layoutManager.tv }
|
{ itemAction: layoutManager.tv }
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { BaseItemKind, ImageType } from '@jellyfin/sdk/lib/generated-client';
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
|
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||||
import { getImageApi } from '@jellyfin/sdk/lib/utils/api/image-api';
|
import { getImageApi } from '@jellyfin/sdk/lib/utils/api/image-api';
|
||||||
import { useApi } from 'hooks/useApi';
|
import { useApi } from 'hooks/useApi';
|
||||||
import { getDesiredAspect } from '../cardBuilderUtils';
|
import { getDesiredAspect } from '../cardBuilderUtils';
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import type { ItemDto, NullableNumber, NullableString } from 'types/itemDto';
|
import type { ItemDto, NullableNumber, NullableString } from 'types/itemDto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
@ -98,10 +99,10 @@ function isCoverImage(
|
||||||
function shouldShowPreferBanner(
|
function shouldShowPreferBanner(
|
||||||
imageTagsBanner: NullableString,
|
imageTagsBanner: NullableString,
|
||||||
cardOptions: CardOptions,
|
cardOptions: CardOptions,
|
||||||
shape: NullableString
|
shape: CardShape | undefined
|
||||||
): boolean {
|
): boolean {
|
||||||
return (
|
return (
|
||||||
(cardOptions.preferBanner || shape === 'banner')
|
(cardOptions.preferBanner || shape === CardShape.Banner)
|
||||||
&& Boolean(imageTagsBanner)
|
&& Boolean(imageTagsBanner)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +153,7 @@ function shouldShowPreferThumb(itemType: NullableString, cardOptions: CardOption
|
||||||
function getCardImageInfo(
|
function getCardImageInfo(
|
||||||
item: ItemDto,
|
item: ItemDto,
|
||||||
cardOptions: CardOptions,
|
cardOptions: CardOptions,
|
||||||
shape: NullableString
|
shape: CardShape | undefined
|
||||||
) {
|
) {
|
||||||
const width = cardOptions.width;
|
const width = cardOptions.width;
|
||||||
let height;
|
let height;
|
||||||
|
@ -251,7 +252,7 @@ function getCardImageInfo(
|
||||||
interface UseCardImageUrlProps {
|
interface UseCardImageUrlProps {
|
||||||
item: ItemDto;
|
item: ItemDto;
|
||||||
cardOptions: CardOptions;
|
cardOptions: CardOptions;
|
||||||
shape: NullableString;
|
shape: CardShape | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useCardImageUrl({ item, cardOptions, shape }: UseCardImageUrlProps) {
|
function useCardImageUrl({ item, cardOptions, shape }: UseCardImageUrlProps) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import { randomInt } from '../../utils/number';
|
import { randomInt } from '../../utils/number';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
@ -54,15 +55,15 @@ export const isResizable = (windowWidth: number): boolean => {
|
||||||
*/
|
*/
|
||||||
export const resolveMixedShapeByAspectRatio = (primaryImageAspectRatio: number | null | undefined) => {
|
export const resolveMixedShapeByAspectRatio = (primaryImageAspectRatio: number | null | undefined) => {
|
||||||
if (primaryImageAspectRatio === undefined || primaryImageAspectRatio === null) {
|
if (primaryImageAspectRatio === undefined || primaryImageAspectRatio === null) {
|
||||||
return 'mixedSquare';
|
return CardShape.MixedSquare;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primaryImageAspectRatio >= 1.33) {
|
if (primaryImageAspectRatio >= 1.33) {
|
||||||
return 'mixedBackdrop';
|
return CardShape.MixedBackdrop;
|
||||||
} else if (primaryImageAspectRatio > 0.71) {
|
} else if (primaryImageAspectRatio > 0.71) {
|
||||||
return 'mixedSquare';
|
return CardShape.MixedSquare;
|
||||||
} else {
|
} else {
|
||||||
return 'mixedPortrait';
|
return CardShape.MixedPortrait;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ const useIndicator = (item: ItemDto) => {
|
||||||
const getProgressBar = (progressOptions?: ProgressOptions) => {
|
const getProgressBar = (progressOptions?: ProgressOptions) => {
|
||||||
if (
|
if (
|
||||||
enableProgressIndicator(item.Type, item.MediaType)
|
enableProgressIndicator(item.Type, item.MediaType)
|
||||||
&& item.Type !== 'Recording'
|
&& item.Type !== BaseItemKind.Recording
|
||||||
) {
|
) {
|
||||||
const playedPercentage = progressOptions?.userData?.PlayedPercentage ?
|
const playedPercentage = progressOptions?.userData?.PlayedPercentage ?
|
||||||
progressOptions.userData.PlayedPercentage :
|
progressOptions.userData.PlayedPercentage :
|
||||||
|
|
|
@ -30,7 +30,7 @@ const ListWrapper: FC<ListWrapperProps> = ({
|
||||||
'itemAction listItem-button listItem-focusscale'
|
'itemAction listItem-button listItem-focusscale'
|
||||||
)}
|
)}
|
||||||
data-action={action}
|
data-action={action}
|
||||||
aria-label={title}
|
aria-label={title || ''}
|
||||||
{...dataAttributes}
|
{...dataAttributes}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import type { BaseItemDtoImageBlurHashes, BaseItemKind, ImageType, UserItemDataDto } from '@jellyfin/sdk/lib/generated-client';
|
import type { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||||
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
import type { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||||
|
import type { UserItemDataDto } from '@jellyfin/sdk/lib/generated-client/models/user-item-data-dto';
|
||||||
|
import type { BaseItemDtoImageBlurHashes } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto-image-blur-hashes';
|
||||||
|
import type { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import type { ItemDto, NullableString } from './itemDto';
|
import type { ItemDto, NullableString } from './itemDto';
|
||||||
import { ParentId } from './library';
|
import type { ParentId } from './library';
|
||||||
|
|
||||||
export interface CardOptions {
|
export interface CardOptions {
|
||||||
itemsContainer?: HTMLElement | null;
|
itemsContainer?: HTMLElement | null;
|
||||||
|
@ -20,7 +24,8 @@ export interface CardOptions {
|
||||||
preferDisc?: boolean;
|
preferDisc?: boolean;
|
||||||
preferLogo?: boolean;
|
preferLogo?: boolean;
|
||||||
scalable?: boolean;
|
scalable?: boolean;
|
||||||
shape?: string | null;
|
shape?: CardShape;
|
||||||
|
defaultShape?: CardShape;
|
||||||
lazy?: boolean;
|
lazy?: boolean;
|
||||||
cardLayout?: boolean | null;
|
cardLayout?: boolean | null;
|
||||||
showParentTitle?: boolean;
|
showParentTitle?: boolean;
|
||||||
|
@ -39,7 +44,6 @@ export interface CardOptions {
|
||||||
lines?: number;
|
lines?: number;
|
||||||
context?: CollectionType;
|
context?: CollectionType;
|
||||||
action?: string | null;
|
action?: string | null;
|
||||||
defaultShape?: string;
|
|
||||||
indexBy?: string;
|
indexBy?: string;
|
||||||
parentId?: ParentId;
|
parentId?: ParentId;
|
||||||
showMenu?: boolean;
|
showMenu?: boolean;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { BaseItemDto, SeriesTimerInfoDto } from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
||||||
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
import type { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
||||||
|
import type { ItemDto } from './itemDto';
|
||||||
export interface ListOptions {
|
export interface ListOptions {
|
||||||
items?: BaseItemDto[] | SeriesTimerInfoDto[] | null;
|
items?: ItemDto[] | null;
|
||||||
index?: string;
|
index?: string;
|
||||||
showIndex?: boolean;
|
showIndex?: boolean;
|
||||||
action?: string | null;
|
action?: string | null;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { UserItemDataDto } from '@jellyfin/sdk/lib/generated-client';
|
import type { UserItemDataDto } from '@jellyfin/sdk/lib/generated-client/models/user-item-data-dto';
|
||||||
|
|
||||||
export interface ProgressOptions {
|
export interface ProgressOptions {
|
||||||
containerClass: string,
|
containerClass: string,
|
||||||
|
|
|
@ -5,7 +5,15 @@ export enum CardShape {
|
||||||
Portrait = 'portrait',
|
Portrait = 'portrait',
|
||||||
PortraitOverflow = 'overflowPortrait',
|
PortraitOverflow = 'overflowPortrait',
|
||||||
Square = 'square',
|
Square = 'square',
|
||||||
SquareOverflow = 'overflowSquare'
|
SquareOverflow = 'overflowSquare',
|
||||||
|
Auto = 'auto',
|
||||||
|
AutoHome = 'autohome',
|
||||||
|
AutoOverflow = 'autooverflow',
|
||||||
|
AutoVertical = 'autoVertical',
|
||||||
|
Mixed = 'mixed',
|
||||||
|
MixedSquare = 'mixedSquare',
|
||||||
|
MixedBackdrop = 'mixedBackdrop',
|
||||||
|
MixedPortrait = 'mixedPortrait',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSquareShape(enableOverflow = true) {
|
export function getSquareShape(enableOverflow = true) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-ite
|
||||||
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
||||||
import { SortOrder } from '@jellyfin/sdk/lib/generated-client/models/sort-order';
|
import { SortOrder } from '@jellyfin/sdk/lib/generated-client/models/sort-order';
|
||||||
import * as userSettings from 'scripts/settings/userSettings';
|
import * as userSettings from 'scripts/settings/userSettings';
|
||||||
|
import { CardShape } from 'utils/card';
|
||||||
import { Section, SectionType, SectionApiMethod } from 'types/sections';
|
import { Section, SectionType, SectionApiMethod } from 'types/sections';
|
||||||
|
|
||||||
export const getSuggestionSections = (): Section[] => {
|
export const getSuggestionSections = (): Section[] => {
|
||||||
|
@ -29,7 +30,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
shape: 'overflowBackdrop',
|
shape: CardShape.BackdropOverflow,
|
||||||
showYear: true
|
showYear: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -43,7 +44,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
shape: 'overflowPortrait',
|
shape: CardShape.PortraitOverflow,
|
||||||
showYear: true
|
showYear: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -57,7 +58,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
shape: 'overflowBackdrop',
|
shape: CardShape.BackdropOverflow,
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
inheritThumb:
|
inheritThumb:
|
||||||
!userSettings.useEpisodeImagesInNextUpAndResume(undefined),
|
!userSettings.useEpisodeImagesInNextUpAndResume(undefined),
|
||||||
|
@ -74,7 +75,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
shape: 'overflowBackdrop',
|
shape: CardShape.BackdropOverflow,
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
showSeriesYear: true,
|
showSeriesYear: true,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
|
@ -90,7 +91,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
type: SectionType.NextUp,
|
type: SectionType.NextUp,
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
shape: 'overflowBackdrop',
|
shape: CardShape.BackdropOverflow,
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
inheritThumb:
|
inheritThumb:
|
||||||
!userSettings.useEpisodeImagesInNextUpAndResume(undefined),
|
!userSettings.useEpisodeImagesInNextUpAndResume(undefined),
|
||||||
|
@ -107,7 +108,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
showUnplayedIndicator: false,
|
showUnplayedIndicator: false,
|
||||||
shape: 'overflowSquare',
|
shape: CardShape.SquareOverflow,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
coverImage: true
|
coverImage: true
|
||||||
|
@ -125,7 +126,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
showUnplayedIndicator: false,
|
showUnplayedIndicator: false,
|
||||||
shape: 'overflowSquare',
|
shape: CardShape.SquareOverflow,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
action: 'instantmix',
|
action: 'instantmix',
|
||||||
overlayMoreButton: true,
|
overlayMoreButton: true,
|
||||||
|
@ -144,7 +145,7 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
showUnplayedIndicator: false,
|
showUnplayedIndicator: false,
|
||||||
shape: 'overflowSquare',
|
shape: CardShape.SquareOverflow,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
action: 'instantmix',
|
action: 'instantmix',
|
||||||
overlayMoreButton: true,
|
overlayMoreButton: true,
|
||||||
|
@ -157,8 +158,8 @@ export const getSuggestionSections = (): Section[] => {
|
||||||
export const getProgramSections = (): Section[] => {
|
export const getProgramSections = (): Section[] => {
|
||||||
const cardOptions = {
|
const cardOptions = {
|
||||||
inheritThumb: false,
|
inheritThumb: false,
|
||||||
shape: 'autooverflow',
|
shape: CardShape.AutoOverflow,
|
||||||
defaultShape: 'overflowBackdrop',
|
defaultShape: CardShape.BackdropOverflow,
|
||||||
centerText: true,
|
centerText: true,
|
||||||
coverImage: true,
|
coverImage: true,
|
||||||
overlayText: false,
|
overlayText: false,
|
||||||
|
@ -309,8 +310,8 @@ export const getProgramSections = (): Section[] => {
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
showYear: true,
|
showYear: true,
|
||||||
lines: 2,
|
lines: 2,
|
||||||
shape: 'autooverflow',
|
shape: CardShape.AutoOverflow,
|
||||||
defaultShape: 'overflowBackdrop',
|
defaultShape: CardShape.BackdropOverflow,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
coverImage: true,
|
coverImage: true,
|
||||||
|
@ -328,8 +329,8 @@ export const getProgramSections = (): Section[] => {
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
showYear: false,
|
showYear: false,
|
||||||
showParentTitle: false,
|
showParentTitle: false,
|
||||||
shape: 'autooverflow',
|
shape: CardShape.AutoOverflow,
|
||||||
defaultShape: 'overflowBackdrop',
|
defaultShape: CardShape.BackdropOverflow,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
coverImage: true,
|
coverImage: true,
|
||||||
cardLayout: false,
|
cardLayout: false,
|
||||||
|
@ -347,8 +348,8 @@ export const getProgramSections = (): Section[] => {
|
||||||
isInProgress: true
|
isInProgress: true
|
||||||
},
|
},
|
||||||
cardOptions: {
|
cardOptions: {
|
||||||
shape: 'autooverflow',
|
shape: CardShape.AutoOverflow,
|
||||||
defaultShape: 'backdrop',
|
defaultShape: CardShape.Backdrop,
|
||||||
showParentTitle: false,
|
showParentTitle: false,
|
||||||
showParentTitleOrTitle: true,
|
showParentTitleOrTitle: true,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue