Add pop-out player for audio/video in web UI (#14870)

Fix #11160
This commit is contained in:
Eugen Rochko
2020-09-28 13:29:43 +02:00
committed by GitHub
parent 5bbc9a4f78
commit d88a79b456
20 changed files with 648 additions and 58 deletions

View File

@ -104,20 +104,23 @@ class Video extends React.PureComponent {
width: PropTypes.number,
height: PropTypes.number,
sensitive: PropTypes.bool,
startTime: PropTypes.number,
currentTime: PropTypes.number,
onOpenVideo: PropTypes.func,
onCloseVideo: PropTypes.func,
detailed: PropTypes.bool,
inline: PropTypes.bool,
editable: PropTypes.bool,
alwaysVisible: PropTypes.bool,
cacheWidth: PropTypes.func,
visible: PropTypes.bool,
onToggleVisibility: PropTypes.func,
deployPictureInPicture: PropTypes.func,
intl: PropTypes.object.isRequired,
blurhash: PropTypes.string,
link: PropTypes.node,
autoPlay: PropTypes.bool,
defaultVolume: PropTypes.number,
volume: PropTypes.number,
muted: PropTypes.bool,
};
state = {
@ -297,6 +300,15 @@ class Video extends React.PureComponent {
document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
if (!this.state.paused && this.video && this.props.deployPictureInPicture) {
this.props.deployPictureInPicture('video', {
src: this.props.src,
currentTime: this.video.currentTime,
muted: this.video.muted,
volume: this.video.volume,
});
}
}
componentWillReceiveProps (nextProps) {
@ -328,7 +340,18 @@ class Video extends React.PureComponent {
const inView = (top <= (window.innerHeight || document.documentElement.clientHeight)) && (top + height >= 0);
if (!this.state.paused && !inView) {
this.setState({ paused: true }, () => this.video.pause());
this.video.pause();
if (this.props.deployPictureInPicture) {
this.props.deployPictureInPicture('video', {
src: this.props.src,
currentTime: this.video.currentTime,
muted: this.video.muted,
volume: this.video.volume,
});
}
this.setState({ paused: true });
}
}, 150, { trailing: true })
@ -361,15 +384,21 @@ class Video extends React.PureComponent {
}
handleLoadedData = () => {
if (this.props.startTime) {
this.video.currentTime = this.props.startTime;
const { currentTime, volume, muted, autoPlay } = this.props;
if (currentTime) {
this.video.currentTime = currentTime;
}
if (this.props.defaultVolume !== undefined) {
this.video.volume = this.props.defaultVolume;
if (volume !== undefined) {
this.video.volume = volume;
}
if (this.props.autoPlay) {
if (muted !== undefined) {
this.video.muted = muted;
}
if (autoPlay) {
this.video.play();
}
}
@ -414,9 +443,9 @@ class Video extends React.PureComponent {
}
render () {
const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link, editable, blurhash } = this.props;
const { preview, src, inline, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link, editable, blurhash } = this.props;
const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100;
const progress = Math.min((currentTime / duration) * 100, 100);
const playerStyle = {};
let { width, height } = this.props;
@ -430,7 +459,7 @@ class Video extends React.PureComponent {
let preload;
if (startTime || fullscreen || dragging) {
if (this.props.currentTime || fullscreen || dragging) {
preload = 'auto';
} else if (detailed) {
preload = 'metadata';
@ -530,7 +559,7 @@ class Video extends React.PureComponent {
</div>
<div className='video-player__buttons right'>
{(!onCloseVideo && !editable && !fullscreen) && <button type='button' title={intl.formatMessage(messages.hide)} aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
{(!onCloseVideo && !editable && !fullscreen && !this.props.alwaysVisible) && <button type='button' title={intl.formatMessage(messages.hide)} aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
{(!fullscreen && onOpenVideo) && <button type='button' title={intl.formatMessage(messages.expand)} aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><Icon id='expand' fixedWidth /></button>}
{onCloseVideo && <button type='button' title={intl.formatMessage(messages.close)} aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><Icon id='compress' fixedWidth /></button>}
<button type='button' title={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><Icon id={fullscreen ? 'compress' : 'arrows-alt'} fixedWidth /></button>