mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
Removing default download freqeuncy so channels will not be downloaded without a url and frequency. Adding channel unique url constraint. Handling when a Channel's directory may still be relative in DB. Adding TODOs to remove old favorites. Removing outdated favorites from config after favorites have been created. Testing that old-style favorited videos in the config are imported. Removing channels_by_link. Using list to store channels in config. Moving channel import function into lib. Supporting old channel import with links. Bumping version for channel.link removal. Removing all reference to Channel.link in app and api. Adding relative property to MediaPathType. Testing that a channel can be downloaded after it has a frequency added. All tests pass. Video and Channel tests pass without channel.link. Removing channel.link usage in channel api. Changing video Statistics page to About.
183 lines
6.3 KiB
JavaScript
183 lines
6.3 KiB
JavaScript
import React, {useState} from 'react';
|
|
import Icon from "semantic-ui-react/dist/commonjs/elements/Icon";
|
|
import {deleteVideo, favoriteVideo} from "../api";
|
|
import Button from "semantic-ui-react/dist/commonjs/elements/Button";
|
|
import {Link} from "react-router-dom";
|
|
import {humanFileSize, humanNumber, secondsToTimestamp, uploadDate, VideoCard} from "./Common";
|
|
import {Confirm, Segment, Tab} from "semantic-ui-react";
|
|
import Grid from "semantic-ui-react/dist/commonjs/collections/Grid";
|
|
import Container from "semantic-ui-react/dist/commonjs/elements/Container";
|
|
|
|
const MEDIA_PATH = '/media';
|
|
|
|
|
|
function VideoPage(props) {
|
|
let {video, channel} = props;
|
|
let [deleteOpen, setDeleteOpen] = useState(false);
|
|
|
|
async function handleDeleteVideo(video_id) {
|
|
try {
|
|
await deleteVideo(video_id)
|
|
} catch (e) {
|
|
setDeleteOpen(false);
|
|
throw e;
|
|
}
|
|
props.history.goBack();
|
|
}
|
|
|
|
let videoUrl = `${MEDIA_PATH}/${encodeURIComponent(video.video_path)}`;
|
|
|
|
let posterUrl = null;
|
|
if (video.poster_path) {
|
|
posterUrl = `${MEDIA_PATH}/${encodeURIComponent(video.poster_path)}`;
|
|
}
|
|
let captionsUrl = null;
|
|
if (video.caption_path) {
|
|
captionsUrl = `${MEDIA_PATH}/${encodeURIComponent(video.caption_path)}`;
|
|
}
|
|
|
|
let description = 'No description available.';
|
|
let viewCount = video.view_count;
|
|
if (video.info_json) {
|
|
description = video.info_json['description'];
|
|
viewCount = viewCount || video.info_json['view_count'];
|
|
}
|
|
|
|
let [favorite, setFavorite] = React.useState(video.favorite);
|
|
let handleFavorite = async (e) => {
|
|
e.preventDefault();
|
|
let new_favorite = await favoriteVideo(video.id, !!!favorite);
|
|
setFavorite(new_favorite);
|
|
}
|
|
let favorite_button;
|
|
if (favorite) {
|
|
favorite_button = (
|
|
<Button color='green' style={{'margin': '0.5em'}}
|
|
onClick={handleFavorite}>
|
|
<Icon name='heart'/>
|
|
Unfavorite
|
|
</Button>
|
|
);
|
|
} else {
|
|
favorite_button = (
|
|
<Button basic color='green' style={{'margin': '0.5em'}}
|
|
onClick={handleFavorite}>
|
|
<Icon name='heart'/>
|
|
Favorite
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
let descriptionPane = {
|
|
menuItem: 'Description', render: () => <Tab.Pane>
|
|
<pre className="wrap-text">
|
|
{description || 'No description'}
|
|
</pre>
|
|
</Tab.Pane>
|
|
};
|
|
|
|
let aboutPane = {
|
|
menuItem: 'About', render: () => <Tab.Pane>
|
|
<h3>Size</h3>
|
|
<p>{video.size ? humanFileSize(video.size) : '???'}</p>
|
|
|
|
<h3>Source URL</h3>
|
|
<p>{video.url ? <a href={video.url}>{video.url}</a> : 'N/A'}</p>
|
|
|
|
<h3>View Count</h3>
|
|
<p>{viewCount ? humanNumber(viewCount) : 'N/A'}</p>
|
|
|
|
<h3>Censored</h3>
|
|
<p>{video.censored ? 'Yes' : 'No'}</p>
|
|
|
|
<h3>File Name</h3>
|
|
<pre style={{backgroundColor: '#ccc', padding: '0.4em'}}>{video.video_path}</pre>
|
|
|
|
<h3>File Modification Time</h3>
|
|
<p>{video.modification_datetime ? secondsToTimestamp(video.modification_datetime) : null}</p>
|
|
</Tab.Pane>
|
|
}
|
|
|
|
let captionsPane = {
|
|
menuItem: 'Captions', render: () => <Tab.Pane>
|
|
<pre>{video.caption}</pre>
|
|
</Tab.Pane>
|
|
};
|
|
|
|
let tabPanes = [descriptionPane, aboutPane, captionsPane];
|
|
|
|
return (
|
|
<>
|
|
<Container>
|
|
<Button
|
|
style={{marginTop: '1em', marginBottom: '1em'}}
|
|
onClick={() => props.history.goBack()}
|
|
>
|
|
<Icon name='left arrow'/>
|
|
Back
|
|
</Button>
|
|
</Container>
|
|
|
|
<video controls
|
|
autoPlay={props.autoplay !== undefined ? props.autoplay : true}
|
|
poster={posterUrl}
|
|
id="player"
|
|
playsInline={true}
|
|
style={{maxWidth: '100%'}}
|
|
>
|
|
<source src={videoUrl} type="video/mp4"/>
|
|
<track kind="captions" label="English captions" src={captionsUrl} srcLang="en" default/>
|
|
</video>
|
|
|
|
<Container style={{marginTop: '1em'}}>
|
|
<Segment>
|
|
|
|
<h2>{video.title || video.video_path}</h2>
|
|
{video.upload_date && <h3>{uploadDate(video.upload_date)}</h3>}
|
|
<h3>
|
|
{channel && <Link to={`/videos/channel/${channel.id}/video`}>
|
|
{channel.name}
|
|
</Link>}
|
|
</h3>
|
|
|
|
<p>
|
|
{favorite_button}
|
|
<a href={videoUrl}>
|
|
<Button style={{margin: '0.5em'}}>
|
|
<Icon name='download'/>
|
|
Download
|
|
</Button>
|
|
</a>
|
|
<Button
|
|
color='red'
|
|
onClick={() => setDeleteOpen(true)}
|
|
style={{margin: '0.5em'}}
|
|
>Delete</Button>
|
|
<Confirm
|
|
open={deleteOpen}
|
|
content='Are you sure you want to delete this video? All files related to this video will be deleted. It will not be downloaded again!'
|
|
confirmButton='Delete'
|
|
onCancel={() => setDeleteOpen(false)}
|
|
onConfirm={() => handleDeleteVideo(video.id)}
|
|
/>
|
|
</p>
|
|
</Segment>
|
|
|
|
<Tab panes={tabPanes}/>
|
|
|
|
<Grid columns={2} stackable>
|
|
<Grid.Row>
|
|
<Grid.Column textAlign='left'>
|
|
{props.prev && <><h3>Older</h3><VideoCard video={props.prev}/></>}
|
|
</Grid.Column>
|
|
<Grid.Column textAlign='left'>
|
|
{props.next && <><h3>Newer</h3><VideoCard video={props.next}/></>}
|
|
</Grid.Column>
|
|
</Grid.Row>
|
|
</Grid>
|
|
</Container>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default VideoPage;
|