From a3eff3c0ae94aaf43293ef9964be6da223bc9c5b Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 10 Aug 2024 04:09:59 +0300 Subject: [PATCH 1/5] Update PrimaryMediaInfo option naming --- src/components/listview/List/ListContent.tsx | 10 +- src/components/listview/List/ListItemBody.tsx | 6 +- src/components/mediainfo/PrimaryMediaInfo.tsx | 76 +++++----- src/components/mediainfo/type.ts | 10 ++ .../mediainfo/usePrimaryMediaInfo.tsx | 131 +++++++++--------- 5 files changed, 116 insertions(+), 117 deletions(-) create mode 100644 src/components/mediainfo/type.ts diff --git a/src/components/listview/List/ListContent.tsx b/src/components/listview/List/ListContent.tsx index 6d4d49b83a..4e257c5003 100644 --- a/src/components/listview/List/ListContent.tsx +++ b/src/components/listview/List/ListContent.tsx @@ -79,11 +79,11 @@ const ListContent: FC = ({ )} diff --git a/src/components/listview/List/ListItemBody.tsx b/src/components/listview/List/ListItemBody.tsx index ef44c5a76a..93e90a5e32 100644 --- a/src/components/listview/List/ListItemBody.tsx +++ b/src/components/listview/List/ListItemBody.tsx @@ -62,9 +62,9 @@ const ListItemBody: FC = ({ )} diff --git a/src/components/mediainfo/PrimaryMediaInfo.tsx b/src/components/mediainfo/PrimaryMediaInfo.tsx index 74a1af2fbb..5f8aca0941 100644 --- a/src/components/mediainfo/PrimaryMediaInfo.tsx +++ b/src/components/mediainfo/PrimaryMediaInfo.tsx @@ -12,54 +12,46 @@ import EndsAt from './EndsAt'; import { ItemMediaKind } from 'types/base/models/item-media-kind'; import type { ItemDto } from 'types/base/models/item-dto'; import type { MiscInfo } from 'types/mediaInfoItem'; +import type { PrimaryInfoOpts } from './type'; -interface PrimaryMediaInfoProps { +interface PrimaryMediaInfoProps extends PrimaryInfoOpts { className?: string; item: ItemDto; - isYearEnabled?: boolean; - isContainerEnabled?: boolean; - isEpisodeTitleEnabled?: boolean; - isCriticRatingEnabled?: boolean; - isEndsAtEnabled?: boolean; - isOriginalAirDateEnabled?: boolean; - isRuntimeEnabled?: boolean; - isProgramIndicatorEnabled?: boolean; - isEpisodeTitleIndexNumberEnabled?: boolean; - isOfficialRatingEnabled?: boolean; - isStarRatingEnabled?: boolean; - isCaptionIndicatorEnabled?: boolean; - isMissingIndicatorEnabled?: boolean; - getMissingIndicator: () => React.JSX.Element | null + showStarRatingInfo?: boolean; + showCaptionIndicatorInfo?: boolean; + showCriticRatingInfo?: boolean; + showEndsAtInfo?: boolean; + showMissingIndicatorInfo?: boolean; + getMissingIndicator?: () => React.JSX.Element | null } const PrimaryMediaInfo: FC = ({ className, item, - isYearEnabled = false, - isContainerEnabled = false, - isEpisodeTitleEnabled = false, - isCriticRatingEnabled = false, - isEndsAtEnabled = false, - isOriginalAirDateEnabled = false, - isRuntimeEnabled = false, - isProgramIndicatorEnabled = false, - isEpisodeTitleIndexNumberEnabled = false, - isOfficialRatingEnabled = false, - isStarRatingEnabled = false, - isCaptionIndicatorEnabled = false, - isMissingIndicatorEnabled = false, + showYearInfo, + showAudioContainerInfo, + showEpisodeTitleInfo, + showOriginalAirDateInfo, + showRuntimeInfo, + showProgramIndicatorInfo, + includeEpisodeTitleIndexNumber, + showOfficialRatingInfo, + showStarRatingInfo = false, + showCaptionIndicatorInfo = false, + showCriticRatingInfo = false, + showEndsAtInfo = false, getMissingIndicator }) => { const miscInfo = usePrimaryMediaInfo({ item, - isYearEnabled, - isContainerEnabled, - isEpisodeTitleEnabled, - isOriginalAirDateEnabled, - isRuntimeEnabled, - isProgramIndicatorEnabled, - isEpisodeTitleIndexNumberEnabled, - isOfficialRatingEnabled + showYearInfo, + showAudioContainerInfo, + showEpisodeTitleInfo, + showOriginalAirDateInfo, + showRuntimeInfo, + showProgramIndicatorInfo, + includeEpisodeTitleIndexNumber, + showOfficialRatingInfo }); const { StartDate, @@ -80,24 +72,22 @@ const PrimaryMediaInfo: FC = ({ {miscInfo.map((info, index) => renderMediaInfo(info, index))} - {isStarRatingEnabled && CommunityRating && ( + {showStarRatingInfo && CommunityRating && ( )} - {HasSubtitles && isCaptionIndicatorEnabled && } + {showCaptionIndicatorInfo && HasSubtitles && } - {CriticRating && isCriticRatingEnabled && ( + {showCriticRatingInfo && CriticRating && ( )} - {isEndsAtEnabled + {showEndsAtInfo && MediaType === ItemMediaKind.Video && RunTimeTicks && !StartDate && } - {isMissingIndicatorEnabled && ( - getMissingIndicator() - )} + {getMissingIndicator?.()} ); }; diff --git a/src/components/mediainfo/type.ts b/src/components/mediainfo/type.ts new file mode 100644 index 0000000000..4bb8aee9f8 --- /dev/null +++ b/src/components/mediainfo/type.ts @@ -0,0 +1,10 @@ +export interface PrimaryInfoOpts { + showYearInfo?: boolean; + showAudioContainerInfo?: boolean; + showEpisodeTitleInfo?: boolean; + includeEpisodeTitleIndexNumber?: boolean; + showOriginalAirDateInfo?: boolean; + showRuntimeInfo?: boolean; + showProgramIndicatorInfo?: boolean; + showOfficialRatingInfo?: boolean; +} diff --git a/src/components/mediainfo/usePrimaryMediaInfo.tsx b/src/components/mediainfo/usePrimaryMediaInfo.tsx index b79ecf503b..327fbc4412 100644 --- a/src/components/mediainfo/usePrimaryMediaInfo.tsx +++ b/src/components/mediainfo/usePrimaryMediaInfo.tsx @@ -9,6 +9,7 @@ import { ItemStatus } from 'types/base/models/item-status'; import type { NullableNumber, NullableString } from 'types/base/common/shared/types'; import type { ItemDto } from 'types/base/models/item-dto'; import type { MiscInfo } from 'types/mediaInfoItem'; +import { PrimaryInfoOpts } from './type'; function shouldShowFolderRuntime( itemType: ItemKind, @@ -28,7 +29,7 @@ function addTrackCountOrItemCount( itemSongCount: NullableNumber, itemChildCount: NullableNumber, itemRunTimeTicks: NullableNumber, - itemType: NullableString, + itemType: ItemKind, addMiscInfo: (val: MiscInfo) => void ): void { if (showFolderRuntime) { @@ -51,14 +52,14 @@ function addTrackCountOrItemCount( function addOriginalAirDateInfo( itemType: ItemKind, itemMediaType: ItemMediaKind, - isOriginalAirDateEnabled: boolean, + showOriginalAirDateInfo: boolean, itemPremiereDate: NullableString, addMiscInfo: (val: MiscInfo) => void ): void { if ( itemPremiereDate && (itemType === ItemKind.Episode || itemMediaType === ItemMediaKind.Photo) - && isOriginalAirDateEnabled + && showOriginalAirDateInfo ) { try { //don't modify date to locale if episode. Only Dates (not times) are stored, or editable in the edit metadata dialog @@ -104,7 +105,7 @@ function addProgramIndicatorInfo( ): void { if ( program?.IsLive - && userSettings.get('guide-indicator-live', false) === 'true' + && userSettings.get('guide-indicator-live') === 'true' ) { addMiscInfo({ text: globalize.translate('Live'), @@ -112,7 +113,7 @@ function addProgramIndicatorInfo( }); } else if ( program?.IsPremiere - && userSettings.get('guide-indicator-premiere', false) === 'true' + && userSettings.get('guide-indicator-premiere') === 'true' ) { addMiscInfo({ text: globalize.translate('Premiere'), @@ -121,7 +122,7 @@ function addProgramIndicatorInfo( } else if ( program?.IsSeries && !program?.IsRepeat - && userSettings.get('guide-indicator-new', false) === 'true' + && userSettings.get('guide-indicator-new') === 'true' ) { addMiscInfo({ text: globalize.translate('New'), @@ -130,7 +131,7 @@ function addProgramIndicatorInfo( } else if ( program?.IsSeries && program?.IsRepeat - && userSettings.get('guide-indicator-repeat', false) === 'true' + && userSettings.get('guide-indicator-repeat') === 'true' ) { addMiscInfo({ text: globalize.translate('Repeat'), @@ -141,11 +142,11 @@ function addProgramIndicatorInfo( function addProgramIndicators( item: ItemDto, - isYearEnabled: boolean, - isEpisodeTitleEnabled: boolean, - isOriginalAirDateEnabled: boolean, - isProgramIndicatorEnabled: boolean, - isEpisodeTitleIndexNumberEnabled: boolean, + showYearInfo: boolean, + showEpisodeTitleInfo: boolean, + showOriginalAirDateInfo: boolean, + showProgramIndicatorInfo: boolean, + includeEpisodeTitleIndexNumber: boolean, addMiscInfo: (val: MiscInfo) => void ): void { if (item.Type === ItemKind.Program || item.Type === ItemKind.Timer) { @@ -154,16 +155,16 @@ function addProgramIndicators( program = item.ProgramInfo; } - if (isProgramIndicatorEnabled !== false) { + if (showProgramIndicatorInfo !== false) { addProgramIndicatorInfo(program, addMiscInfo); } addProgramTextInfo( program, - isEpisodeTitleEnabled, - isEpisodeTitleIndexNumberEnabled, - isOriginalAirDateEnabled, - isYearEnabled, + showEpisodeTitleInfo, + includeEpisodeTitleIndexNumber, + showOriginalAirDateInfo, + showYearInfo, addMiscInfo ); } @@ -171,16 +172,18 @@ function addProgramIndicators( function addProgramTextInfo( program: ItemDto, - isEpisodeTitleEnabled: boolean, - isEpisodeTitleIndexNumberEnabled: boolean, - isOriginalAirDateEnabled: boolean, - isYearEnabled: boolean, + showEpisodeTitleInfo: boolean, + includeEpisodeTitleIndexNumber: boolean, + showOriginalAirDateInfo: boolean, + showYearInfo: boolean, addMiscInfo: (val: MiscInfo) => void ): void { - if ((program?.IsSeries || program?.EpisodeTitle) - && isEpisodeTitleEnabled !== false) { + if ( + (program?.IsSeries || program?.EpisodeTitle) + && showEpisodeTitleInfo !== false + ) { const text = itemHelper.getDisplayName(program, { - includeIndexNumber: isEpisodeTitleIndexNumberEnabled + includeIndexNumber: includeEpisodeTitleIndexNumber }); if (text) { @@ -188,11 +191,11 @@ function addProgramTextInfo( } } else if ( program?.ProductionYear - && ((program?.IsMovie && isOriginalAirDateEnabled !== false) - || isYearEnabled !== false) + && ((program?.IsMovie && showOriginalAirDateInfo !== false) + || showYearInfo !== false) ) { addMiscInfo({ text: program.ProductionYear }); - } else if (program?.PremiereDate && isOriginalAirDateEnabled !== false) { + } else if (program?.PremiereDate && showOriginalAirDateInfo !== false) { try { const date = datetime.parseISO8601Date(program.PremiereDate); const text = globalize.translate( @@ -233,12 +236,12 @@ function addStartDateInfo( function addSeriesProductionYearInfo( itemProductionYear: NullableNumber, itemType: ItemKind, - isYearEnabled: boolean, + showYearInfo: boolean, itemStatus: ItemStatus, itemEndDate: NullableString, addMiscInfo: (val: MiscInfo) => void ): void { - if (itemProductionYear && isYearEnabled && itemType === ItemKind.Series) { + if (itemProductionYear && showYearInfo && itemType === ItemKind.Series) { if (itemStatus === ItemStatus.Continuing) { addMiscInfo({ text: globalize.translate( @@ -281,7 +284,7 @@ function addproductionYearWithEndDate( } function addYearInfo( - isYearEnabled: boolean, + showYearInfo: boolean, itemType: ItemKind, itemMediaType: ItemMediaKind, itemProductionYear: NullableNumber, @@ -289,7 +292,7 @@ function addYearInfo( addMiscInfo: (val: MiscInfo) => void ): void { if ( - isYearEnabled + showYearInfo && itemType !== ItemKind.Series && itemType !== ItemKind.Episode && itemType !== ItemKind.Person @@ -326,7 +329,7 @@ function addRunTimeInfo( itemRunTimeTicks: NullableNumber, itemType: ItemKind, showFolderRuntime: boolean, - isRuntimeEnabled: boolean, + showRuntimeInfo: boolean, addMiscInfo: (val: MiscInfo) => void ): void { if ( @@ -336,7 +339,7 @@ function addRunTimeInfo( && itemType !== ItemKind.Timer && itemType !== ItemKind.Book && !showFolderRuntime - && isRuntimeEnabled + && showRuntimeInfo ) { if (itemType === ItemKind.Audio) { addMiscInfo({ text: datetime.getDisplayRunningTime(itemRunTimeTicks) }); @@ -349,29 +352,33 @@ function addRunTimeInfo( function addOfficialRatingInfo( itemOfficialRating: NullableString, itemType: ItemKind, - isOfficialRatingEnabled: boolean, + showOfficialRatingInfo: boolean, addMiscInfo: (val: MiscInfo) => void ): void { if ( itemOfficialRating - && isOfficialRatingEnabled + && showOfficialRatingInfo && itemType !== ItemKind.Season && itemType !== ItemKind.Episode ) { addMiscInfo({ text: itemOfficialRating, - cssClass: 'mediaInfoOfficialRating' + cssClass: 'mediaInfoText mediaInfoOfficialRating' }); } } function addAudioContainer( itemContainer: NullableString, - isContainerEnabled: boolean, + showAudioContainerInfo: boolean, itemType: ItemKind, addMiscInfo: (val: MiscInfo) => void ): void { - if (itemContainer && isContainerEnabled && itemType === ItemKind.Audio) { + if ( + itemContainer + && showAudioContainerInfo + && itemType === ItemKind.Audio + ) { addMiscInfo({ text: itemContainer }); } } @@ -389,28 +396,20 @@ function addPhotoSize( } } -interface UsePrimaryMediaInfoProps { +interface UsePrimaryMediaInfoProps extends PrimaryInfoOpts { item: ItemDto; - isYearEnabled: boolean; - isContainerEnabled: boolean; - isEpisodeTitleEnabled: boolean; - isOriginalAirDateEnabled: boolean; - isRuntimeEnabled: boolean; - isProgramIndicatorEnabled: boolean; - isEpisodeTitleIndexNumberEnabled: boolean; - isOfficialRatingEnabled: boolean; } function usePrimaryMediaInfo({ item, - isYearEnabled = false, - isContainerEnabled = false, - isEpisodeTitleEnabled = false, - isOriginalAirDateEnabled = false, - isRuntimeEnabled = false, - isProgramIndicatorEnabled = false, - isEpisodeTitleIndexNumberEnabled = false, - isOfficialRatingEnabled = false + showYearInfo = false, + showAudioContainerInfo = false, + showEpisodeTitleInfo = false, + showOriginalAirDateInfo = false, + showRuntimeInfo = false, + showProgramIndicatorInfo = false, + includeEpisodeTitleIndexNumber = false, + showOfficialRatingInfo = false }: UsePrimaryMediaInfoProps) { const { EndDate, @@ -455,7 +454,7 @@ function usePrimaryMediaInfo({ addOriginalAirDateInfo( Type, MediaType, - isOriginalAirDateEnabled, + showOriginalAirDateInfo, PremiereDate, addMiscInfo ); @@ -474,7 +473,7 @@ function usePrimaryMediaInfo({ addSeriesProductionYearInfo( ProductionYear, Type, - isYearEnabled, + showYearInfo, Status, EndDate, addMiscInfo @@ -482,16 +481,16 @@ function usePrimaryMediaInfo({ addProgramIndicators( item, - isProgramIndicatorEnabled, - isEpisodeTitleEnabled, - isEpisodeTitleIndexNumberEnabled, - isOriginalAirDateEnabled, - isYearEnabled, + showProgramIndicatorInfo, + showEpisodeTitleInfo, + includeEpisodeTitleIndexNumber, + showOriginalAirDateInfo, + showYearInfo, addMiscInfo ); addYearInfo( - isYearEnabled, + showYearInfo, Type, MediaType, ProductionYear, @@ -503,14 +502,14 @@ function usePrimaryMediaInfo({ RunTimeTicks, Type, showFolderRuntime, - isRuntimeEnabled, + showRuntimeInfo, addMiscInfo ); addOfficialRatingInfo( OfficialRating, Type, - isOfficialRatingEnabled, + showOfficialRatingInfo, addMiscInfo ); @@ -518,7 +517,7 @@ function usePrimaryMediaInfo({ addPhotoSize(MediaType, Width, Height, addMiscInfo); - addAudioContainer(Container, isContainerEnabled, Type, addMiscInfo); + addAudioContainer(Container, showAudioContainerInfo, Type, addMiscInfo); return miscInfo; } From fabfb9b1732a05e1f4b846cf1d36bbbd35be9111 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 22 Aug 2024 00:50:43 +0300 Subject: [PATCH 2/5] Add more options for PrimaryMediaInfo --- src/components/listview/List/ListContent.tsx | 5 +- src/components/listview/List/ListItemBody.tsx | 1 + src/components/listview/listview.scss | 1 + src/components/mediainfo/CaptionMediaInfo.tsx | 3 +- src/components/mediainfo/EndsAt.tsx | 1 - src/components/mediainfo/MediaInfoItem.tsx | 1 - src/components/mediainfo/PrimaryMediaInfo.tsx | 40 ++++- src/components/mediainfo/StarIcons.tsx | 10 +- src/components/mediainfo/mediainfo.js | 2 +- src/components/mediainfo/mediainfo.scss | 14 -- src/components/mediainfo/type.ts | 6 + .../mediainfo/usePrimaryMediaInfo.tsx | 160 +++++++++++------- 12 files changed, 150 insertions(+), 94 deletions(-) diff --git a/src/components/listview/List/ListContent.tsx b/src/components/listview/List/ListContent.tsx index 4e257c5003..0b9bc03d01 100644 --- a/src/components/listview/List/ListContent.tsx +++ b/src/components/listview/List/ListContent.tsx @@ -78,12 +78,13 @@ const ListContent: FC = ({ {listOptions.showMediaInfo !== false && enableSideMediaInfo && ( )} diff --git a/src/components/listview/List/ListItemBody.tsx b/src/components/listview/List/ListItemBody.tsx index 93e90a5e32..90e9cb502e 100644 --- a/src/components/listview/List/ListItemBody.tsx +++ b/src/components/listview/List/ListItemBody.tsx @@ -61,6 +61,7 @@ const ListItemBody: FC = ({ {listOptions.showMediaInfo !== false && !enableSideMediaInfo && ( = ({ className }) => { const cssClass = classNames( 'mediaInfoItem', - 'mediaInfoText', 'closedCaptionMediaInfoText', className ); return ( - + ); }; diff --git a/src/components/mediainfo/EndsAt.tsx b/src/components/mediainfo/EndsAt.tsx index fa26d0801f..2f2f9f48a3 100644 --- a/src/components/mediainfo/EndsAt.tsx +++ b/src/components/mediainfo/EndsAt.tsx @@ -12,7 +12,6 @@ interface EndsAtProps { const EndsAt: FC = ({ runTimeTicks, className }) => { const cssClass = classNames( 'mediaInfoItem', - 'mediaInfoText', 'endsAt', className ); diff --git a/src/components/mediainfo/MediaInfoItem.tsx b/src/components/mediainfo/MediaInfoItem.tsx index d38635ac2d..8eeb7307ca 100644 --- a/src/components/mediainfo/MediaInfoItem.tsx +++ b/src/components/mediainfo/MediaInfoItem.tsx @@ -12,7 +12,6 @@ interface MediaInfoItemProps { const MediaInfoItem: FC = ({ className, miscInfo }) => { const cssClass = classNames( 'mediaInfoItem', - 'mediaInfoText', className, miscInfo?.cssClass ); diff --git a/src/components/mediainfo/PrimaryMediaInfo.tsx b/src/components/mediainfo/PrimaryMediaInfo.tsx index 5f8aca0941..2237198b0e 100644 --- a/src/components/mediainfo/PrimaryMediaInfo.tsx +++ b/src/components/mediainfo/PrimaryMediaInfo.tsx @@ -16,26 +16,34 @@ import type { PrimaryInfoOpts } from './type'; interface PrimaryMediaInfoProps extends PrimaryInfoOpts { className?: string; + infoclass?: string; item: ItemDto; showStarRatingInfo?: boolean; showCaptionIndicatorInfo?: boolean; showCriticRatingInfo?: boolean; showEndsAtInfo?: boolean; showMissingIndicatorInfo?: boolean; - getMissingIndicator?: () => React.JSX.Element | null + getMissingIndicator?: () => React.JSX.Element | null; } const PrimaryMediaInfo: FC = ({ className, + infoclass, item, showYearInfo, showAudioContainerInfo, showEpisodeTitleInfo, showOriginalAirDateInfo, + showFolderRuntimeInfo, showRuntimeInfo, + showItemCountInfo, + showSeriesTimerInfo, + showStartDateInfo, showProgramIndicatorInfo, includeEpisodeTitleIndexNumber, showOfficialRatingInfo, + showVideo3DFormatInfo, + showPhotoSizeInfo, showStarRatingInfo = false, showCaptionIndicatorInfo = false, showCriticRatingInfo = false, @@ -48,10 +56,16 @@ const PrimaryMediaInfo: FC = ({ showAudioContainerInfo, showEpisodeTitleInfo, showOriginalAirDateInfo, + showFolderRuntimeInfo, showRuntimeInfo, + showItemCountInfo, + showSeriesTimerInfo, + showStartDateInfo, showProgramIndicatorInfo, includeEpisodeTitleIndexNumber, - showOfficialRatingInfo + showOfficialRatingInfo, + showVideo3DFormatInfo, + showPhotoSizeInfo }); const { StartDate, @@ -64,8 +78,8 @@ const PrimaryMediaInfo: FC = ({ const cssClass = classNames(className); - const renderMediaInfo = (info: MiscInfo | undefined, index: number) => ( - + const renderMediaInfo = (info: MiscInfo, index: number) => ( + ); return ( @@ -73,19 +87,29 @@ const PrimaryMediaInfo: FC = ({ {miscInfo.map((info, index) => renderMediaInfo(info, index))} {showStarRatingInfo && CommunityRating && ( - + )} - {showCaptionIndicatorInfo && HasSubtitles && } + {showCaptionIndicatorInfo && HasSubtitles && ( + + )} {showCriticRatingInfo && CriticRating && ( - + )} {showEndsAtInfo && MediaType === ItemMediaKind.Video && RunTimeTicks - && !StartDate && } + && !StartDate && ( + + )} {getMissingIndicator?.()} diff --git a/src/components/mediainfo/StarIcons.tsx b/src/components/mediainfo/StarIcons.tsx index 0d38453d7e..ca2a1859d4 100644 --- a/src/components/mediainfo/StarIcons.tsx +++ b/src/components/mediainfo/StarIcons.tsx @@ -13,16 +13,18 @@ const StarIcons: FC = ({ className, communityRating }) => { const theme = useTheme(); const cssClass = classNames( 'mediaInfoItem', - 'mediaInfoText', 'starRatingContainer', className ); return ( - + {communityRating.toFixed(1)} ); diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 2fdc5d09bf..4ce337f586 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -271,7 +271,7 @@ export function getMediaInfoHtml(item, options = {}) { if (options.officialRating !== false && item.OfficialRating && item.Type !== 'Season' && item.Type !== 'Episode') { miscInfo.push({ text: item.OfficialRating, - cssClass: 'mediaInfoOfficialRating' + cssClass: 'mediaInfoText mediaInfoOfficialRating' }); } diff --git a/src/components/mediainfo/mediainfo.scss b/src/components/mediainfo/mediainfo.scss index cb623b685d..668d1f4ed1 100644 --- a/src/components/mediainfo/mediainfo.scss +++ b/src/components/mediainfo/mediainfo.scss @@ -46,8 +46,6 @@ align-items: center; justify-content: center; vertical-align: middle; - padding-top: 0; - padding-bottom: 0; } .starIcon { @@ -94,15 +92,3 @@ .closedCaptionMediaInfoText { 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%; -} diff --git a/src/components/mediainfo/type.ts b/src/components/mediainfo/type.ts index 4bb8aee9f8..0e20bf1394 100644 --- a/src/components/mediainfo/type.ts +++ b/src/components/mediainfo/type.ts @@ -4,7 +4,13 @@ export interface PrimaryInfoOpts { showEpisodeTitleInfo?: boolean; includeEpisodeTitleIndexNumber?: boolean; showOriginalAirDateInfo?: boolean; + showFolderRuntimeInfo?: boolean; showRuntimeInfo?: boolean; + showItemCountInfo?: boolean; + showSeriesTimerInfo?: boolean; + showStartDateInfo?: boolean; showProgramIndicatorInfo?: boolean; showOfficialRatingInfo?: boolean; + showVideo3DFormatInfo?: boolean; + showPhotoSizeInfo?: boolean; } diff --git a/src/components/mediainfo/usePrimaryMediaInfo.tsx b/src/components/mediainfo/usePrimaryMediaInfo.tsx index 327fbc4412..49452ec6a9 100644 --- a/src/components/mediainfo/usePrimaryMediaInfo.tsx +++ b/src/components/mediainfo/usePrimaryMediaInfo.tsx @@ -6,42 +6,53 @@ 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 { MiscInfo } from 'types/mediaInfoItem'; import { PrimaryInfoOpts } from './type'; function shouldShowFolderRuntime( + showFolderRuntimeInfo: boolean, itemType: ItemKind, itemMediaType: ItemMediaKind ): boolean { return ( - itemType === ItemKind.MusicAlbum - || itemMediaType === ItemMediaKind.MusicArtist - || itemType === ItemKind.Playlist - || itemMediaType === ItemMediaKind.Playlist - || itemMediaType === ItemMediaKind.MusicGenre + showFolderRuntimeInfo + && (itemType === ItemKind.MusicAlbum + || itemMediaType === ItemMediaKind.MusicArtist + || itemType === ItemKind.Playlist + || itemMediaType === ItemMediaKind.Playlist + || itemMediaType === ItemMediaKind.MusicGenre) ); } function addTrackCountOrItemCount( - showFolderRuntime: boolean, + isFolderRuntimeEnabled: boolean, + showItemCountInfo: boolean, itemSongCount: NullableNumber, itemChildCount: NullableNumber, itemRunTimeTicks: NullableNumber, itemType: ItemKind, addMiscInfo: (val: MiscInfo) => void ): void { - if (showFolderRuntime) { - const count = itemSongCount ?? itemChildCount; + if (isFolderRuntimeEnabled) { + const count = itemSongCount || itemChildCount; if (count) { addMiscInfo({ text: globalize.translate('TrackCount', count) }); } 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; if (count) { addMiscInfo({ text: globalize.translate('ItemCount', count) }); @@ -50,16 +61,17 @@ function addTrackCountOrItemCount( } function addOriginalAirDateInfo( + showOriginalAirDateInfo: boolean, itemType: ItemKind, itemMediaType: ItemMediaKind, - showOriginalAirDateInfo: boolean, itemPremiereDate: NullableString, addMiscInfo: (val: MiscInfo) => void ): void { if ( - itemPremiereDate - && (itemType === ItemKind.Episode || itemMediaType === ItemMediaKind.Photo) - && showOriginalAirDateInfo + showOriginalAirDateInfo + && (itemType === ItemKind.Episode + || itemMediaType === ItemMediaKind.Photo) + && itemPremiereDate ) { try { //don't modify date to locale if episode. Only Dates (not times) are stored, or editable in the edit metadata dialog @@ -75,6 +87,7 @@ function addOriginalAirDateInfo( } function addSeriesTimerInfo( + showSeriesTimerInfo: boolean, itemType: ItemKind, itemRecordAnyTime: boolean | undefined, itemStartDate: NullableString, @@ -82,7 +95,7 @@ function addSeriesTimerInfo( itemChannelName: NullableString, addMiscInfo: (val: MiscInfo) => void ): void { - if (itemType === ItemKind.SeriesTimer) { + if (showSeriesTimerInfo && itemType === ItemKind.SeriesTimer) { if (itemRecordAnyTime) { addMiscInfo({ text: globalize.translate('Anytime') }); } else { @@ -93,7 +106,7 @@ function addSeriesTimerInfo( addMiscInfo({ text: globalize.translate('AllChannels') }); } else { addMiscInfo({ - text: itemChannelName ?? globalize.translate('OneChannel') + text: itemChannelName || globalize.translate('OneChannel') }); } } @@ -141,12 +154,12 @@ function addProgramIndicatorInfo( } function addProgramIndicators( - item: ItemDto, showYearInfo: boolean, showEpisodeTitleInfo: boolean, showOriginalAirDateInfo: boolean, showProgramIndicatorInfo: boolean, includeEpisodeTitleIndexNumber: boolean, + item: ItemDto, addMiscInfo: (val: MiscInfo) => void ): void { if (item.Type === ItemKind.Program || item.Type === ItemKind.Timer) { @@ -155,33 +168,30 @@ function addProgramIndicators( program = item.ProgramInfo; } - if (showProgramIndicatorInfo !== false) { + if (showProgramIndicatorInfo) { addProgramIndicatorInfo(program, addMiscInfo); } addProgramTextInfo( - program, showEpisodeTitleInfo, includeEpisodeTitleIndexNumber, showOriginalAirDateInfo, showYearInfo, + program, addMiscInfo ); } } function addProgramTextInfo( - program: ItemDto, showEpisodeTitleInfo: boolean, includeEpisodeTitleIndexNumber: boolean, showOriginalAirDateInfo: boolean, showYearInfo: boolean, + program: ItemDto, addMiscInfo: (val: MiscInfo) => void ): void { - if ( - (program?.IsSeries || program?.EpisodeTitle) - && showEpisodeTitleInfo !== false - ) { + if (showEpisodeTitleInfo && (program.IsSeries || program.EpisodeTitle)) { const text = itemHelper.getDisplayName(program, { includeIndexNumber: includeEpisodeTitleIndexNumber }); @@ -190,12 +200,11 @@ function addProgramTextInfo( addMiscInfo({ text: text }); } } else if ( - program?.ProductionYear - && ((program?.IsMovie && showOriginalAirDateInfo !== false) - || showYearInfo !== false) + ((showOriginalAirDateInfo && program.IsMovie) || showYearInfo) + && program.ProductionYear ) { addMiscInfo({ text: program.ProductionYear }); - } else if (program?.PremiereDate && showOriginalAirDateInfo !== false) { + } else if (showOriginalAirDateInfo && program.PremiereDate) { try { const date = datetime.parseISO8601Date(program.PremiereDate); const text = globalize.translate( @@ -210,12 +219,14 @@ function addProgramTextInfo( } function addStartDateInfo( + showStartDateInfo: boolean, itemStartDate: NullableString, itemType: ItemKind, addMiscInfo: (val: MiscInfo) => void ): void { if ( - itemStartDate + showStartDateInfo + && itemStartDate && itemType !== ItemKind.Program && itemType !== ItemKind.SeriesTimer && itemType !== ItemKind.Timer @@ -234,14 +245,14 @@ function addStartDateInfo( } function addSeriesProductionYearInfo( + showYearInfo: boolean, itemProductionYear: NullableNumber, itemType: ItemKind, - showYearInfo: boolean, itemStatus: ItemStatus, itemEndDate: NullableString, addMiscInfo: (val: MiscInfo) => void ): void { - if (itemProductionYear && showYearInfo && itemType === ItemKind.Series) { + if (showYearInfo && itemProductionYear && itemType === ItemKind.Series) { if (itemStatus === ItemStatus.Continuing) { addMiscInfo({ text: globalize.translate( @@ -252,7 +263,11 @@ function addSeriesProductionYearInfo( ) }); } else { - addproductionYearWithEndDate(itemProductionYear, itemEndDate, addMiscInfo); + addproductionYearWithEndDate( + itemProductionYear, + itemEndDate, + addMiscInfo + ); } } } @@ -317,47 +332,52 @@ function addYearInfo( } function addVideo3DFormat( + showVideo3DFormatInfo: boolean, itemVideo3DFormat: NullableString, addMiscInfo: (val: MiscInfo) => void ): void { - if (itemVideo3DFormat) { + if (showVideo3DFormatInfo && itemVideo3DFormat) { addMiscInfo({ text: '3D' }); } } function addRunTimeInfo( + isFolderRuntimeEnabled: boolean, + showRuntimeInfo: boolean, itemRunTimeTicks: NullableNumber, itemType: ItemKind, - showFolderRuntime: boolean, - showRuntimeInfo: boolean, addMiscInfo: (val: MiscInfo) => void ): void { if ( - itemRunTimeTicks + !isFolderRuntimeEnabled + && showRuntimeInfo + && itemRunTimeTicks && itemType !== ItemKind.Series && itemType !== ItemKind.Program && itemType !== ItemKind.Timer && itemType !== ItemKind.Book - && !showFolderRuntime - && showRuntimeInfo ) { if (itemType === ItemKind.Audio) { - addMiscInfo({ text: datetime.getDisplayRunningTime(itemRunTimeTicks) }); + addMiscInfo({ + text: datetime.getDisplayRunningTime(itemRunTimeTicks) + }); } else { - addMiscInfo({ text: datetime.getDisplayDuration(itemRunTimeTicks) }); + addMiscInfo({ + text: datetime.getDisplayDuration(itemRunTimeTicks) + }); } } } function addOfficialRatingInfo( + showOfficialRatingInfo: boolean, itemOfficialRating: NullableString, itemType: ItemKind, - showOfficialRatingInfo: boolean, addMiscInfo: (val: MiscInfo) => void ): void { if ( - itemOfficialRating - && showOfficialRatingInfo + showOfficialRatingInfo + && itemOfficialRating && itemType !== ItemKind.Season && itemType !== ItemKind.Episode ) { @@ -369,14 +389,14 @@ function addOfficialRatingInfo( } function addAudioContainer( - itemContainer: NullableString, showAudioContainerInfo: boolean, + itemContainer: NullableString, itemType: ItemKind, addMiscInfo: (val: MiscInfo) => void ): void { if ( - itemContainer - && showAudioContainerInfo + showAudioContainerInfo + && itemContainer && itemType === ItemKind.Audio ) { addMiscInfo({ text: itemContainer }); @@ -384,12 +404,18 @@ function addAudioContainer( } function addPhotoSize( + showPhotoSizeInfo: boolean, itemMediaType: ItemMediaKind, itemWidth: NullableNumber, itemHeight: NullableNumber, addMiscInfo: (val: MiscInfo) => void ): void { - if (itemMediaType === ItemMediaKind.Photo && itemWidth && itemHeight) { + if ( + showPhotoSizeInfo + && itemMediaType === ItemMediaKind.Photo + && itemWidth + && itemHeight + ) { const size = `${itemWidth}x${itemHeight}`; addMiscInfo({ text: size }); @@ -406,10 +432,16 @@ function usePrimaryMediaInfo({ showAudioContainerInfo = false, showEpisodeTitleInfo = false, showOriginalAirDateInfo = false, + showFolderRuntimeInfo = false, showRuntimeInfo = false, + showItemCountInfo = false, + showSeriesTimerInfo = false, + showStartDateInfo = false, showProgramIndicatorInfo = false, includeEpisodeTitleIndexNumber = false, - showOfficialRatingInfo = false + showOfficialRatingInfo = false, + showVideo3DFormatInfo = false, + showPhotoSizeInfo = false }: UsePrimaryMediaInfoProps) { const { EndDate, @@ -440,10 +472,15 @@ function usePrimaryMediaInfo({ } }; - const showFolderRuntime = shouldShowFolderRuntime(Type, MediaType); + const isFolderRuntimeEnabled = shouldShowFolderRuntime( + showFolderRuntimeInfo, + Type, + MediaType + ); addTrackCountOrItemCount( - showFolderRuntime, + isFolderRuntimeEnabled, + showItemCountInfo, SongCount, ChildCount, RunTimeTicks, @@ -452,14 +489,15 @@ function usePrimaryMediaInfo({ ); addOriginalAirDateInfo( + showOriginalAirDateInfo, Type, MediaType, - showOriginalAirDateInfo, PremiereDate, addMiscInfo ); addSeriesTimerInfo( + showSeriesTimerInfo, Type, RecordAnyTime, StartDate, @@ -468,24 +506,24 @@ function usePrimaryMediaInfo({ addMiscInfo ); - addStartDateInfo(StartDate, Type, addMiscInfo); + addStartDateInfo(showStartDateInfo, StartDate, Type, addMiscInfo); addSeriesProductionYearInfo( + showYearInfo, ProductionYear, Type, - showYearInfo, Status, EndDate, addMiscInfo ); addProgramIndicators( - item, showProgramIndicatorInfo, showEpisodeTitleInfo, includeEpisodeTitleIndexNumber, showOriginalAirDateInfo, showYearInfo, + item, addMiscInfo ); @@ -499,25 +537,25 @@ function usePrimaryMediaInfo({ ); addRunTimeInfo( + isFolderRuntimeEnabled, + showRuntimeInfo, RunTimeTicks, Type, - showFolderRuntime, - showRuntimeInfo, addMiscInfo ); addOfficialRatingInfo( + showOfficialRatingInfo, OfficialRating, Type, - showOfficialRatingInfo, addMiscInfo ); - addVideo3DFormat(Video3DFormat, addMiscInfo); + addVideo3DFormat(showVideo3DFormatInfo, Video3DFormat, addMiscInfo); - addPhotoSize(MediaType, Width, Height, addMiscInfo); + addPhotoSize(showPhotoSizeInfo, MediaType, Width, Height, addMiscInfo); - addAudioContainer(Container, showAudioContainerInfo, Type, addMiscInfo); + addAudioContainer(showAudioContainerInfo, Container, Type, addMiscInfo); return miscInfo; } From 82d70763bb07b59de59345f0d5ab31814c2f88e4 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 22 Aug 2024 01:01:59 +0300 Subject: [PATCH 3/5] Add Secondary Media Info --- src/components/mediainfo/MediaInfoItem.tsx | 30 +++-- .../mediainfo/SecondaryMediaInfo.tsx | 55 ++++++++ src/components/mediainfo/type.ts | 9 ++ .../mediainfo/useSecondaryMediaInfo.tsx | 124 ++++++++++++++++++ src/types/mediaInfoItem.ts | 10 +- 5 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 src/components/mediainfo/SecondaryMediaInfo.tsx create mode 100644 src/components/mediainfo/useSecondaryMediaInfo.tsx diff --git a/src/components/mediainfo/MediaInfoItem.tsx b/src/components/mediainfo/MediaInfoItem.tsx index 8eeb7307ca..545414c37a 100644 --- a/src/components/mediainfo/MediaInfoItem.tsx +++ b/src/components/mediainfo/MediaInfoItem.tsx @@ -1,24 +1,38 @@ import React, { type FC } from 'react'; import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; import classNames from 'classnames'; import type { MiscInfo } from 'types/mediaInfoItem'; interface MediaInfoItemProps { className?: string; - miscInfo?: MiscInfo ; + miscInfo: MiscInfo ; } const MediaInfoItem: FC = ({ className, miscInfo }) => { - const cssClass = classNames( - 'mediaInfoItem', - className, - miscInfo?.cssClass - ); + const { text, textAction, cssClass } = miscInfo; + + const renderText = () => { + if (textAction) { + return ( + + {textAction.title} + + ); + } else { + return text; + } + }; return ( - - {miscInfo?.text} + + {renderText()} ); }; diff --git a/src/components/mediainfo/SecondaryMediaInfo.tsx b/src/components/mediainfo/SecondaryMediaInfo.tsx new file mode 100644 index 0000000000..dae138cef4 --- /dev/null +++ b/src/components/mediainfo/SecondaryMediaInfo.tsx @@ -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 = ({ + 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) => ( + + ); + + return ( + + {miscInfo.map((info, index) => renderMediaInfo(info, index))} + + {showTimerIndicatorInfo !== false && indicator.getTimerIndicator()} + + ); +}; + +export default SecondaryMediaInfo; diff --git a/src/components/mediainfo/type.ts b/src/components/mediainfo/type.ts index 0e20bf1394..ab5bf19422 100644 --- a/src/components/mediainfo/type.ts +++ b/src/components/mediainfo/type.ts @@ -14,3 +14,12 @@ export interface PrimaryInfoOpts { showVideo3DFormatInfo?: boolean; showPhotoSizeInfo?: boolean; } + +export interface SecondaryInfoOpts { + showProgramTimeInfo?: boolean; + showStartDateInfo?: boolean; + showEndDateInfo?: boolean; + showChannelNumberInfo?: boolean; + showChannelInfo?: boolean; + channelInteractive?: boolean; +} diff --git a/src/components/mediainfo/useSecondaryMediaInfo.tsx b/src/components/mediainfo/useSecondaryMediaInfo.tsx new file mode 100644 index 0000000000..c7bbb0d708 --- /dev/null +++ b/src/components/mediainfo/useSecondaryMediaInfo.tsx @@ -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; diff --git a/src/types/mediaInfoItem.ts b/src/types/mediaInfoItem.ts index 3620fad620..e8c3dc168d 100644 --- a/src/types/mediaInfoItem.ts +++ b/src/types/mediaInfoItem.ts @@ -1,4 +1,10 @@ -export interface MiscInfo { - text?: string | number; +interface TextAction { + url: string; + title: string; + cssClass?: string; +} +export interface MiscInfo { + text?: string | number; + textAction?: TextAction; cssClass?: string; } From 106392b9cba9d73e3a0a3f6d0d0887584ed71e91 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Thu, 22 Aug 2024 01:04:18 +0300 Subject: [PATCH 4/5] Add Media Info Stats --- src/components/mediainfo/MediaInfoItem.tsx | 4 +- src/components/mediainfo/MediaInfoStats.tsx | 49 ++++ src/components/mediainfo/type.ts | 9 + .../mediainfo/useMediaInfoStats.tsx | 229 ++++++++++++++++++ src/types/mediaInfoItem.ts | 1 + 5 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/components/mediainfo/MediaInfoStats.tsx create mode 100644 src/components/mediainfo/useMediaInfoStats.tsx diff --git a/src/components/mediainfo/MediaInfoItem.tsx b/src/components/mediainfo/MediaInfoItem.tsx index 545414c37a..35159ddfc6 100644 --- a/src/components/mediainfo/MediaInfoItem.tsx +++ b/src/components/mediainfo/MediaInfoItem.tsx @@ -11,7 +11,7 @@ interface MediaInfoItemProps { } const MediaInfoItem: FC = ({ className, miscInfo }) => { - const { text, textAction, cssClass } = miscInfo; + const { text, textAction, cssClass, type } = miscInfo; const renderText = () => { if (textAction) { @@ -31,7 +31,7 @@ const MediaInfoItem: FC = ({ className, miscInfo }) => { }; return ( - + {renderText()} ); diff --git a/src/components/mediainfo/MediaInfoStats.tsx b/src/components/mediainfo/MediaInfoStats.tsx new file mode 100644 index 0000000000..08984770b1 --- /dev/null +++ b/src/components/mediainfo/MediaInfoStats.tsx @@ -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 = ({ + 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) => ( + + ); + + return ( + + {mediaInfoStats.map((info, index) => renderMediaInfo(info, index))} + + ); +}; + +export default MediaInfoStats; diff --git a/src/components/mediainfo/type.ts b/src/components/mediainfo/type.ts index ab5bf19422..2a5a51edec 100644 --- a/src/components/mediainfo/type.ts +++ b/src/components/mediainfo/type.ts @@ -23,3 +23,12 @@ export interface SecondaryInfoOpts { showChannelInfo?: boolean; channelInteractive?: boolean; } + +export interface MediaInfoStatsOpts { + showVideoTypeInfo?: boolean; + showResolutionInfo?: boolean; + showVideoStreamCodecInfo?: boolean; + showAudoChannelInfo?: boolean; + showAudioStreamCodecInfo?: boolean; + showDateAddedInfo?: boolean; +} diff --git a/src/components/mediainfo/useMediaInfoStats.tsx b/src/components/mediainfo/useMediaInfoStats.tsx new file mode 100644 index 0000000000..593d17788f --- /dev/null +++ b/src/components/mediainfo/useMediaInfoStats.tsx @@ -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; diff --git a/src/types/mediaInfoItem.ts b/src/types/mediaInfoItem.ts index e8c3dc168d..faa6ebc374 100644 --- a/src/types/mediaInfoItem.ts +++ b/src/types/mediaInfoItem.ts @@ -5,6 +5,7 @@ interface TextAction { } export interface MiscInfo { text?: string | number; + type?: string; textAction?: TextAction; cssClass?: string; } From b681e5a1c812026af2a14c6ea466dd98167245d2 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sat, 24 Aug 2024 04:31:25 +0300 Subject: [PATCH 5/5] Removed unused prop --- src/components/mediainfo/PrimaryMediaInfo.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/mediainfo/PrimaryMediaInfo.tsx b/src/components/mediainfo/PrimaryMediaInfo.tsx index 2237198b0e..00bdaa7390 100644 --- a/src/components/mediainfo/PrimaryMediaInfo.tsx +++ b/src/components/mediainfo/PrimaryMediaInfo.tsx @@ -22,7 +22,6 @@ interface PrimaryMediaInfoProps extends PrimaryInfoOpts { showCaptionIndicatorInfo?: boolean; showCriticRatingInfo?: boolean; showEndsAtInfo?: boolean; - showMissingIndicatorInfo?: boolean; getMissingIndicator?: () => React.JSX.Element | null; }