mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #5850 from grafixeyehero/move-reusable-component
Move reusable Text Lines component to common file
This commit is contained in:
commit
3e8592e29e
9 changed files with 172 additions and 103 deletions
74
src/components/common/textLines/TextLines.tsx
Normal file
74
src/components/common/textLines/TextLines.tsx
Normal file
|
@ -0,0 +1,74 @@
|
|||
import React, { type FC, type PropsWithChildren } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
import useTextLines from './useTextLines';
|
||||
|
||||
import type { ItemDto } from 'types/base/models/item-dto';
|
||||
import type { TextLine, TextLineOpts } from './types';
|
||||
|
||||
interface TextWrapperProps {
|
||||
isHeading?: boolean;
|
||||
isLargeStyle?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const TextWrapper: FC<PropsWithChildren<TextWrapperProps>> = ({
|
||||
isHeading,
|
||||
isLargeStyle,
|
||||
className,
|
||||
children
|
||||
}) => {
|
||||
if (isHeading) {
|
||||
return (
|
||||
<Typography className={classNames('primary', className)} variant={isLargeStyle ? 'h1' : 'h3'}>
|
||||
{children}
|
||||
</Typography>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Box className={classNames('secondary', className )}>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
interface TextLinesProps {
|
||||
item: ItemDto;
|
||||
textLineOpts?: TextLineOpts;
|
||||
isLargeStyle?: boolean;
|
||||
className?: string;
|
||||
textClassName?: string;
|
||||
}
|
||||
|
||||
const TextLines: FC<TextLinesProps> = ({
|
||||
item,
|
||||
textLineOpts,
|
||||
isLargeStyle,
|
||||
className,
|
||||
textClassName
|
||||
}) => {
|
||||
const { textLines } = useTextLines({ item, textLineOpts });
|
||||
|
||||
const renderTextlines = (text: TextLine, index: number) => {
|
||||
return (
|
||||
<TextWrapper
|
||||
key={index}
|
||||
isHeading={index === 0}
|
||||
isLargeStyle={isLargeStyle}
|
||||
className={textClassName}
|
||||
>
|
||||
<bdi>{text.title}</bdi>
|
||||
</TextWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={className}>
|
||||
{textLines?.map((text, index) => renderTextlines(text, index))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextLines;
|
18
src/components/common/textLines/types.ts
Normal file
18
src/components/common/textLines/types.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
export interface TextLine {
|
||||
title?: string;
|
||||
cssClass?: string;
|
||||
}
|
||||
|
||||
export interface TextLineOpts {
|
||||
showProgramDateTime?: boolean;
|
||||
showProgramTime?: boolean;
|
||||
showChannel?: boolean;
|
||||
showTitle?: boolean;
|
||||
showParentTitle?: boolean;
|
||||
showIndexNumber?: boolean;
|
||||
parentTitleWithTitle?: boolean;
|
||||
showArtist?: boolean;
|
||||
showCurrentProgram?: boolean;
|
||||
includeIndexNumber?: boolean;
|
||||
includeParentInfoInTitle?: boolean;
|
||||
}
|
160
src/components/common/textLines/useTextLines.tsx
Normal file
160
src/components/common/textLines/useTextLines.tsx
Normal file
|
@ -0,0 +1,160 @@
|
|||
import itemHelper from '../../itemHelper';
|
||||
import datetime from 'scripts/datetime';
|
||||
import type { ItemDto } from 'types/base/models/item-dto';
|
||||
import type { TextLine, TextLineOpts } from './types';
|
||||
import { ItemKind } from 'types/base/models/item-kind';
|
||||
|
||||
function getParentTitle(
|
||||
item: ItemDto,
|
||||
showParentTitle: boolean | undefined,
|
||||
parentTitleWithTitle: boolean | undefined,
|
||||
displayName: string | null | undefined
|
||||
) {
|
||||
let parentTitle;
|
||||
if (showParentTitle) {
|
||||
if (item.Type === ItemKind.Season || item.Type === ItemKind.Episode) {
|
||||
parentTitle = item.SeriesName;
|
||||
} else if (item.IsSeries || (item.EpisodeTitle && item.Name)) {
|
||||
parentTitle = item.Name;
|
||||
}
|
||||
}
|
||||
if (showParentTitle && parentTitleWithTitle) {
|
||||
if (displayName && parentTitle) {
|
||||
parentTitle += ' - ';
|
||||
}
|
||||
parentTitle = (parentTitle ?? '') + displayName;
|
||||
}
|
||||
return parentTitle;
|
||||
}
|
||||
|
||||
function getNameOrIndexWithName(
|
||||
item: ItemDto,
|
||||
showIndexNumber?: boolean,
|
||||
includeParentInfoInTitle?: boolean,
|
||||
includeIndexNumber?: boolean
|
||||
) {
|
||||
let displayName = itemHelper.getDisplayName(item, {
|
||||
includeParentInfo: includeParentInfoInTitle,
|
||||
includeIndexNumber
|
||||
});
|
||||
|
||||
if (showIndexNumber && item.IndexNumber != null) {
|
||||
displayName = `${item.IndexNumber}. ${displayName}`;
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
interface UseTextLinesProps {
|
||||
item: ItemDto;
|
||||
textLineOpts?: TextLineOpts;
|
||||
}
|
||||
|
||||
function useTextLines({ item, textLineOpts = {} }: UseTextLinesProps) {
|
||||
const {
|
||||
showTitle,
|
||||
showProgramDateTime,
|
||||
showProgramTime,
|
||||
showChannel,
|
||||
showParentTitle,
|
||||
showIndexNumber,
|
||||
parentTitleWithTitle,
|
||||
showArtist,
|
||||
showCurrentProgram,
|
||||
includeParentInfoInTitle,
|
||||
includeIndexNumber
|
||||
} = textLineOpts;
|
||||
|
||||
const textLines: TextLine[] = [];
|
||||
|
||||
const addTextLine = (textLine: TextLine) => {
|
||||
if (textLine) {
|
||||
textLines.push(textLine);
|
||||
}
|
||||
};
|
||||
|
||||
const addProgramDateTime = () => {
|
||||
if (showProgramDateTime) {
|
||||
const programDateTime = datetime.toLocaleString(
|
||||
datetime.parseISO8601Date(item.StartDate),
|
||||
{
|
||||
weekday: 'long',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit'
|
||||
}
|
||||
);
|
||||
addTextLine({ title: programDateTime });
|
||||
}
|
||||
};
|
||||
|
||||
const addProgramTime = () => {
|
||||
if (showProgramTime) {
|
||||
const programTime = datetime.getDisplayTime(
|
||||
datetime.parseISO8601Date(item.StartDate)
|
||||
);
|
||||
addTextLine({ title: programTime });
|
||||
}
|
||||
};
|
||||
|
||||
const addChannelName = () => {
|
||||
if (showChannel && item.ChannelName) {
|
||||
addTextLine({ title: item.ChannelName });
|
||||
}
|
||||
};
|
||||
|
||||
const displayName = getNameOrIndexWithName(item, showIndexNumber, includeParentInfoInTitle, includeIndexNumber);
|
||||
|
||||
const parentTitle = getParentTitle(item, showParentTitle, parentTitleWithTitle, displayName );
|
||||
|
||||
const addParentTitle = () => {
|
||||
if (parentTitle) {
|
||||
addTextLine({ title: parentTitle });
|
||||
}
|
||||
};
|
||||
|
||||
const addDisplayName = () => {
|
||||
if (displayName && !parentTitleWithTitle && showTitle !== false) {
|
||||
addTextLine({ title: displayName });
|
||||
}
|
||||
};
|
||||
|
||||
const addAlbumArtistOrArtists = () => {
|
||||
if (item.IsFolder && showArtist !== false) {
|
||||
if (item.AlbumArtist && item.Type === ItemKind.MusicAlbum) {
|
||||
addTextLine({ title: item.AlbumArtist });
|
||||
}
|
||||
} else if (showArtist) {
|
||||
const artistItems = item.ArtistItems;
|
||||
if (artistItems && item.Type !== ItemKind.MusicAlbum) {
|
||||
const artists = artistItems.map((a) => a.Name).join(', ');
|
||||
addTextLine({ title: artists });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addCurrentProgram = () => {
|
||||
if (item.Type === ItemKind.TvChannel && item.CurrentProgram && showCurrentProgram !== false) {
|
||||
const currentProgram = itemHelper.getDisplayName(item.CurrentProgram, {
|
||||
includeParentInfo: includeParentInfoInTitle,
|
||||
includeIndexNumber
|
||||
});
|
||||
|
||||
addTextLine({ title: currentProgram });
|
||||
}
|
||||
};
|
||||
|
||||
addProgramDateTime();
|
||||
addProgramTime();
|
||||
addChannelName();
|
||||
addParentTitle();
|
||||
addDisplayName();
|
||||
addAlbumArtistOrArtists();
|
||||
addCurrentProgram();
|
||||
|
||||
return {
|
||||
textLines
|
||||
};
|
||||
}
|
||||
|
||||
export default useTextLines;
|
Loading…
Add table
Add a link
Reference in a new issue