2020-10-25 18:48:23 +00:00
|
|
|
import React from 'react';
|
2020-11-27 22:43:12 +00:00
|
|
|
|
2020-10-25 18:48:23 +00:00
|
|
|
import style from './Player.module.css';
|
2020-11-27 22:43:12 +00:00
|
|
|
import plyrstyle from 'plyr-react/dist/plyr.css'
|
2020-07-26 18:17:29 +02:00
|
|
|
|
2020-11-27 22:43:12 +00:00
|
|
|
import {Plyr} from 'plyr-react';
|
2020-10-25 18:48:23 +00:00
|
|
|
import SideBar, {SideBarItem, SideBarTitle} from '../../elements/SideBar/SideBar';
|
|
|
|
import Tag from '../../elements/Tag/Tag';
|
2020-12-11 18:23:13 +00:00
|
|
|
import AddTagPopup from '../../elements/Popups/AddTagPopup/AddTagPopup';
|
2020-10-25 18:48:23 +00:00
|
|
|
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
|
2020-12-11 18:23:13 +00:00
|
|
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
|
|
import {faPlusCircle} from '@fortawesome/free-solid-svg-icons';
|
|
|
|
import AddActorPopup from '../../elements/Popups/AddActorPopup/AddActorPopup';
|
|
|
|
import ActorTile from '../../elements/ActorTile/ActorTile';
|
|
|
|
import GlobalInfos from '../../GlobalInfos';
|
2020-05-31 23:22:50 +02:00
|
|
|
|
|
|
|
|
2020-08-12 17:50:25 +00:00
|
|
|
/**
|
|
|
|
* Player page loads when a video is selected to play and handles the video view
|
|
|
|
* and actions such as tag adding and liking
|
|
|
|
*/
|
2020-05-31 23:22:50 +02:00
|
|
|
class Player extends React.Component {
|
2020-06-01 19:09:32 +02:00
|
|
|
options = {
|
|
|
|
controls: [
|
|
|
|
'play-large', // The large play button in the center
|
|
|
|
'play', // Play/pause playback
|
|
|
|
'progress', // The progress bar and scrubber for playback and buffering
|
|
|
|
'current-time', // The current time of playback
|
|
|
|
'duration', // The full duration of the media
|
|
|
|
'mute', // Toggle mute
|
|
|
|
'volume', // Volume control
|
|
|
|
'captions', // Toggle captions
|
|
|
|
'settings', // Settings menu
|
|
|
|
'airplay', // Airplay (currently Safari only)
|
|
|
|
'download', // Show a download button with a link to either the current source or a custom URL you specify in your options
|
2020-10-25 18:48:23 +00:00
|
|
|
'fullscreen' // Toggle fullscreen
|
2020-06-01 19:09:32 +02:00
|
|
|
]
|
|
|
|
};
|
2020-05-31 23:22:50 +02:00
|
|
|
|
2020-08-05 17:55:51 +00:00
|
|
|
constructor(props, context) {
|
|
|
|
super(props, context);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
sources: null,
|
|
|
|
movie_id: null,
|
|
|
|
movie_name: null,
|
|
|
|
likes: null,
|
|
|
|
quality: null,
|
|
|
|
length: null,
|
|
|
|
tags: [],
|
2020-09-26 18:43:30 +00:00
|
|
|
suggesttag: [],
|
2020-12-11 18:23:13 +00:00
|
|
|
popupvisible: false,
|
|
|
|
actorpopupvisible: false
|
2020-08-05 17:55:51 +00:00
|
|
|
};
|
2020-10-09 14:00:51 +00:00
|
|
|
|
|
|
|
this.quickAddTag = this.quickAddTag.bind(this);
|
2020-08-05 17:55:51 +00:00
|
|
|
}
|
|
|
|
|
2020-06-01 19:09:32 +02:00
|
|
|
componentDidMount() {
|
2020-12-11 18:23:13 +00:00
|
|
|
// initial fetch of current movie data
|
2020-06-01 19:09:32 +02:00
|
|
|
this.fetchMovieData();
|
2020-05-31 23:22:50 +02:00
|
|
|
}
|
|
|
|
|
2020-09-26 18:43:30 +00:00
|
|
|
/**
|
|
|
|
* quick add callback to add tag to db and change gui correctly
|
2020-11-04 23:52:22 +01:00
|
|
|
* @param tagId id of tag to add
|
|
|
|
* @param tagName name of tag to add
|
2020-09-26 18:43:30 +00:00
|
|
|
*/
|
2020-11-04 23:52:22 +01:00
|
|
|
quickAddTag(tagId, tagName) {
|
2020-09-26 18:43:30 +00:00
|
|
|
const updateRequest = new FormData();
|
|
|
|
updateRequest.append('action', 'addTag');
|
2020-11-04 23:52:22 +01:00
|
|
|
updateRequest.append('id', tagId);
|
2020-09-26 18:43:30 +00:00
|
|
|
updateRequest.append('movieid', this.props.movie_id);
|
|
|
|
|
|
|
|
fetch('/api/tags.php', {method: 'POST', body: updateRequest})
|
|
|
|
.then((response) => response.json()
|
|
|
|
.then((result) => {
|
2020-10-25 18:48:23 +00:00
|
|
|
if (result.result !== 'success') {
|
|
|
|
console.error('error occured while writing to db -- todo error handling');
|
2020-09-26 18:43:30 +00:00
|
|
|
console.error(result.result);
|
|
|
|
} else {
|
2020-10-25 18:48:23 +00:00
|
|
|
// check if tag has already been added
|
2020-11-04 23:52:22 +01:00
|
|
|
const tagIndex = this.state.tags.map(function (e) {
|
2020-10-25 18:48:23 +00:00
|
|
|
return e.tag_name;
|
2020-11-04 23:52:22 +01:00
|
|
|
}).indexOf(tagName);
|
2020-09-26 18:43:30 +00:00
|
|
|
|
2020-10-25 18:48:23 +00:00
|
|
|
// only add tag if it isn't already there
|
2020-11-04 23:52:22 +01:00
|
|
|
if (tagIndex === -1) {
|
2020-10-25 18:48:23 +00:00
|
|
|
// update tags if successful
|
|
|
|
let array = [...this.state.suggesttag]; // make a separate copy of the array (because of setState)
|
|
|
|
const quickaddindex = this.state.suggesttag.map(function (e) {
|
|
|
|
return e.tag_id;
|
2020-11-04 23:52:22 +01:00
|
|
|
}).indexOf(tagId);
|
2020-09-26 18:43:30 +00:00
|
|
|
|
2020-10-25 18:48:23 +00:00
|
|
|
// check if tag is available in quickadds
|
|
|
|
if (quickaddindex !== -1) {
|
|
|
|
array.splice(quickaddindex, 1);
|
|
|
|
|
|
|
|
this.setState({
|
2020-11-04 23:52:22 +01:00
|
|
|
tags: [...this.state.tags, {tag_name: tagName}],
|
2020-10-25 18:48:23 +00:00
|
|
|
suggesttag: array
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setState({
|
2020-11-04 23:52:22 +01:00
|
|
|
tags: [...this.state.tags, {tag_name: tagName}]
|
2020-10-25 18:48:23 +00:00
|
|
|
});
|
|
|
|
}
|
2020-09-26 18:43:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2020-10-09 14:00:51 +00:00
|
|
|
/**
|
|
|
|
* handle the popovers generated according to state changes
|
|
|
|
* @returns {JSX.Element}
|
|
|
|
*/
|
|
|
|
handlePopOvers() {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{this.state.popupvisible ?
|
2020-12-11 18:23:13 +00:00
|
|
|
<AddTagPopup onHide={() => {this.setState({popupvisible: false});}}
|
2020-10-09 14:00:51 +00:00
|
|
|
submit={this.quickAddTag}
|
|
|
|
movie_id={this.state.movie_id}/> :
|
|
|
|
null
|
|
|
|
}
|
2020-12-11 18:23:13 +00:00
|
|
|
{
|
|
|
|
this.state.actorpopupvisible ?
|
|
|
|
<AddActorPopup onHide={() => {
|
|
|
|
this.refetchActors();
|
|
|
|
this.setState({actorpopupvisible: false});
|
|
|
|
}} movie_id={this.state.movie_id}/> : null
|
|
|
|
}
|
2020-10-09 14:00:51 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-09-26 18:43:30 +00:00
|
|
|
/**
|
|
|
|
* generate sidebar with all items
|
|
|
|
*/
|
|
|
|
assembleSideBar() {
|
|
|
|
return (
|
|
|
|
<SideBar>
|
|
|
|
<SideBarTitle>Infos:</SideBarTitle>
|
|
|
|
<Line/>
|
|
|
|
<SideBarItem><b>{this.state.likes}</b> Likes!</SideBarItem>
|
|
|
|
{this.state.quality !== 0 ?
|
|
|
|
<SideBarItem><b>{this.state.quality}p</b> Quality!</SideBarItem> : null}
|
|
|
|
{this.state.length !== 0 ?
|
2020-12-11 18:23:13 +00:00
|
|
|
<SideBarItem><b>{Math.round(this.state.length / 60)}</b> Minutes of length!</SideBarItem> : null}
|
2020-09-26 18:43:30 +00:00
|
|
|
<Line/>
|
|
|
|
<SideBarTitle>Tags:</SideBarTitle>
|
|
|
|
{this.state.tags.map((m) => (
|
2020-12-11 18:23:13 +00:00
|
|
|
<Tag key={m.tag_name}>{m.tag_name}</Tag>
|
2020-09-26 18:43:30 +00:00
|
|
|
))}
|
|
|
|
<Line/>
|
|
|
|
<SideBarTitle>Tag Quickadd:</SideBarTitle>
|
|
|
|
{this.state.suggesttag.map((m) => (
|
|
|
|
<Tag
|
|
|
|
key={m.tag_name}
|
|
|
|
onclick={() => {
|
|
|
|
this.quickAddTag(m.tag_id, m.tag_name);
|
|
|
|
}}>
|
|
|
|
{m.tag_name}
|
|
|
|
</Tag>
|
|
|
|
))}
|
|
|
|
</SideBar>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-05-31 23:22:50 +02:00
|
|
|
render() {
|
|
|
|
return (
|
2020-06-01 21:36:55 +02:00
|
|
|
<div id='videocontainer'>
|
2020-06-19 00:16:18 +02:00
|
|
|
<PageTitle
|
|
|
|
title='Watch'
|
|
|
|
subtitle={this.state.movie_name}/>
|
|
|
|
|
2020-09-26 18:43:30 +00:00
|
|
|
{this.assembleSideBar()}
|
2020-06-02 22:52:28 +02:00
|
|
|
|
2020-07-08 00:14:08 +02:00
|
|
|
<div className={style.videowrapper}>
|
2020-06-02 22:52:28 +02:00
|
|
|
{/* video component is added here */}
|
2020-11-27 22:43:12 +00:00
|
|
|
{this.state.sources ? <Plyr
|
|
|
|
style={plyrstyle}
|
|
|
|
source={this.state.sources}
|
2020-06-02 22:52:28 +02:00
|
|
|
options={this.options}/> :
|
|
|
|
<div>not loaded yet</div>}
|
2020-07-08 00:14:08 +02:00
|
|
|
<div className={style.videoactions}>
|
2020-12-11 18:23:13 +00:00
|
|
|
<button className={style.button} style={{backgroundColor: 'green'}} onClick={() => this.likebtn()}>
|
|
|
|
Like this Video!
|
|
|
|
</button>
|
2020-11-20 21:31:07 +01:00
|
|
|
<button className={style.button} style={{backgroundColor: '#3574fe'}} onClick={() => this.setState({popupvisible: true})}>
|
|
|
|
Give this Video a Tag
|
|
|
|
</button>
|
|
|
|
<button className={style.button} style={{backgroundColor: 'red'}} onClick={() => {
|
|
|
|
this.deleteVideo();
|
|
|
|
}}>Delete Video
|
2020-10-19 21:12:07 +00:00
|
|
|
</button>
|
2020-06-01 17:58:48 +02:00
|
|
|
</div>
|
2020-12-11 18:23:13 +00:00
|
|
|
{/* rendering of actor tiles */}
|
|
|
|
<div className={style.actorcontainer}>
|
|
|
|
{this.state.actors ?
|
|
|
|
this.state.actors.map((actr) => (
|
|
|
|
<ActorTile actor={actr}/>
|
|
|
|
)) : <></>
|
|
|
|
}
|
|
|
|
<div className={style.actorAddTile} onClick={() => {
|
|
|
|
this.addActor();
|
|
|
|
}}>
|
|
|
|
<div className={style.actorAddTile_thumbnail}>
|
|
|
|
<FontAwesomeIcon style={{
|
|
|
|
lineHeight: '130px'
|
|
|
|
}} icon={faPlusCircle} size='5x'/>
|
|
|
|
</div>
|
|
|
|
<div className={style.actorAddTile_name}>Add Actor</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2020-06-01 17:58:48 +02:00
|
|
|
</div>
|
2020-07-08 00:14:08 +02:00
|
|
|
<button className={style.closebutton} onClick={() => this.closebtn()}>Close</button>
|
2020-10-09 14:00:51 +00:00
|
|
|
{
|
|
|
|
// handle the popovers switched on and off according to state changes
|
|
|
|
this.handlePopOvers()
|
|
|
|
}
|
2020-05-31 23:22:50 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2020-06-01 19:09:32 +02:00
|
|
|
|
2020-08-12 17:50:25 +00:00
|
|
|
/**
|
|
|
|
* fetch all the required infos of a video from backend
|
|
|
|
*/
|
2020-06-02 16:15:12 +02:00
|
|
|
fetchMovieData() {
|
2020-06-01 19:09:32 +02:00
|
|
|
const updateRequest = new FormData();
|
|
|
|
updateRequest.append('action', 'loadVideo');
|
|
|
|
updateRequest.append('movieid', this.props.movie_id);
|
|
|
|
|
2020-08-12 17:50:25 +00:00
|
|
|
fetch('/api/video.php', {method: 'POST', body: updateRequest})
|
2020-06-01 19:09:32 +02:00
|
|
|
.then((response) => response.json())
|
|
|
|
.then((result) => {
|
|
|
|
this.setState({
|
|
|
|
sources: {
|
|
|
|
type: 'video',
|
|
|
|
sources: [
|
|
|
|
{
|
|
|
|
src: result.movie_url,
|
|
|
|
type: 'video/mp4',
|
2020-10-25 18:48:23 +00:00
|
|
|
size: 1080
|
2020-06-01 19:09:32 +02:00
|
|
|
}
|
|
|
|
],
|
|
|
|
poster: result.thumbnail
|
|
|
|
},
|
2020-06-06 11:48:12 +00:00
|
|
|
movie_id: result.movie_id,
|
2020-06-02 22:52:28 +02:00
|
|
|
movie_name: result.movie_name,
|
2020-06-02 16:15:12 +02:00
|
|
|
likes: result.likes,
|
|
|
|
quality: result.quality,
|
2020-06-03 12:26:10 +02:00
|
|
|
length: result.length,
|
2020-09-26 18:43:30 +00:00
|
|
|
tags: result.tags,
|
2020-12-11 18:23:13 +00:00
|
|
|
suggesttag: result.suggesttag,
|
|
|
|
actors: result.actors
|
2020-06-01 19:09:32 +02:00
|
|
|
});
|
2020-09-26 18:43:30 +00:00
|
|
|
console.log(this.state);
|
2020-06-01 19:09:32 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-12 17:50:25 +00:00
|
|
|
/**
|
|
|
|
* click handler for the like btn
|
|
|
|
*/
|
2020-06-01 19:09:32 +02:00
|
|
|
likebtn() {
|
|
|
|
const updateRequest = new FormData();
|
|
|
|
updateRequest.append('action', 'addLike');
|
|
|
|
updateRequest.append('movieid', this.props.movie_id);
|
|
|
|
|
2020-08-12 17:50:25 +00:00
|
|
|
fetch('/api/video.php', {method: 'POST', body: updateRequest})
|
2020-06-12 15:57:30 +00:00
|
|
|
.then((response) => response.json()
|
|
|
|
.then((result) => {
|
2020-10-25 18:48:23 +00:00
|
|
|
if (result.result === 'success') {
|
2020-09-26 18:43:30 +00:00
|
|
|
// likes +1 --> avoid reload of all data
|
2020-10-25 18:48:23 +00:00
|
|
|
this.setState({likes: this.state.likes + 1});
|
2020-06-12 15:57:30 +00:00
|
|
|
} else {
|
2020-10-25 18:48:23 +00:00
|
|
|
console.error('an error occured while liking');
|
2020-09-26 18:43:30 +00:00
|
|
|
console.error(result);
|
2020-06-12 15:57:30 +00:00
|
|
|
}
|
|
|
|
}));
|
2020-06-01 19:09:32 +02:00
|
|
|
}
|
|
|
|
|
2020-08-12 17:50:25 +00:00
|
|
|
/**
|
|
|
|
* closebtn click handler
|
|
|
|
* calls callback to viewbinding to show previous page agains
|
|
|
|
*/
|
2020-06-01 19:09:32 +02:00
|
|
|
closebtn() {
|
2020-12-11 18:23:13 +00:00
|
|
|
GlobalInfos.getViewBinding().returnToLastElement();
|
2020-06-01 19:09:32 +02:00
|
|
|
}
|
2020-10-03 07:06:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* delete the current video and return to last page
|
|
|
|
*/
|
|
|
|
deleteVideo() {
|
|
|
|
const updateRequest = new FormData();
|
|
|
|
updateRequest.append('action', 'deleteVideo');
|
|
|
|
updateRequest.append('movieid', this.props.movie_id);
|
|
|
|
|
|
|
|
fetch('/api/video.php', {method: 'POST', body: updateRequest})
|
|
|
|
.then((response) => response.json()
|
|
|
|
.then((result) => {
|
2020-10-25 18:48:23 +00:00
|
|
|
if (result.result === 'success') {
|
2020-10-03 07:06:27 +00:00
|
|
|
// return to last element if successful
|
2020-12-11 18:23:13 +00:00
|
|
|
GlobalInfos.getViewBinding().returnToLastElement();
|
2020-10-03 07:06:27 +00:00
|
|
|
} else {
|
2020-10-25 18:48:23 +00:00
|
|
|
console.error('an error occured while liking');
|
2020-10-03 07:06:27 +00:00
|
|
|
console.error(result);
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
2020-12-11 18:23:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* show the actor add popup
|
|
|
|
*/
|
|
|
|
addActor() {
|
|
|
|
this.setState({actorpopupvisible: true});
|
|
|
|
}
|
|
|
|
|
|
|
|
refetchActors() {
|
|
|
|
const req = new FormData();
|
|
|
|
req.append('action', 'getActorsOfVideo');
|
|
|
|
req.append('videoid', this.props.movie_id);
|
|
|
|
|
|
|
|
console.log('refrething actors');
|
|
|
|
|
|
|
|
fetch('/api/actor.php', {method: 'POST', body: req})
|
|
|
|
.then((response) => response.json()
|
|
|
|
.then((result) => {
|
|
|
|
this.setState({actors: result});
|
|
|
|
}));
|
|
|
|
}
|
2020-05-31 23:22:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export default Player;
|