mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add shared ItemStatus and ItemDtoQueryResult Type
This commit is contained in:
parent
656799cce7
commit
5fbc417e3b
24 changed files with 219 additions and 183 deletions
|
@ -1,4 +1,3 @@
|
||||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
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';
|
||||||
|
@ -12,12 +11,13 @@ import { appRouter } from 'components/router/appRouter';
|
||||||
import SectionContainer from './SectionContainer';
|
import SectionContainer from './SectionContainer';
|
||||||
import { CardShape } from 'utils/card';
|
import { CardShape } from 'utils/card';
|
||||||
import type { ParentId } from 'types/library';
|
import type { ParentId } from 'types/library';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface GenresSectionContainerProps {
|
interface GenresSectionContainerProps {
|
||||||
parentId: ParentId;
|
parentId: ParentId;
|
||||||
collectionType: CollectionType | undefined;
|
collectionType: CollectionType | undefined;
|
||||||
itemType: BaseItemKind[];
|
itemType: BaseItemKind[];
|
||||||
genre: BaseItemDto;
|
genre: ItemDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GenresSectionContainer: FC<GenresSectionContainerProps> = ({
|
const GenresSectionContainer: FC<GenresSectionContainerProps> = ({
|
||||||
|
@ -47,7 +47,7 @@ const GenresSectionContainer: FC<GenresSectionContainerProps> = ({
|
||||||
|
|
||||||
const { isLoading, data: itemsResult } = useGetItems(getParametersOptions());
|
const { isLoading, data: itemsResult } = useGetItems(getParametersOptions());
|
||||||
|
|
||||||
const getRouteUrl = (item: BaseItemDto) => {
|
const getRouteUrl = (item: ItemDto) => {
|
||||||
return appRouter.getRouteUrl(item, {
|
return appRouter.getRouteUrl(item, {
|
||||||
context: collectionType,
|
context: collectionType,
|
||||||
parentId: parentId
|
parentId: parentId
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import type { BaseItemDto, SeriesTimerInfoDto } from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import React, { FC, useCallback } from 'react';
|
import React, { FC, useCallback } from 'react';
|
||||||
import { IconButton } from '@mui/material';
|
import { IconButton } from '@mui/material';
|
||||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||||
|
@ -8,10 +7,11 @@ import globalize from 'lib/globalize';
|
||||||
import { getFiltersQuery } from 'utils/items';
|
import { getFiltersQuery } from 'utils/items';
|
||||||
import { LibraryViewSettings } from 'types/library';
|
import { LibraryViewSettings } from 'types/library';
|
||||||
import { LibraryTab } from 'types/libraryTab';
|
import { LibraryTab } from 'types/libraryTab';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface PlayAllButtonProps {
|
interface PlayAllButtonProps {
|
||||||
item: BaseItemDto | null | undefined;
|
item: ItemDto | undefined;
|
||||||
items: BaseItemDto[] | SeriesTimerInfoDto[];
|
items: ItemDto[];
|
||||||
viewType: LibraryTab;
|
viewType: LibraryTab;
|
||||||
hasFilters: boolean;
|
hasFilters: boolean;
|
||||||
libraryViewSettings: LibraryViewSettings
|
libraryViewSettings: LibraryViewSettings
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import type { BaseItemDto, SeriesTimerInfoDto } from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import React, { FC, useCallback } from 'react';
|
import React, { FC, useCallback } from 'react';
|
||||||
import { IconButton } from '@mui/material';
|
import { IconButton } from '@mui/material';
|
||||||
import QueueIcon from '@mui/icons-material/Queue';
|
import QueueIcon from '@mui/icons-material/Queue';
|
||||||
|
|
||||||
import { playbackManager } from 'components/playback/playbackmanager';
|
import { playbackManager } from 'components/playback/playbackmanager';
|
||||||
import globalize from 'lib/globalize';
|
import globalize from 'lib/globalize';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface QueueButtonProps {
|
interface QueueButtonProps {
|
||||||
item: BaseItemDto | undefined
|
item: ItemDto | undefined
|
||||||
items: BaseItemDto[] | SeriesTimerInfoDto[];
|
items: ItemDto[];
|
||||||
hasFilters: boolean;
|
hasFilters: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import type { BaseItemDto, TimerInfoDto } from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
import ItemsContainer from 'elements/emby-itemscontainer/ItemsContainer';
|
import ItemsContainer from 'elements/emby-itemscontainer/ItemsContainer';
|
||||||
|
@ -6,11 +5,12 @@ import Scroller from 'elements/emby-scroller/Scroller';
|
||||||
import LinkButton from 'elements/emby-button/LinkButton';
|
import LinkButton from 'elements/emby-button/LinkButton';
|
||||||
import Cards from 'components/cardbuilder/Card/Cards';
|
import Cards from 'components/cardbuilder/Card/Cards';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface SectionContainerProps {
|
interface SectionContainerProps {
|
||||||
url?: string;
|
url?: string;
|
||||||
sectionTitle: string;
|
sectionTitle: string;
|
||||||
items: BaseItemDto[] | TimerInfoDto[];
|
items: ItemDto[];
|
||||||
cardOptions: CardOptions;
|
cardOptions: CardOptions;
|
||||||
reloadItems?: () => void;
|
reloadItems?: () => void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import type { 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 React, { FC, useCallback } from 'react';
|
import React, { FC, useCallback } from 'react';
|
||||||
import { IconButton } from '@mui/material';
|
import { IconButton } from '@mui/material';
|
||||||
|
@ -9,10 +8,11 @@ import globalize from 'lib/globalize';
|
||||||
import { getFiltersQuery } from 'utils/items';
|
import { getFiltersQuery } from 'utils/items';
|
||||||
import { LibraryViewSettings } from 'types/library';
|
import { LibraryViewSettings } from 'types/library';
|
||||||
import { LibraryTab } from 'types/libraryTab';
|
import { LibraryTab } from 'types/libraryTab';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface ShuffleButtonProps {
|
interface ShuffleButtonProps {
|
||||||
item: BaseItemDto | null | undefined;
|
item: ItemDto | undefined;
|
||||||
items: BaseItemDto[] | SeriesTimerInfoDto[];
|
items: ItemDto[];
|
||||||
viewType: LibraryTab
|
viewType: LibraryTab
|
||||||
hasFilters: boolean;
|
hasFilters: boolean;
|
||||||
libraryViewSettings: LibraryViewSettings
|
libraryViewSettings: LibraryViewSettings
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import {
|
import type { RecommendationDto } from '@jellyfin/sdk/lib/generated-client/models/recommendation-dto';
|
||||||
type RecommendationDto,
|
import { RecommendationType } from '@jellyfin/sdk/lib/generated-client/models/recommendation-type';
|
||||||
RecommendationType
|
|
||||||
} from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import React, { type FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import {
|
import {
|
||||||
useGetMovieRecommendations,
|
useGetMovieRecommendations,
|
||||||
|
@ -14,6 +12,7 @@ import SectionContainer from './SectionContainer';
|
||||||
import { CardShape } from 'utils/card';
|
import { CardShape } from 'utils/card';
|
||||||
import type { ParentId } from 'types/library';
|
import type { ParentId } from 'types/library';
|
||||||
import type { Section, SectionType } from 'types/sections';
|
import type { Section, SectionType } from 'types/sections';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
interface SuggestionsSectionViewProps {
|
interface SuggestionsSectionViewProps {
|
||||||
parentId: ParentId;
|
parentId: ParentId;
|
||||||
|
@ -116,7 +115,7 @@ const SuggestionsSectionView: FC<SuggestionsSectionViewProps> = ({
|
||||||
// eslint-disable-next-line react/no-array-index-key
|
// eslint-disable-next-line react/no-array-index-key
|
||||||
key={`${recommendation.CategoryId}-${index}`} // use a unique id return value may have duplicate id
|
key={`${recommendation.CategoryId}-${index}`} // use a unique id return value may have duplicate id
|
||||||
sectionTitle={getRecommendationTittle(recommendation)}
|
sectionTitle={getRecommendationTittle(recommendation)}
|
||||||
items={recommendation.Items ?? []}
|
items={(recommendation.Items as ItemDto[]) ?? []}
|
||||||
cardOptions={{
|
cardOptions={{
|
||||||
queryKey: ['MovieRecommendations'],
|
queryKey: ['MovieRecommendations'],
|
||||||
shape: CardShape.PortraitOverflow,
|
shape: CardShape.PortraitOverflow,
|
||||||
|
|
|
@ -6,6 +6,7 @@ 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 { CardShape } from 'utils/card';
|
||||||
|
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,11 @@ import React, { type FC } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import useCardText from './useCardText';
|
import useCardText from './useCardText';
|
||||||
import layoutManager from 'components/layoutManager';
|
import layoutManager from 'components/layoutManager';
|
||||||
import MoreVertIconButton from '../../common/MoreVertIconButton';
|
import MoreVertIconButton from 'components/common/MoreVertIconButton';
|
||||||
|
import Image from 'components/common/Image';
|
||||||
|
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
import Image from 'components/common/Image';
|
|
||||||
|
|
||||||
const shouldShowDetailsMenu = (
|
const shouldShowDetailsMenu = (
|
||||||
cardOptions: CardOptions,
|
cardOptions: CardOptions,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
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';
|
||||||
|
@ -7,6 +6,7 @@ import RefreshIndicator from 'elements/emby-itemrefreshindicator/RefreshIndicato
|
||||||
import Media from '../../common/Media';
|
import Media from '../../common/Media';
|
||||||
import CardInnerFooter from './CardInnerFooter';
|
import CardInnerFooter from './CardInnerFooter';
|
||||||
|
|
||||||
|
import { ItemKind } from 'types/base/models/item-kind';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ const CardImageContainer: FC<CardImageContainerProps> = ({
|
||||||
const cardImageClass = classNames(
|
const cardImageClass = classNames(
|
||||||
'cardImageContainer',
|
'cardImageContainer',
|
||||||
{ coveredImage: coveredImage },
|
{ coveredImage: coveredImage },
|
||||||
{ 'coveredImage-contain': coveredImage && item.Type === BaseItemKind.TvChannel }
|
{ 'coveredImage-contain': coveredImage && item.Type === ItemKind.TvChannel }
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -53,7 +53,7 @@ const CardImageContainer: FC<CardImageContainerProps> = ({
|
||||||
indicator.getChildCountIndicator() :
|
indicator.getChildCountIndicator() :
|
||||||
indicator.getPlayedIndicator()}
|
indicator.getPlayedIndicator()}
|
||||||
|
|
||||||
{(item.Type === BaseItemKind.CollectionFolder
|
{(item.Type === ItemKind.CollectionFolder
|
||||||
|| item.CollectionType) && (
|
|| item.CollectionType) && (
|
||||||
<RefreshIndicator item={item} />
|
<RefreshIndicator item={item} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { type FC } from 'react';
|
import React, { type FC } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import CardFooterText from './CardFooterText';
|
import CardFooterText from './CardFooterText';
|
||||||
|
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
|
||||||
import { LocationType } from '@jellyfin/sdk/lib/generated-client/models/location-type';
|
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';
|
||||||
|
@ -7,6 +6,8 @@ import { appRouter } from 'components/router/appRouter';
|
||||||
import PlayArrowIconButton from '../../common/PlayArrowIconButton';
|
import PlayArrowIconButton from '../../common/PlayArrowIconButton';
|
||||||
import MoreVertIconButton from '../../common/MoreVertIconButton';
|
import MoreVertIconButton from '../../common/MoreVertIconButton';
|
||||||
|
|
||||||
|
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';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
@ -19,8 +20,8 @@ const sholudShowOverlayPlayButton = (
|
||||||
&& !item.IsPlaceHolder
|
&& !item.IsPlaceHolder
|
||||||
&& (item.LocationType !== LocationType.Virtual
|
&& (item.LocationType !== LocationType.Virtual
|
||||||
|| !item.MediaType
|
|| !item.MediaType
|
||||||
|| item.Type === BaseItemKind.Program)
|
|| item.Type === ItemKind.Program)
|
||||||
&& item.Type !== BaseItemKind.Person
|
&& item.Type !== ItemKind.Person
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ const CardOverlayButtons: FC<CardOverlayButtonsProps> = ({
|
||||||
&& !cardOptions.overlayInfoButton
|
&& !cardOptions.overlayInfoButton
|
||||||
&& !cardOptions.cardLayout
|
&& !cardOptions.cardLayout
|
||||||
) {
|
) {
|
||||||
overlayPlayButton = item.MediaType === 'Video';
|
overlayPlayButton = item.MediaType === ItemMediaKind.Video;
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = appRouter.getRouteUrl(item, {
|
const url = appRouter.getRouteUrl(item, {
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import {
|
|
||||||
BaseItemDto,
|
|
||||||
BaseItemKind,
|
|
||||||
BaseItemPerson,
|
|
||||||
ImageType
|
|
||||||
} from '@jellyfin/sdk/lib/generated-client';
|
|
||||||
import { Api } from '@jellyfin/sdk';
|
import { Api } from '@jellyfin/sdk';
|
||||||
|
import type { BaseItemPerson } from '@jellyfin/sdk/lib/generated-client/models/base-item-person';
|
||||||
|
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 { appRouter } from 'components/router/appRouter';
|
import { appRouter } from 'components/router/appRouter';
|
||||||
|
@ -12,14 +8,15 @@ import layoutManager from 'components/layoutManager';
|
||||||
import itemHelper from 'components/itemHelper';
|
import itemHelper from 'components/itemHelper';
|
||||||
import globalize from 'lib/globalize';
|
import globalize from 'lib/globalize';
|
||||||
import datetime from 'scripts/datetime';
|
import datetime from 'scripts/datetime';
|
||||||
|
|
||||||
import { isUsingLiveTvNaming } from '../cardBuilderUtils';
|
import { isUsingLiveTvNaming } from '../cardBuilderUtils';
|
||||||
|
import { getDataAttributes } from 'utils/items';
|
||||||
|
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 { NullableNumber, NullableString } from 'types/base/common/shared/types';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
import type { DataAttributes } from 'types/dataAttributes';
|
import type { DataAttributes } from 'types/dataAttributes';
|
||||||
import { getDataAttributes } from 'utils/items';
|
|
||||||
|
|
||||||
export function getCardLogoUrl(
|
export function getCardLogoUrl(
|
||||||
item: ItemDto,
|
item: ItemDto,
|
||||||
|
@ -142,15 +139,15 @@ export function getAirTimeText(
|
||||||
return airTimeText;
|
return airTimeText;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isGenreOrStudio(itemType: NullableString) {
|
function isGenreOrStudio(itemType: ItemKind) {
|
||||||
return itemType === BaseItemKind.Genre || itemType === BaseItemKind.Studio;
|
return itemType === ItemKind.Genre || itemType === ItemKind.Studio;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMusicGenreOrMusicArtist(
|
function isMusicGenreOrMusicArtist(
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
context: NullableString
|
context: NullableString
|
||||||
) {
|
) {
|
||||||
return itemType === BaseItemKind.MusicGenre || context === 'MusicArtist';
|
return itemType === ItemKind.MusicGenre || context === 'MusicArtist';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMovieCount(itemMovieCount: NullableNumber) {
|
function getMovieCount(itemMovieCount: NullableNumber) {
|
||||||
|
@ -213,8 +210,8 @@ function getParentTitle(
|
||||||
item: ItemDto
|
item: ItemDto
|
||||||
) {
|
) {
|
||||||
if (isOuterFooter && item.AlbumArtists?.length) {
|
if (isOuterFooter && item.AlbumArtists?.length) {
|
||||||
(item.AlbumArtists[0] as BaseItemDto).Type = BaseItemKind.MusicArtist;
|
(item.AlbumArtists[0] as ItemDto).Type = ItemKind.MusicArtist;
|
||||||
(item.AlbumArtists[0] as BaseItemDto).IsFolder = true;
|
(item.AlbumArtists[0] as ItemDto).IsFolder = true;
|
||||||
return getTextActionButton(item.AlbumArtists[0], null, serverId);
|
return getTextActionButton(item.AlbumArtists[0], null, serverId);
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
@ -250,7 +247,7 @@ export function getItemCounts(cardOptions: CardOptions, item: ItemDto) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.Type === BaseItemKind.Playlist) {
|
if (item.Type === ItemKind.Playlist) {
|
||||||
const runTimeTicksText = getRunTimeTicks(item.RunTimeTicks);
|
const runTimeTicksText = getRunTimeTicks(item.RunTimeTicks);
|
||||||
addCount(runTimeTicksText);
|
addCount(runTimeTicksText);
|
||||||
} else if (isGenreOrStudio(item.Type)) {
|
} else if (isGenreOrStudio(item.Type)) {
|
||||||
|
@ -271,7 +268,7 @@ export function getItemCounts(cardOptions: CardOptions, item: ItemDto) {
|
||||||
|
|
||||||
const musicVideoCountText = getMusicVideoCount(item.MusicVideoCount);
|
const musicVideoCountText = getMusicVideoCount(item.MusicVideoCount);
|
||||||
addCount(musicVideoCountText);
|
addCount(musicVideoCountText);
|
||||||
} else if (item.Type === BaseItemKind.Series) {
|
} else if (item.Type === ItemKind.Series) {
|
||||||
const recursiveItemCountText = getRecursiveItemCount(
|
const recursiveItemCountText = getRecursiveItemCount(
|
||||||
item.RecursiveItemCount
|
item.RecursiveItemCount
|
||||||
);
|
);
|
||||||
|
@ -283,12 +280,12 @@ export function getItemCounts(cardOptions: CardOptions, item: ItemDto) {
|
||||||
|
|
||||||
export function shouldShowTitle(
|
export function shouldShowTitle(
|
||||||
showTitle: boolean | string | undefined,
|
showTitle: boolean | string | undefined,
|
||||||
itemType: NullableString
|
itemType: ItemKind
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
Boolean(showTitle)
|
Boolean(showTitle)
|
||||||
|| itemType === BaseItemKind.PhotoAlbum
|
|| itemType === ItemKind.PhotoAlbum
|
||||||
|| itemType === BaseItemKind.Folder
|
|| itemType === ItemKind.Folder
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,12 +297,12 @@ export function shouldShowOtherText(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shouldShowParentTitleUnderneath(
|
export function shouldShowParentTitleUnderneath(
|
||||||
itemType: NullableString
|
itemType: ItemKind
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
itemType === BaseItemKind.MusicAlbum
|
itemType === ItemKind.MusicAlbum
|
||||||
|| itemType === BaseItemKind.Audio
|
|| itemType === ItemKind.Audio
|
||||||
|| itemType === BaseItemKind.MusicVideo
|
|| itemType === ItemKind.MusicVideo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,16 +335,16 @@ function shouldShowSeriesYearOrYear(
|
||||||
|
|
||||||
function shouldShowCurrentProgram(
|
function shouldShowCurrentProgram(
|
||||||
showCurrentProgram: boolean | undefined,
|
showCurrentProgram: boolean | undefined,
|
||||||
itemType: NullableString
|
itemType: ItemKind
|
||||||
) {
|
) {
|
||||||
return showCurrentProgram && itemType === BaseItemKind.TvChannel;
|
return showCurrentProgram && itemType === ItemKind.TvChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowCurrentProgramTime(
|
function shouldShowCurrentProgramTime(
|
||||||
showCurrentProgramTime: boolean | undefined,
|
showCurrentProgramTime: boolean | undefined,
|
||||||
itemType: NullableString
|
itemType: ItemKind
|
||||||
) {
|
) {
|
||||||
return showCurrentProgramTime && itemType === BaseItemKind.TvChannel;
|
return showCurrentProgramTime && itemType === ItemKind.TvChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowPersonRoleOrType(
|
function shouldShowPersonRoleOrType(
|
||||||
|
@ -475,7 +472,7 @@ function getSeriesTimerTime(item: ItemDto) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentProgramTime(CurrentProgram: BaseItemDto | undefined) {
|
function getCurrentProgramTime(CurrentProgram: ItemDto | undefined) {
|
||||||
if (CurrentProgram) {
|
if (CurrentProgram) {
|
||||||
return getAirTimeText(CurrentProgram, false, true) || '';
|
return getAirTimeText(CurrentProgram, false, true) || '';
|
||||||
} else {
|
} else {
|
||||||
|
@ -483,7 +480,7 @@ function getCurrentProgramTime(CurrentProgram: BaseItemDto | undefined) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentProgramName(CurrentProgram: BaseItemDto | undefined) {
|
function getCurrentProgramName(CurrentProgram: ItemDto | undefined) {
|
||||||
if (CurrentProgram) {
|
if (CurrentProgram) {
|
||||||
return CurrentProgram.Name;
|
return CurrentProgram.Name;
|
||||||
} else {
|
} else {
|
||||||
|
@ -498,7 +495,7 @@ function getChannelName(item: ItemDto) {
|
||||||
Id: item.ChannelId,
|
Id: item.ChannelId,
|
||||||
ServerId: item.ServerId,
|
ServerId: item.ServerId,
|
||||||
Name: item.ChannelName,
|
Name: item.ChannelName,
|
||||||
Type: BaseItemKind.TvChannel,
|
Type: ItemKind.TvChannel,
|
||||||
MediaType: item.MediaType,
|
MediaType: item.MediaType,
|
||||||
IsFolder: false
|
IsFolder: false
|
||||||
},
|
},
|
||||||
|
@ -548,7 +545,7 @@ function getProductionYear(item: ItemDto) {
|
||||||
&& datetime.toLocaleString(item.ProductionYear, {
|
&& datetime.toLocaleString(item.ProductionYear, {
|
||||||
useGrouping: false
|
useGrouping: false
|
||||||
});
|
});
|
||||||
if (item.Type === BaseItemKind.Series) {
|
if (item.Type === ItemKind.Series) {
|
||||||
if (item.Status === 'Continuing') {
|
if (item.Status === 'Continuing') {
|
||||||
return globalize.translate(
|
return globalize.translate(
|
||||||
'SeriesYearToPresent',
|
'SeriesYearToPresent',
|
||||||
|
@ -575,7 +572,7 @@ function getMediaTitle(cardOptions: CardOptions, item: ItemDto): TextLine {
|
||||||
const name =
|
const name =
|
||||||
cardOptions.showTitle === 'auto'
|
cardOptions.showTitle === 'auto'
|
||||||
&& !item.IsFolder
|
&& !item.IsFolder
|
||||||
&& item.MediaType === 'Photo' ?
|
&& item.MediaType === ItemMediaKind.Photo ?
|
||||||
'' :
|
'' :
|
||||||
itemHelper.getDisplayName(item, {
|
itemHelper.getDisplayName(item, {
|
||||||
includeParentInfo: cardOptions.includeParentInfoInTitle
|
includeParentInfo: cardOptions.includeParentInfoInTitle
|
||||||
|
@ -599,7 +596,7 @@ function getParentTitleOrTitle(
|
||||||
): TextLine {
|
): TextLine {
|
||||||
if (
|
if (
|
||||||
isOuterFooter
|
isOuterFooter
|
||||||
&& item.Type === BaseItemKind.Episode
|
&& item.Type === ItemKind.Episode
|
||||||
&& item.SeriesName
|
&& item.SeriesName
|
||||||
) {
|
) {
|
||||||
if (item.SeriesId) {
|
if (item.SeriesId) {
|
||||||
|
@ -607,7 +604,7 @@ function getParentTitleOrTitle(
|
||||||
Id: item.SeriesId,
|
Id: item.SeriesId,
|
||||||
ServerId: item.ServerId,
|
ServerId: item.ServerId,
|
||||||
Name: item.SeriesName,
|
Name: item.SeriesName,
|
||||||
Type: BaseItemKind.Series,
|
Type: ItemKind.Series,
|
||||||
IsFolder: true
|
IsFolder: true
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
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 {
|
||||||
|
@ -9,6 +8,8 @@ import { getDataAttributes } from 'utils/items';
|
||||||
import { CardShape } from 'utils/card';
|
import { CardShape } from 'utils/card';
|
||||||
import layoutManager from 'components/layoutManager';
|
import layoutManager from 'components/layoutManager';
|
||||||
|
|
||||||
|
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';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ function useCard({ item, cardOptions }: UseCardProps) {
|
||||||
const action = resolveAction({
|
const action = resolveAction({
|
||||||
defaultAction: cardOptions.action ?? 'link',
|
defaultAction: cardOptions.action ?? 'link',
|
||||||
isFolder: item.IsFolder ?? false,
|
isFolder: item.IsFolder ?? false,
|
||||||
isPhoto: item.MediaType === 'Photo'
|
isPhoto: item.MediaType === ItemMediaKind.Photo
|
||||||
});
|
});
|
||||||
|
|
||||||
let shape = cardOptions.shape;
|
let shape = cardOptions.shape;
|
||||||
|
@ -84,9 +85,9 @@ function useCard({ item, cardOptions }: UseCardProps) {
|
||||||
{ groupedCard: cardOptions.showChildCountIndicator && item.ChildCount },
|
{ groupedCard: cardOptions.showChildCountIndicator && item.ChildCount },
|
||||||
{
|
{
|
||||||
'card-withuserdata':
|
'card-withuserdata':
|
||||||
item.Type !== BaseItemKind.MusicAlbum
|
item.Type !== ItemKind.MusicAlbum
|
||||||
&& item.Type !== BaseItemKind.MusicArtist
|
&& item.Type !== ItemKind.MusicArtist
|
||||||
&& item.Type !== BaseItemKind.Audio
|
&& item.Type !== ItemKind.Audio
|
||||||
},
|
},
|
||||||
{ itemAction: layoutManager.tv }
|
{ itemAction: layoutManager.tv }
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
|
||||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
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 { 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 { NullableNumber, NullableString } from 'types/base/common/shared/types';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { CardOptions } from 'types/cardOptions';
|
import type { CardOptions } from 'types/cardOptions';
|
||||||
|
@ -25,7 +27,7 @@ function getPreferThumbInfo(item: ItemDto, cardOptions: CardOptions) {
|
||||||
} else if (
|
} else if (
|
||||||
item.ParentThumbItemId
|
item.ParentThumbItemId
|
||||||
&& cardOptions.inheritThumb !== false
|
&& cardOptions.inheritThumb !== false
|
||||||
&& item.MediaType !== 'Photo'
|
&& item.MediaType !== ItemMediaKind.Photo
|
||||||
) {
|
) {
|
||||||
imgType = ImageType.Thumb;
|
imgType = ImageType.Thumb;
|
||||||
imgTag = item.ParentThumbImageTag;
|
imgTag = item.ParentThumbImageTag;
|
||||||
|
@ -117,12 +119,12 @@ function shouldShowPreferDisc(
|
||||||
|
|
||||||
function shouldShowImageTagsPrimary(item: ItemDto): boolean {
|
function shouldShowImageTagsPrimary(item: ItemDto): boolean {
|
||||||
return (
|
return (
|
||||||
Boolean(item.ImageTags?.Primary) && (item.Type !== BaseItemKind.Episode || item.ChildCount !== 0)
|
Boolean(item.ImageTags?.Primary) && (item.Type !== ItemKind.Episode || item.ChildCount !== 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowImageTagsThumb(item: ItemDto): boolean {
|
function shouldShowImageTagsThumb(item: ItemDto): boolean {
|
||||||
return item.Type === BaseItemKind.Season && Boolean(item.ImageTags?.Thumb);
|
return item.Type === ItemKind.Season && Boolean(item.ImageTags?.Thumb);
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowSeriesThumbImageTag(
|
function shouldShowSeriesThumbImageTag(
|
||||||
|
@ -147,8 +149,8 @@ function shouldShowAlbumPrimaryImageTag(item: ItemDto): boolean {
|
||||||
return Boolean(item.AlbumId) && Boolean(item.AlbumPrimaryImageTag);
|
return Boolean(item.AlbumId) && Boolean(item.AlbumPrimaryImageTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldShowPreferThumb(itemType: NullableString, cardOptions: CardOptions): boolean {
|
function shouldShowPreferThumb(itemType: ItemKind, cardOptions: CardOptions): boolean {
|
||||||
return Boolean(cardOptions.preferThumb) && !(itemType === BaseItemKind.Program || itemType === BaseItemKind.Episode);
|
return Boolean(cardOptions.preferThumb) && !(itemType === ItemKind.Program || itemType === ItemKind.Episode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCardImageInfo(
|
function getCardImageInfo(
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
|
||||||
import { LocationType } from '@jellyfin/sdk/lib/generated-client/models/location-type';
|
import { LocationType } from '@jellyfin/sdk/lib/generated-client/models/location-type';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
|
@ -13,9 +12,15 @@ import FolderIcon from '@mui/icons-material/Folder';
|
||||||
import PhotoAlbumIcon from '@mui/icons-material/PhotoAlbum';
|
import PhotoAlbumIcon from '@mui/icons-material/PhotoAlbum';
|
||||||
import PhotoIcon from '@mui/icons-material/Photo';
|
import PhotoIcon from '@mui/icons-material/Photo';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import datetime from 'scripts/datetime';
|
import datetime from 'scripts/datetime';
|
||||||
import itemHelper from 'components/itemHelper';
|
import itemHelper from 'components/itemHelper';
|
||||||
import AutoTimeProgressBar from 'elements/emby-progressbar/AutoTimeProgressBar';
|
import AutoTimeProgressBar from 'elements/emby-progressbar/AutoTimeProgressBar';
|
||||||
|
|
||||||
|
import { ItemKind } from 'types/base/models/item-kind';
|
||||||
|
import { ItemMediaKind } from 'types/base/models/item-media-kind';
|
||||||
|
import { ItemStatus } from 'types/base/models/item-status';
|
||||||
|
|
||||||
import type { NullableString } from 'types/base/common/shared/types';
|
import type { NullableString } from 'types/base/common/shared/types';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { ProgressOptions } from 'types/progressOptions';
|
import type { ProgressOptions } from 'types/progressOptions';
|
||||||
|
@ -32,25 +37,25 @@ const getTypeIcon = (itemType: NullableString) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const enableProgressIndicator = (
|
const enableProgressIndicator = (
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
itemMediaType: NullableString
|
itemMediaType: ItemMediaKind
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
(itemMediaType === 'Video' && itemType !== BaseItemKind.TvChannel)
|
(itemMediaType === ItemMediaKind.Video && itemType !== ItemKind.TvChannel)
|
||||||
|| itemType === BaseItemKind.AudioBook
|
|| itemType === ItemKind.AudioBook
|
||||||
|| itemType === 'AudioPodcast'
|
|| itemType === ItemKind.AudioPodcast
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const enableAutoTimeProgressIndicator = (
|
const enableAutoTimeProgressIndicator = (
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
itemStartDate: NullableString,
|
itemStartDate: NullableString,
|
||||||
itemEndDate: NullableString
|
itemEndDate: NullableString
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
(itemType === BaseItemKind.Program
|
(itemType === ItemKind.Program
|
||||||
|| itemType === 'Timer'
|
|| itemType === ItemKind.Timer
|
||||||
|| itemType === BaseItemKind.Recording)
|
|| itemType === ItemKind.Recording)
|
||||||
&& Boolean(itemStartDate)
|
&& Boolean(itemStartDate)
|
||||||
&& Boolean(itemEndDate)
|
&& Boolean(itemEndDate)
|
||||||
);
|
);
|
||||||
|
@ -76,7 +81,7 @@ const useIndicator = (item: ItemDto) => {
|
||||||
|
|
||||||
const getMissingIndicator = () => {
|
const getMissingIndicator = () => {
|
||||||
if (
|
if (
|
||||||
item.Type === BaseItemKind.Episode
|
item.Type === ItemKind.Episode
|
||||||
&& item.LocationType === LocationType.Virtual
|
&& item.LocationType === LocationType.Virtual
|
||||||
) {
|
) {
|
||||||
if (item.PremiereDate) {
|
if (item.PremiereDate) {
|
||||||
|
@ -102,11 +107,11 @@ const useIndicator = (item: ItemDto) => {
|
||||||
|
|
||||||
let status;
|
let status;
|
||||||
|
|
||||||
if (item.Type === 'SeriesTimer') {
|
if (item.Type === ItemKind.SeriesTimer) {
|
||||||
return <FiberSmartRecordIcon className={indicatorIconClass} />;
|
return <FiberSmartRecordIcon className={indicatorIconClass} />;
|
||||||
} else if (item.TimerId || item.SeriesTimerId) {
|
} else if (item.TimerId || item.SeriesTimerId) {
|
||||||
status = item.Status || 'Cancelled';
|
status = item.Status || ItemStatus.Cancelled;
|
||||||
} else if (item.Type === 'Timer') {
|
} else if (item.Type === ItemKind.Timer) {
|
||||||
status = item.Status;
|
status = item.Status;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -116,7 +121,7 @@ const useIndicator = (item: ItemDto) => {
|
||||||
return (
|
return (
|
||||||
<FiberSmartRecordIcon
|
<FiberSmartRecordIcon
|
||||||
className={`${indicatorIconClass} ${
|
className={`${indicatorIconClass} ${
|
||||||
status === 'Cancelled' ? 'timerIndicator-inactive' : ''
|
status === ItemStatus.Cancelled ? 'timerIndicator-inactive' : ''
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -198,7 +203,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 !== BaseItemKind.Recording
|
&& item.Type !== ItemKind.Recording
|
||||||
) {
|
) {
|
||||||
const playedPercentage = progressOptions?.userData?.PlayedPercentage ?
|
const playedPercentage = progressOptions?.userData?.PlayedPercentage ?
|
||||||
progressOptions.userData.PlayedPercentage :
|
progressOptions.userData.PlayedPercentage :
|
||||||
|
@ -231,8 +236,8 @@ const useIndicator = (item: ItemDto) => {
|
||||||
|
|
||||||
if (pct > 0 && pct < 100) {
|
if (pct > 0 && pct < 100) {
|
||||||
const isRecording =
|
const isRecording =
|
||||||
item.Type === 'Timer'
|
item.Type === ItemKind.Timer
|
||||||
|| item.Type === BaseItemKind.Recording
|
|| item.Type === ItemKind.Recording
|
||||||
|| Boolean(item.TimerId);
|
|| Boolean(item.TimerId);
|
||||||
return (
|
return (
|
||||||
<AutoTimeProgressBar
|
<AutoTimeProgressBar
|
||||||
|
|
|
@ -8,6 +8,8 @@ import StarIcons from './StarIcons';
|
||||||
import CaptionMediaInfo from './CaptionMediaInfo';
|
import CaptionMediaInfo from './CaptionMediaInfo';
|
||||||
import CriticRatingMediaInfo from './CriticRatingMediaInfo';
|
import CriticRatingMediaInfo from './CriticRatingMediaInfo';
|
||||||
import EndsAt from './EndsAt';
|
import EndsAt from './EndsAt';
|
||||||
|
|
||||||
|
import { ItemMediaKind } from 'types/base/models/item-media-kind';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { MiscInfo } from 'types/mediaInfoItem';
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ const PrimaryMediaInfo: FC<PrimaryMediaInfoProps> = ({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isEndsAtEnabled
|
{isEndsAtEnabled
|
||||||
&& MediaType === 'Video'
|
&& MediaType === ItemMediaKind.Video
|
||||||
&& RunTimeTicks
|
&& RunTimeTicks
|
||||||
&& !StartDate && <EndsAt runTimeTicks={RunTimeTicks} />}
|
&& !StartDate && <EndsAt runTimeTicks={RunTimeTicks} />}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
|
||||||
import * as userSettings from 'scripts/settings/userSettings';
|
import * as userSettings from 'scripts/settings/userSettings';
|
||||||
import datetime from 'scripts/datetime';
|
import datetime from 'scripts/datetime';
|
||||||
import globalize from 'lib/globalize';
|
import globalize from 'lib/globalize';
|
||||||
import itemHelper from '../itemHelper';
|
import itemHelper from '../itemHelper';
|
||||||
|
|
||||||
|
import { ItemKind } from 'types/base/models/item-kind';
|
||||||
|
import { ItemMediaKind } from 'types/base/models/item-media-kind';
|
||||||
|
import { ItemStatus } from 'types/base/models/item-status';
|
||||||
import type { NullableNumber, NullableString } from 'types/base/common/shared/types';
|
import type { NullableNumber, NullableString } from 'types/base/common/shared/types';
|
||||||
import type { ItemDto } from 'types/base/models/item-dto';
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
import type { MiscInfo } from 'types/mediaInfoItem';
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
|
||||||
function shouldShowFolderRuntime(
|
function shouldShowFolderRuntime(
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
itemMediaType: NullableString
|
itemMediaType: ItemMediaKind
|
||||||
): boolean {
|
): boolean {
|
||||||
return (
|
return (
|
||||||
itemType === BaseItemKind.MusicAlbum
|
itemType === ItemKind.MusicAlbum
|
||||||
|| itemMediaType === 'MusicArtist'
|
|| itemMediaType === ItemMediaKind.MusicArtist
|
||||||
|| itemType === BaseItemKind.Playlist
|
|| itemType === ItemKind.Playlist
|
||||||
|| itemMediaType === 'Playlist'
|
|| itemMediaType === ItemMediaKind.Playlist
|
||||||
|| itemMediaType === 'MusicGenre'
|
|| itemMediaType === ItemMediaKind.MusicGenre
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +40,7 @@ function addTrackCountOrItemCount(
|
||||||
if (itemRunTimeTicks) {
|
if (itemRunTimeTicks) {
|
||||||
addMiscInfo({ text: datetime.getDisplayDuration(itemRunTimeTicks) });
|
addMiscInfo({ text: datetime.getDisplayDuration(itemRunTimeTicks) });
|
||||||
}
|
}
|
||||||
} else if (itemType === BaseItemKind.PhotoAlbum || itemType === BaseItemKind.BoxSet) {
|
} else if (itemType === ItemKind.PhotoAlbum || itemType === ItemKind.BoxSet) {
|
||||||
const count = itemChildCount;
|
const count = itemChildCount;
|
||||||
if (count) {
|
if (count) {
|
||||||
addMiscInfo({ text: globalize.translate('ItemCount', count) });
|
addMiscInfo({ text: globalize.translate('ItemCount', count) });
|
||||||
|
@ -46,22 +49,22 @@ function addTrackCountOrItemCount(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addOriginalAirDateInfo(
|
function addOriginalAirDateInfo(
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
itemMediaType: NullableString,
|
itemMediaType: ItemMediaKind,
|
||||||
isOriginalAirDateEnabled: boolean,
|
isOriginalAirDateEnabled: boolean,
|
||||||
itemPremiereDate: NullableString,
|
itemPremiereDate: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemPremiereDate
|
itemPremiereDate
|
||||||
&& (itemType === BaseItemKind.Episode || itemMediaType === 'Photo')
|
&& (itemType === ItemKind.Episode || itemMediaType === ItemMediaKind.Photo)
|
||||||
&& isOriginalAirDateEnabled
|
&& isOriginalAirDateEnabled
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
//don't modify date to locale if episode. Only Dates (not times) are stored, or editable in the edit metadata dialog
|
//don't modify date to locale if episode. Only Dates (not times) are stored, or editable in the edit metadata dialog
|
||||||
const date = datetime.parseISO8601Date(
|
const date = datetime.parseISO8601Date(
|
||||||
itemPremiereDate,
|
itemPremiereDate,
|
||||||
itemType !== BaseItemKind.Episode
|
itemType !== ItemKind.Episode
|
||||||
);
|
);
|
||||||
addMiscInfo({ text: datetime.toLocaleDateString(date) });
|
addMiscInfo({ text: datetime.toLocaleDateString(date) });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -71,14 +74,14 @@ function addOriginalAirDateInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSeriesTimerInfo(
|
function addSeriesTimerInfo(
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
itemRecordAnyTime: boolean | undefined,
|
itemRecordAnyTime: boolean | undefined,
|
||||||
itemStartDate: NullableString,
|
itemStartDate: NullableString,
|
||||||
itemRecordAnyChannel: boolean | undefined,
|
itemRecordAnyChannel: boolean | undefined,
|
||||||
itemChannelName: NullableString,
|
itemChannelName: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemType === 'SeriesTimer') {
|
if (itemType === ItemKind.SeriesTimer) {
|
||||||
if (itemRecordAnyTime) {
|
if (itemRecordAnyTime) {
|
||||||
addMiscInfo({ text: globalize.translate('Anytime') });
|
addMiscInfo({ text: globalize.translate('Anytime') });
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,9 +148,9 @@ function addProgramIndicators(
|
||||||
isEpisodeTitleIndexNumberEnabled: boolean,
|
isEpisodeTitleIndexNumberEnabled: boolean,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (item.Type === BaseItemKind.Program || item.Type === 'Timer') {
|
if (item.Type === ItemKind.Program || item.Type === ItemKind.Timer) {
|
||||||
let program = item;
|
let program = item;
|
||||||
if (item.Type === 'Timer' && item.ProgramInfo) {
|
if (item.Type === ItemKind.Timer && item.ProgramInfo) {
|
||||||
program = item.ProgramInfo;
|
program = item.ProgramInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,20 +208,20 @@ function addProgramTextInfo(
|
||||||
|
|
||||||
function addStartDateInfo(
|
function addStartDateInfo(
|
||||||
itemStartDate: NullableString,
|
itemStartDate: NullableString,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemStartDate
|
itemStartDate
|
||||||
&& itemType !== BaseItemKind.Program
|
&& itemType !== ItemKind.Program
|
||||||
&& itemType !== 'SeriesTimer'
|
&& itemType !== ItemKind.SeriesTimer
|
||||||
&& itemType !== 'Timer'
|
&& itemType !== ItemKind.Timer
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const date = datetime.parseISO8601Date(itemStartDate);
|
const date = datetime.parseISO8601Date(itemStartDate);
|
||||||
addMiscInfo({ text: datetime.toLocaleDateString(date) });
|
addMiscInfo({ text: datetime.toLocaleDateString(date) });
|
||||||
|
|
||||||
if (itemType !== BaseItemKind.Recording) {
|
if (itemType !== ItemKind.Recording) {
|
||||||
addMiscInfo({ text: datetime.getDisplayTime(date) });
|
addMiscInfo({ text: datetime.getDisplayTime(date) });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -229,14 +232,14 @@ function addStartDateInfo(
|
||||||
|
|
||||||
function addSeriesProductionYearInfo(
|
function addSeriesProductionYearInfo(
|
||||||
itemProductionYear: NullableNumber,
|
itemProductionYear: NullableNumber,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
isYearEnabled: boolean,
|
isYearEnabled: boolean,
|
||||||
itemStatus: NullableString,
|
itemStatus: ItemStatus,
|
||||||
itemEndDate: NullableString,
|
itemEndDate: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemProductionYear && isYearEnabled && itemType === BaseItemKind.Series) {
|
if (itemProductionYear && isYearEnabled && itemType === ItemKind.Series) {
|
||||||
if (itemStatus === 'Continuing') {
|
if (itemStatus === ItemStatus.Continuing) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: globalize.translate(
|
text: globalize.translate(
|
||||||
'SeriesYearToPresent',
|
'SeriesYearToPresent',
|
||||||
|
@ -279,20 +282,20 @@ function addproductionYearWithEndDate(
|
||||||
|
|
||||||
function addYearInfo(
|
function addYearInfo(
|
||||||
isYearEnabled: boolean,
|
isYearEnabled: boolean,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
itemMediaType: NullableString,
|
itemMediaType: ItemMediaKind,
|
||||||
itemProductionYear: NullableNumber,
|
itemProductionYear: NullableNumber,
|
||||||
itemPremiereDate: NullableString,
|
itemPremiereDate: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
isYearEnabled
|
isYearEnabled
|
||||||
&& itemType !== BaseItemKind.Series
|
&& itemType !== ItemKind.Series
|
||||||
&& itemType !== BaseItemKind.Episode
|
&& itemType !== ItemKind.Episode
|
||||||
&& itemType !== BaseItemKind.Person
|
&& itemType !== ItemKind.Person
|
||||||
&& itemMediaType !== 'Photo'
|
&& itemMediaType !== ItemMediaKind.Photo
|
||||||
&& itemType !== BaseItemKind.Program
|
&& itemType !== ItemKind.Program
|
||||||
&& itemType !== BaseItemKind.Season
|
&& itemType !== ItemKind.Season
|
||||||
) {
|
) {
|
||||||
if (itemProductionYear) {
|
if (itemProductionYear) {
|
||||||
addMiscInfo({ text: itemProductionYear });
|
addMiscInfo({ text: itemProductionYear });
|
||||||
|
@ -321,21 +324,21 @@ function addVideo3DFormat(
|
||||||
|
|
||||||
function addRunTimeInfo(
|
function addRunTimeInfo(
|
||||||
itemRunTimeTicks: NullableNumber,
|
itemRunTimeTicks: NullableNumber,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
showFolderRuntime: boolean,
|
showFolderRuntime: boolean,
|
||||||
isRuntimeEnabled: boolean,
|
isRuntimeEnabled: boolean,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemRunTimeTicks
|
itemRunTimeTicks
|
||||||
&& itemType !== BaseItemKind.Series
|
&& itemType !== ItemKind.Series
|
||||||
&& itemType !== BaseItemKind.Program
|
&& itemType !== ItemKind.Program
|
||||||
&& itemType !== 'Timer'
|
&& itemType !== ItemKind.Timer
|
||||||
&& itemType !== BaseItemKind.Book
|
&& itemType !== ItemKind.Book
|
||||||
&& !showFolderRuntime
|
&& !showFolderRuntime
|
||||||
&& isRuntimeEnabled
|
&& isRuntimeEnabled
|
||||||
) {
|
) {
|
||||||
if (itemType === BaseItemKind.Audio) {
|
if (itemType === ItemKind.Audio) {
|
||||||
addMiscInfo({ text: datetime.getDisplayRunningTime(itemRunTimeTicks) });
|
addMiscInfo({ text: datetime.getDisplayRunningTime(itemRunTimeTicks) });
|
||||||
} else {
|
} else {
|
||||||
addMiscInfo({ text: datetime.getDisplayDuration(itemRunTimeTicks) });
|
addMiscInfo({ text: datetime.getDisplayDuration(itemRunTimeTicks) });
|
||||||
|
@ -345,15 +348,15 @@ function addRunTimeInfo(
|
||||||
|
|
||||||
function addOfficialRatingInfo(
|
function addOfficialRatingInfo(
|
||||||
itemOfficialRating: NullableString,
|
itemOfficialRating: NullableString,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
isOfficialRatingEnabled: boolean,
|
isOfficialRatingEnabled: boolean,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemOfficialRating
|
itemOfficialRating
|
||||||
&& isOfficialRatingEnabled
|
&& isOfficialRatingEnabled
|
||||||
&& itemType !== BaseItemKind.Season
|
&& itemType !== ItemKind.Season
|
||||||
&& itemType !== BaseItemKind.Episode
|
&& itemType !== ItemKind.Episode
|
||||||
) {
|
) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: itemOfficialRating,
|
text: itemOfficialRating,
|
||||||
|
@ -365,21 +368,21 @@ function addOfficialRatingInfo(
|
||||||
function addAudioContainer(
|
function addAudioContainer(
|
||||||
itemContainer: NullableString,
|
itemContainer: NullableString,
|
||||||
isContainerEnabled: boolean,
|
isContainerEnabled: boolean,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemContainer && isContainerEnabled && itemType === BaseItemKind.Audio) {
|
if (itemContainer && isContainerEnabled && itemType === ItemKind.Audio) {
|
||||||
addMiscInfo({ text: itemContainer });
|
addMiscInfo({ text: itemContainer });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPhotoSize(
|
function addPhotoSize(
|
||||||
itemMediaType: NullableString,
|
itemMediaType: ItemMediaKind,
|
||||||
itemWidth: NullableNumber,
|
itemWidth: NullableNumber,
|
||||||
itemHeight: NullableNumber,
|
itemHeight: NullableNumber,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemMediaType === 'Photo' && itemWidth && itemHeight) {
|
if (itemMediaType === ItemMediaKind.Photo && itemWidth && itemHeight) {
|
||||||
const size = `${itemWidth}x${itemHeight}`;
|
const size = `${itemWidth}x${itemHeight}`;
|
||||||
|
|
||||||
addMiscInfo({ text: size });
|
addMiscInfo({ text: size });
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import type { AxiosRequestConfig } from 'axios';
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
import type { ItemsApiGetItemsRequest, PlaylistsApiMoveItemRequest } from '@jellyfin/sdk/lib/generated-client';
|
import type { ItemsApiGetItemsRequest, PlaylistsApiMoveItemRequest } from '@jellyfin/sdk/lib/generated-client';
|
||||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
|
||||||
import type { TimerInfoDto } from '@jellyfin/sdk/lib/generated-client/models/timer-info-dto';
|
|
||||||
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 { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||||
|
@ -26,9 +24,13 @@ import globalize from 'lib/globalize';
|
||||||
import { type JellyfinApiContext, useApi } from './useApi';
|
import { type JellyfinApiContext, useApi } from './useApi';
|
||||||
import { getAlphaPickerQuery, getFieldsQuery, getFiltersQuery, getLimitQuery } from 'utils/items';
|
import { getAlphaPickerQuery, getFieldsQuery, getFiltersQuery, getLimitQuery } from 'utils/items';
|
||||||
import { getProgramSections, getSuggestionSections } from 'utils/sections';
|
import { getProgramSections, getSuggestionSections } from 'utils/sections';
|
||||||
|
|
||||||
import type { LibraryViewSettings, ParentId } from 'types/library';
|
import type { LibraryViewSettings, ParentId } from 'types/library';
|
||||||
import { type Section, type SectionType, SectionApiMethod } from 'types/sections';
|
import { type Section, type SectionType, SectionApiMethod } from 'types/sections';
|
||||||
import { LibraryTab } from 'types/libraryTab';
|
import { LibraryTab } from 'types/libraryTab';
|
||||||
|
import { ItemKind } from 'types/base/models/item-kind';
|
||||||
|
import type { ItemDtoQueryResult } from 'types/base/models/item-dto-query-result';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
const fetchGetItems = async (
|
const fetchGetItems = async (
|
||||||
currentApi: JellyfinApiContext,
|
currentApi: JellyfinApiContext,
|
||||||
|
@ -46,7 +48,7 @@ const fetchGetItems = async (
|
||||||
signal: options?.signal
|
signal: options?.signal
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data as ItemDtoQueryResult;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,7 +63,8 @@ export const useGetItems = (parametersOptions: ItemsApiGetItemsRequest) => {
|
||||||
],
|
],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) =>
|
||||||
fetchGetItems(currentApi, parametersOptions, { signal }),
|
fetchGetItems(currentApi, parametersOptions, { signal }),
|
||||||
gcTime: parametersOptions.sortBy?.includes(ItemSortBy.Random) ? 0 : undefined
|
gcTime: parametersOptions.sortBy?.includes(ItemSortBy.Random) ? 0 : undefined,
|
||||||
|
enabled: !!currentApi.api && !!currentApi.user?.Id
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,8 +98,8 @@ export const useGetMovieRecommendations = (isMovieRecommendationEnabled: boolean
|
||||||
const currentApi = useApi();
|
const currentApi = useApi();
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['MovieRecommendations', isMovieRecommendationEnabled, parentId],
|
queryKey: ['MovieRecommendations', isMovieRecommendationEnabled, parentId],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) => fetchGetMovieRecommendations(currentApi, parentId, { signal }),
|
||||||
isMovieRecommendationEnabled ? fetchGetMovieRecommendations(currentApi, parentId, { signal }) : []
|
enabled: !!currentApi.api && !!currentApi.user?.Id && isMovieRecommendationEnabled
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,7 +124,7 @@ const fetchGetGenres = async (
|
||||||
signal: options?.signal
|
signal: options?.signal
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data as ItemDtoQueryResult;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,7 +134,7 @@ export const useGetGenres = (itemType: BaseItemKind[], parentId: ParentId) => {
|
||||||
queryKey: ['Genres', parentId],
|
queryKey: ['Genres', parentId],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) =>
|
||||||
fetchGetGenres(currentApi, itemType, parentId, { signal }),
|
fetchGetGenres(currentApi, itemType, parentId, { signal }),
|
||||||
enabled: !!parentId
|
enabled: !!currentApi.api && !!currentApi.user?.Id && !!parentId
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,7 +173,7 @@ export const useGetStudios = (parentId: ParentId, itemType: BaseItemKind[]) => {
|
||||||
queryKey: ['Studios', parentId, itemType],
|
queryKey: ['Studios', parentId, itemType],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) =>
|
||||||
fetchGetStudios(currentApi, parentId, itemType, { signal }),
|
fetchGetStudios(currentApi, parentId, itemType, { signal }),
|
||||||
enabled: !!parentId && !isLivetv
|
enabled: !!currentApi.api && !!currentApi.user?.Id && !!parentId && !isLivetv
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,7 +211,7 @@ export const useGetQueryFiltersLegacy = (
|
||||||
fetchGetQueryFiltersLegacy(currentApi, parentId, itemType, {
|
fetchGetQueryFiltersLegacy(currentApi, parentId, itemType, {
|
||||||
signal
|
signal
|
||||||
}),
|
}),
|
||||||
enabled: !!parentId && !isLivetv
|
enabled: !!currentApi.api && !!currentApi.user?.Id && !!parentId && !isLivetv
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -334,7 +337,7 @@ const fetchGetItemsViewByType = async (
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response.data;
|
return response.data as ItemDtoQueryResult;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -366,8 +369,8 @@ export const useGetItemsViewByType = (
|
||||||
),
|
),
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
placeholderData : keepPreviousData,
|
placeholderData : keepPreviousData,
|
||||||
enabled:
|
enabled: !!currentApi.api && !!currentApi.user?.Id
|
||||||
[
|
&& [
|
||||||
LibraryTab.Movies,
|
LibraryTab.Movies,
|
||||||
LibraryTab.Favorites,
|
LibraryTab.Favorites,
|
||||||
LibraryTab.Collections,
|
LibraryTab.Collections,
|
||||||
|
@ -413,13 +416,13 @@ export const usePlaylistsMoveItemMutation = () => {
|
||||||
|
|
||||||
type GroupsUpcomingEpisodes = {
|
type GroupsUpcomingEpisodes = {
|
||||||
name: string;
|
name: string;
|
||||||
items: BaseItemDto[];
|
items: ItemDto[];
|
||||||
};
|
};
|
||||||
|
|
||||||
function groupsUpcomingEpisodes(items: BaseItemDto[]) {
|
function groupsUpcomingEpisodes(items: ItemDto[]) {
|
||||||
const groups: GroupsUpcomingEpisodes[] = [];
|
const groups: GroupsUpcomingEpisodes[] = [];
|
||||||
let currentGroupName = '';
|
let currentGroupName = '';
|
||||||
let currentGroup: BaseItemDto[] = [];
|
let currentGroup: ItemDto[] = [];
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
let dateText = '';
|
let dateText = '';
|
||||||
|
@ -483,7 +486,7 @@ const fetchGetGroupsUpcomingEpisodes = async (
|
||||||
signal: options?.signal
|
signal: options?.signal
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const items = response.data.Items ?? [];
|
const items = (response.data.Items as ItemDto[]) || [];
|
||||||
|
|
||||||
return groupsUpcomingEpisodes(items);
|
return groupsUpcomingEpisodes(items);
|
||||||
}
|
}
|
||||||
|
@ -495,7 +498,7 @@ export const useGetGroupsUpcomingEpisodes = (parentId: ParentId) => {
|
||||||
queryKey: ['GroupsUpcomingEpisodes', parentId],
|
queryKey: ['GroupsUpcomingEpisodes', parentId],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) =>
|
||||||
fetchGetGroupsUpcomingEpisodes(currentApi, parentId, { signal }),
|
fetchGetGroupsUpcomingEpisodes(currentApi, parentId, { signal }),
|
||||||
enabled: !!parentId
|
enabled: !!currentApi.api && !!currentApi.user?.Id && !!parentId
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -573,17 +576,17 @@ export const useTogglePlayedMutation = () => {
|
||||||
|
|
||||||
export type GroupsTimers = {
|
export type GroupsTimers = {
|
||||||
name: string;
|
name: string;
|
||||||
timerInfo: TimerInfoDto[];
|
timerInfo: ItemDto[];
|
||||||
};
|
};
|
||||||
|
|
||||||
function groupsTimers(timers: TimerInfoDto[], indexByDate?: boolean) {
|
function groupsTimers(timers: ItemDto[], indexByDate?: boolean) {
|
||||||
const items = timers.map(function (t) {
|
const items = timers.map(function (t) {
|
||||||
t.Type = 'Timer';
|
t.Type = ItemKind.Timer;
|
||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
const groups: GroupsTimers[] = [];
|
const groups: GroupsTimers[] = [];
|
||||||
let currentGroupName = '';
|
let currentGroupName = '';
|
||||||
let currentGroup: TimerInfoDto[] = [];
|
let currentGroup: ItemDto[] = [];
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
let dateText = '';
|
let dateText = '';
|
||||||
|
@ -642,7 +645,7 @@ const fetchGetTimers = async (
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const timers = response.data.Items ?? [];
|
const timers = (response.data.Items as ItemDto[]) || [];
|
||||||
|
|
||||||
return groupsTimers(timers, indexByDate);
|
return groupsTimers(timers, indexByDate);
|
||||||
}
|
}
|
||||||
|
@ -652,8 +655,8 @@ export const useGetTimers = (isUpcomingRecordingsEnabled: boolean, indexByDate?:
|
||||||
const currentApi = useApi();
|
const currentApi = useApi();
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['Timers', { isUpcomingRecordingsEnabled, indexByDate }],
|
queryKey: ['Timers', { isUpcomingRecordingsEnabled, indexByDate }],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) => fetchGetTimers(currentApi, indexByDate, { signal }),
|
||||||
isUpcomingRecordingsEnabled ? fetchGetTimers(currentApi, indexByDate, { signal }) : []
|
enabled: !!currentApi.api && !!currentApi.user?.Id && isUpcomingRecordingsEnabled
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -838,13 +841,13 @@ const fetchGetSectionItems = async (
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response;
|
return response as ItemDto[] || [] ;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type SectionWithItems = {
|
type SectionWithItems = {
|
||||||
section: Section;
|
section: Section;
|
||||||
items: BaseItemDto[];
|
items: ItemDto[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSectionsWithItems = async (
|
const getSectionsWithItems = async (
|
||||||
|
@ -886,7 +889,7 @@ export const useGetSuggestionSectionsWithItems = (
|
||||||
queryKey: ['SuggestionSectionWithItems', { suggestionSectionType }],
|
queryKey: ['SuggestionSectionWithItems', { suggestionSectionType }],
|
||||||
queryFn: ({ signal }) =>
|
queryFn: ({ signal }) =>
|
||||||
getSectionsWithItems(currentApi, parentId, sections, suggestionSectionType, { signal }),
|
getSectionsWithItems(currentApi, parentId, sections, suggestionSectionType, { signal }),
|
||||||
enabled: !!parentId
|
enabled: !!currentApi.api && !!currentApi.user?.Id && !!parentId
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -898,7 +901,7 @@ export const useGetProgramsSectionsWithItems = (
|
||||||
const sections = getProgramSections();
|
const sections = getProgramSections();
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['ProgramSectionWithItems', { programSectionType }],
|
queryKey: ['ProgramSectionWithItems', { programSectionType }],
|
||||||
queryFn: ({ signal }) => getSectionsWithItems(currentApi, parentId, sections, programSectionType, { signal })
|
queryFn: ({ signal }) => getSectionsWithItems(currentApi, parentId, sections, programSectionType, { signal }),
|
||||||
|
enabled: !!currentApi.api && !!currentApi.user?.Id
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||||
import type { AxiosRequestConfig } from 'axios';
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
|
|
||||||
import { useApi } from './useApi';
|
import { useApi } from './useApi';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
|
||||||
const fetchItem = async (
|
const fetchItem = async (
|
||||||
api?: Api,
|
api?: Api,
|
||||||
|
@ -16,7 +17,7 @@ const fetchItem = async (
|
||||||
|
|
||||||
const response = await getUserLibraryApi(api)
|
const response = await getUserLibraryApi(api)
|
||||||
.getItem({ userId, itemId }, options);
|
.getItem({ userId, itemId }, options);
|
||||||
return response.data;
|
return response.data as ItemDto;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getItemQuery = (
|
export const getItemQuery = (
|
||||||
|
|
7
src/types/base/models/item-dto-query-result.ts
Normal file
7
src/types/base/models/item-dto-query-result.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { ItemDto } from './item-dto';
|
||||||
|
|
||||||
|
export interface ItemDtoQueryResult {
|
||||||
|
Items?: Array<ItemDto>;
|
||||||
|
TotalRecordCount?: number;
|
||||||
|
StartIndex?: number;
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
import type { BaseItemDto, BaseItemKind, CollectionTypeOptions, RecordingStatus, SearchHint, SeriesTimerInfoDto, TimerInfoDto, UserItemDataDto, VirtualFolderInfo } from '@jellyfin/sdk/lib/generated-client';
|
import type { BaseItemDto, CollectionTypeOptions, SearchHint, SeriesTimerInfoDto, TimerInfoDto, UserItemDataDto, VirtualFolderInfo } from '@jellyfin/sdk/lib/generated-client';
|
||||||
|
import type { ItemStatus } from './item-status';
|
||||||
|
import type { ItemKind } from './item-kind';
|
||||||
|
import type { ItemMediaKind } from './item-media-kind';
|
||||||
|
|
||||||
type BaseItem = Omit<BaseItemDto, 'ChannelId' | 'EndDate' | 'Id' | 'StartDate' | 'Status' | 'Type' | 'Artists' | 'MediaType' | 'Name' | 'CollectionType'>;
|
type BaseItem = Omit<BaseItemDto, 'ChannelId' | 'EndDate' | 'Id' | 'StartDate' | 'Status' | 'Type' | 'Artists' | 'MediaType' | 'Name' | 'CollectionType' | 'CurrentProgram'>;
|
||||||
type TimerInfo = Omit<TimerInfoDto, 'ChannelId' | 'EndDate' | 'Id' | 'StartDate' | 'Status' | 'Type' | 'Name'>;
|
type TimerInfo = Omit<TimerInfoDto, 'ChannelId' | 'EndDate' | 'Id' | 'StartDate' | 'Status' | 'Type' | 'Name' | 'ProgramInfo'>;
|
||||||
type SeriesTimerInfo = Omit<SeriesTimerInfoDto, 'ChannelId' | 'EndDate' | 'Id' | 'StartDate' | 'Type' | 'Name'>;
|
type SeriesTimerInfo = Omit<SeriesTimerInfoDto, 'ChannelId' | 'EndDate' | 'Id' | 'StartDate' | 'Type' | 'Name'>;
|
||||||
type SearchHintItem = Omit<SearchHint, 'ItemId' |'Artists' | 'Id' | 'MediaType' | 'Name' | 'StartDate' | 'Type'>;
|
type SearchHintItem = Omit<SearchHint, 'ItemId' |'Artists' | 'Id' | 'MediaType' | 'Name' | 'StartDate' | 'Type'>;
|
||||||
type UserItem = Omit<UserItemDataDto, 'ItemId'>;
|
type UserItem = Omit<UserItemDataDto, 'ItemId'>;
|
||||||
|
@ -12,11 +15,13 @@ export interface ItemDto extends BaseItem, TimerInfo, SeriesTimerInfo, SearchHin
|
||||||
'EndDate'?: string | null;
|
'EndDate'?: string | null;
|
||||||
'Id'?: string | null;
|
'Id'?: string | null;
|
||||||
'StartDate'?: string | null;
|
'StartDate'?: string | null;
|
||||||
'Type'?: BaseItemKind | string | null;
|
'Type'?: ItemKind;
|
||||||
'Status'?: RecordingStatus | string | null;
|
'Status'?: ItemStatus;
|
||||||
'CollectionType'?: CollectionTypeOptions | string | null;
|
'CollectionType'?: CollectionTypeOptions | string | null;
|
||||||
'Artists'?: Array<string> | null;
|
'Artists'?: Array<string> | null;
|
||||||
'MediaType'?: string | null;
|
'MediaType'?: ItemMediaKind;
|
||||||
'Name'?: string | null;
|
'Name'?: string | null;
|
||||||
'ItemId'?: string | null;
|
'ItemId'?: string | null;
|
||||||
|
'ProgramInfo'?: ItemDto;
|
||||||
|
'CurrentProgram'?: ItemDto;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@ import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-ite
|
||||||
export const ItemKind = {
|
export const ItemKind = {
|
||||||
...BaseItemKind,
|
...BaseItemKind,
|
||||||
Timer: 'Timer',
|
Timer: 'Timer',
|
||||||
SeriesTimer: 'SeriesTimer'
|
SeriesTimer: 'SeriesTimer',
|
||||||
|
AudioPodcast: 'AudioPodcast'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||||
export type ItemKind = keyof typeof ItemKind;
|
export type ItemKind = typeof ItemKind[keyof typeof ItemKind] | undefined;
|
||||||
|
|
||||||
export type ItemType = ItemKind | null | undefined;
|
|
||||||
|
|
|
@ -10,6 +10,4 @@ export const ItemMediaKind = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||||
export type ItemMediaKind = keyof typeof ItemMediaKind;
|
export type ItemMediaKind = typeof ItemMediaKind[keyof typeof ItemMediaKind] | undefined;
|
||||||
|
|
||||||
export type ItemMediaType = ItemMediaKind | null | undefined;
|
|
||||||
|
|
10
src/types/base/models/item-status.ts
Normal file
10
src/types/base/models/item-status.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { RecordingStatus } from '@jellyfin/sdk/lib/generated-client/models/recording-status';
|
||||||
|
import { SeriesStatus } from '@jellyfin/sdk/lib/generated-client/models/series-status';
|
||||||
|
|
||||||
|
export const ItemStatus = {
|
||||||
|
...RecordingStatus,
|
||||||
|
...SeriesStatus
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||||
|
export type ItemStatus = typeof ItemStatus[keyof typeof ItemStatus] | undefined;
|
Loading…
Add table
Add a link
Reference in a new issue