mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #5938 from grafixeyehero/Add-SecondaryMediaInfo&Stats
Add Secondary Media Info & Media Info Stats
This commit is contained in:
commit
e528847b7c
17 changed files with 738 additions and 188 deletions
|
@ -78,12 +78,13 @@ const ListContent: FC<ListContentProps> = ({
|
||||||
{listOptions.showMediaInfo !== false && enableSideMediaInfo && (
|
{listOptions.showMediaInfo !== false && enableSideMediaInfo && (
|
||||||
<PrimaryMediaInfo
|
<PrimaryMediaInfo
|
||||||
className='secondary listItemMediaInfo'
|
className='secondary listItemMediaInfo'
|
||||||
|
infoclass='mediaInfoText'
|
||||||
item={item}
|
item={item}
|
||||||
isRuntimeEnabled={true}
|
showRuntimeInfo
|
||||||
isStarRatingEnabled={true}
|
showOfficialRatingInfo
|
||||||
isCaptionIndicatorEnabled={true}
|
showOriginalAirDateInfo
|
||||||
isEpisodeTitleEnabled={true}
|
showStarRatingInfo
|
||||||
isOfficialRatingEnabled={true}
|
showCaptionIndicatorInfo
|
||||||
getMissingIndicator={indicator.getMissingIndicator}
|
getMissingIndicator={indicator.getMissingIndicator}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -61,10 +61,11 @@ const ListItemBody: FC<ListItemBodyProps> = ({
|
||||||
{listOptions.showMediaInfo !== false && !enableSideMediaInfo && (
|
{listOptions.showMediaInfo !== false && !enableSideMediaInfo && (
|
||||||
<PrimaryMediaInfo
|
<PrimaryMediaInfo
|
||||||
className='secondary listItemMediaInfo listItemBodyText'
|
className='secondary listItemMediaInfo listItemBodyText'
|
||||||
|
infoclass='mediaInfoText'
|
||||||
item={item}
|
item={item}
|
||||||
isEpisodeTitleEnabled={true}
|
showEpisodeTitleInfo
|
||||||
isOriginalAirDateEnabled={true}
|
showOriginalAirDateInfo
|
||||||
isCaptionIndicatorEnabled={true}
|
showCaptionIndicatorInfo
|
||||||
getMissingIndicator={getMissingIndicator}
|
getMissingIndicator={getMissingIndicator}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
.listItemMediaInfo {
|
.listItemMediaInfo {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.listItem {
|
.listItem {
|
||||||
|
|
|
@ -10,14 +10,13 @@ interface CaptionMediaInfoProps {
|
||||||
const CaptionMediaInfo: FC<CaptionMediaInfoProps> = ({ className }) => {
|
const CaptionMediaInfo: FC<CaptionMediaInfoProps> = ({ className }) => {
|
||||||
const cssClass = classNames(
|
const cssClass = classNames(
|
||||||
'mediaInfoItem',
|
'mediaInfoItem',
|
||||||
'mediaInfoText',
|
|
||||||
'closedCaptionMediaInfoText',
|
'closedCaptionMediaInfoText',
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className={cssClass}>
|
<Box className={cssClass}>
|
||||||
<ClosedCaptionIcon fontSize={'small'} />
|
<ClosedCaptionIcon />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,6 @@ interface EndsAtProps {
|
||||||
const EndsAt: FC<EndsAtProps> = ({ runTimeTicks, className }) => {
|
const EndsAt: FC<EndsAtProps> = ({ runTimeTicks, className }) => {
|
||||||
const cssClass = classNames(
|
const cssClass = classNames(
|
||||||
'mediaInfoItem',
|
'mediaInfoItem',
|
||||||
'mediaInfoText',
|
|
||||||
'endsAt',
|
'endsAt',
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,25 +1,38 @@
|
||||||
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 Link from '@mui/material/Link';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { MiscInfo } from 'types/mediaInfoItem';
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
|
||||||
interface MediaInfoItemProps {
|
interface MediaInfoItemProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
miscInfo?: MiscInfo ;
|
miscInfo: MiscInfo ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MediaInfoItem: FC<MediaInfoItemProps> = ({ className, miscInfo }) => {
|
const MediaInfoItem: FC<MediaInfoItemProps> = ({ className, miscInfo }) => {
|
||||||
const cssClass = classNames(
|
const { text, textAction, cssClass, type } = miscInfo;
|
||||||
'mediaInfoItem',
|
|
||||||
'mediaInfoText',
|
const renderText = () => {
|
||||||
className,
|
if (textAction) {
|
||||||
miscInfo?.cssClass
|
return (
|
||||||
);
|
<Link
|
||||||
|
className={classNames(textAction.cssClass, className)}
|
||||||
|
href={textAction.url}
|
||||||
|
title={textAction.title}
|
||||||
|
color='inherit'
|
||||||
|
>
|
||||||
|
{textAction.title}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className={cssClass}>
|
<Box className={classNames('mediaInfoItem', cssClass, type, className)}>
|
||||||
{miscInfo?.text}
|
{renderText()}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
49
src/components/mediainfo/MediaInfoStats.tsx
Normal file
49
src/components/mediainfo/MediaInfoStats.tsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import React, { type FC } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import useMediaInfoStats from './useMediaInfoStats';
|
||||||
|
|
||||||
|
import MediaInfoItem from './MediaInfoItem';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
import type { MediaInfoStatsOpts } from './type';
|
||||||
|
|
||||||
|
interface MediaInfoStatsProps extends MediaInfoStatsOpts {
|
||||||
|
className?: string;
|
||||||
|
infoclass?: string;
|
||||||
|
item: ItemDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MediaInfoStats: FC<MediaInfoStatsProps> = ({
|
||||||
|
className,
|
||||||
|
infoclass,
|
||||||
|
item,
|
||||||
|
showResolutionInfo,
|
||||||
|
showVideoStreamCodecInfo,
|
||||||
|
showAudoChannelInfo,
|
||||||
|
showAudioStreamCodecInfo,
|
||||||
|
showDateAddedInfo
|
||||||
|
}) => {
|
||||||
|
const mediaInfoStats = useMediaInfoStats({
|
||||||
|
item,
|
||||||
|
showResolutionInfo,
|
||||||
|
showVideoStreamCodecInfo,
|
||||||
|
showAudoChannelInfo,
|
||||||
|
showAudioStreamCodecInfo,
|
||||||
|
showDateAddedInfo
|
||||||
|
});
|
||||||
|
|
||||||
|
const cssClass = classNames(className);
|
||||||
|
|
||||||
|
const renderMediaInfo = (info: MiscInfo, index: number) => (
|
||||||
|
<MediaInfoItem key={index} className={infoclass} miscInfo={info} />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box className={cssClass}>
|
||||||
|
{mediaInfoStats.map((info, index) => renderMediaInfo(info, index))}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MediaInfoStats;
|
|
@ -12,54 +12,59 @@ import EndsAt from './EndsAt';
|
||||||
import { ItemMediaKind } from 'types/base/models/item-media-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 { MiscInfo } from 'types/mediaInfoItem';
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
import type { PrimaryInfoOpts } from './type';
|
||||||
|
|
||||||
interface PrimaryMediaInfoProps {
|
interface PrimaryMediaInfoProps extends PrimaryInfoOpts {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
infoclass?: string;
|
||||||
item: ItemDto;
|
item: ItemDto;
|
||||||
isYearEnabled?: boolean;
|
showStarRatingInfo?: boolean;
|
||||||
isContainerEnabled?: boolean;
|
showCaptionIndicatorInfo?: boolean;
|
||||||
isEpisodeTitleEnabled?: boolean;
|
showCriticRatingInfo?: boolean;
|
||||||
isCriticRatingEnabled?: boolean;
|
showEndsAtInfo?: boolean;
|
||||||
isEndsAtEnabled?: boolean;
|
getMissingIndicator?: () => React.JSX.Element | null;
|
||||||
isOriginalAirDateEnabled?: boolean;
|
|
||||||
isRuntimeEnabled?: boolean;
|
|
||||||
isProgramIndicatorEnabled?: boolean;
|
|
||||||
isEpisodeTitleIndexNumberEnabled?: boolean;
|
|
||||||
isOfficialRatingEnabled?: boolean;
|
|
||||||
isStarRatingEnabled?: boolean;
|
|
||||||
isCaptionIndicatorEnabled?: boolean;
|
|
||||||
isMissingIndicatorEnabled?: boolean;
|
|
||||||
getMissingIndicator: () => React.JSX.Element | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PrimaryMediaInfo: FC<PrimaryMediaInfoProps> = ({
|
const PrimaryMediaInfo: FC<PrimaryMediaInfoProps> = ({
|
||||||
className,
|
className,
|
||||||
|
infoclass,
|
||||||
item,
|
item,
|
||||||
isYearEnabled = false,
|
showYearInfo,
|
||||||
isContainerEnabled = false,
|
showAudioContainerInfo,
|
||||||
isEpisodeTitleEnabled = false,
|
showEpisodeTitleInfo,
|
||||||
isCriticRatingEnabled = false,
|
showOriginalAirDateInfo,
|
||||||
isEndsAtEnabled = false,
|
showFolderRuntimeInfo,
|
||||||
isOriginalAirDateEnabled = false,
|
showRuntimeInfo,
|
||||||
isRuntimeEnabled = false,
|
showItemCountInfo,
|
||||||
isProgramIndicatorEnabled = false,
|
showSeriesTimerInfo,
|
||||||
isEpisodeTitleIndexNumberEnabled = false,
|
showStartDateInfo,
|
||||||
isOfficialRatingEnabled = false,
|
showProgramIndicatorInfo,
|
||||||
isStarRatingEnabled = false,
|
includeEpisodeTitleIndexNumber,
|
||||||
isCaptionIndicatorEnabled = false,
|
showOfficialRatingInfo,
|
||||||
isMissingIndicatorEnabled = false,
|
showVideo3DFormatInfo,
|
||||||
|
showPhotoSizeInfo,
|
||||||
|
showStarRatingInfo = false,
|
||||||
|
showCaptionIndicatorInfo = false,
|
||||||
|
showCriticRatingInfo = false,
|
||||||
|
showEndsAtInfo = false,
|
||||||
getMissingIndicator
|
getMissingIndicator
|
||||||
}) => {
|
}) => {
|
||||||
const miscInfo = usePrimaryMediaInfo({
|
const miscInfo = usePrimaryMediaInfo({
|
||||||
item,
|
item,
|
||||||
isYearEnabled,
|
showYearInfo,
|
||||||
isContainerEnabled,
|
showAudioContainerInfo,
|
||||||
isEpisodeTitleEnabled,
|
showEpisodeTitleInfo,
|
||||||
isOriginalAirDateEnabled,
|
showOriginalAirDateInfo,
|
||||||
isRuntimeEnabled,
|
showFolderRuntimeInfo,
|
||||||
isProgramIndicatorEnabled,
|
showRuntimeInfo,
|
||||||
isEpisodeTitleIndexNumberEnabled,
|
showItemCountInfo,
|
||||||
isOfficialRatingEnabled
|
showSeriesTimerInfo,
|
||||||
|
showStartDateInfo,
|
||||||
|
showProgramIndicatorInfo,
|
||||||
|
includeEpisodeTitleIndexNumber,
|
||||||
|
showOfficialRatingInfo,
|
||||||
|
showVideo3DFormatInfo,
|
||||||
|
showPhotoSizeInfo
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
StartDate,
|
StartDate,
|
||||||
|
@ -72,32 +77,40 @@ const PrimaryMediaInfo: FC<PrimaryMediaInfoProps> = ({
|
||||||
|
|
||||||
const cssClass = classNames(className);
|
const cssClass = classNames(className);
|
||||||
|
|
||||||
const renderMediaInfo = (info: MiscInfo | undefined, index: number) => (
|
const renderMediaInfo = (info: MiscInfo, index: number) => (
|
||||||
<MediaInfoItem key={index} miscInfo={info} />
|
<MediaInfoItem key={index} className={infoclass} miscInfo={info} />
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className={cssClass}>
|
<Box className={cssClass}>
|
||||||
{miscInfo.map((info, index) => renderMediaInfo(info, index))}
|
{miscInfo.map((info, index) => renderMediaInfo(info, index))}
|
||||||
|
|
||||||
{isStarRatingEnabled && CommunityRating && (
|
{showStarRatingInfo && CommunityRating && (
|
||||||
<StarIcons communityRating={CommunityRating} />
|
<StarIcons
|
||||||
|
className={infoclass}
|
||||||
|
communityRating={CommunityRating}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{HasSubtitles && isCaptionIndicatorEnabled && <CaptionMediaInfo />}
|
{showCaptionIndicatorInfo && HasSubtitles && (
|
||||||
|
<CaptionMediaInfo className={infoclass} />
|
||||||
{CriticRating && isCriticRatingEnabled && (
|
|
||||||
<CriticRatingMediaInfo criticRating={CriticRating} />
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isEndsAtEnabled
|
{showCriticRatingInfo && CriticRating && (
|
||||||
|
<CriticRatingMediaInfo
|
||||||
|
className={infoclass}
|
||||||
|
criticRating={CriticRating}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showEndsAtInfo
|
||||||
&& MediaType === ItemMediaKind.Video
|
&& MediaType === ItemMediaKind.Video
|
||||||
&& RunTimeTicks
|
&& RunTimeTicks
|
||||||
&& !StartDate && <EndsAt runTimeTicks={RunTimeTicks} />}
|
&& !StartDate && (
|
||||||
|
<EndsAt className={infoclass} runTimeTicks={RunTimeTicks} />
|
||||||
{isMissingIndicatorEnabled && (
|
|
||||||
getMissingIndicator()
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{getMissingIndicator?.()}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
55
src/components/mediainfo/SecondaryMediaInfo.tsx
Normal file
55
src/components/mediainfo/SecondaryMediaInfo.tsx
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import React, { type FC } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import useSecondaryMediaInfo from './useSecondaryMediaInfo';
|
||||||
|
import useIndicator from 'components/indicators/useIndicator';
|
||||||
|
import MediaInfoItem from './MediaInfoItem';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
import { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
import type { SecondaryInfoOpts } from './type';
|
||||||
|
|
||||||
|
interface SecondaryMediaInfoProps extends SecondaryInfoOpts {
|
||||||
|
className?: string;
|
||||||
|
infoclass?: string;
|
||||||
|
item: ItemDto;
|
||||||
|
showTimerIndicatorInfo?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SecondaryMediaInfo: FC<SecondaryMediaInfoProps> = ({
|
||||||
|
className,
|
||||||
|
infoclass,
|
||||||
|
item,
|
||||||
|
showProgramTimeInfo,
|
||||||
|
showStartDateInfo,
|
||||||
|
showChannelNumberInfo,
|
||||||
|
showChannelInfo,
|
||||||
|
channelInteractive,
|
||||||
|
showTimerIndicatorInfo = false
|
||||||
|
}) => {
|
||||||
|
const miscInfo = useSecondaryMediaInfo({
|
||||||
|
item,
|
||||||
|
showProgramTimeInfo,
|
||||||
|
showStartDateInfo,
|
||||||
|
showChannelNumberInfo,
|
||||||
|
showChannelInfo,
|
||||||
|
channelInteractive
|
||||||
|
});
|
||||||
|
|
||||||
|
const indicator = useIndicator(item);
|
||||||
|
|
||||||
|
const cssClass = classNames(className);
|
||||||
|
|
||||||
|
const renderMediaInfo = (info: MiscInfo, index: number) => (
|
||||||
|
<MediaInfoItem key={index} className={infoclass} miscInfo={info} />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box className={cssClass}>
|
||||||
|
{miscInfo.map((info, index) => renderMediaInfo(info, index))}
|
||||||
|
|
||||||
|
{showTimerIndicatorInfo !== false && indicator.getTimerIndicator()}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SecondaryMediaInfo;
|
|
@ -13,16 +13,18 @@ const StarIcons: FC<StarIconsProps> = ({ className, communityRating }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const cssClass = classNames(
|
const cssClass = classNames(
|
||||||
'mediaInfoItem',
|
'mediaInfoItem',
|
||||||
'mediaInfoText',
|
|
||||||
'starRatingContainer',
|
'starRatingContainer',
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className={cssClass}>
|
<Box className={cssClass}>
|
||||||
<StarIcon fontSize={'small'} sx={{
|
<StarIcon
|
||||||
color: theme.palette.starIcon.main
|
fontSize={'small'}
|
||||||
}} />
|
sx={{
|
||||||
|
color: theme.palette.starIcon.main
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{communityRating.toFixed(1)}
|
{communityRating.toFixed(1)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
|
@ -271,7 +271,7 @@ export function getMediaInfoHtml(item, options = {}) {
|
||||||
if (options.officialRating !== false && item.OfficialRating && item.Type !== 'Season' && item.Type !== 'Episode') {
|
if (options.officialRating !== false && item.OfficialRating && item.Type !== 'Season' && item.Type !== 'Episode') {
|
||||||
miscInfo.push({
|
miscInfo.push({
|
||||||
text: item.OfficialRating,
|
text: item.OfficialRating,
|
||||||
cssClass: 'mediaInfoOfficialRating'
|
cssClass: 'mediaInfoText mediaInfoOfficialRating'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.starIcon {
|
.starIcon {
|
||||||
|
@ -94,15 +92,3 @@
|
||||||
.closedCaptionMediaInfoText {
|
.closedCaptionMediaInfoText {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mediaInfoOfficialRating {
|
|
||||||
border: 0.09em solid currentColor;
|
|
||||||
padding: 0 0.6em;
|
|
||||||
height: 1.3em;
|
|
||||||
line-height: 1.8em;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 0.1em;
|
|
||||||
font-size: 96%;
|
|
||||||
}
|
|
||||||
|
|
34
src/components/mediainfo/type.ts
Normal file
34
src/components/mediainfo/type.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
export interface PrimaryInfoOpts {
|
||||||
|
showYearInfo?: boolean;
|
||||||
|
showAudioContainerInfo?: boolean;
|
||||||
|
showEpisodeTitleInfo?: boolean;
|
||||||
|
includeEpisodeTitleIndexNumber?: boolean;
|
||||||
|
showOriginalAirDateInfo?: boolean;
|
||||||
|
showFolderRuntimeInfo?: boolean;
|
||||||
|
showRuntimeInfo?: boolean;
|
||||||
|
showItemCountInfo?: boolean;
|
||||||
|
showSeriesTimerInfo?: boolean;
|
||||||
|
showStartDateInfo?: boolean;
|
||||||
|
showProgramIndicatorInfo?: boolean;
|
||||||
|
showOfficialRatingInfo?: boolean;
|
||||||
|
showVideo3DFormatInfo?: boolean;
|
||||||
|
showPhotoSizeInfo?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SecondaryInfoOpts {
|
||||||
|
showProgramTimeInfo?: boolean;
|
||||||
|
showStartDateInfo?: boolean;
|
||||||
|
showEndDateInfo?: boolean;
|
||||||
|
showChannelNumberInfo?: boolean;
|
||||||
|
showChannelInfo?: boolean;
|
||||||
|
channelInteractive?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MediaInfoStatsOpts {
|
||||||
|
showVideoTypeInfo?: boolean;
|
||||||
|
showResolutionInfo?: boolean;
|
||||||
|
showVideoStreamCodecInfo?: boolean;
|
||||||
|
showAudoChannelInfo?: boolean;
|
||||||
|
showAudioStreamCodecInfo?: boolean;
|
||||||
|
showDateAddedInfo?: boolean;
|
||||||
|
}
|
229
src/components/mediainfo/useMediaInfoStats.tsx
Normal file
229
src/components/mediainfo/useMediaInfoStats.tsx
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
import { MediaStreamType } from '@jellyfin/sdk/lib/generated-client/models/media-stream-type';
|
||||||
|
import { VideoType } from '@jellyfin/sdk/lib/generated-client/models/video-type';
|
||||||
|
import type { MediaStream } from '@jellyfin/sdk/lib/generated-client/models/media-stream';
|
||||||
|
import itemHelper from 'components/itemHelper';
|
||||||
|
import datetime from 'scripts/datetime';
|
||||||
|
import globalize from 'lib/globalize';
|
||||||
|
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
import type { NullableString } from 'types/base/common/shared/types';
|
||||||
|
import type { MediaInfoStatsOpts } from './type';
|
||||||
|
|
||||||
|
const getResolution = (label: string, isInterlaced?: boolean) =>
|
||||||
|
isInterlaced ? `${label}i` : label;
|
||||||
|
|
||||||
|
const getResolutionText = (
|
||||||
|
showResolutionInfo: boolean,
|
||||||
|
stream: MediaStream
|
||||||
|
) => {
|
||||||
|
const { Width, Height, IsInterlaced } = stream;
|
||||||
|
|
||||||
|
if (showResolutionInfo && Width && Height) {
|
||||||
|
switch (true) {
|
||||||
|
case Width >= 3800 || Height >= 2000:
|
||||||
|
return '4K';
|
||||||
|
case Width >= 2500 || Height >= 1400:
|
||||||
|
return getResolution('1440p', IsInterlaced);
|
||||||
|
case Width >= 1800 || Height >= 1000:
|
||||||
|
return getResolution('1080p', IsInterlaced);
|
||||||
|
case Width >= 1200 || Height >= 700:
|
||||||
|
return getResolution('720p', IsInterlaced);
|
||||||
|
case Width >= 700 || Height >= 400:
|
||||||
|
return getResolution('480p', IsInterlaced);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAudoChannelText = (
|
||||||
|
showAudoChannelInfo: boolean,
|
||||||
|
stream: MediaStream
|
||||||
|
) => {
|
||||||
|
const { Channels } = stream;
|
||||||
|
|
||||||
|
if (showAudoChannelInfo && Channels) {
|
||||||
|
switch (true) {
|
||||||
|
case Channels === 8:
|
||||||
|
return '7.1';
|
||||||
|
case Channels === 7:
|
||||||
|
return '6.1';
|
||||||
|
case Channels === 6:
|
||||||
|
return '5.1';
|
||||||
|
case Channels === 2:
|
||||||
|
return '2.0';
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getAudioStreamForDisplay(item: ItemDto) {
|
||||||
|
const mediaSource = (item.MediaSources || [])[0] || {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
(mediaSource.MediaStreams || []).filter((i) => {
|
||||||
|
return (
|
||||||
|
i.Type === MediaStreamType.Audio
|
||||||
|
&& (i.Index === mediaSource.DefaultAudioStreamIndex
|
||||||
|
|| mediaSource.DefaultAudioStreamIndex == null)
|
||||||
|
);
|
||||||
|
})[0] || {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVideoStreamForDisplay(item: ItemDto) {
|
||||||
|
const mediaSource = (item.MediaSources || [])[0] || {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
(mediaSource.MediaStreams || []).filter((i) => {
|
||||||
|
return i.Type === MediaStreamType.Video;
|
||||||
|
})[0] || {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addVideoType(
|
||||||
|
showVideoTypeInfo: boolean,
|
||||||
|
itemVideoType: VideoType | undefined,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
if (showVideoTypeInfo) {
|
||||||
|
if (itemVideoType === VideoType.Dvd) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: 'Dvd' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemVideoType === VideoType.BluRay) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: 'BluRay' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResolution(
|
||||||
|
showResolutionInfo: boolean,
|
||||||
|
videoStream: MediaStream,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
const resolutionText = getResolutionText(showResolutionInfo, videoStream);
|
||||||
|
|
||||||
|
if (resolutionText) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: resolutionText });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addVideoStreamCodec(
|
||||||
|
showVideoCodecInfo: boolean,
|
||||||
|
videoStreamCodec: NullableString,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
if (showVideoCodecInfo && videoStreamCodec) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: videoStreamCodec });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addAudoChannel(
|
||||||
|
showAudoChannelInfo: boolean,
|
||||||
|
audioStream: MediaStream,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
const audioChannelText = getAudoChannelText(
|
||||||
|
showAudoChannelInfo,
|
||||||
|
audioStream
|
||||||
|
);
|
||||||
|
|
||||||
|
if (audioChannelText) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: audioChannelText });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addAudioStreamCodec(
|
||||||
|
showAudioStreamCodecInfo: boolean,
|
||||||
|
audioStream: MediaStream,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
const audioCodec = (audioStream.Codec || '').toLowerCase();
|
||||||
|
|
||||||
|
if (showAudioStreamCodecInfo) {
|
||||||
|
if (
|
||||||
|
(audioCodec === 'dca' || audioCodec === 'dts')
|
||||||
|
&& audioStream?.Profile
|
||||||
|
) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: audioStream.Profile });
|
||||||
|
} else if (audioStream?.Codec) {
|
||||||
|
addMiscInfo({ type: 'mediainfo', text: audioStream.Codec });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDateAdded(
|
||||||
|
showDateAddedInfo: boolean,
|
||||||
|
item: ItemDto,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
if (
|
||||||
|
showDateAddedInfo
|
||||||
|
&& item.DateCreated
|
||||||
|
&& itemHelper.enableDateAddedDisplay(item)
|
||||||
|
) {
|
||||||
|
const dateCreated = datetime.parseISO8601Date(item.DateCreated);
|
||||||
|
addMiscInfo({
|
||||||
|
type: 'added',
|
||||||
|
text: globalize.translate(
|
||||||
|
'AddedOnValue',
|
||||||
|
`${datetime.toLocaleDateString(
|
||||||
|
dateCreated
|
||||||
|
)} ${datetime.getDisplayTime(dateCreated)}`
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UseMediaInfoStatsProps extends MediaInfoStatsOpts {
|
||||||
|
item: ItemDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
function useMediaInfoStats({
|
||||||
|
item,
|
||||||
|
showVideoTypeInfo = false,
|
||||||
|
showResolutionInfo = false,
|
||||||
|
showVideoStreamCodecInfo = false,
|
||||||
|
showAudoChannelInfo = false,
|
||||||
|
showAudioStreamCodecInfo = false,
|
||||||
|
showDateAddedInfo = false
|
||||||
|
}: UseMediaInfoStatsProps) {
|
||||||
|
const miscInfo: MiscInfo[] = [];
|
||||||
|
|
||||||
|
const addMiscInfo = (val: MiscInfo) => {
|
||||||
|
if (val) {
|
||||||
|
miscInfo.push(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const videoStream = getVideoStreamForDisplay(item);
|
||||||
|
|
||||||
|
const audioStream = getAudioStreamForDisplay(item);
|
||||||
|
|
||||||
|
addVideoType(showVideoTypeInfo, item.VideoType, addMiscInfo);
|
||||||
|
|
||||||
|
addResolution(showResolutionInfo, videoStream, addMiscInfo);
|
||||||
|
|
||||||
|
addVideoStreamCodec(
|
||||||
|
showVideoStreamCodecInfo,
|
||||||
|
videoStream.Codec,
|
||||||
|
addMiscInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
addAudoChannel(showAudoChannelInfo, audioStream, addMiscInfo);
|
||||||
|
|
||||||
|
addAudioStreamCodec(showAudioStreamCodecInfo, audioStream, addMiscInfo);
|
||||||
|
|
||||||
|
addDateAdded(showDateAddedInfo, item, addMiscInfo);
|
||||||
|
|
||||||
|
return miscInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMediaInfoStats;
|
|
@ -6,41 +6,53 @@ import itemHelper from '../itemHelper';
|
||||||
import { ItemKind } from 'types/base/models/item-kind';
|
import { ItemKind } from 'types/base/models/item-kind';
|
||||||
import { ItemMediaKind } from 'types/base/models/item-media-kind';
|
import { ItemMediaKind } from 'types/base/models/item-media-kind';
|
||||||
import { ItemStatus } from 'types/base/models/item-status';
|
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';
|
||||||
|
import { PrimaryInfoOpts } from './type';
|
||||||
|
|
||||||
function shouldShowFolderRuntime(
|
function shouldShowFolderRuntime(
|
||||||
|
showFolderRuntimeInfo: boolean,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
itemMediaType: ItemMediaKind
|
itemMediaType: ItemMediaKind
|
||||||
): boolean {
|
): boolean {
|
||||||
return (
|
return (
|
||||||
itemType === ItemKind.MusicAlbum
|
showFolderRuntimeInfo
|
||||||
|| itemMediaType === ItemMediaKind.MusicArtist
|
&& (itemType === ItemKind.MusicAlbum
|
||||||
|| itemType === ItemKind.Playlist
|
|| itemMediaType === ItemMediaKind.MusicArtist
|
||||||
|| itemMediaType === ItemMediaKind.Playlist
|
|| itemType === ItemKind.Playlist
|
||||||
|| itemMediaType === ItemMediaKind.MusicGenre
|
|| itemMediaType === ItemMediaKind.Playlist
|
||||||
|
|| itemMediaType === ItemMediaKind.MusicGenre)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTrackCountOrItemCount(
|
function addTrackCountOrItemCount(
|
||||||
showFolderRuntime: boolean,
|
isFolderRuntimeEnabled: boolean,
|
||||||
|
showItemCountInfo: boolean,
|
||||||
itemSongCount: NullableNumber,
|
itemSongCount: NullableNumber,
|
||||||
itemChildCount: NullableNumber,
|
itemChildCount: NullableNumber,
|
||||||
itemRunTimeTicks: NullableNumber,
|
itemRunTimeTicks: NullableNumber,
|
||||||
itemType: NullableString,
|
itemType: ItemKind,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (showFolderRuntime) {
|
if (isFolderRuntimeEnabled) {
|
||||||
const count = itemSongCount ?? itemChildCount;
|
const count = itemSongCount || itemChildCount;
|
||||||
if (count) {
|
if (count) {
|
||||||
addMiscInfo({ text: globalize.translate('TrackCount', count) });
|
addMiscInfo({ text: globalize.translate('TrackCount', count) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemRunTimeTicks) {
|
if (itemRunTimeTicks) {
|
||||||
addMiscInfo({ text: datetime.getDisplayDuration(itemRunTimeTicks) });
|
addMiscInfo({
|
||||||
|
text: datetime.getDisplayDuration(itemRunTimeTicks)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (itemType === ItemKind.PhotoAlbum || itemType === ItemKind.BoxSet) {
|
} else if (
|
||||||
|
showItemCountInfo
|
||||||
|
&& (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) });
|
||||||
|
@ -49,16 +61,17 @@ function addTrackCountOrItemCount(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addOriginalAirDateInfo(
|
function addOriginalAirDateInfo(
|
||||||
|
showOriginalAirDateInfo: boolean,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
itemMediaType: ItemMediaKind,
|
itemMediaType: ItemMediaKind,
|
||||||
isOriginalAirDateEnabled: boolean,
|
|
||||||
itemPremiereDate: NullableString,
|
itemPremiereDate: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemPremiereDate
|
showOriginalAirDateInfo
|
||||||
&& (itemType === ItemKind.Episode || itemMediaType === ItemMediaKind.Photo)
|
&& (itemType === ItemKind.Episode
|
||||||
&& isOriginalAirDateEnabled
|
|| itemMediaType === ItemMediaKind.Photo)
|
||||||
|
&& itemPremiereDate
|
||||||
) {
|
) {
|
||||||
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
|
||||||
|
@ -74,6 +87,7 @@ function addOriginalAirDateInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSeriesTimerInfo(
|
function addSeriesTimerInfo(
|
||||||
|
showSeriesTimerInfo: boolean,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
itemRecordAnyTime: boolean | undefined,
|
itemRecordAnyTime: boolean | undefined,
|
||||||
itemStartDate: NullableString,
|
itemStartDate: NullableString,
|
||||||
|
@ -81,7 +95,7 @@ function addSeriesTimerInfo(
|
||||||
itemChannelName: NullableString,
|
itemChannelName: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemType === ItemKind.SeriesTimer) {
|
if (showSeriesTimerInfo && itemType === ItemKind.SeriesTimer) {
|
||||||
if (itemRecordAnyTime) {
|
if (itemRecordAnyTime) {
|
||||||
addMiscInfo({ text: globalize.translate('Anytime') });
|
addMiscInfo({ text: globalize.translate('Anytime') });
|
||||||
} else {
|
} else {
|
||||||
|
@ -92,7 +106,7 @@ function addSeriesTimerInfo(
|
||||||
addMiscInfo({ text: globalize.translate('AllChannels') });
|
addMiscInfo({ text: globalize.translate('AllChannels') });
|
||||||
} else {
|
} else {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: itemChannelName ?? globalize.translate('OneChannel')
|
text: itemChannelName || globalize.translate('OneChannel')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +118,7 @@ function addProgramIndicatorInfo(
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
program?.IsLive
|
program?.IsLive
|
||||||
&& userSettings.get('guide-indicator-live', false) === 'true'
|
&& userSettings.get('guide-indicator-live') === 'true'
|
||||||
) {
|
) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: globalize.translate('Live'),
|
text: globalize.translate('Live'),
|
||||||
|
@ -112,7 +126,7 @@ function addProgramIndicatorInfo(
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
program?.IsPremiere
|
program?.IsPremiere
|
||||||
&& userSettings.get('guide-indicator-premiere', false) === 'true'
|
&& userSettings.get('guide-indicator-premiere') === 'true'
|
||||||
) {
|
) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: globalize.translate('Premiere'),
|
text: globalize.translate('Premiere'),
|
||||||
|
@ -121,7 +135,7 @@ function addProgramIndicatorInfo(
|
||||||
} else if (
|
} else if (
|
||||||
program?.IsSeries
|
program?.IsSeries
|
||||||
&& !program?.IsRepeat
|
&& !program?.IsRepeat
|
||||||
&& userSettings.get('guide-indicator-new', false) === 'true'
|
&& userSettings.get('guide-indicator-new') === 'true'
|
||||||
) {
|
) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: globalize.translate('New'),
|
text: globalize.translate('New'),
|
||||||
|
@ -130,7 +144,7 @@ function addProgramIndicatorInfo(
|
||||||
} else if (
|
} else if (
|
||||||
program?.IsSeries
|
program?.IsSeries
|
||||||
&& program?.IsRepeat
|
&& program?.IsRepeat
|
||||||
&& userSettings.get('guide-indicator-repeat', false) === 'true'
|
&& userSettings.get('guide-indicator-repeat') === 'true'
|
||||||
) {
|
) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: globalize.translate('Repeat'),
|
text: globalize.translate('Repeat'),
|
||||||
|
@ -140,12 +154,12 @@ function addProgramIndicatorInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProgramIndicators(
|
function addProgramIndicators(
|
||||||
|
showYearInfo: boolean,
|
||||||
|
showEpisodeTitleInfo: boolean,
|
||||||
|
showOriginalAirDateInfo: boolean,
|
||||||
|
showProgramIndicatorInfo: boolean,
|
||||||
|
includeEpisodeTitleIndexNumber: boolean,
|
||||||
item: ItemDto,
|
item: ItemDto,
|
||||||
isYearEnabled: boolean,
|
|
||||||
isEpisodeTitleEnabled: boolean,
|
|
||||||
isOriginalAirDateEnabled: boolean,
|
|
||||||
isProgramIndicatorEnabled: boolean,
|
|
||||||
isEpisodeTitleIndexNumberEnabled: boolean,
|
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (item.Type === ItemKind.Program || item.Type === ItemKind.Timer) {
|
if (item.Type === ItemKind.Program || item.Type === ItemKind.Timer) {
|
||||||
|
@ -154,45 +168,43 @@ function addProgramIndicators(
|
||||||
program = item.ProgramInfo;
|
program = item.ProgramInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isProgramIndicatorEnabled !== false) {
|
if (showProgramIndicatorInfo) {
|
||||||
addProgramIndicatorInfo(program, addMiscInfo);
|
addProgramIndicatorInfo(program, addMiscInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
addProgramTextInfo(
|
addProgramTextInfo(
|
||||||
|
showEpisodeTitleInfo,
|
||||||
|
includeEpisodeTitleIndexNumber,
|
||||||
|
showOriginalAirDateInfo,
|
||||||
|
showYearInfo,
|
||||||
program,
|
program,
|
||||||
isEpisodeTitleEnabled,
|
|
||||||
isEpisodeTitleIndexNumberEnabled,
|
|
||||||
isOriginalAirDateEnabled,
|
|
||||||
isYearEnabled,
|
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProgramTextInfo(
|
function addProgramTextInfo(
|
||||||
|
showEpisodeTitleInfo: boolean,
|
||||||
|
includeEpisodeTitleIndexNumber: boolean,
|
||||||
|
showOriginalAirDateInfo: boolean,
|
||||||
|
showYearInfo: boolean,
|
||||||
program: ItemDto,
|
program: ItemDto,
|
||||||
isEpisodeTitleEnabled: boolean,
|
|
||||||
isEpisodeTitleIndexNumberEnabled: boolean,
|
|
||||||
isOriginalAirDateEnabled: boolean,
|
|
||||||
isYearEnabled: boolean,
|
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if ((program?.IsSeries || program?.EpisodeTitle)
|
if (showEpisodeTitleInfo && (program.IsSeries || program.EpisodeTitle)) {
|
||||||
&& isEpisodeTitleEnabled !== false) {
|
|
||||||
const text = itemHelper.getDisplayName(program, {
|
const text = itemHelper.getDisplayName(program, {
|
||||||
includeIndexNumber: isEpisodeTitleIndexNumberEnabled
|
includeIndexNumber: includeEpisodeTitleIndexNumber
|
||||||
});
|
});
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
addMiscInfo({ text: text });
|
addMiscInfo({ text: text });
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
program?.ProductionYear
|
((showOriginalAirDateInfo && program.IsMovie) || showYearInfo)
|
||||||
&& ((program?.IsMovie && isOriginalAirDateEnabled !== false)
|
&& program.ProductionYear
|
||||||
|| isYearEnabled !== false)
|
|
||||||
) {
|
) {
|
||||||
addMiscInfo({ text: program.ProductionYear });
|
addMiscInfo({ text: program.ProductionYear });
|
||||||
} else if (program?.PremiereDate && isOriginalAirDateEnabled !== false) {
|
} else if (showOriginalAirDateInfo && program.PremiereDate) {
|
||||||
try {
|
try {
|
||||||
const date = datetime.parseISO8601Date(program.PremiereDate);
|
const date = datetime.parseISO8601Date(program.PremiereDate);
|
||||||
const text = globalize.translate(
|
const text = globalize.translate(
|
||||||
|
@ -207,12 +219,14 @@ function addProgramTextInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStartDateInfo(
|
function addStartDateInfo(
|
||||||
|
showStartDateInfo: boolean,
|
||||||
itemStartDate: NullableString,
|
itemStartDate: NullableString,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemStartDate
|
showStartDateInfo
|
||||||
|
&& itemStartDate
|
||||||
&& itemType !== ItemKind.Program
|
&& itemType !== ItemKind.Program
|
||||||
&& itemType !== ItemKind.SeriesTimer
|
&& itemType !== ItemKind.SeriesTimer
|
||||||
&& itemType !== ItemKind.Timer
|
&& itemType !== ItemKind.Timer
|
||||||
|
@ -231,14 +245,14 @@ function addStartDateInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSeriesProductionYearInfo(
|
function addSeriesProductionYearInfo(
|
||||||
|
showYearInfo: boolean,
|
||||||
itemProductionYear: NullableNumber,
|
itemProductionYear: NullableNumber,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
isYearEnabled: boolean,
|
|
||||||
itemStatus: ItemStatus,
|
itemStatus: ItemStatus,
|
||||||
itemEndDate: NullableString,
|
itemEndDate: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemProductionYear && isYearEnabled && itemType === ItemKind.Series) {
|
if (showYearInfo && itemProductionYear && itemType === ItemKind.Series) {
|
||||||
if (itemStatus === ItemStatus.Continuing) {
|
if (itemStatus === ItemStatus.Continuing) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: globalize.translate(
|
text: globalize.translate(
|
||||||
|
@ -249,7 +263,11 @@ function addSeriesProductionYearInfo(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
addproductionYearWithEndDate(itemProductionYear, itemEndDate, addMiscInfo);
|
addproductionYearWithEndDate(
|
||||||
|
itemProductionYear,
|
||||||
|
itemEndDate,
|
||||||
|
addMiscInfo
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +299,7 @@ function addproductionYearWithEndDate(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addYearInfo(
|
function addYearInfo(
|
||||||
isYearEnabled: boolean,
|
showYearInfo: boolean,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
itemMediaType: ItemMediaKind,
|
itemMediaType: ItemMediaKind,
|
||||||
itemProductionYear: NullableNumber,
|
itemProductionYear: NullableNumber,
|
||||||
|
@ -289,7 +307,7 @@ function addYearInfo(
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
isYearEnabled
|
showYearInfo
|
||||||
&& itemType !== ItemKind.Series
|
&& itemType !== ItemKind.Series
|
||||||
&& itemType !== ItemKind.Episode
|
&& itemType !== ItemKind.Episode
|
||||||
&& itemType !== ItemKind.Person
|
&& itemType !== ItemKind.Person
|
||||||
|
@ -314,103 +332,116 @@ function addYearInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addVideo3DFormat(
|
function addVideo3DFormat(
|
||||||
|
showVideo3DFormatInfo: boolean,
|
||||||
itemVideo3DFormat: NullableString,
|
itemVideo3DFormat: NullableString,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemVideo3DFormat) {
|
if (showVideo3DFormatInfo && itemVideo3DFormat) {
|
||||||
addMiscInfo({ text: '3D' });
|
addMiscInfo({ text: '3D' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRunTimeInfo(
|
function addRunTimeInfo(
|
||||||
|
isFolderRuntimeEnabled: boolean,
|
||||||
|
showRuntimeInfo: boolean,
|
||||||
itemRunTimeTicks: NullableNumber,
|
itemRunTimeTicks: NullableNumber,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
showFolderRuntime: boolean,
|
|
||||||
isRuntimeEnabled: boolean,
|
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemRunTimeTicks
|
!isFolderRuntimeEnabled
|
||||||
|
&& showRuntimeInfo
|
||||||
|
&& itemRunTimeTicks
|
||||||
&& itemType !== ItemKind.Series
|
&& itemType !== ItemKind.Series
|
||||||
&& itemType !== ItemKind.Program
|
&& itemType !== ItemKind.Program
|
||||||
&& itemType !== ItemKind.Timer
|
&& itemType !== ItemKind.Timer
|
||||||
&& itemType !== ItemKind.Book
|
&& itemType !== ItemKind.Book
|
||||||
&& !showFolderRuntime
|
|
||||||
&& isRuntimeEnabled
|
|
||||||
) {
|
) {
|
||||||
if (itemType === ItemKind.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)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addOfficialRatingInfo(
|
function addOfficialRatingInfo(
|
||||||
|
showOfficialRatingInfo: boolean,
|
||||||
itemOfficialRating: NullableString,
|
itemOfficialRating: NullableString,
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
isOfficialRatingEnabled: boolean,
|
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (
|
if (
|
||||||
itemOfficialRating
|
showOfficialRatingInfo
|
||||||
&& isOfficialRatingEnabled
|
&& itemOfficialRating
|
||||||
&& itemType !== ItemKind.Season
|
&& itemType !== ItemKind.Season
|
||||||
&& itemType !== ItemKind.Episode
|
&& itemType !== ItemKind.Episode
|
||||||
) {
|
) {
|
||||||
addMiscInfo({
|
addMiscInfo({
|
||||||
text: itemOfficialRating,
|
text: itemOfficialRating,
|
||||||
cssClass: 'mediaInfoOfficialRating'
|
cssClass: 'mediaInfoText mediaInfoOfficialRating'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAudioContainer(
|
function addAudioContainer(
|
||||||
|
showAudioContainerInfo: boolean,
|
||||||
itemContainer: NullableString,
|
itemContainer: NullableString,
|
||||||
isContainerEnabled: boolean,
|
|
||||||
itemType: ItemKind,
|
itemType: ItemKind,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemContainer && isContainerEnabled && itemType === ItemKind.Audio) {
|
if (
|
||||||
|
showAudioContainerInfo
|
||||||
|
&& itemContainer
|
||||||
|
&& itemType === ItemKind.Audio
|
||||||
|
) {
|
||||||
addMiscInfo({ text: itemContainer });
|
addMiscInfo({ text: itemContainer });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPhotoSize(
|
function addPhotoSize(
|
||||||
|
showPhotoSizeInfo: boolean,
|
||||||
itemMediaType: ItemMediaKind,
|
itemMediaType: ItemMediaKind,
|
||||||
itemWidth: NullableNumber,
|
itemWidth: NullableNumber,
|
||||||
itemHeight: NullableNumber,
|
itemHeight: NullableNumber,
|
||||||
addMiscInfo: (val: MiscInfo) => void
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
): void {
|
): void {
|
||||||
if (itemMediaType === ItemMediaKind.Photo && itemWidth && itemHeight) {
|
if (
|
||||||
|
showPhotoSizeInfo
|
||||||
|
&& itemMediaType === ItemMediaKind.Photo
|
||||||
|
&& itemWidth
|
||||||
|
&& itemHeight
|
||||||
|
) {
|
||||||
const size = `${itemWidth}x${itemHeight}`;
|
const size = `${itemWidth}x${itemHeight}`;
|
||||||
|
|
||||||
addMiscInfo({ text: size });
|
addMiscInfo({ text: size });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UsePrimaryMediaInfoProps {
|
interface UsePrimaryMediaInfoProps extends PrimaryInfoOpts {
|
||||||
item: ItemDto;
|
item: ItemDto;
|
||||||
isYearEnabled: boolean;
|
|
||||||
isContainerEnabled: boolean;
|
|
||||||
isEpisodeTitleEnabled: boolean;
|
|
||||||
isOriginalAirDateEnabled: boolean;
|
|
||||||
isRuntimeEnabled: boolean;
|
|
||||||
isProgramIndicatorEnabled: boolean;
|
|
||||||
isEpisodeTitleIndexNumberEnabled: boolean;
|
|
||||||
isOfficialRatingEnabled: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function usePrimaryMediaInfo({
|
function usePrimaryMediaInfo({
|
||||||
item,
|
item,
|
||||||
isYearEnabled = false,
|
showYearInfo = false,
|
||||||
isContainerEnabled = false,
|
showAudioContainerInfo = false,
|
||||||
isEpisodeTitleEnabled = false,
|
showEpisodeTitleInfo = false,
|
||||||
isOriginalAirDateEnabled = false,
|
showOriginalAirDateInfo = false,
|
||||||
isRuntimeEnabled = false,
|
showFolderRuntimeInfo = false,
|
||||||
isProgramIndicatorEnabled = false,
|
showRuntimeInfo = false,
|
||||||
isEpisodeTitleIndexNumberEnabled = false,
|
showItemCountInfo = false,
|
||||||
isOfficialRatingEnabled = false
|
showSeriesTimerInfo = false,
|
||||||
|
showStartDateInfo = false,
|
||||||
|
showProgramIndicatorInfo = false,
|
||||||
|
includeEpisodeTitleIndexNumber = false,
|
||||||
|
showOfficialRatingInfo = false,
|
||||||
|
showVideo3DFormatInfo = false,
|
||||||
|
showPhotoSizeInfo = false
|
||||||
}: UsePrimaryMediaInfoProps) {
|
}: UsePrimaryMediaInfoProps) {
|
||||||
const {
|
const {
|
||||||
EndDate,
|
EndDate,
|
||||||
|
@ -441,10 +472,15 @@ function usePrimaryMediaInfo({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showFolderRuntime = shouldShowFolderRuntime(Type, MediaType);
|
const isFolderRuntimeEnabled = shouldShowFolderRuntime(
|
||||||
|
showFolderRuntimeInfo,
|
||||||
|
Type,
|
||||||
|
MediaType
|
||||||
|
);
|
||||||
|
|
||||||
addTrackCountOrItemCount(
|
addTrackCountOrItemCount(
|
||||||
showFolderRuntime,
|
isFolderRuntimeEnabled,
|
||||||
|
showItemCountInfo,
|
||||||
SongCount,
|
SongCount,
|
||||||
ChildCount,
|
ChildCount,
|
||||||
RunTimeTicks,
|
RunTimeTicks,
|
||||||
|
@ -453,14 +489,15 @@ function usePrimaryMediaInfo({
|
||||||
);
|
);
|
||||||
|
|
||||||
addOriginalAirDateInfo(
|
addOriginalAirDateInfo(
|
||||||
|
showOriginalAirDateInfo,
|
||||||
Type,
|
Type,
|
||||||
MediaType,
|
MediaType,
|
||||||
isOriginalAirDateEnabled,
|
|
||||||
PremiereDate,
|
PremiereDate,
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
addSeriesTimerInfo(
|
addSeriesTimerInfo(
|
||||||
|
showSeriesTimerInfo,
|
||||||
Type,
|
Type,
|
||||||
RecordAnyTime,
|
RecordAnyTime,
|
||||||
StartDate,
|
StartDate,
|
||||||
|
@ -469,29 +506,29 @@ function usePrimaryMediaInfo({
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
addStartDateInfo(StartDate, Type, addMiscInfo);
|
addStartDateInfo(showStartDateInfo, StartDate, Type, addMiscInfo);
|
||||||
|
|
||||||
addSeriesProductionYearInfo(
|
addSeriesProductionYearInfo(
|
||||||
|
showYearInfo,
|
||||||
ProductionYear,
|
ProductionYear,
|
||||||
Type,
|
Type,
|
||||||
isYearEnabled,
|
|
||||||
Status,
|
Status,
|
||||||
EndDate,
|
EndDate,
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
addProgramIndicators(
|
addProgramIndicators(
|
||||||
|
showProgramIndicatorInfo,
|
||||||
|
showEpisodeTitleInfo,
|
||||||
|
includeEpisodeTitleIndexNumber,
|
||||||
|
showOriginalAirDateInfo,
|
||||||
|
showYearInfo,
|
||||||
item,
|
item,
|
||||||
isProgramIndicatorEnabled,
|
|
||||||
isEpisodeTitleEnabled,
|
|
||||||
isEpisodeTitleIndexNumberEnabled,
|
|
||||||
isOriginalAirDateEnabled,
|
|
||||||
isYearEnabled,
|
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
addYearInfo(
|
addYearInfo(
|
||||||
isYearEnabled,
|
showYearInfo,
|
||||||
Type,
|
Type,
|
||||||
MediaType,
|
MediaType,
|
||||||
ProductionYear,
|
ProductionYear,
|
||||||
|
@ -500,25 +537,25 @@ function usePrimaryMediaInfo({
|
||||||
);
|
);
|
||||||
|
|
||||||
addRunTimeInfo(
|
addRunTimeInfo(
|
||||||
|
isFolderRuntimeEnabled,
|
||||||
|
showRuntimeInfo,
|
||||||
RunTimeTicks,
|
RunTimeTicks,
|
||||||
Type,
|
Type,
|
||||||
showFolderRuntime,
|
|
||||||
isRuntimeEnabled,
|
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
addOfficialRatingInfo(
|
addOfficialRatingInfo(
|
||||||
|
showOfficialRatingInfo,
|
||||||
OfficialRating,
|
OfficialRating,
|
||||||
Type,
|
Type,
|
||||||
isOfficialRatingEnabled,
|
|
||||||
addMiscInfo
|
addMiscInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
addVideo3DFormat(Video3DFormat, addMiscInfo);
|
addVideo3DFormat(showVideo3DFormatInfo, Video3DFormat, addMiscInfo);
|
||||||
|
|
||||||
addPhotoSize(MediaType, Width, Height, addMiscInfo);
|
addPhotoSize(showPhotoSizeInfo, MediaType, Width, Height, addMiscInfo);
|
||||||
|
|
||||||
addAudioContainer(Container, isContainerEnabled, Type, addMiscInfo);
|
addAudioContainer(showAudioContainerInfo, Container, Type, addMiscInfo);
|
||||||
|
|
||||||
return miscInfo;
|
return miscInfo;
|
||||||
}
|
}
|
||||||
|
|
124
src/components/mediainfo/useSecondaryMediaInfo.tsx
Normal file
124
src/components/mediainfo/useSecondaryMediaInfo.tsx
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
import datetime from 'scripts/datetime';
|
||||||
|
import { appRouter } from 'components/router/appRouter';
|
||||||
|
import type { NullableString } from 'types/base/common/shared/types';
|
||||||
|
import type { ItemDto } from 'types/base/models/item-dto';
|
||||||
|
import type { MiscInfo } from 'types/mediaInfoItem';
|
||||||
|
import { ItemKind } from 'types/base/models/item-kind';
|
||||||
|
import type { SecondaryInfoOpts } from './type';
|
||||||
|
|
||||||
|
function addProgramTime(
|
||||||
|
showProgramTimeInfo: boolean,
|
||||||
|
showStartDateInfo: boolean,
|
||||||
|
showEndDateInfo: boolean,
|
||||||
|
itemStartDate: NullableString,
|
||||||
|
itemEndDate: NullableString,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
let programTimeText = '';
|
||||||
|
let date;
|
||||||
|
|
||||||
|
if (showProgramTimeInfo && itemStartDate) {
|
||||||
|
try {
|
||||||
|
date = datetime.parseISO8601Date(itemStartDate);
|
||||||
|
|
||||||
|
if (showStartDateInfo) {
|
||||||
|
programTimeText += datetime.toLocaleDateString(date, {
|
||||||
|
weekday: 'short',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
programTimeText += ` ${datetime.getDisplayTime(date)}`;
|
||||||
|
|
||||||
|
if (showEndDateInfo && itemEndDate) {
|
||||||
|
date = datetime.parseISO8601Date(itemEndDate);
|
||||||
|
programTimeText += ` - ${datetime.getDisplayTime(date)}`;
|
||||||
|
}
|
||||||
|
addMiscInfo({ text: programTimeText });
|
||||||
|
} catch (e) {
|
||||||
|
console.error('error parsing date:', itemStartDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addChannelNumber(
|
||||||
|
showChannelNumberInfo: boolean,
|
||||||
|
itemChannelNumber: NullableString,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
): void {
|
||||||
|
if (showChannelNumberInfo && itemChannelNumber) {
|
||||||
|
addMiscInfo({
|
||||||
|
text: `CH ${itemChannelNumber}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addChannelName = (
|
||||||
|
showChannelInfo: boolean,
|
||||||
|
channelInteractive: boolean,
|
||||||
|
item: ItemDto,
|
||||||
|
addMiscInfo: (val: MiscInfo) => void
|
||||||
|
) => {
|
||||||
|
if (showChannelInfo && item.ChannelName) {
|
||||||
|
if (channelInteractive && item.ChannelId) {
|
||||||
|
const url = appRouter.getRouteUrl({
|
||||||
|
ServerId: item.ServerId,
|
||||||
|
Type: ItemKind.TvChannel,
|
||||||
|
Name: item.ChannelName,
|
||||||
|
Id: item.ChannelId
|
||||||
|
});
|
||||||
|
|
||||||
|
addMiscInfo({
|
||||||
|
textAction: {
|
||||||
|
url,
|
||||||
|
title: item.ChannelName
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addMiscInfo({ text: item.ChannelName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface UseSecondaryMediaInfoProps extends SecondaryInfoOpts {
|
||||||
|
item: ItemDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
function useSecondaryMediaInfo({
|
||||||
|
item,
|
||||||
|
showProgramTimeInfo = false,
|
||||||
|
showStartDateInfo = false,
|
||||||
|
showEndDateInfo = false,
|
||||||
|
showChannelNumberInfo = false,
|
||||||
|
showChannelInfo = false,
|
||||||
|
channelInteractive = false
|
||||||
|
}: UseSecondaryMediaInfoProps) {
|
||||||
|
const { EndDate, StartDate, ChannelNumber } = item;
|
||||||
|
|
||||||
|
const miscInfo: MiscInfo[] = [];
|
||||||
|
|
||||||
|
if (item.Type === ItemKind.Program) {
|
||||||
|
const addMiscInfo = (val: MiscInfo) => {
|
||||||
|
if (val) {
|
||||||
|
miscInfo.push(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addProgramTime(
|
||||||
|
showProgramTimeInfo,
|
||||||
|
showStartDateInfo,
|
||||||
|
showEndDateInfo,
|
||||||
|
StartDate,
|
||||||
|
EndDate,
|
||||||
|
addMiscInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
addChannelNumber(showChannelNumberInfo, ChannelNumber, addMiscInfo);
|
||||||
|
|
||||||
|
addChannelName(showChannelInfo, channelInteractive, item, addMiscInfo);
|
||||||
|
}
|
||||||
|
return miscInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useSecondaryMediaInfo;
|
|
@ -1,4 +1,11 @@
|
||||||
export interface MiscInfo {
|
interface TextAction {
|
||||||
text?: string | number;
|
url: string;
|
||||||
|
title: string;
|
||||||
|
cssClass?: string;
|
||||||
|
}
|
||||||
|
export interface MiscInfo {
|
||||||
|
text?: string | number;
|
||||||
|
type?: string;
|
||||||
|
textAction?: TextAction;
|
||||||
cssClass?: string;
|
cssClass?: string;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue