Video player #14

Merged
innocuous-symmetry merged 10 commits from video-player into master 2022-02-08 17:36:39 +00:00
3 changed files with 130 additions and 20 deletions

View File

@@ -64,6 +64,19 @@ img, video {
color: rgb(97, 49, 95);
}
.gallery-statement {
color: rgb(228, 180, 226);
}
.gallery-statement a {
color: white;
text-decoration: none;
}
.gallery-statement a:active {
color:rgb(97, 49, 95);
}
.num-comments {
display: inline-flex;
background-color: #7196be;
@@ -80,6 +93,20 @@ img, video {
color:rgb(228, 180, 226);
}
/* Video player */
.video-player {
display: inline-flex;
flex-direction: column;
align-items: center;
}
#post-audio {
position: relative;
height: 3.5rem;
width: 60%;
}
/* Handles comment styles on toggle */
.comments-visible {

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
// import { useDispatch } from "react-redux";
import Discussion from "../discussion/Discussion";
import VideoPlayer from "../video/VideoPlayer";
import './Post.css';
export default function Post({data, key}) {
@@ -14,11 +14,6 @@ export default function Post({data, key}) {
let media = data.post_hint === 'image' && data.url;
let permalink = data.permalink;
let selftext = data.selftext;
let video = data.is_video ? `${data.url}/DASH_1080.mp4` : null; // to do: handle media edge cases, especially video
// fallback_url: "https://v.redd.it/0rditq5l49g81/DASH_1080.mp4?source=fallback"
// url: "https://v.redd.it/0rditq5l49g81"
// id: "sm2wym"
const limit = 300;
const [body, setBody] = useState(selftext);
@@ -75,7 +70,7 @@ export default function Post({data, key}) {
if (data.crosspost_parent_list[0].is_video) {
return (
<>
<video controls src={data.crosspost_parent_list[0].media.reddit_video.fallback_url}>This video is not supported by your browser.</video>
<VideoPlayer data={data} src={data.crosspost_parent_list[0].url} />
<p className="crosspost-from">Crosspost from {data.crosspost_parent_list[0].subreddit_name_prefixed}</p>
</>
);
@@ -90,6 +85,10 @@ export default function Post({data, key}) {
return;
}
}
// Render function below:
// Each is preceded by a conditional so the program does not throw an error
// before the fetch requests' promises are fulfilled.
return (
<>
@@ -99,23 +98,17 @@ export default function Post({data, key}) {
<a className="title" href={`https://reddit.com${permalink}`}>{title}</a>
: <p>[untitled]</p>}
{media ? <img alt={title} src={media} /> : ''}
{data.crosspost_parent_list ? handleCrosspost() : ''}
{media ? <img alt={title} src={media} /> : null}
{data.crosspost_parent_list ? handleCrosspost() : null}
{data.gallery_data ?
<p>View the gallery of photos corresponding to this post <a href={data.url}>here</a>.</p>
<p className="gallery-statement">View the gallery of photos corresponding to this post <a href={data.url}>here</a>.</p>
: null}
{video ?
<video
controls
poster={data.thumbnail}
preload="auto"
src={video}>
Your video is not supported by the browser.
</video>
: ''}
{data.is_video ?
<VideoPlayer data={data} />
: null}
{body ?
<p onMouseOver={handleHover} onMouseOut={handleMouseOut}>{body}</p>

View File

@@ -0,0 +1,90 @@
import { useState, useEffect, useRef } from 'react';
export default function VideoPlayer({data, src}) {
const vidControls = useRef();
const vid = useRef();
const aud = useRef(); // identifies location of video/audio in DOM
const [playing, setPlaying] = useState(false); // handles play/pause logic
const [audio, setAudio] = useState(null);
const crossPostSrc = src;
let url; // contains video source, routed accordingly by logic below
if (crossPostSrc) {
url = crossPostSrc; // ... for crossposts
} else if (data.url) {
url = data.url; // ... for local posts, where the url
} else { // can be accessed at data.url
url = null; // otherwise, is null
}
useEffect(() => { // checks the endpoint where audio may be found
let checking = true; // if the fetch request throws an error, audio is set to null;
const checkForAudio = async() => { // otherwise, audio is set to the endpoint, which is evaluated
try { // below as truthy, and rendered in the page
await fetch(`${url}/DASH_audio.mp4`)
.then((response) => {
let status = response.status;
if (status > 400) {
setAudio(null);
} else {
setAudio(`${url}/DASH_audio.mp4`);
}
});
} catch(e) {
console.log(e);
}
}
if (checking) {
checkForAudio();
checking = false;
}
return () => {
checking = false;
}
}, [url, audio]);
useEffect(() => { // this section handles simultaneous playback of audio and video
if (!audio) {
return;
}
if (playing) {
vid.current.play(); // synchronizes play/pause between two components
vid.current.currentTime = aud.current.currentTime; // according to section of state
} else if (!playing) {
vid.current.pause();
}
}, [playing, audio, aud, vid]);
return (
<div className="video-player">
{
!audio ?
<>
<video id="post-video-no-audio" ref={vidControls} controls src={`${url}/DASH_1080.mp4` || `${url}/DASH_1080.mp4?source=fallback`}>
This video is not supported by your browser.
</video>
</>
:
<>
<video id="post-video" ref={vid} autoPlay={playing ? true : false} src={`${url}/DASH_1080.mp4`}>
This video is not supported by your browser.
</video>
<video id="post-audio" ref={aud} controls onPlay={() => setPlaying(true)} onPause={() => setPlaying(false)} src={audio}>
This video is not supported by your browser.
</video>
</>
}
</div>
);
}