Merge pull request #1044 from lbryio/issue/1012

Fixes Video Player "waits for metadata" bug
This commit is contained in:
Igor Gassmann 2018-02-25 18:30:58 -05:00 committed by GitHub
commit 47cd0193b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 64 deletions

View file

@ -1,5 +1,4 @@
const { remote } = require('electron'); import { remote } from 'electron';
import React from 'react'; import React from 'react';
import { Thumbnail } from 'component/common'; import { Thumbnail } from 'component/common';
import player from 'render-media'; import player from 'render-media';
@ -21,33 +20,21 @@ class VideoPlayer extends React.PureComponent {
this.togglePlayListener = this.togglePlay.bind(this); this.togglePlayListener = this.togglePlay.bind(this);
} }
componentWillReceiveProps(next) {
const el = this.refs.media.children[0];
if (!this.props.paused && next.paused && !el.paused) el.pause();
}
componentDidMount() { componentDidMount() {
const container = this.refs.media; const container = this.media;
const { const { contentType, changeVolume, volume, position, claim } = this.props;
contentType,
downloadPath,
mediaType,
changeVolume,
volume,
position,
claim,
uri,
} = this.props;
const loadedMetadata = e => { const loadedMetadata = () => {
this.setState({ hasMetadata: true, startedPlaying: true }); this.setState({ hasMetadata: true, startedPlaying: true });
this.refs.media.children[0].play(); this.media.children[0].play();
}; };
const renderMediaCallback = err => {
if (err) this.setState({ unplayable: true }); const renderMediaCallback = error => {
if (error) this.setState({ unplayable: true });
}; };
// Handle fullscreen change for the Windows platform // Handle fullscreen change for the Windows platform
const win32FullScreenChange = e => { const win32FullScreenChange = () => {
const win = remote.BrowserWindow.getFocusedWindow(); const win = remote.BrowserWindow.getFocusedWindow();
if (process.platform === 'win32') { if (process.platform === 'win32') {
win.setMenu(document.webkitIsFullScreen ? null : remote.Menu.getApplicationMenu()); win.setMenu(document.webkitIsFullScreen ? null : remote.Menu.getApplicationMenu());
@ -61,13 +48,13 @@ class VideoPlayer extends React.PureComponent {
player.append( player.append(
this.file(), this.file(),
container, container,
{ autoplay: false, controls: true }, { autoplay: true, controls: true },
renderMediaCallback.bind(this) renderMediaCallback.bind(this)
); );
} }
document.addEventListener('keydown', this.togglePlayListener); document.addEventListener('keydown', this.togglePlayListener);
const mediaElement = this.refs.media.children[0]; const mediaElement = this.media.children[0];
if (mediaElement) { if (mediaElement) {
mediaElement.currentTime = position || 0; mediaElement.currentTime = position || 0;
mediaElement.addEventListener('play', () => this.props.doPlay()); mediaElement.addEventListener('play', () => this.props.doPlay());
@ -87,29 +74,38 @@ class VideoPlayer extends React.PureComponent {
} }
} }
componentWillReceiveProps(next) {
const el = this.media.children[0];
if (!this.props.paused && next.paused && !el.paused) el.pause();
}
componentDidUpdate() {
const { contentType, downloadCompleted } = this.props;
const { startedPlaying } = this.state;
if (this.playableType() && !startedPlaying && downloadCompleted) {
const container = this.media.children[0];
if (VideoPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
this.renderAudio(this.media, true);
} else {
player.render(this.file(), container, {
autoplay: true,
controls: true,
});
}
}
}
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener('keydown', this.togglePlayListener); document.removeEventListener('keydown', this.togglePlayListener);
const mediaElement = this.refs.media.children[0]; const mediaElement = this.media.children[0];
if (mediaElement) { if (mediaElement) {
mediaElement.removeEventListener('click', this.togglePlayListener); mediaElement.removeEventListener('click', this.togglePlayListener);
} }
this.props.doPause(); this.props.doPause();
} }
renderAudio(container, autoplay) {
if (container.firstChild) {
container.firstChild.remove();
}
// clear the container
const { downloadPath } = this.props;
const audio = document.createElement('audio');
audio.autoplay = autoplay;
audio.controls = true;
audio.src = downloadPath;
container.appendChild(audio);
}
togglePlay(event) { togglePlay(event) {
// ignore all events except click and spacebar keydown, or input events in a form control // ignore all events except click and spacebar keydown, or input events in a form control
if ( if (
@ -119,7 +115,7 @@ class VideoPlayer extends React.PureComponent {
return; return;
} }
event.preventDefault(); event.preventDefault();
const mediaElement = this.refs.media.children[0]; const mediaElement = this.media.children[0];
if (mediaElement) { if (mediaElement) {
if (!mediaElement.paused) { if (!mediaElement.paused) {
mediaElement.pause(); mediaElement.pause();
@ -129,24 +125,6 @@ class VideoPlayer extends React.PureComponent {
} }
} }
componentDidUpdate() {
const { contentType, downloadCompleted } = this.props;
const { startedPlaying } = this.state;
if (this.playableType() && !startedPlaying && downloadCompleted) {
const container = this.refs.media.children[0];
if (VideoPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
this.renderAudio(this.refs.media, true);
} else {
player.render(this.file(), container, {
autoplay: true,
controls: true,
});
}
}
}
file() { file() {
const { downloadPath, filename } = this.props; const { downloadPath, filename } = this.props;
@ -162,14 +140,26 @@ class VideoPlayer extends React.PureComponent {
return ['audio', 'video'].indexOf(mediaType) !== -1; return ['audio', 'video'].indexOf(mediaType) !== -1;
} }
renderAudio(container, autoplay) {
if (container.firstChild) {
container.firstChild.remove();
}
// clear the container
const { downloadPath } = this.props;
const audio = document.createElement('audio');
audio.autoplay = autoplay;
audio.controls = true;
audio.src = downloadPath;
container.appendChild(audio);
}
render() { render() {
const { mediaType, poster } = this.props; const { mediaType, poster } = this.props;
const { hasMetadata, unplayable } = this.state; const { hasMetadata, unplayable } = this.state;
const noMetadataMessage = 'Waiting for metadata.'; const noMetadataMessage = 'Waiting for metadata.';
const unplayableMessage = "Sorry, looks like we can't play this file."; const unplayableMessage = "Sorry, looks like we can't play this file.";
const needsMetadata = this.playableType();
return ( return (
<div> <div>
{['audio', 'application'].indexOf(mediaType) !== -1 && {['audio', 'application'].indexOf(mediaType) !== -1 &&
@ -179,7 +169,12 @@ class VideoPlayer extends React.PureComponent {
!hasMetadata && !hasMetadata &&
!unplayable && <LoadingScreen status={noMetadataMessage} />} !unplayable && <LoadingScreen status={noMetadataMessage} />}
{unplayable && <LoadingScreen status={unplayableMessage} spinner={false} />} {unplayable && <LoadingScreen status={unplayableMessage} spinner={false} />}
<div ref="media" className="media" /> <div
ref={container => {
this.media = container;
}}
className="media"
/>
</div> </div>
); );
} }

View file

@ -2,10 +2,10 @@ import { remote } from 'electron';
const application = remote.app; const application = remote.app;
const { dock } = application; const { dock } = application;
const win = remote.BrowserWindow.getFocusedWindow(); const browserWindow = remote.getCurrentWindow();
const setBadge = text => { const setBadge = text => {
if (!dock) return; if (!dock) return;
if (win.isFocused()) return; if (browserWindow.isFocused()) return;
dock.setBadge(text); dock.setBadge(text);
}; };