gdq-archive/frontend/components/VideoListItem.tsx

142 lines
3.9 KiB
TypeScript

/**
* Copyright (C) 2019-2021 Carl Kittelberger <icedream@icedream.pw>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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';
import hourglassImage from '../images/hourglass.svg';
export default function VideoListItem({
thumbnailServerURL,
duration,
id,
fileName,
slug,
title,
sourceVideoStart,
sourceVideoEnd,
}: {
thumbnailServerURL: string,
duration: number | string,
id: string,
fileName: string,
slug: string,
title: string,
sourceVideoStart: number | string,
sourceVideoEnd: number | string,
}) {
let displayDuration = null;
if (duration !== null) {
if (typeof duration === 'string') {
displayDuration = parseFloat(duration);
} else {
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 listGroupItem = (
<ListGroup.Item action>
<Media>
<Image
className={['mr-3', style.thumbnail].join(' ')}
src={
fileName
? getThumbnailURL(thumbnailServerURL, id, fileName, 90 * 1000, {
width: 96,
})
: hourglassImage
}
srcSet={[96, 96 * 2, 96 * 3]
.map((width) => [
fileName
? getThumbnailURL(thumbnailServerURL, id, fileName, 90 * 1000, {
width,
})
: hourglassImage,
`${width}w`,
])
.map((item) => item.join(' '))
.join(', ')}
alt={title}
/>
<Media.Body>
<h5 className="mt-0 mb-3">{title}</h5>
<p>
{!fileName ? (
<span>
<FontAwesomeIcon icon="hourglass" />
{' '}
Coming up
</span>
) : ''}
{displayDuration !== null ? (
<span>
<FontAwesomeIcon icon="clock" />
{' '}
<FormattedDuration
seconds={displayDuration}
format="{hours} {minutes} {seconds}"
unitDisplay="short"
/>
</span>
) : ''}
</p>
</Media.Body>
</Media>
</ListGroup.Item>
);
if (fileName) {
return (
<Link passHref href="/[id]/[vslug]" as={`/${id}/${slug}`}>
{listGroupItem}
</Link>
);
}
return listGroupItem;
}