cleanup and fix flow issues
This commit is contained in:
parent
0754bb1a7f
commit
767c69e132
4 changed files with 53 additions and 26 deletions
|
@ -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()),
|
||||
});
|
||||
|
|
|
@ -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} />;
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue