mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add Secondary Media Info
This commit is contained in:
parent
fabfb9b173
commit
82d70763bb
5 changed files with 218 additions and 10 deletions
|
@ -1,24 +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 } = miscInfo;
|
||||||
'mediaInfoItem',
|
|
||||||
className,
|
const renderText = () => {
|
||||||
miscInfo?.cssClass
|
if (textAction) {
|
||||||
);
|
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, className)}>
|
||||||
{miscInfo?.text}
|
{renderText()}
|
||||||
</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;
|
|
@ -14,3 +14,12 @@ export interface PrimaryInfoOpts {
|
||||||
showVideo3DFormatInfo?: boolean;
|
showVideo3DFormatInfo?: boolean;
|
||||||
showPhotoSizeInfo?: boolean;
|
showPhotoSizeInfo?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SecondaryInfoOpts {
|
||||||
|
showProgramTimeInfo?: boolean;
|
||||||
|
showStartDateInfo?: boolean;
|
||||||
|
showEndDateInfo?: boolean;
|
||||||
|
showChannelNumberInfo?: boolean;
|
||||||
|
showChannelInfo?: boolean;
|
||||||
|
channelInteractive?: boolean;
|
||||||
|
}
|
||||||
|
|
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,10 @@
|
||||||
export interface MiscInfo {
|
interface TextAction {
|
||||||
text?: string | number;
|
url: string;
|
||||||
|
title: string;
|
||||||
|
cssClass?: string;
|
||||||
|
}
|
||||||
|
export interface MiscInfo {
|
||||||
|
text?: string | number;
|
||||||
|
textAction?: TextAction;
|
||||||
cssClass?: string;
|
cssClass?: string;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue