From 660f76ecfe747f2365f20c5c9ce415a575c09d13 Mon Sep 17 00:00:00 2001 From: Yiannis Christodoulou Date: Tue, 8 Jul 2025 06:03:43 +0300 Subject: [PATCH] feat: Keep a backup from old videojs files --- .../VideoPlayer.jsx | 257 ++++ .../VideoPlayer.scss | 0 .../VideoPlayerByPageLink.jsx | 0 .../list-item/includes/items/includes.js | 265 ++-- .../media-viewer/VideoViewer/index.js | 1155 +++++++++-------- .../components/video-player/VideoPlayer.jsx | 257 ---- 6 files changed, 1012 insertions(+), 922 deletions(-) create mode 100644 frontend/src/static/js/components/__OLD_VIDEOJS__video-player/VideoPlayer.jsx rename frontend/src/static/js/components/{video-player => __OLD_VIDEOJS__video-player}/VideoPlayer.scss (100%) rename frontend/src/static/js/components/{video-player => __OLD_VIDEOJS__video-player}/VideoPlayerByPageLink.jsx (100%) delete mode 100644 frontend/src/static/js/components/video-player/VideoPlayer.jsx 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 += - '