cleanup and fix flow issues

This commit is contained in:
Sean Yesmunt 2020-04-28 15:33:30 -04:00
parent 0754bb1a7f
commit 767c69e132
4 changed files with 53 additions and 26 deletions

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { makeSelectClaimForUri, makeSelectFileInfoForUri, makeSelectThumbnailForUri } from 'lbry-redux';
import { doChangeVolume, doChangeMute, doAnalyticsView } from 'redux/actions/app';
import { selectVolume, selectMute } from 'redux/selectors/app';
import { savePosition, doSetPlayingUri } from 'redux/actions/content';
import { savePosition } from 'redux/actions/content';
import VideoViewer from './view';
import { withRouter } from 'react-router';
import { doClaimEligiblePurchaseRewards } from 'lbryinc';
@ -31,7 +31,6 @@ const perform = dispatch => ({
changeVolume: volume => dispatch(doChangeVolume(volume)),
savePosition: (uri, position) => dispatch(savePosition(uri, position)),
changeMute: muted => dispatch(doChangeMute(muted)),
setPlayingUri: uri => dispatch(doSetPlayingUri(uri)),
doAnalyticsView: (uri, timeToStart) => dispatch(doAnalyticsView(uri, timeToStart)),
claimRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
});

View file

@ -1,17 +1,28 @@
// @flow
import React, { useEffect, useRef } from 'react';
import classnames from 'classnames';
import videojs from 'video.js/dist/alt/video.core.novtt.min.js';
import 'video.js/dist/alt/video-js-cdn.min.css';
import eventTracking from 'videojs-event-tracking';
import isUserTyping from 'util/detect-typing';
export type Player = {
on: (string, (any) => void) => void,
isFullscreen: () => boolean,
exitFullscreen: () => boolean,
requestFullscreen: () => boolean,
play: () => Promise<any>,
volume: (?number) => number,
muted: (?boolean) => boolean,
dispose: () => void,
currentTime: number => void,
};
type Props = {
source: string,
sourceType: string,
poster: boolean,
autoplay: boolean,
onPlayerReady: () => null,
onVolumeChange: () => null,
poster: ?string,
onPlayerReady: Player => void,
isAudio: boolean,
startMuted: boolean,
};
@ -27,12 +38,17 @@ type VideoJSOptions = {
};
const VIDEO_JS_OPTIONS: VideoJSOptions = {
controls: true,
preload: 'auto',
playbackRates: [0.25, 0.5, 0.75, 1, 1.1, 1.25, 1.5, 1.75, 2],
responsive: true,
controls: true,
};
const IS_IOS =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
const F11_KEYCODE = 122;
const SPACE_BAR_KEYCODE = 32;
const SMALL_F_KEYCODE = 70;
@ -55,8 +71,9 @@ if (!Object.keys(videojs.getPlugins()).includes('eventTracking')) {
/*
properties for this component should be kept to ONLY those that if changed should REQUIRE an entirely new videojs element
*/
export default React.memo(function VideoJs(props: Props) {
export default React.memo<Props>(function VideoJs(props: Props) {
const { startMuted, source, sourceType, poster, isAudio, onPlayerReady } = props;
let player: ?Player;
const containerRef = useRef();
const videoJsOptions = {
...VIDEO_JS_OPTIONS,
@ -74,7 +91,7 @@ export default React.memo(function VideoJs(props: Props) {
videoJsOptions.muted = startMuted;
function handleKeyDown(e: KeyboardEvent) {
const videoNode = containerRef.current && containerRef.current.querySelector('video, audio');
const videoNode: ?HTMLVideoElement = containerRef.current && containerRef.current.querySelector('video, audio');
if (!videoNode || isUserTyping()) {
return;
@ -85,8 +102,8 @@ export default React.memo(function VideoJs(props: Props) {
}
// Fullscreen toggle shortcuts
if (e.keyCode === FULLSCREEN_KEYCODE || e.keyCode === F11_KEYCODE) {
if (player && !player.isFullscreen()) {
if (player && (e.keyCode === FULLSCREEN_KEYCODE || e.keyCode === F11_KEYCODE)) {
if (!player.isFullscreen()) {
player.requestFullscreen();
} else {
player.exitFullscreen();
@ -111,21 +128,22 @@ export default React.memo(function VideoJs(props: Props) {
}
}
let player;
// Create the video element. Note that a new videojs instantiation will happen on *every* render, so do not add props to this component!
useEffect(() => {
if (containerRef.current) {
const wrapper = document.createElement('div');
wrapper.setAttribute('data-vjs-player', true);
wrapper.setAttribute('data-vjs-player', 'true');
const el = document.createElement(isAudio ? 'audio' : 'video');
el.className = 'video-js';
el.playsinline = true;
wrapper.appendChild(el);
// $FlowFixMe
containerRef.current.appendChild(wrapper);
player = videojs(el, videoJsOptions, () => {
onPlayerReady(player);
if (player) {
onPlayerReady(player);
}
});
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
@ -137,10 +155,14 @@ export default React.memo(function VideoJs(props: Props) {
return () => {
window.removeEventListener('keydown', handleKeyDown);
player.dispose();
if (player) {
player.dispose();
}
};
}
});
return <div className="video-js-parent" ref={containerRef} />;
// $FlowFixMe
return <div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef} />;
});

View file

@ -1,6 +1,7 @@
// @flow
import React, { useEffect, useState, useContext, useCallback } from 'react';
import { stopContextMenu } from 'util/context-menu';
import type { Player } from './internal/videojs';
import VideoJs from './internal/videojs';
import analytics from 'analytics';
@ -13,6 +14,8 @@ import FileViewerEmbeddedEnded from 'lbrytv/component/fileViewerEmbeddedEnded';
import FileViewerEmbeddedTitle from 'lbrytv/component/fileViewerEmbeddedTitle';
import LoadingScreen from 'component/common/loading-screen';
const PLAY_TIMEOUT_ERROR = 'play_timeout_error';
type Props = {
position: number,
changeVolume: number => void,
@ -28,7 +31,6 @@ type Props = {
autoplayIfEmbedded: boolean,
doAnalyticsView: (string, number) => Promise<any>,
claimRewards: () => void,
setPlayingUri: (?string) => void,
};
/*
@ -52,7 +54,6 @@ function VideoViewer(props: Props) {
autoplayIfEmbedded,
doAnalyticsView,
claimRewards,
setPlayingUri,
} = props;
const claimId = claim && claim.claim_id;
const isAudio = contentType.includes('audio');
@ -109,7 +110,7 @@ function VideoViewer(props: Props) {
setIsPlaying(false);
}
const onPlayerReady = useCallback(player => {
const onPlayerReady = useCallback((player: Player) => {
if (!embedded) {
player.muted(muted);
player.volume(volume);
@ -120,22 +121,21 @@ function VideoViewer(props: Props) {
if (shouldPlay) {
const playPromise = player.play();
const timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => reject('test'), 1000);
setTimeout(() => reject(PLAY_TIMEOUT_ERROR), 1000);
});
Promise.race([playPromise, timeoutPromise]).catch(error => {
if (error === 'test') {
if (error === PLAY_TIMEOUT_ERROR) {
// The player promise hung
// This is probably in firefox
// Try playing again, it works?
// The second attempt usually works
player.play();
} else {
// Autoplay was actually blocked by the browser.
// Autoplay was actually blocked by the browser
// Reset everything so the user sees the thumbnail/play button and can start it on their own
setIsLoading(false);
setIsPlaying(false);
}
console.log('error', error);
});
}

View file

@ -288,6 +288,12 @@
width: 100%;
}
.video-js-parent--ios {
.vjs-control-bar {
display: none;
}
}
// By default no video js play button
.vjs-big-play-button {
display: none;