diff --git a/frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayer.jsx b/frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayer.jsx new file mode 100644 index 00000000..f19e9923 --- /dev/null +++ b/frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayer.jsx @@ -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 ( +
+
+ + error_outline + + {props.errorMessage} +
+
+ ); +} + +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 ? ( + + ) : ( +
+
+ + error_outline + + {props.errorMessage} +
+
+ ); +} + +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: {}, +}; diff --git a/frontend/src/static/js/components/video-player/VideoPlayer.scss b/frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayer.scss similarity index 100% rename from frontend/src/static/js/components/video-player/VideoPlayer.scss rename to frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayer.scss diff --git a/frontend/src/static/js/components/video-player/VideoPlayerByPageLink.jsx b/frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayerByPageLink.jsx similarity index 100% rename from frontend/src/static/js/components/video-player/VideoPlayerByPageLink.jsx rename to frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayerByPageLink.jsx diff --git a/frontend/src/static/js/components/list-item/includes/items/includes.js b/frontend/src/static/js/components/list-item/includes/items/includes.js index 93c758a6..768e5063 100644 --- a/frontend/src/static/js/components/list-item/includes/items/includes.js +++ b/frontend/src/static/js/components/list-item/includes/items/includes.js @@ -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 : ( -
-
{props.description}
-
- ); + return '' === props.description ? null : ( +
+
{props.description}
+
+ ); } export function ItemMain(props) { - return
{props.children}
; + return
{props.children}
; } export function ItemMainInLink(props) { - return ( - - - {props.children} - - - ); + return ( + + + {props.children} + + + ); } export function ItemTitle(props) { - return '' === props.title ? null : ( -

- {props.title} -

- ); + return '' === props.title ? null : ( +

+ {props.title} +

+ ); } export function ItemTitleLink(props) { - return '' === props.title ? null : ( -

- - {props.title} - -

- ); + return '' === props.title ? null : ( +

+ + {props.title} + +

+ ); } export function UserItemMemberSince(props) { - return ; + return ; } export function TaxonomyItemMediaCount(props) { - return ( - - {' ' + props.count} media - - ); + return ( + + {' ' + props.count} media + + ); } export function PlaylistItemMetaDate(props) { - return ( - - - - - - ); + return ( + + + + + + ); } 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 : ( - - {translateString("EDIT MEDIA")} - - ); + return !link ? null : ( + + {translateString('EDIT MEDIA')} + + ); } 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 ( - - {!props.src ? null : ( -
-
-
- )} -
- ); + return ( + + {!props.src ? null : ( +
+
+
+ )} +
+ ); } 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 ; + return ; } export function MediaItemAuthor(props) { - return '' === props.name ? null : ( - - {props.name} - - ); + return '' === props.name ? null : ( + + {props.name} + + ); } export function MediaItemAuthorLink(props) { - return '' === props.name ? null : ( - - - {props.name} - - - ); + return '' === props.name ? null : ( + + + {props.name} + + + ); } export function MediaItemMetaViews(props) { - return ( - {formatViewsNumber(props.views) + ' ' + (1 >= props.views ? translateString('view') : translateString('views'))} - ); + return ( + + {formatViewsNumber(props.views) + + ' ' + + (1 >= props.views ? translateString('view') : translateString('views'))} + + ); } export function MediaItemMetaDate(props) { - return ( - - - - ); + return ( + + + + ); } export function MediaItemDuration(props) { - return ( - - - {props.text} - - - ); + return ( + + + {props.text} + + + ); } 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 ; + return ; } export function MediaItemVideoPlayer(props) { - return ( -
-
- -
-
- ); + return ( +
+
+ stop component tou VideoPlayerByPageLink + {/* */} +
+
+ ); } export function MediaItemPlaylistIndex(props) { - return ( -
-
-
- {props.inPlayback && props.index === props.activeIndex ? ( - play_arrow - ) : ( - props.index - )} + return ( +
+
+
+ {props.inPlayback && props.index === props.activeIndex ? ( + play_arrow + ) : ( + props.index + )} +
+
-
-
- ); + ); } diff --git a/frontend/src/static/js/components/media-viewer/VideoViewer/index.js b/frontend/src/static/js/components/media-viewer/VideoViewer/index.js index 7cec399c..905b242e 100644 --- a/frontend/src/static/js/components/media-viewer/VideoViewer/index.js +++ b/frontend/src/static/js/components/media-viewer/VideoViewer/index.js @@ -6,647 +6,732 @@ import { PageStore, MediaPageStore, VideoViewerStore } from '../../../utils/stor import { addClassname, removeClassname, formatInnerLink } from '../../../utils/helpers/'; import { BrowserCache, UpNextLoaderView, MediaDurationInfo, PlayerRecommendedMedia } from '../../../utils/classes/'; import { - orderedSupportedVideoFormats, - videoAvailableCodecsAndResolutions, - extractDefaultVideoResolution, + orderedSupportedVideoFormats, + videoAvailableCodecsAndResolutions, + extractDefaultVideoResolution, } from './functions'; -import { VideoPlayer, VideoPlayerError } from '../../video-player/VideoPlayer'; +// import { VideoPlayer, VideoPlayerError } from '../../video-player/VideoPlayer'; +import VideoJSEmbed from '../../VideoJS/VideoJSEmbed'; import '../VideoViewer.scss'; function filterVideoEncoding(encoding_status) { - switch (encoding_status) { - case 'running_X': - MediaPageStore.set('media-load-error-type', 'encodingRunning'); - MediaPageStore.set('media-load-error-message', 'Media encoding is currently running. Try again in few minutes.'); - break; - case 'pending_X': - MediaPageStore.set('media-load-error-type', 'encodingPending'); - MediaPageStore.set('media-load-error-message', 'Media encoding is pending'); - break; - case 'fail': - MediaPageStore.set('media-load-error-type', 'encodingFailed'); - MediaPageStore.set('media-load-error-message', 'Media encoding failed'); - break; - } + switch (encoding_status) { + case 'running_X': + MediaPageStore.set('media-load-error-type', 'encodingRunning'); + MediaPageStore.set( + 'media-load-error-message', + 'Media encoding is currently running. Try again in few minutes.' + ); + break; + case 'pending_X': + MediaPageStore.set('media-load-error-type', 'encodingPending'); + MediaPageStore.set('media-load-error-message', 'Media encoding is pending'); + break; + case 'fail': + MediaPageStore.set('media-load-error-type', 'encodingFailed'); + MediaPageStore.set('media-load-error-message', 'Media encoding failed'); + break; + } } export default class VideoViewer extends React.PureComponent { - constructor(props) { - super(props); + constructor(props) { + super(props); - this.state = { - displayPlayer: false, - }; + this.state = { + displayPlayer: false, + }; - this.videoSources = []; + this.videoSources = []; - filterVideoEncoding(this.props.data.encoding_status); + filterVideoEncoding(this.props.data.encoding_status); - if (null !== MediaPageStore.get('media-load-error-type')) { - this.state.displayPlayer = true; - return; - } - - if ('string' === typeof this.props.data.poster_url) { - this.videoPoster = formatInnerLink(this.props.data.poster_url, this.props.siteUrl); - } else if ('string' === typeof this.props.data.thumbnail_url) { - this.videoPoster = formatInnerLink(this.props.data.thumbnail_url, this.props.siteUrl); - } - - this.videoInfo = videoAvailableCodecsAndResolutions(this.props.data.encodings_info, this.props.data.hls_info); - - const resolutionsKeys = Object.keys(this.videoInfo); - - if (!resolutionsKeys.length) { - this.videoInfo = null; - } else { - let defaultResolution = VideoViewerStore.get('video-quality'); - - if (null === defaultResolution || ('Auto' === defaultResolution && void 0 === this.videoInfo['Auto'])) { - defaultResolution = 720; // Default resolution. - } - - let defaultVideoResolution = extractDefaultVideoResolution(defaultResolution, this.videoInfo); - - if ('Auto' === defaultResolution && void 0 !== this.videoInfo['Auto']) { - this.videoSources.push({ src: this.videoInfo['Auto'].url[0] }); - } - - const supportedFormats = orderedSupportedVideoFormats(); - - let srcUrl, k; - - k = 0; - while (k < this.videoInfo[defaultVideoResolution].format.length) { - if ('hls' === this.videoInfo[defaultVideoResolution].format[k]) { - this.videoSources.push({ src: this.videoInfo[defaultVideoResolution].url[k] }); - break; + if (null !== MediaPageStore.get('media-load-error-type')) { + this.state.displayPlayer = true; + return; } - k += 1; - } - for (k in this.props.data.encodings_info[defaultVideoResolution]) { - if (this.props.data.encodings_info[defaultVideoResolution].hasOwnProperty(k)) { - if (supportedFormats.support[k]) { - srcUrl = this.props.data.encodings_info[defaultVideoResolution][k].url; + if ('string' === typeof this.props.data.poster_url) { + this.videoPoster = formatInnerLink(this.props.data.poster_url, this.props.siteUrl); + } else if ('string' === typeof this.props.data.thumbnail_url) { + this.videoPoster = formatInnerLink(this.props.data.thumbnail_url, this.props.siteUrl); + } - if (!!srcUrl) { - srcUrl = formatInnerLink(srcUrl, this.props.siteUrl); + this.videoInfo = videoAvailableCodecsAndResolutions(this.props.data.encodings_info, this.props.data.hls_info); - this.videoSources.push({ - src: srcUrl /*.replace("http://", "//").replace("https://", "//")*/, - encodings_status: this.props.data.encodings_info[defaultVideoResolution][k].status, - }); + const resolutionsKeys = Object.keys(this.videoInfo); + + if (!resolutionsKeys.length) { + this.videoInfo = null; + } else { + let defaultResolution = VideoViewerStore.get('video-quality'); + + if (null === defaultResolution || ('Auto' === defaultResolution && void 0 === this.videoInfo['Auto'])) { + defaultResolution = 720; // Default resolution. } - } - } - } - // console.log( supportedFormats ); - // console.log( this.videoInfo ); - // console.log( defaultVideoResolution ); - // console.log( this.videoSources ); + let defaultVideoResolution = extractDefaultVideoResolution(defaultResolution, this.videoInfo); + + if ('Auto' === defaultResolution && void 0 !== this.videoInfo['Auto']) { + this.videoSources.push({ src: this.videoInfo['Auto'].url[0] }); + } + + const supportedFormats = orderedSupportedVideoFormats(); + + let srcUrl, k; + + k = 0; + while (k < this.videoInfo[defaultVideoResolution].format.length) { + if ('hls' === this.videoInfo[defaultVideoResolution].format[k]) { + this.videoSources.push({ + src: this.videoInfo[defaultVideoResolution].url[k], + }); + break; + } + k += 1; + } + + for (k in this.props.data.encodings_info[defaultVideoResolution]) { + if (this.props.data.encodings_info[defaultVideoResolution].hasOwnProperty(k)) { + if (supportedFormats.support[k]) { + srcUrl = this.props.data.encodings_info[defaultVideoResolution][k].url; + + if (!!srcUrl) { + srcUrl = formatInnerLink(srcUrl, this.props.siteUrl); + + this.videoSources.push({ + src: srcUrl /*.replace("http://", "//").replace("https://", "//")*/, + encodings_status: this.props.data.encodings_info[defaultVideoResolution][k].status, + }); + } + } + } + } + + // console.log( supportedFormats ); + // console.log( this.videoInfo ); + // console.log( defaultVideoResolution ); + // console.log( this.videoSources ); + } + + if (this.videoSources.length) { + if ( + !this.props.inEmbed && + 1 === this.videoSources.length && + 'running' === this.videoSources[0].encodings_status + ) { + MediaPageStore.set('media-load-error-type', 'encodingRunning'); + MediaPageStore.set( + 'media-load-error-message', + 'Media encoding is currently running. Try again in few minutes.' + ); + return; + } + } else { + switch (MediaPageStore.get('media-load-error-type')) { + case 'encodingRunning': + case 'encodingPending': + case 'encodingFailed': + break; + default: + console.warn('VIDEO DEBUG:', "Video files don't exist"); + } + } + + PageStore.on('switched_media_auto_play', this.onUpdateMediaAutoPlay.bind(this)); + + this.browserCache = new BrowserCache(SiteContext._currentValue.id, 86400); // Keep cache data "fresh" for one day. + + const _MediaDurationInfo = new MediaDurationInfo(); + + _MediaDurationInfo.update(this.props.data.duration); + + this.durationISO8601 = _MediaDurationInfo.ISO8601(); + + this.playerElem = null; + + this.playerInstance = null; + + this.onPlayerInit = this.onPlayerInit.bind(this); + + this.onClickNext = this.onClickNext.bind(this); + this.onClickPrevious = this.onClickPrevious.bind(this); + this.onStateUpdate = this.onStateUpdate.bind(this); + + this.onVideoEnd = this.onVideoEnd.bind(this); + this.onVideoRestart = this.onVideoRestart.bind(this); } - if (this.videoSources.length) { - if ( - !this.props.inEmbed && - 1 === this.videoSources.length && - 'running' === this.videoSources[0].encodings_status - ) { - MediaPageStore.set('media-load-error-type', 'encodingRunning'); - MediaPageStore.set( - 'media-load-error-message', - 'Media encoding is currently running. Try again in few minutes.' - ); - return; - } - } else { - switch (MediaPageStore.get('media-load-error-type')) { - case 'encodingRunning': - case 'encodingPending': - case 'encodingFailed': - break; - default: - console.warn('VIDEO DEBUG:', "Video files don't exist"); - } - } + componentDidMount() { + if (this.videoSources.length) { + this.recommendedMedia = this.props.data.related_media.length + ? new PlayerRecommendedMedia( + this.props.data.related_media, + this.props.inEmbed, + !PageStore.get('config-media-item').displayViews + ) + : null; - PageStore.on('switched_media_auto_play', this.onUpdateMediaAutoPlay.bind(this)); + this.upNextLoaderView = + !this.props.inEmbed && this.props.data.related_media.length + ? new UpNextLoaderView(this.props.data.related_media[0]) + : null; - this.browserCache = new BrowserCache(SiteContext._currentValue.id, 86400); // Keep cache data "fresh" for one day. + let topLeftHtml = null; - const _MediaDurationInfo = new MediaDurationInfo(); + if (this.props.inEmbed) { + let titleLink = document.createElement('a'); + let userThumbLink = document.createElement('a'); - _MediaDurationInfo.update(this.props.data.duration); + topLeftHtml = document.createElement('div'); + topLeftHtml.setAttribute('class', 'media-links-top-left'); - this.durationISO8601 = _MediaDurationInfo.ISO8601(); + if (titleLink) { + titleLink.setAttribute('class', 'title-link'); + titleLink.setAttribute('href', this.props.data.url); + titleLink.setAttribute('title', this.props.data.title); + titleLink.setAttribute('target', '_blank'); + titleLink.innerHTML = this.props.data.title; + } - this.playerElem = null; + if (userThumbLink) { + userThumbLink.setAttribute('class', 'user-thumb-link'); + userThumbLink.setAttribute( + 'href', + formatInnerLink(this.props.data.author_profile, this.props.siteUrl) + ); + userThumbLink.setAttribute('title', this.props.data.author_name); + userThumbLink.setAttribute('target', '_blank'); + userThumbLink.setAttribute( + 'style', + 'background-image:url(' + + formatInnerLink(MediaPageStore.get('media-author-thumbnail-url'), this.props.siteUrl) + + ')' + ); + } - this.playerInstance = null; + topLeftHtml.appendChild(userThumbLink); + topLeftHtml.appendChild(titleLink); + } - this.onPlayerInit = this.onPlayerInit.bind(this); + const mediaUrl = MediaPageStore.get('media-url'); - this.onClickNext = this.onClickNext.bind(this); - this.onClickPrevious = this.onClickPrevious.bind(this); - this.onStateUpdate = this.onStateUpdate.bind(this); - - this.onVideoEnd = this.onVideoEnd.bind(this); - this.onVideoRestart = this.onVideoRestart.bind(this); - } - - componentDidMount() { - if (this.videoSources.length) { - this.recommendedMedia = this.props.data.related_media.length - ? new PlayerRecommendedMedia( - this.props.data.related_media, - this.props.inEmbed, - !PageStore.get('config-media-item').displayViews - ) - : null; - - this.upNextLoaderView = - !this.props.inEmbed && this.props.data.related_media.length - ? new UpNextLoaderView(this.props.data.related_media[0]) - : null; - - let topLeftHtml = null; - - if (this.props.inEmbed) { - let titleLink = document.createElement('a'); - let userThumbLink = document.createElement('a'); - - topLeftHtml = document.createElement('div'); - topLeftHtml.setAttribute('class', 'media-links-top-left'); - - if (titleLink) { - titleLink.setAttribute('class', 'title-link'); - titleLink.setAttribute('href', this.props.data.url); - titleLink.setAttribute('title', this.props.data.title); - titleLink.setAttribute('target', '_blank'); - titleLink.innerHTML = this.props.data.title; - } - - if (userThumbLink) { - userThumbLink.setAttribute('class', 'user-thumb-link'); - userThumbLink.setAttribute('href', formatInnerLink(this.props.data.author_profile, this.props.siteUrl)); - userThumbLink.setAttribute('title', this.props.data.author_name); - userThumbLink.setAttribute('target', '_blank'); - userThumbLink.setAttribute( - 'style', - 'background-image:url(' + - formatInnerLink(MediaPageStore.get('media-author-thumbnail-url'), this.props.siteUrl) + - ')' - ); - } - - topLeftHtml.appendChild(userThumbLink); - topLeftHtml.appendChild(titleLink); - } - - const mediaUrl = MediaPageStore.get('media-url'); - - let bottomRightHTML = - ''; - bottomRightHTML += - '
\ + let bottomRightHTML = + ''; + bottomRightHTML += + ''; - this.cornerLayers = { - topLeft: topLeftHtml, - topRight: this.upNextLoaderView ? this.upNextLoaderView.html() : null, - bottomLeft: this.recommendedMedia ? this.recommendedMedia.html() : null, - bottomRight: this.props.inEmbed ? bottomRightHTML : null, - }; + this.cornerLayers = { + topLeft: topLeftHtml, + topRight: this.upNextLoaderView ? this.upNextLoaderView.html() : null, + bottomLeft: this.recommendedMedia ? this.recommendedMedia.html() : null, + bottomRight: this.props.inEmbed ? bottomRightHTML : null, + }; - this.setState( - { - displayPlayer: true, - }, - function () { - setTimeout(function () { - const shareBtn = document.querySelector('.share-video-btn'); - const shareWrap = document.querySelector('.share-options-wrapper'); - const shareInner = document.querySelector('.share-options-inner'); - if (shareBtn) { - shareBtn.addEventListener('click', function (ev) { - addClassname(document.querySelector('.video-js.vjs-mediacms'), 'vjs-visible-share-options'); - }); - } - if (shareWrap) { - shareWrap.addEventListener('click', function (ev) { - if (ev.target === shareInner || ev.target === shareWrap) { - removeClassname(document.querySelector('.video-js.vjs-mediacms'), 'vjs-visible-share-options'); + this.setState( + { + displayPlayer: true, + }, + function () { + setTimeout(function () { + const shareBtn = document.querySelector('.share-video-btn'); + const shareWrap = document.querySelector('.share-options-wrapper'); + const shareInner = document.querySelector('.share-options-inner'); + if (shareBtn) { + shareBtn.addEventListener('click', function (ev) { + addClassname( + document.querySelector('.video-js.vjs-mediacms'), + 'vjs-visible-share-options' + ); + }); + } + if (shareWrap) { + shareWrap.addEventListener('click', function (ev) { + if (ev.target === shareInner || ev.target === shareWrap) { + removeClassname( + document.querySelector('.video-js.vjs-mediacms'), + 'vjs-visible-share-options' + ); + } + }); + } + }, 1000); } - }); + ); + } + } + + componentWillUnmount() { + this.unsetRecommendedMedia(); + } + + initRecommendedMedia() { + if (null === this.recommendedMedia) { + return; + } + + if (!this.props.inEmbed) { + this.recommendedMedia.init(); + } + + this.playerInstance.player.on('fullscreenchange', this.recommendedMedia.onResize); + + PageStore.on('window_resize', this.recommendedMedia.onResize); + + VideoViewerStore.on('changed_viewer_mode', this.recommendedMedia.onResize); + } + + unsetRecommendedMedia() { + if (null === this.recommendedMedia) { + return; + } + this.playerInstance.player.off('fullscreenchange', this.recommendedMedia.onResize); + PageStore.removeListener('window_resize', this.recommendedMedia.onResize); + VideoViewerStore.removeListener('changed_viewer_mode', this.recommendedMedia.onResize); + this.recommendedMedia.destroy(); + } + + onClickNext() { + const playlistId = MediaPageStore.get('playlist-id'); + + let nextLink; + + if (playlistId) { + nextLink = MediaPageStore.get('playlist-next-media-url'); + + if (null === nextLink) { + nextLink = this.props.data.related_media[0].url; } - }, 1000); - } - ); - } - } - - componentWillUnmount() { - this.unsetRecommendedMedia(); - } - - initRecommendedMedia() { - if (null === this.recommendedMedia) { - return; - } - - if (!this.props.inEmbed) { - this.recommendedMedia.init(); - } - - this.playerInstance.player.on('fullscreenchange', this.recommendedMedia.onResize); - - PageStore.on('window_resize', this.recommendedMedia.onResize); - - VideoViewerStore.on('changed_viewer_mode', this.recommendedMedia.onResize); - } - - unsetRecommendedMedia() { - if (null === this.recommendedMedia) { - return; - } - this.playerInstance.player.off('fullscreenchange', this.recommendedMedia.onResize); - PageStore.removeListener('window_resize', this.recommendedMedia.onResize); - VideoViewerStore.removeListener('changed_viewer_mode', this.recommendedMedia.onResize); - this.recommendedMedia.destroy(); - } - - onClickNext() { - const playlistId = MediaPageStore.get('playlist-id'); - - let nextLink; - - if (playlistId) { - nextLink = MediaPageStore.get('playlist-next-media-url'); - - if (null === nextLink) { - nextLink = this.props.data.related_media[0].url; - } - } else if (!this.props.inEmbed) { - nextLink = this.props.data.related_media[0].url; - } - - window.location.href = nextLink; - } - - onClickPrevious() { - const playlistId = MediaPageStore.get('playlist-id'); - - let previousLink; - - if (playlistId) { - previousLink = MediaPageStore.get('playlist-previous-media-url'); - - if (null === previousLink) { - previousLink = this.props.data.related_media[0].url; - } - } else if (!this.props.inEmbed) { - previousLink = this.props.data.related_media[0].url; - } - - window.location.href = previousLink; - } - - onStateUpdate(newState) { - if (VideoViewerStore.get('in-theater-mode') !== newState.theaterMode) { - VideoViewerActions.set_viewer_mode(newState.theaterMode); - } - - if (VideoViewerStore.get('player-volume') !== newState.volume) { - VideoViewerActions.set_player_volume(newState.volume); - } - - if (VideoViewerStore.get('player-sound-muted') !== newState.soundMuted) { - VideoViewerActions.set_player_sound_muted(newState.soundMuted); - } - - if (VideoViewerStore.get('video-quality') !== newState.quality) { - VideoViewerActions.set_video_quality(newState.quality); - } - - if (VideoViewerStore.get('video-playback-speed') !== newState.playbackSpeed) { - VideoViewerActions.set_video_playback_speed(newState.playbackSpeed); - } - } - - onPlayerInit(instance, elem) { - this.playerElem = elem; - this.playerInstance = instance; - - if (this.upNextLoaderView) { - this.upNextLoaderView.setVideoJsPlayerElem(this.playerInstance.player.el_); - this.onUpdateMediaAutoPlay(); - } - - if (!this.props.inEmbed) { - this.playerElem.parentNode.focus(); // Focus on player. - } - - if (null !== this.recommendedMedia) { - this.recommendedMedia.initWrappers(this.playerElem.parentNode); - - if (this.props.inEmbed) { - this.playerInstance.player.one('pause', this.recommendedMedia.init); - this.initRecommendedMedia(); - } - } - - this.playerInstance.player.one('ended', this.onVideoEnd); - } - - onVideoRestart() { - if (null !== this.recommendedMedia) { - this.recommendedMedia.updateDisplayType('inline'); - - if (this.props.inEmbed) { - this.playerInstance.player.one('pause', this.recommendedMedia.init); - } - - this.playerInstance.player.one('ended', this.onVideoEnd); - } - } - - onVideoEnd() { - if (null !== this.recommendedMedia) { - if (!this.props.inEmbed) { - this.initRecommendedMedia(); - } - - this.recommendedMedia.updateDisplayType('full'); - this.playerInstance.player.one('playing', this.onVideoRestart); - } - - const playlistId = this.props.inEmbed ? null : MediaPageStore.get('playlist-id'); - - if (playlistId) { - const moreMediaEl = document.querySelector('.video-player .more-media'); - const actionsAnimEl = document.querySelector('.video-player .vjs-actions-anim'); - - this.upNextLoaderView.cancelTimer(); - - const nextMediaUrl = MediaPageStore.get('playlist-next-media-url'); - - if (nextMediaUrl) { - if (moreMediaEl) { - moreMediaEl.style.display = 'none'; + } else if (!this.props.inEmbed) { + nextLink = this.props.data.related_media[0].url; } - if (actionsAnimEl) { - actionsAnimEl.style.display = 'none'; - } - - window.location.href = nextMediaUrl; - } - - this.upNextLoaderView.hideTimerView(); - - return; + window.location.href = nextLink; } - if (this.upNextLoaderView) { - if (PageStore.get('media-auto-play')) { - this.upNextLoaderView.startTimer(); - this.playerInstance.player.one( - 'play', - function () { + onClickPrevious() { + const playlistId = MediaPageStore.get('playlist-id'); + + let previousLink; + + if (playlistId) { + previousLink = MediaPageStore.get('playlist-previous-media-url'); + + if (null === previousLink) { + previousLink = this.props.data.related_media[0].url; + } + } else if (!this.props.inEmbed) { + previousLink = this.props.data.related_media[0].url; + } + + window.location.href = previousLink; + } + + onStateUpdate(newState) { + if (VideoViewerStore.get('in-theater-mode') !== newState.theaterMode) { + VideoViewerActions.set_viewer_mode(newState.theaterMode); + } + + if (VideoViewerStore.get('player-volume') !== newState.volume) { + VideoViewerActions.set_player_volume(newState.volume); + } + + if (VideoViewerStore.get('player-sound-muted') !== newState.soundMuted) { + VideoViewerActions.set_player_sound_muted(newState.soundMuted); + } + + if (VideoViewerStore.get('video-quality') !== newState.quality) { + VideoViewerActions.set_video_quality(newState.quality); + } + + if (VideoViewerStore.get('video-playback-speed') !== newState.playbackSpeed) { + VideoViewerActions.set_video_playback_speed(newState.playbackSpeed); + } + } + + onPlayerInit(instance, elem) { + this.playerElem = elem; + this.playerInstance = instance; + + if (this.upNextLoaderView) { + this.upNextLoaderView.setVideoJsPlayerElem(this.playerInstance.player.el_); + this.onUpdateMediaAutoPlay(); + } + + if (!this.props.inEmbed) { + this.playerElem.parentNode.focus(); // Focus on player. + } + + if (null !== this.recommendedMedia) { + this.recommendedMedia.initWrappers(this.playerElem.parentNode); + + if (this.props.inEmbed) { + this.playerInstance.player.one('pause', this.recommendedMedia.init); + this.initRecommendedMedia(); + } + } + + this.playerInstance.player.one('ended', this.onVideoEnd); + } + + onVideoRestart() { + if (null !== this.recommendedMedia) { + this.recommendedMedia.updateDisplayType('inline'); + + if (this.props.inEmbed) { + this.playerInstance.player.one('pause', this.recommendedMedia.init); + } + + this.playerInstance.player.one('ended', this.onVideoEnd); + } + } + + onVideoEnd() { + if (null !== this.recommendedMedia) { + if (!this.props.inEmbed) { + this.initRecommendedMedia(); + } + + this.recommendedMedia.updateDisplayType('full'); + this.playerInstance.player.one('playing', this.onVideoRestart); + } + + const playlistId = this.props.inEmbed ? null : MediaPageStore.get('playlist-id'); + + if (playlistId) { + const moreMediaEl = document.querySelector('.video-player .more-media'); + const actionsAnimEl = document.querySelector('.video-player .vjs-actions-anim'); + this.upNextLoaderView.cancelTimer(); - }.bind(this) - ); - } else { - this.upNextLoaderView.cancelTimer(); - } - } - } - onUpdateMediaAutoPlay() { - if (this.upNextLoaderView) { - if (PageStore.get('media-auto-play')) { - this.upNextLoaderView.showTimerView(this.playerInstance.isEnded()); - } else { - this.upNextLoaderView.hideTimerView(); - } - } - } + const nextMediaUrl = MediaPageStore.get('playlist-next-media-url'); - render() { - let nextLink = null; - let previousLink = null; + if (nextMediaUrl) { + if (moreMediaEl) { + moreMediaEl.style.display = 'none'; + } - const playlistId = this.props.inEmbed ? null : MediaPageStore.get('playlist-id'); + if (actionsAnimEl) { + actionsAnimEl.style.display = 'none'; + } - if (playlistId) { - nextLink = MediaPageStore.get('playlist-next-media-url'); - previousLink = MediaPageStore.get('playlist-previous-media-url'); - } else { - nextLink = - this.props.data.related_media.length && !this.props.inEmbed ? this.props.data.related_media[0].url : null; - } + window.location.href = nextMediaUrl; + } - const previewSprite = !!this.props.data.sprites_url - ? { - url: this.props.siteUrl + '/' + this.props.data.sprites_url.replace(/^\//g, ''), - frame: { width: 160, height: 90, seconds: 10 }, + this.upNextLoaderView.hideTimerView(); + + return; } - : null; - return ( -
-
- {this.state.displayPlayer && null !== MediaPageStore.get('media-load-error-type') ? ( - - ) : null} + if (this.upNextLoaderView) { + if (PageStore.get('media-auto-play')) { + this.upNextLoaderView.startTimer(); + this.playerInstance.player.one( + 'play', + function () { + this.upNextLoaderView.cancelTimer(); + }.bind(this) + ); + } else { + this.upNextLoaderView.cancelTimer(); + } + } + } - {this.state.displayPlayer && null == MediaPageStore.get('media-load-error-type') ? ( -
- - {(site) => ( - - )} - -
- ) : null} -
-
- ); - } + onUpdateMediaAutoPlay() { + if (this.upNextLoaderView) { + if (PageStore.get('media-auto-play')) { + this.upNextLoaderView.showTimerView(this.playerInstance.isEnded()); + } else { + this.upNextLoaderView.hideTimerView(); + } + } + } + + render() { + let nextLink = null; + let previousLink = null; + + const playlistId = this.props.inEmbed ? null : MediaPageStore.get('playlist-id'); + + if (playlistId) { + nextLink = MediaPageStore.get('playlist-next-media-url'); + previousLink = MediaPageStore.get('playlist-previous-media-url'); + } else { + nextLink = + this.props.data.related_media.length && !this.props.inEmbed + ? this.props.data.related_media[0].url + : null; + } + + const previewSprite = !!this.props.data.sprites_url + ? { + url: this.props.siteUrl + '/' + this.props.data.sprites_url.replace(/^\//g, ''), + frame: { width: 160, height: 90, seconds: 10 }, + } + : null; + + return ( + <> + {/* {React.createElement(VideoJSEmbed, { + data: this.props.data, + siteUrl: window.MediaCMS.site.url, + onLoad: () => console.log('Video js loaded in VideoViewer'), + onError: (error) => console.error('Video js error in VideoViewer:', error), + })} */} + +
+
+ {this.state.displayPlayer && null == MediaPageStore.get('media-load-error-type') ? ( +
+ + {(site) => { + return React.createElement(VideoJSEmbed, { + data: this.props.data, + playerVolume: this.browserCache.get('player-volume'), + playerSoundMuted: this.browserCache.get('player-sound-muted'), + videoQuality: this.browserCache.get('video-quality'), + videoPlaybackSpeed: parseInt( + this.browserCache.get('video-playback-speed'), + 10 + ), + inTheaterMode: this.browserCache.get('in-theater-mode'), + siteId: site.id, + siteUrl: site.url, + info: this.videoInfo, + cornerLayers: this.cornerLayers, + sources: this.videoSources, + poster: this.videoPoster, + previewSprite: previewSprite, + subtitlesInfo: this.props.data.subtitles_info, + enableAutoplay: !this.props.inEmbed, + inEmbed: this.props.inEmbed, + hasTheaterMode: !this.props.inEmbed, + hasNextLink: !!nextLink, + hasPreviousLink: !!previousLink, + errorMessage: MediaPageStore.get('media-load-error-message'), + onClickNextCallback: this.onClickNext, + onClickPreviousCallback: this.onClickPrevious, + onStateUpdateCallback: this.onStateUpdate, + onPlayerInitCallback: this.onPlayerInit, + }); + }} + +
+ ) : null} +
+
+ + {/*
+
+ {this.state.displayPlayer && null !== MediaPageStore.get('media-load-error-type') ? ( + + ) : null} + + {this.state.displayPlayer && null == MediaPageStore.get('media-load-error-type') ? ( +
+ + {(site) => ( + + )} + +
+ ) : null} +
+
*/} + + ); + } } VideoViewer.defaultProps = { - inEmbed: !0, - siteUrl: PropTypes.string.isRequired, + inEmbed: !0, + siteUrl: PropTypes.string.isRequired, }; VideoViewer.propTypes = { - inEmbed: PropTypes.bool, + inEmbed: PropTypes.bool, }; function findGetParameter(parameterName) { - let result = null; - let tmp = []; - var items = location.search.substr(1).split('&'); - for (let i = 0; i < items.length; i++) { - tmp = items[i].split('='); - if (tmp[0] === parameterName) { - result = decodeURIComponent(tmp[1]); + let result = null; + let tmp = []; + var items = location.search.substr(1).split('&'); + for (let i = 0; i < items.length; i++) { + tmp = items[i].split('='); + if (tmp[0] === parameterName) { + result = decodeURIComponent(tmp[1]); + } } - } - return result; + return result; } - function handleCanvas(videoElem) { // Make sure it's a video element +function handleCanvas(videoElem) { + // Make sure it's a video element - if (!videoElem || !videoElem.tagName || videoElem.tagName.toLowerCase() !== 'video') { - console.error('Invalid video element:', videoElem); - return; - } + if (!videoElem || !videoElem.tagName || videoElem.tagName.toLowerCase() !== 'video') { + console.error('Invalid video element:', videoElem); + return; + } - const Player = videojs(videoElem); - Player.playsinline(true); + const Player = videojs(videoElem); + Player.playsinline(true); - Player.on('loadedmetadata', function () { - const muted = parseInt(findGetParameter('muted')); - const autoplay = parseInt(findGetParameter('autoplay')); - const timestamp = parseInt(findGetParameter('t')); + Player.on('loadedmetadata', function () { + const muted = parseInt(findGetParameter('muted')); + const autoplay = parseInt(findGetParameter('autoplay')); + const timestamp = parseInt(findGetParameter('t')); - // Handle timestamp clicks - document.addEventListener('click', function (e) { - if (e.target.classList.contains('video-timestamp')) { - e.preventDefault(); - const timestamp = parseInt(e.target.dataset.timestamp, 10); + // Handle timestamp clicks + document.addEventListener('click', function (e) { + if (e.target.classList.contains('video-timestamp')) { + e.preventDefault(); + const timestamp = parseInt(e.target.dataset.timestamp, 10); + + if (timestamp >= 0 && timestamp < Player.duration()) { + Player.currentTime(timestamp); + } else if (timestamp >= 0) { + Player.play(); + } + } + }); + + if (muted == 1) { + Player.muted(true); + } if (timestamp >= 0 && timestamp < Player.duration()) { - Player.currentTime(timestamp); - } else if (timestamp >= 0) { - Player.play(); + // Start the video from the given time + Player.currentTime(timestamp); + } else if (timestamp >= 0 && timestamp >= Player.duration()) { + // Restart the video if the given time is greater than the duration + Player.play(); + } + if (autoplay === 1) { + Player.play(); } - } }); - - if (muted == 1) { - Player.muted(true); - } - - if (timestamp >= 0 && timestamp < Player.duration()) { - // Start the video from the given time - Player.currentTime(timestamp); - } else if (timestamp >= 0 && timestamp >= Player.duration()) { - // Restart the video if the given time is greater than the duration - Player.play(); - } - if (autoplay === 1) { - Player.play(); - } - }); } const observer = new MutationObserver((mutations, me) => { - const playerContainer = document.querySelector('.video-js.vjs-mediacms'); - if (playerContainer) { - const video = playerContainer.querySelector('video'); - if (video) { - handleCanvas(video); - me.disconnect(); + const playerContainer = document.querySelector('.video-js.vjs-mediacms'); + if (playerContainer) { + const video = playerContainer.querySelector('video'); + if (video) { + handleCanvas(video); + me.disconnect(); + } } - } }); observer.observe(document, { - childList: true, - subtree: true, + childList: true, + subtree: true, }); diff --git a/frontend/src/static/js/components/video-player/VideoPlayer.jsx b/frontend/src/static/js/components/video-player/VideoPlayer.jsx deleted file mode 100644 index baa79c90..00000000 --- a/frontend/src/static/js/components/video-player/VideoPlayer.jsx +++ /dev/null @@ -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 ( -
-
- - error_outline - - {props.errorMessage} -
-
- ); -} - -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 ? ( - - ) : ( -
-
- - error_outline - - {props.errorMessage} -
-
- ); -} - -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: {}, -};