101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
import React from 'react';
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
|
|
import ListGroup from 'react-bootstrap/ListGroup';
|
|
import Media from 'react-bootstrap/Media';
|
|
import Image from 'react-bootstrap/Image';
|
|
|
|
import Link from 'next/link';
|
|
|
|
import { getThumbnailURL } from '../util';
|
|
|
|
import FormattedDuration from './localization/FormattedDuration';
|
|
|
|
import style from './VideoListItem.module.scss';
|
|
import sanitizeTitle from '../util/sanitizeTitle';
|
|
|
|
export default function VideoListItem({
|
|
thumbnailServerURL,
|
|
duration,
|
|
id,
|
|
fileName,
|
|
title,
|
|
sourceVideoStart,
|
|
sourceVideoEnd,
|
|
}: {
|
|
thumbnailServerURL: string,
|
|
duration: number | string,
|
|
id: string,
|
|
fileName: string,
|
|
title: string,
|
|
sourceVideoStart: number | string,
|
|
sourceVideoEnd: number | string,
|
|
}) {
|
|
let displayDuration = null;
|
|
if (duration !== null) {
|
|
displayDuration = duration;
|
|
} else if (
|
|
sourceVideoStart !== null
|
|
&& sourceVideoEnd !== null
|
|
&& sourceVideoStart !== sourceVideoEnd
|
|
) {
|
|
let videoEnd: number;
|
|
if (typeof sourceVideoEnd === 'string') {
|
|
videoEnd = parseFloat(sourceVideoEnd);
|
|
} else {
|
|
videoEnd = sourceVideoEnd;
|
|
}
|
|
let videoStart: number;
|
|
if (typeof sourceVideoStart === 'string') {
|
|
videoStart = parseFloat(sourceVideoStart);
|
|
} else {
|
|
videoStart = sourceVideoStart;
|
|
}
|
|
displayDuration = videoEnd - videoStart;
|
|
}
|
|
const titleUrlSlug = sanitizeTitle(title);
|
|
return (
|
|
<Link passHref href="/[id]/[vslug]" as={`/${id}/${titleUrlSlug}`}>
|
|
<ListGroup.Item action>
|
|
<Media>
|
|
<Image
|
|
className={['mr-3', style.thumbnail].join(' ')}
|
|
src={getThumbnailURL(thumbnailServerURL, id, fileName, 90 * 1000, {
|
|
width: 96,
|
|
})}
|
|
srcSet={[96, 96 * 2, 96 * 3]
|
|
.map((width) => [
|
|
getThumbnailURL(thumbnailServerURL, id, fileName, 90 * 1000, {
|
|
width,
|
|
}),
|
|
`${width}w`,
|
|
])
|
|
.map((item) => item.join(' '))
|
|
.join(', ')}
|
|
alt={title}
|
|
/>
|
|
<Media.Body>
|
|
<h5 className="mt-0 mb-3">{title}</h5>
|
|
<p>
|
|
{displayDuration !== null ? (
|
|
<span>
|
|
<FontAwesomeIcon icon="clock" />
|
|
{' '}
|
|
<FormattedDuration
|
|
seconds={displayDuration}
|
|
format="{hours} {minutes} {seconds}"
|
|
unitDisplay="short"
|
|
/>
|
|
</span>
|
|
) : (
|
|
''
|
|
)}
|
|
</p>
|
|
</Media.Body>
|
|
</Media>
|
|
</ListGroup.Item>
|
|
</Link>
|
|
);
|
|
}
|