mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-06 15:38:53 -05:00
feat: Keep a backup from old videojs files
This commit is contained in:
parent
3be86f91f7
commit
660f76ecfe
@ -0,0 +1,257 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import urlParse from 'url-parse';
|
||||
|
||||
import MediaPlayer from 'mediacms-player/dist/mediacms-player.js';
|
||||
import 'mediacms-player/dist/mediacms-player.css';
|
||||
|
||||
import './VideoPlayer.scss';
|
||||
|
||||
export function formatInnerLink(url, baseUrl) {
|
||||
let link = urlParse(url, {});
|
||||
|
||||
if ('' === link.origin || 'null' === link.origin || !link.origin) {
|
||||
link = urlParse(baseUrl + '/' + url.replace(/^\//g, ''), {});
|
||||
}
|
||||
|
||||
return link.toString();
|
||||
}
|
||||
|
||||
export function VideoPlayerError(props) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
<div className="error-container-inner">
|
||||
<span className="icon-wrap">
|
||||
<i className="material-icons">error_outline</i>
|
||||
</span>
|
||||
<span className="msg-wrap">{props.errorMessage}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
VideoPlayerError.propTypes = {
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export function VideoPlayer(props) {
|
||||
const videoElemRef = useRef(null);
|
||||
|
||||
let player = null;
|
||||
|
||||
const playerStates = {
|
||||
playerVolume: props.playerVolume,
|
||||
playerSoundMuted: props.playerSoundMuted,
|
||||
videoQuality: props.videoQuality,
|
||||
videoPlaybackSpeed: props.videoPlaybackSpeed,
|
||||
inTheaterMode: props.inTheaterMode,
|
||||
};
|
||||
|
||||
playerStates.playerVolume =
|
||||
null === playerStates.playerVolume ? 1 : Math.max(Math.min(Number(playerStates.playerVolume), 1), 0);
|
||||
playerStates.playerSoundMuted = null !== playerStates.playerSoundMuted ? playerStates.playerSoundMuted : !1;
|
||||
playerStates.videoQuality = null !== playerStates.videoQuality ? playerStates.videoQuality : 'Auto';
|
||||
playerStates.videoPlaybackSpeed = null !== playerStates.videoPlaybackSpeed ? playerStates.videoPlaybackSpeed : !1;
|
||||
playerStates.inTheaterMode = null !== playerStates.inTheaterMode ? playerStates.inTheaterMode : !1;
|
||||
|
||||
function onClickNext() {
|
||||
if (void 0 !== props.onClickNextCallback) {
|
||||
props.onClickNextCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function onClickPrevious() {
|
||||
if (void 0 !== props.onClickPreviousCallback) {
|
||||
props.onClickPreviousCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function onPlayerStateUpdate(newState) {
|
||||
if (playerStates.playerVolume !== newState.volume) {
|
||||
playerStates.playerVolume = newState.volume;
|
||||
}
|
||||
|
||||
if (playerStates.playerSoundMuted !== newState.soundMuted) {
|
||||
playerStates.playerSoundMuted = newState.soundMuted;
|
||||
}
|
||||
|
||||
if (playerStates.videoQuality !== newState.quality) {
|
||||
playerStates.videoQuality = newState.quality;
|
||||
}
|
||||
|
||||
if (playerStates.videoPlaybackSpeed !== newState.playbackSpeed) {
|
||||
playerStates.videoPlaybackSpeed = newState.playbackSpeed;
|
||||
}
|
||||
|
||||
if (playerStates.inTheaterMode !== newState.theaterMode) {
|
||||
playerStates.inTheaterMode = newState.theaterMode;
|
||||
}
|
||||
|
||||
if (void 0 !== props.onStateUpdateCallback) {
|
||||
props.onStateUpdateCallback(newState);
|
||||
}
|
||||
}
|
||||
|
||||
function initPlayer() {
|
||||
if (null !== player || null !== props.errorMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.inEmbed) {
|
||||
window.removeEventListener('focus', initPlayer);
|
||||
document.removeEventListener('visibilitychange', initPlayer);
|
||||
}
|
||||
|
||||
if (!videoElemRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.inEmbed) {
|
||||
videoElemRef.current.focus(); // Focus on player before instance init.
|
||||
}
|
||||
|
||||
const subtitles = {
|
||||
on: false,
|
||||
};
|
||||
|
||||
if (void 0 !== props.subtitlesInfo && null !== props.subtitlesInfo && props.subtitlesInfo.length) {
|
||||
subtitles.languages = [];
|
||||
|
||||
let i = 0;
|
||||
while (i < props.subtitlesInfo.length) {
|
||||
if (
|
||||
void 0 !== props.subtitlesInfo[i].src &&
|
||||
void 0 !== props.subtitlesInfo[i].srclang &&
|
||||
void 0 !== props.subtitlesInfo[i].label
|
||||
) {
|
||||
subtitles.languages.push({
|
||||
src: formatInnerLink(props.subtitlesInfo[i].src, props.siteUrl),
|
||||
srclang: props.subtitlesInfo[i].srclang,
|
||||
label: props.subtitlesInfo[i].label,
|
||||
});
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (subtitles.languages.length) {
|
||||
subtitles.on = true;
|
||||
}
|
||||
}
|
||||
|
||||
player = new MediaPlayer(
|
||||
videoElemRef.current,
|
||||
{
|
||||
enabledTouchControls: true,
|
||||
sources: props.sources,
|
||||
poster: props.poster,
|
||||
autoplay: props.enableAutoplay,
|
||||
bigPlayButton: true,
|
||||
controlBar: {
|
||||
theaterMode: props.hasTheaterMode,
|
||||
pictureInPicture: false,
|
||||
next: props.hasNextLink ? true : false,
|
||||
previous: props.hasPreviousLink ? true : false,
|
||||
},
|
||||
subtitles: subtitles,
|
||||
cornerLayers: props.cornerLayers,
|
||||
videoPreviewThumb: props.previewSprite,
|
||||
},
|
||||
{
|
||||
volume: playerStates.playerVolume,
|
||||
soundMuted: playerStates.playerSoundMuted,
|
||||
theaterMode: playerStates.inTheaterMode,
|
||||
theSelectedQuality: void 0, // @note: Allow auto resolution selection by sources order.
|
||||
theSelectedPlaybackSpeed: playerStates.videoPlaybackSpeed || 1,
|
||||
},
|
||||
props.info,
|
||||
[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
|
||||
onPlayerStateUpdate,
|
||||
onClickNext,
|
||||
onClickPrevious
|
||||
);
|
||||
|
||||
if (void 0 !== props.onPlayerInitCallback) {
|
||||
props.onPlayerInitCallback(player, videoElemRef.current);
|
||||
}
|
||||
}
|
||||
|
||||
function unsetPlayer() {
|
||||
if (null === player) {
|
||||
return;
|
||||
}
|
||||
videojs(videoElemRef.current).dispose();
|
||||
player = null;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (props.inEmbed || document.hasFocus() || 'visible' === document.visibilityState) {
|
||||
initPlayer();
|
||||
} else {
|
||||
window.addEventListener('focus', initPlayer);
|
||||
document.addEventListener('visibilitychange', initPlayer);
|
||||
}
|
||||
|
||||
/*
|
||||
// We don't need this because we have a custom function in frontend/src/static/js/components/media-viewer/VideoViewer/index.js:617
|
||||
player && player.player.one('loadedmetadata', () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const paramT = Number(urlParams.get('t'));
|
||||
const timestamp = !isNaN(paramT) ? paramT : 0;
|
||||
player.player.currentTime(timestamp);
|
||||
}); */
|
||||
|
||||
return () => {
|
||||
unsetPlayer();
|
||||
|
||||
if (void 0 !== props.onUnmountCallback) {
|
||||
props.onUnmountCallback();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null === props.errorMessage ? (
|
||||
<video ref={videoElemRef} className="video-js vjs-mediacms native-dimensions"></video>
|
||||
) : (
|
||||
<div className="error-container">
|
||||
<div className="error-container-inner">
|
||||
<span className="icon-wrap">
|
||||
<i className="material-icons">error_outline</i>
|
||||
</span>
|
||||
<span className="msg-wrap">{props.errorMessage}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
VideoPlayer.propTypes = {
|
||||
playerVolume: PropTypes.string,
|
||||
playerSoundMuted: PropTypes.bool,
|
||||
videoQuality: PropTypes.string,
|
||||
videoPlaybackSpeed: PropTypes.number,
|
||||
inTheaterMode: PropTypes.bool,
|
||||
siteId: PropTypes.string.isRequired,
|
||||
siteUrl: PropTypes.string.isRequired,
|
||||
errorMessage: PropTypes.string,
|
||||
cornerLayers: PropTypes.object,
|
||||
subtitlesInfo: PropTypes.array.isRequired,
|
||||
inEmbed: PropTypes.bool.isRequired,
|
||||
sources: PropTypes.array.isRequired,
|
||||
info: PropTypes.object.isRequired,
|
||||
enableAutoplay: PropTypes.bool.isRequired,
|
||||
hasTheaterMode: PropTypes.bool.isRequired,
|
||||
hasNextLink: PropTypes.bool.isRequired,
|
||||
hasPreviousLink: PropTypes.bool.isRequired,
|
||||
poster: PropTypes.string,
|
||||
previewSprite: PropTypes.object,
|
||||
onClickPreviousCallback: PropTypes.func,
|
||||
onClickNextCallback: PropTypes.func,
|
||||
onPlayerInitCallback: PropTypes.func,
|
||||
onStateUpdateCallback: PropTypes.func,
|
||||
onUnmountCallback: PropTypes.func,
|
||||
};
|
||||
|
||||
VideoPlayer.defaultProps = {
|
||||
errorMessage: null,
|
||||
cornerLayers: {},
|
||||
};
|
||||
@ -1,198 +1,203 @@
|
||||
import React from 'react';
|
||||
import { format } from 'timeago.js';
|
||||
import { formatViewsNumber, imageExtension } from '../../../../utils/helpers/';
|
||||
import { VideoPlayerByPageLink } from '../../../video-player/VideoPlayerByPageLink';
|
||||
// import { VideoPlayerByPageLink } from '../../../video-player/VideoPlayerByPageLink';
|
||||
import { translateString } from '../../../../utils/helpers/';
|
||||
|
||||
export function ItemDescription(props) {
|
||||
return '' === props.description ? null : (
|
||||
<div className="item-description">
|
||||
<div>{props.description}</div>
|
||||
</div>
|
||||
);
|
||||
return '' === props.description ? null : (
|
||||
<div className="item-description">
|
||||
<div>{props.description}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ItemMain(props) {
|
||||
return <div className="item-main">{props.children}</div>;
|
||||
return <div className="item-main">{props.children}</div>;
|
||||
}
|
||||
|
||||
export function ItemMainInLink(props) {
|
||||
return (
|
||||
<ItemMain>
|
||||
<a className="item-content-link" href={props.link} title={props.title}>
|
||||
{props.children}
|
||||
</a>
|
||||
</ItemMain>
|
||||
);
|
||||
return (
|
||||
<ItemMain>
|
||||
<a className="item-content-link" href={props.link} title={props.title}>
|
||||
{props.children}
|
||||
</a>
|
||||
</ItemMain>
|
||||
);
|
||||
}
|
||||
|
||||
export function ItemTitle(props) {
|
||||
return '' === props.title ? null : (
|
||||
<h3>
|
||||
<span aria-label={props.ariaLabel}>{props.title}</span>
|
||||
</h3>
|
||||
);
|
||||
return '' === props.title ? null : (
|
||||
<h3>
|
||||
<span aria-label={props.ariaLabel}>{props.title}</span>
|
||||
</h3>
|
||||
);
|
||||
}
|
||||
|
||||
export function ItemTitleLink(props) {
|
||||
return '' === props.title ? null : (
|
||||
<h3>
|
||||
<a href={props.link} title={props.title}>
|
||||
<span aria-label={props.ariaLabel}>{props.title}</span>
|
||||
</a>
|
||||
</h3>
|
||||
);
|
||||
return '' === props.title ? null : (
|
||||
<h3>
|
||||
<a href={props.link} title={props.title}>
|
||||
<span aria-label={props.ariaLabel}>{props.title}</span>
|
||||
</a>
|
||||
</h3>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserItemMemberSince(props) {
|
||||
return <time key="member-since">Member for {format(new Date(props.date)).replace(' ago', '')}</time>;
|
||||
return <time key="member-since">Member for {format(new Date(props.date)).replace(' ago', '')}</time>;
|
||||
}
|
||||
|
||||
export function TaxonomyItemMediaCount(props) {
|
||||
return (
|
||||
<span key="item-media-count" className="item-media-count">
|
||||
{' ' + props.count} media
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<span key="item-media-count" className="item-media-count">
|
||||
{' ' + props.count} media
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function PlaylistItemMetaDate(props) {
|
||||
return (
|
||||
<span className="item-meta">
|
||||
<span className="playlist-date">
|
||||
<time dateTime={props.dateTime}>{props.text}</time>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<span className="item-meta">
|
||||
<span className="playlist-date">
|
||||
<time dateTime={props.dateTime}>{props.text}</time>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemEditLink(props) {
|
||||
let link = props.link;
|
||||
let link = props.link;
|
||||
|
||||
if (link && window.MediaCMS.site.devEnv) {
|
||||
link = '/edit-media.html';
|
||||
}
|
||||
if (link && window.MediaCMS.site.devEnv) {
|
||||
link = '/edit-media.html';
|
||||
}
|
||||
|
||||
return !link ? null : (
|
||||
<a href={link} title={translateString("Edit media")} className="item-edit-link">
|
||||
{translateString("EDIT MEDIA")}
|
||||
</a>
|
||||
);
|
||||
return !link ? null : (
|
||||
<a href={link} title={translateString('Edit media')} className="item-edit-link">
|
||||
{translateString('EDIT MEDIA')}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemThumbnailLink(props) {
|
||||
const attr = {
|
||||
key: 'item-thumb',
|
||||
href: props.link,
|
||||
title: props.title,
|
||||
tabIndex: '-1',
|
||||
'aria-hidden': true,
|
||||
className: 'item-thumb' + (!props.src ? ' no-thumb' : ''),
|
||||
style: !props.src ? null : { backgroundImage: "url('" + props.src + "')" },
|
||||
};
|
||||
const attr = {
|
||||
key: 'item-thumb',
|
||||
href: props.link,
|
||||
title: props.title,
|
||||
tabIndex: '-1',
|
||||
'aria-hidden': true,
|
||||
className: 'item-thumb' + (!props.src ? ' no-thumb' : ''),
|
||||
style: !props.src ? null : { backgroundImage: "url('" + props.src + "')" },
|
||||
};
|
||||
|
||||
return (
|
||||
<a {...attr}>
|
||||
{!props.src ? null : (
|
||||
<div key="item-type-icon" className="item-type-icon">
|
||||
<div></div>
|
||||
</div>
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
return (
|
||||
<a {...attr}>
|
||||
{!props.src ? null : (
|
||||
<div key="item-type-icon" className="item-type-icon">
|
||||
<div></div>
|
||||
</div>
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserItemThumbnailLink(props) {
|
||||
const attr = {
|
||||
key: 'item-thumb',
|
||||
href: props.link,
|
||||
title: props.title,
|
||||
tabIndex: '-1',
|
||||
'aria-hidden': true,
|
||||
className: 'item-thumb' + (!props.src ? ' no-thumb' : ''),
|
||||
style: !props.src ? null : { backgroundImage: "url('" + props.src + "')" },
|
||||
};
|
||||
const attr = {
|
||||
key: 'item-thumb',
|
||||
href: props.link,
|
||||
title: props.title,
|
||||
tabIndex: '-1',
|
||||
'aria-hidden': true,
|
||||
className: 'item-thumb' + (!props.src ? ' no-thumb' : ''),
|
||||
style: !props.src ? null : { backgroundImage: "url('" + props.src + "')" },
|
||||
};
|
||||
|
||||
return <a {...attr}></a>;
|
||||
return <a {...attr}></a>;
|
||||
}
|
||||
|
||||
export function MediaItemAuthor(props) {
|
||||
return '' === props.name ? null : (
|
||||
<span className="item-author">
|
||||
<span>{props.name}</span>
|
||||
</span>
|
||||
);
|
||||
return '' === props.name ? null : (
|
||||
<span className="item-author">
|
||||
<span>{props.name}</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemAuthorLink(props) {
|
||||
return '' === props.name ? null : (
|
||||
<span className="item-author">
|
||||
<a href={props.link} title={props.name}>
|
||||
<span>{props.name}</span>
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
return '' === props.name ? null : (
|
||||
<span className="item-author">
|
||||
<a href={props.link} title={props.name}>
|
||||
<span>{props.name}</span>
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemMetaViews(props) {
|
||||
return (
|
||||
<span className="item-views">{formatViewsNumber(props.views) + ' ' + (1 >= props.views ? translateString('view') : translateString('views'))}</span>
|
||||
);
|
||||
return (
|
||||
<span className="item-views">
|
||||
{formatViewsNumber(props.views) +
|
||||
' ' +
|
||||
(1 >= props.views ? translateString('view') : translateString('views'))}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemMetaDate(props) {
|
||||
return (
|
||||
<span className="item-date">
|
||||
<time dateTime={props.dateTime} content={props.time}>
|
||||
{props.text}
|
||||
</time>
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<span className="item-date">
|
||||
<time dateTime={props.dateTime} content={props.time}>
|
||||
{props.text}
|
||||
</time>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemDuration(props) {
|
||||
return (
|
||||
<span className="item-duration">
|
||||
<span aria-label={props.ariaLabel} content={props.time}>
|
||||
{props.text}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<span className="item-duration">
|
||||
<span aria-label={props.ariaLabel} content={props.time}>
|
||||
{props.text}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemVideoPreviewer(props) {
|
||||
if ('' === props.url) {
|
||||
return null;
|
||||
}
|
||||
if ('' === props.url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const src = props.url.split('.').slice(0, -1).join('.');
|
||||
const ext = imageExtension(props.url);
|
||||
const src = props.url.split('.').slice(0, -1).join('.');
|
||||
const ext = imageExtension(props.url);
|
||||
|
||||
return <span className="item-img-preview" data-src={src} data-ext={ext}></span>;
|
||||
return <span className="item-img-preview" data-src={src} data-ext={ext}></span>;
|
||||
}
|
||||
|
||||
export function MediaItemVideoPlayer(props) {
|
||||
return (
|
||||
<div className="item-player-wrapper">
|
||||
<div className="item-player-wrapper-inner">
|
||||
<VideoPlayerByPageLink pageLink={props.mediaPageLink} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="item-player-wrapper">
|
||||
<div className="item-player-wrapper-inner">
|
||||
stop component tou VideoPlayerByPageLink
|
||||
{/* <VideoPlayerByPageLink pageLink={props.mediaPageLink} /> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MediaItemPlaylistIndex(props) {
|
||||
return (
|
||||
<div className="item-order-number">
|
||||
<div>
|
||||
<div data-order={props.index} data-id={props.media_id}>
|
||||
{props.inPlayback && props.index === props.activeIndex ? (
|
||||
<i className="material-icons">play_arrow</i>
|
||||
) : (
|
||||
props.index
|
||||
)}
|
||||
return (
|
||||
<div className="item-order-number">
|
||||
<div>
|
||||
<div data-order={props.index} data-id={props.media_id}>
|
||||
{props.inPlayback && props.index === props.activeIndex ? (
|
||||
<i className="material-icons">play_arrow</i>
|
||||
) : (
|
||||
props.index
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,257 +0,0 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import urlParse from 'url-parse';
|
||||
|
||||
import MediaPlayer from 'mediacms-player/dist/mediacms-player.js';
|
||||
import 'mediacms-player/dist/mediacms-player.css';
|
||||
|
||||
import './VideoPlayer.scss';
|
||||
|
||||
export function formatInnerLink(url, baseUrl) {
|
||||
let link = urlParse(url, {});
|
||||
|
||||
if ('' === link.origin || 'null' === link.origin || !link.origin) {
|
||||
link = urlParse(baseUrl + '/' + url.replace(/^\//g, ''), {});
|
||||
}
|
||||
|
||||
return link.toString();
|
||||
}
|
||||
|
||||
export function VideoPlayerError(props) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
<div className="error-container-inner">
|
||||
<span className="icon-wrap">
|
||||
<i className="material-icons">error_outline</i>
|
||||
</span>
|
||||
<span className="msg-wrap">{props.errorMessage}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
VideoPlayerError.propTypes = {
|
||||
errorMessage: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export function VideoPlayer(props) {
|
||||
const videoElemRef = useRef(null);
|
||||
|
||||
let player = null;
|
||||
|
||||
const playerStates = {
|
||||
playerVolume: props.playerVolume,
|
||||
playerSoundMuted: props.playerSoundMuted,
|
||||
videoQuality: props.videoQuality,
|
||||
videoPlaybackSpeed: props.videoPlaybackSpeed,
|
||||
inTheaterMode: props.inTheaterMode,
|
||||
};
|
||||
|
||||
playerStates.playerVolume =
|
||||
null === playerStates.playerVolume ? 1 : Math.max(Math.min(Number(playerStates.playerVolume), 1), 0);
|
||||
playerStates.playerSoundMuted = null !== playerStates.playerSoundMuted ? playerStates.playerSoundMuted : !1;
|
||||
playerStates.videoQuality = null !== playerStates.videoQuality ? playerStates.videoQuality : 'Auto';
|
||||
playerStates.videoPlaybackSpeed = null !== playerStates.videoPlaybackSpeed ? playerStates.videoPlaybackSpeed : !1;
|
||||
playerStates.inTheaterMode = null !== playerStates.inTheaterMode ? playerStates.inTheaterMode : !1;
|
||||
|
||||
function onClickNext() {
|
||||
if (void 0 !== props.onClickNextCallback) {
|
||||
props.onClickNextCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function onClickPrevious() {
|
||||
if (void 0 !== props.onClickPreviousCallback) {
|
||||
props.onClickPreviousCallback();
|
||||
}
|
||||
}
|
||||
|
||||
function onPlayerStateUpdate(newState) {
|
||||
if (playerStates.playerVolume !== newState.volume) {
|
||||
playerStates.playerVolume = newState.volume;
|
||||
}
|
||||
|
||||
if (playerStates.playerSoundMuted !== newState.soundMuted) {
|
||||
playerStates.playerSoundMuted = newState.soundMuted;
|
||||
}
|
||||
|
||||
if (playerStates.videoQuality !== newState.quality) {
|
||||
playerStates.videoQuality = newState.quality;
|
||||
}
|
||||
|
||||
if (playerStates.videoPlaybackSpeed !== newState.playbackSpeed) {
|
||||
playerStates.videoPlaybackSpeed = newState.playbackSpeed;
|
||||
}
|
||||
|
||||
if (playerStates.inTheaterMode !== newState.theaterMode) {
|
||||
playerStates.inTheaterMode = newState.theaterMode;
|
||||
}
|
||||
|
||||
if (void 0 !== props.onStateUpdateCallback) {
|
||||
props.onStateUpdateCallback(newState);
|
||||
}
|
||||
}
|
||||
|
||||
function initPlayer() {
|
||||
if (null !== player || null !== props.errorMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.inEmbed) {
|
||||
window.removeEventListener('focus', initPlayer);
|
||||
document.removeEventListener('visibilitychange', initPlayer);
|
||||
}
|
||||
|
||||
if (!videoElemRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.inEmbed) {
|
||||
videoElemRef.current.focus(); // Focus on player before instance init.
|
||||
}
|
||||
|
||||
const subtitles = {
|
||||
on: false,
|
||||
};
|
||||
|
||||
if (void 0 !== props.subtitlesInfo && null !== props.subtitlesInfo && props.subtitlesInfo.length) {
|
||||
subtitles.languages = [];
|
||||
|
||||
let i = 0;
|
||||
while (i < props.subtitlesInfo.length) {
|
||||
if (
|
||||
void 0 !== props.subtitlesInfo[i].src &&
|
||||
void 0 !== props.subtitlesInfo[i].srclang &&
|
||||
void 0 !== props.subtitlesInfo[i].label
|
||||
) {
|
||||
subtitles.languages.push({
|
||||
src: formatInnerLink(props.subtitlesInfo[i].src, props.siteUrl),
|
||||
srclang: props.subtitlesInfo[i].srclang,
|
||||
label: props.subtitlesInfo[i].label,
|
||||
});
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (subtitles.languages.length) {
|
||||
subtitles.on = true;
|
||||
}
|
||||
}
|
||||
|
||||
player = new MediaPlayer(
|
||||
videoElemRef.current,
|
||||
{
|
||||
enabledTouchControls: true,
|
||||
sources: props.sources,
|
||||
poster: props.poster,
|
||||
autoplay: props.enableAutoplay,
|
||||
bigPlayButton: true,
|
||||
controlBar: {
|
||||
theaterMode: props.hasTheaterMode,
|
||||
pictureInPicture: false,
|
||||
next: props.hasNextLink ? true : false,
|
||||
previous: props.hasPreviousLink ? true : false,
|
||||
},
|
||||
subtitles: subtitles,
|
||||
cornerLayers: props.cornerLayers,
|
||||
videoPreviewThumb: props.previewSprite,
|
||||
},
|
||||
{
|
||||
volume: playerStates.playerVolume,
|
||||
soundMuted: playerStates.playerSoundMuted,
|
||||
theaterMode: playerStates.inTheaterMode,
|
||||
theSelectedQuality: void 0, // @note: Allow auto resolution selection by sources order.
|
||||
theSelectedPlaybackSpeed: playerStates.videoPlaybackSpeed || 1,
|
||||
},
|
||||
props.info,
|
||||
[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
|
||||
onPlayerStateUpdate,
|
||||
onClickNext,
|
||||
onClickPrevious
|
||||
);
|
||||
|
||||
if (void 0 !== props.onPlayerInitCallback) {
|
||||
props.onPlayerInitCallback(player, videoElemRef.current);
|
||||
}
|
||||
}
|
||||
|
||||
function unsetPlayer() {
|
||||
if (null === player) {
|
||||
return;
|
||||
}
|
||||
videojs(videoElemRef.current).dispose();
|
||||
player = null;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (props.inEmbed || document.hasFocus() || 'visible' === document.visibilityState) {
|
||||
initPlayer();
|
||||
} else {
|
||||
window.addEventListener('focus', initPlayer);
|
||||
document.addEventListener('visibilitychange', initPlayer);
|
||||
}
|
||||
|
||||
/*
|
||||
// We don't need this because we have a custom function in frontend/src/static/js/components/media-viewer/VideoViewer/index.js:617
|
||||
player && player.player.one('loadedmetadata', () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const paramT = Number(urlParams.get('t'));
|
||||
const timestamp = !isNaN(paramT) ? paramT : 0;
|
||||
player.player.currentTime(timestamp);
|
||||
}); */
|
||||
|
||||
return () => {
|
||||
unsetPlayer();
|
||||
|
||||
if (void 0 !== props.onUnmountCallback) {
|
||||
props.onUnmountCallback();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null === props.errorMessage ? (
|
||||
<video ref={videoElemRef} className="video-js vjs-mediacms native-dimensions"></video>
|
||||
) : (
|
||||
<div className="error-container">
|
||||
<div className="error-container-inner">
|
||||
<span className="icon-wrap">
|
||||
<i className="material-icons">error_outline</i>
|
||||
</span>
|
||||
<span className="msg-wrap">{props.errorMessage}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
VideoPlayer.propTypes = {
|
||||
playerVolume: PropTypes.string,
|
||||
playerSoundMuted: PropTypes.bool,
|
||||
videoQuality: PropTypes.string,
|
||||
videoPlaybackSpeed: PropTypes.number,
|
||||
inTheaterMode: PropTypes.bool,
|
||||
siteId: PropTypes.string.isRequired,
|
||||
siteUrl: PropTypes.string.isRequired,
|
||||
errorMessage: PropTypes.string,
|
||||
cornerLayers: PropTypes.object,
|
||||
subtitlesInfo: PropTypes.array.isRequired,
|
||||
inEmbed: PropTypes.bool.isRequired,
|
||||
sources: PropTypes.array.isRequired,
|
||||
info: PropTypes.object.isRequired,
|
||||
enableAutoplay: PropTypes.bool.isRequired,
|
||||
hasTheaterMode: PropTypes.bool.isRequired,
|
||||
hasNextLink: PropTypes.bool.isRequired,
|
||||
hasPreviousLink: PropTypes.bool.isRequired,
|
||||
poster: PropTypes.string,
|
||||
previewSprite: PropTypes.object,
|
||||
onClickPreviousCallback: PropTypes.func,
|
||||
onClickNextCallback: PropTypes.func,
|
||||
onPlayerInitCallback: PropTypes.func,
|
||||
onStateUpdateCallback: PropTypes.func,
|
||||
onUnmountCallback: PropTypes.func,
|
||||
};
|
||||
|
||||
VideoPlayer.defaultProps = {
|
||||
errorMessage: null,
|
||||
cornerLayers: {},
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user