feat: Major Upgrade to Video.js v8 — Chapters Functionality, Fixes and Improvements

This commit is contained in:
Yiannis Christodoulou
2025-10-20 15:30:00 +03:00
committed by GitHub
parent b39072c8ae
commit a5e6e7b9ca
362 changed files with 62326 additions and 238721 deletions

View File

@@ -0,0 +1,231 @@
import React, { useEffect, useRef } from 'react';
/**
* VideoJSEmbed - A React component that embeds the MediaCMS video js
*
* This component dynamically loads the video js's CSS and JS files,
* then creates the required DOM element for the video js to mount to.
*
* Usage:
* <VideoJSEmbed
* data={}
* siteUrl="http://localhost"
* />
*/
const VideoJSEmbed = ({
data,
useRoundedCorners,
isPlayList,
playerVolume,
playerSoundMuted,
videoQuality,
videoPlaybackSpeed,
inTheaterMode,
siteId,
siteUrl,
info,
cornerLayers,
sources,
poster,
previewSprite,
subtitlesInfo,
enableAutoplay,
inEmbed,
hasTheaterMode,
hasNextLink,
nextLink,
hasPreviousLink,
errorMessage,
onClickNextCallback,
onClickPreviousCallback,
onStateUpdateCallback,
onPlayerInitCallback,
}) => {
const containerRef = useRef(null);
const assetsLoadedRef = useRef(false);
const playerInstanceRef = useRef(null);
const inEmbedRef = useRef(inEmbed);
// Helper function to get URL parameters
const getUrlParameter = (name) => {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
};
useEffect(() => {
// Update the ref whenever inEmbed changes
inEmbedRef.current = inEmbed;
// Set the global MEDIA_DATA that the video js expects
if (typeof window !== 'undefined') {
// Get URL parameters for autoplay, muted, and timestamp
const urlTimestamp = getUrlParameter('t');
const urlAutoplay = getUrlParameter('autoplay');
const urlMuted = getUrlParameter('muted');
window.MEDIA_DATA = {
data: data || {},
useRoundedCorners: useRoundedCorners,
isPlayList: isPlayList,
playerVolume: playerVolume || 0.5,
playerSoundMuted: playerSoundMuted || (urlMuted === '1'),
videoQuality: videoQuality || 'auto',
videoPlaybackSpeed: videoPlaybackSpeed || 1,
inTheaterMode: inTheaterMode || false,
siteId: siteId || '',
siteUrl: siteUrl || '',
info: info || {},
cornerLayers: cornerLayers || [],
sources: sources || [],
poster: poster || '',
previewSprite: previewSprite || null,
subtitlesInfo: subtitlesInfo || [],
enableAutoplay: enableAutoplay || (urlAutoplay === '1'),
inEmbed: inEmbed || false,
hasTheaterMode: hasTheaterMode || false,
hasNextLink: hasNextLink || false,
nextLink: nextLink || null,
hasPreviousLink: hasPreviousLink || false,
errorMessage: errorMessage || '',
// URL parameters
urlTimestamp: urlTimestamp ? parseInt(urlTimestamp, 10) : null,
urlAutoplay: urlAutoplay === '1',
urlMuted: urlMuted === '1',
onClickNextCallback: onClickNextCallback || null,
onClickPreviousCallback: onClickPreviousCallback || null,
onStateUpdateCallback: onStateUpdateCallback || null,
onPlayerInitCallback: (instance, elem) => {
// Store the player instance for timestamp functionality
playerInstanceRef.current = instance;
// Call the original callback if provided
if (onPlayerInitCallback) {
onPlayerInitCallback(instance, elem);
}
},
};
}
// Load assets only once
if (!assetsLoadedRef.current) {
loadVideoJSAssets();
assetsLoadedRef.current = true;
}
}, [data, siteUrl, inEmbed]);
// New effect to manually trigger VideoJS mounting for embed players
useEffect(() => {
if (inEmbed && containerRef.current) {
// Small delay to ensure DOM is fully ready, then trigger VideoJS mounting
const timer = setTimeout(() => {
// Try to trigger the VideoJS mount by dispatching a custom event
const event = new CustomEvent('triggerVideoJSMount', {
detail: { targetId: 'video-js-root-embed' }
});
document.dispatchEvent(event);
// Also try to trigger by calling the global function if it exists
if (typeof window !== 'undefined' && window.triggerVideoJSMount) {
window.triggerVideoJSMount();
}
}, 100);
return () => clearTimeout(timer);
}
}, [inEmbed, containerRef.current]);
// Set up timestamp click functionality
useEffect(() => {
const handleTimestampClick = (e) => {
if (e.target.classList.contains('video-timestamp')) {
e.preventDefault();
const timestamp = parseInt(e.target.dataset.timestamp, 10);
// Try to get the player from multiple sources
let player = null;
// First try: from our stored instance
if (playerInstanceRef.current && playerInstanceRef.current.player) {
player = playerInstanceRef.current.player;
}
// Second try: from global window.videojsPlayers
if (!player && typeof window !== 'undefined' && window.videojsPlayers) {
const videoId = inEmbedRef.current ? 'video-embed' : 'video-main';
player = window.videojsPlayers[videoId];
}
// Third try: from the global videojs function looking for existing players
if (!player && typeof window !== 'undefined' && window.videojs) {
const videoElement = document.querySelector(inEmbedRef.current ? '#video-embed' : '#video-main');
if (videoElement && videoElement.player) {
player = videoElement.player;
}
}
// If we found a player, seek to the timestamp
if (player) {
if (timestamp >= 0 && timestamp < player.duration()) {
player.currentTime(timestamp);
} else if (timestamp >= 0) {
player.play();
}
// Scroll to the video player with smooth behavior
const videoElement = document.querySelector(inEmbedRef.current ? '#video-embed' : '#video-main');
if (videoElement) {
videoElement.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'nearest'
});
}
} else {
console.warn('VideoJS player not found for timestamp navigation');
}
}
};
// Add the event listener to the document for timestamp clicks
document.addEventListener('click', handleTimestampClick);
// Cleanup function
return () => {
document.removeEventListener('click', handleTimestampClick);
};
}, []); // Empty dependency array so this effect only runs once
const loadVideoJSAssets = () => {
// Check if assets are already loaded
const existingCSS = document.querySelector('link[href*="video-js.css"]');
const existingJS = document.querySelector('script[src*="video-js.js"]');
// Load CSS if not already loaded
if (!existingCSS) {
const cssLink = document.createElement('link');
cssLink.rel = 'stylesheet';
cssLink.href = siteUrl + '/static/video_js/video-js.css';
document.head.appendChild(cssLink);
}
// Load JS if not already loaded
if (!existingJS) {
const script = document.createElement('script');
script.src = siteUrl + '/static/video_js/video-js.js';
document.head.appendChild(script);
}
};
return (
<div className="video-js-wrapper" ref={containerRef}>
{inEmbed ? <div id="video-js-root-embed" className="video-js-root-embed" /> : <div id="video-js-root-main" className="video-js-root-main" />}
</div>
);
};
VideoJSEmbed.defaultProps = {
data: {},
siteUrl: '',
};
export default VideoJSEmbed;

View File

@@ -9,9 +9,6 @@ import { LinksContext, MemberContext, SiteContext } from '../../utils/contexts/'
import { PopupMain, UserThumbnail } from '../_shared';
import { replaceString } from '../../utils/helpers/';
import './videojs-markers.js';
import './videojs.markers.css';
import { enableMarkers, addMarker } from './videojs-markers_config.js';
import { translateString } from '../../utils/helpers/';
import './Comments.scss';
@@ -457,36 +454,8 @@ export default function CommentsList(props) {
return text.replace(timeRegex, wrapTimestampWithAnchor);
}
function setMentions(text) {
let sanitizedComment = text.split('@(_').join('<a href="/user/');
sanitizedComment = sanitizedComment.split('_)[_').join('">');
return sanitizedComment.split('_]').join('</a>');
}
function setTimestampAnchorsAndMarkers(text, videoPlayer) {
function wrapTimestampWithAnchor(match, string) {
let split = match.split(':'),
s = 0,
m = 1;
let searchParameters = new URLSearchParams(window.location.search);
while (split.length > 0) {
s += m * parseInt(split.pop(), 10);
m *= 60;
}
if (MediaCMS.features.media.actions.timestampTimebar) {
addMarker(videoPlayer, s, text);
}
searchParameters.set('t', s);
const wrapped =
'<a href="' + MediaPageStore.get('media-url').split('?')[0] + '?' + searchParameters + '">' + match + '</a>';
return wrapped;
}
const timeRegex = new RegExp('((\\d)?\\d:)?(\\d)?\\d:\\d\\d', 'g');
return text.replace(timeRegex, wrapTimestampWithAnchor);
}
function onCommentSubmit(commentId) {
onCommentsLoad();

View File

@@ -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>
);
);
}

View File

@@ -1,6 +1,6 @@
import React, { useRef, useState, useEffect, useContext } from 'react';
import PropTypes from 'prop-types';
import { LinksContext } from '../../utils/contexts/';
import { LinksContext, SiteConsumer } from '../../utils/contexts/';
import { PageStore, MediaPageStore } from '../../utils/stores/';
import { PageActions, MediaPageActions } from '../../utils/actions/';
import { CircleIconButton, MaterialIcon, NumericInputWithUnit } from '../_shared/';
@@ -135,7 +135,9 @@ export function MediaShareEmbed(props) {
<div className="share-embed-inner">
<div className="on-left">
<div className="media-embed-wrap">
<VideoViewer data={MediaPageStore.get('media-data')} inEmbed={true} />
<SiteConsumer>
{(site) => <VideoViewer data={MediaPageStore.get('media-data')} siteUrl={site.url} inEmbed={true} />}
</SiteConsumer>
</div>
</div>

View File

@@ -17,7 +17,7 @@ function shareOptionsList() {
while (i < socialMedia.length) {
switch (socialMedia[i]) {
case 'embed':
if ('video' === MediaPageStore.get('media-data').media_type) {
if ('video' === MediaPageStore.get('media-data').media_type || 'audio' === MediaPageStore.get('media-data').media_type) {
ret[socialMedia[i]] = {};
}
break;
@@ -27,66 +27,6 @@ function shareOptionsList() {
shareUrl: 'mailto:?body=' + mediaUrl,
};
break;
case 'fb':
ret[socialMedia[i]] = {
title: 'Facebook',
shareUrl: 'https://www.facebook.com/sharer.php?u=' + mediaUrl,
};
break;
case 'tw':
ret[socialMedia[i]] = {
title: 'Twitter',
shareUrl: 'https://twitter.com/intent/tweet?url=' + mediaUrl,
};
break;
case 'reddit':
ret[socialMedia[i]] = {
title: 'reddit',
shareUrl: 'https://reddit.com/submit?url=' + mediaUrl + '&title=' + mediaTitle,
};
break;
case 'tumblr':
ret[socialMedia[i]] = {
title: 'Tumblr',
shareUrl: 'https://www.tumblr.com/widgets/share/tool?canonicalUrl=' + mediaUrl + '&title=' + mediaTitle,
};
break;
case 'pinterest':
ret[socialMedia[i]] = {
title: 'Pinterest',
shareUrl: 'http://pinterest.com/pin/create/link/?url=' + mediaUrl,
};
break;
case 'vk':
ret[socialMedia[i]] = {
title: 'ВКонтакте',
shareUrl: 'http://vk.com/share.php?url=' + mediaUrl + '&title=' + mediaTitle,
};
break;
case 'linkedin':
ret[socialMedia[i]] = {
title: 'LinkedIn',
shareUrl: 'https://www.linkedin.com/shareArticle?mini=true&url=' + mediaUrl,
};
break;
case 'mix':
ret[socialMedia[i]] = {
title: 'Mix',
shareUrl: 'https://mix.com/add?url=' + mediaUrl,
};
break;
case 'whatsapp':
ret[socialMedia[i]] = {
title: 'WhatsApp',
shareUrl: 'whatsapp://send?text=' + mediaUrl,
};
break;
case 'telegram':
ret[socialMedia[i]] = {
title: 'Telegram',
shareUrl: 'https://t.me/share/url?url=' + mediaUrl + '&text=' + mediaTitle,
};
break;
}
i += 1;
@@ -113,21 +53,6 @@ function ShareOptions() {
</button>
</div>
);
} else if (k === 'whatsapp') {
compList.push(
<div key={'share-' + k} className={'sh-option share-' + k}>
<a
href={shareOptions[k].shareUrl}
title=""
target="_blank"
data-action="share/whatsapp/share"
rel="noreferrer"
>
<span></span>
<span>{shareOptions[k].title}</span>
</a>
</div>
);
} else if (k === 'email') {
compList.push(
<div key="share-email" className="sh-option share-email">

View File

@@ -40,7 +40,7 @@ export function AutoPlay(props) {
<div className="auto-play">
<div className="auto-play-header">
<div className="next-label">{translateString("Up next")}</div>
<div className="auto-play-option">
{/* <div className="auto-play-option">
<label className="checkbox-label right-selectbox" tabIndex={0} onKeyPress={onKeyPress}>
{translateString("AUTOPLAY")}
<span className="checkbox-switcher-wrap">
@@ -54,7 +54,7 @@ export function AutoPlay(props) {
</span>
</span>
</label>
</div>
</div> */}
</div>
<ItemList
className="items-list-hor"

View File

@@ -495,9 +495,6 @@
color: #888;
}
.video-js {
background: none !important;
}
.vjs-big-play-button {
}
@@ -860,6 +857,7 @@
display: table;
width: 100%;
min-height: 40px;
z-index: 999;
> * {
display: table-cell;
@@ -1084,86 +1082,6 @@
}
}
.share-fb {
a,
button {
> *:first-child {
background-color: rgb(59, 89, 152);
background-image: url('../../../images/social-media-icons/fb-logo.png');
}
}
}
.share-tw {
a,
button {
> *:first-child {
background-color: rgb(29, 161, 242);
background-image: url('../../../images/social-media-icons/twitter-logo.png');
}
}
}
.share-reddit {
a,
button {
> *:first-child {
background-color: rgb(255, 69, 0);
background-image: url('../../../images/social-media-icons/reddit-logo.png');
}
}
}
.share-tumblr {
a,
button {
> *:first-child {
background-color: rgb(53, 70, 92);
background-image: url('../../../images/social-media-icons/tumblr-logo.png');
}
}
}
.share-pinterest {
a,
button {
> *:first-child {
background-color: rgb(189, 8, 28);
background-image: url('../../../images/social-media-icons/pinterest-logo.png');
}
}
}
.share-vk {
a,
button {
> *:first-child {
background-color: rgb(70, 128, 194);
background-image: url('../../../images/social-media-icons/vk-logo.png');
}
}
}
.share-linkedin {
a,
button {
> *:first-child {
background-color: rgb(0, 119, 181);
background-image: url('../../../images/social-media-icons/linkedin-logo.png');
}
}
}
.share-mix {
a,
button {
> *:first-child {
background-color: rgb(255, 130, 38);
background-image: url('../../../images/social-media-icons/mix-logo.png');
}
}
}
.share-email {
a,
button {
@@ -1172,27 +1090,6 @@
}
}
}
.share-whatsapp {
a,
button {
> *:first-child {
background-color: rgb(37, 211, 102);
background-image: url('../../../images/social-media-icons/whatsapp-logo.png');
}
}
}
.share-telegram {
a,
button {
> *:first-child {
background-color: rgb(0, 136, 204);
background-position: 11px;
background-image: url('../../../images/social-media-icons/telegram-logo.png');
}
}
}
}
.copy-field {

View File

@@ -1,83 +0,0 @@
export function extractAudioFileFormat(filename) {
let ret = null;
let ext = filename.split('.');
if (ext.length) {
ext = ext[ext.length - 1];
switch (ext) {
case 'webm':
ret = 'audio/webm';
break;
case 'flac':
ret = 'audio/flac';
break;
case 'wave':
ret = 'audio/wave';
break;
case 'wav':
ret = 'audio/wav';
break;
case 'ogg':
ret = 'audio/ogg';
break;
case 'ogg':
ret = 'audio/ogg';
break;
case 'mp3':
case 'mpeg':
ret = 'audio/mpeg';
break;
}
}
return ret;
}
// NOTE: Valid but not get used.
/*export function orderedSupportedAudioFormats( includeAll ){
let order = [];
let supports = {};
let aud = document.createElement('audio');
if(!!aud.canPlayType){
if( 'probably' === aud.canPlayType('audio/webm') || 'maybe' === aud.canPlayType('audio/webm') ){
supports.webm = !0;
order.push( 'webm' );
}
if( 'probably' === aud.canPlayType('audio/flac') || 'maybe' === aud.canPlayType('audio/flac') ){
supports.flac = !0;
order.push( 'flac' );
}
if( 'probably' === aud.canPlayType('audio/wave') || 'maybe' === aud.canPlayType('audio/wave') ){
supports.wave = !0;
order.push( 'wave' );
}
if( 'probably' === aud.canPlayType('audio/wav') || 'maybe' === aud.canPlayType('audio/wav') ){
supports.wav = !0;
order.push( 'wav' );
}
if( 'probably' === aud.canPlayType('audio/ogg') || 'maybe' === aud.canPlayType('audio/ogg') ){
supports.ogg = !0;
order.push( 'ogg' );
}
if( 'probably' === aud.canPlayType('audio/ogg; codecs="opus"') || 'maybe' === aud.canPlayType('audio/ogg; codecs="opus"') ){
supports.oggOpus = !0;
order.push( 'oggOpus' );
}
if( 'probably' === aud.canPlayType('audio/mpeg') || 'maybe' === aud.canPlayType('audio/mpeg') ){
supports.mp3 = !0;
order.push( 'mp3' );
}
}
return {
order: order,
support: supports
};
}*/

View File

@@ -1,364 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import MediaPlayer from 'mediacms-player/dist/mediacms-player.js';
import 'mediacms-player/dist/mediacms-player.css';
import { SiteContext } from '../../../utils/contexts/';
import { formatInnerLink } from '../../../utils/helpers/';
import { PageStore, MediaPageStore, VideoViewerStore as AudioPlayerStore } from '../../../utils/stores/';
import { VideoViewerActions as AudioPlayerActions } from '../../../utils/actions/';
import { UpNextLoaderView, MediaDurationInfo, PlayerRecommendedMedia } from '../../../utils/classes/';
import { extractAudioFileFormat } from './functions';
import '../VideoViewer.scss';
export default class AudioViewer extends React.PureComponent {
constructor(props) {
super(props);
let mediaData = MediaPageStore.get('media-data');
this.AudioPlayerData = {};
this.audioStartedPlaying = false;
let audioURL = formatInnerLink(mediaData.original_media_url, SiteContext._currentValue.url);
this.videoSources = [{ src: audioURL, type: extractAudioFileFormat(audioURL) }];
this.videoPoster = mediaData.poster_url;
this.videoPoster = this.videoPoster ? this.videoPoster : mediaData.thumbnail_url;
this.videoPoster = this.videoPoster ? formatInnerLink(this.videoPoster, SiteContext._currentValue.url) : '';
this.updatePlayerVolume = this.updatePlayerVolume.bind(this);
this.onAudioEnd = this.onAudioEnd.bind(this);
this.onAudioRestart = this.onAudioRestart.bind(this);
PageStore.on('switched_media_auto_play', this.onUpdateMediaAutoPlay.bind(this));
this.wrapperClick = this.wrapperClick.bind(this);
const _MediaDurationInfo = new MediaDurationInfo();
_MediaDurationInfo.update(MediaPageStore.get('media-data').duration);
this.durationISO8601 = _MediaDurationInfo.ISO8601();
}
componentDidMount() {
if (!this.videoSources.length) {
console.warn('Audio DEBUG:', "Audio file doesn't exist");
}
this.recommendedMedia = MediaPageStore.get('media-data').related_media.length
? new PlayerRecommendedMedia(
MediaPageStore.get('media-data').related_media,
this.refs.AudioElem.parentNode,
this.props.inEmbed
)
: null;
this.upNextLoaderView =
!this.props.inEmbed && MediaPageStore.get('media-data').related_media.length
? new UpNextLoaderView(MediaPageStore.get('media-data').related_media[0])
: null;
if (document.hasFocus() || 'visible' === document.visibilityState) {
this.initPlayerInstance();
} else {
this.initPlayerInstance = this.initPlayerInstance.bind(this);
window.addEventListener('focus', this.initPlayerInstance);
document.addEventListener('visibilitychange', this.initPlayerInstance);
}
}
componentWillUnmount() {
if (this.recommendedMedia) {
this.AudioPlayerData.instance.player.off('fullscreenchange', this.recommendedMedia.onResize);
PageStore.removeListener('window_resize', this.recommendedMedia.onResize);
AudioPlayerStore.removeListener('changed_viewer_mode', this.recommendedMedia.onResize);
this.recommendedMedia.destroy();
}
videojs(this.refs.AudioElem).dispose();
this.AudioPlayerData.instance = null;
delete this.AudioPlayerData.instance;
}
initPlayerInstance() {
window.removeEventListener('focus', this.initPlayerInstance);
document.removeEventListener('visibilitychange', this.initPlayerInstance);
this.refs.AudioElem.focus(); // Focus on player before instance init.
this.initPlayerInstance = null;
setTimeout(
function () {
if (!this.AudioPlayerData.instance) {
let titleLink = this.props.inEmbed ? document.createElement('a') : null;
let userThumbLink = this.props.inEmbed ? document.createElement('a') : null;
if (titleLink) {
titleLink.setAttribute('class', 'title-link');
titleLink.setAttribute('href', MediaPageStore.get('media-data').url);
titleLink.setAttribute('title', MediaPageStore.get('media-data').title);
titleLink.setAttribute('target', '_blank');
titleLink.innerHTML = MediaPageStore.get('media-data').title;
}
if (userThumbLink) {
userThumbLink.setAttribute('class', 'user-thumb-link');
userThumbLink.setAttribute('href', MediaPageStore.get('media-data').author_profile);
userThumbLink.setAttribute('title', MediaPageStore.get('media-data').author_name);
userThumbLink.setAttribute('target', '_blank');
userThumbLink.innerHTML = '<img src="' + MediaPageStore.get('media-author-thumbnail-url') + '" alt="" />';
}
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 =
MediaPageStore.get('media-data').related_media.length && !this.props.inEmbed
? MediaPageStore.get('media-data').related_media[0].url
: null;
}
this.AudioPlayerData.instance = new MediaPlayer(
this.refs.AudioElem,
{
sources: this.videoSources,
poster: this.videoPoster,
autoplay: !this.props.inEmbed,
bigPlayButton: true,
controlBar: {
fullscreen: false,
theaterMode: false,
next: !!nextLink,
previous: !!previousLink,
},
cornerLayers: {
topLeft: titleLink,
topRight: this.upNextLoaderView ? this.upNextLoaderView.html() : null,
bottomLeft: this.recommendedMedia ? this.recommendedMedia.html() : null,
bottomRight: userThumbLink,
},
},
{
volume: AudioPlayerStore.get('player-volume'),
soundMuted: AudioPlayerStore.get('player-sound-muted'),
},
null,
null,
this.onAudioPlayerStateUpdate.bind(this),
this.onClickNextButton.bind(this),
this.onClickPreviousButton.bind(this)
);
if (this.upNextLoaderView) {
this.upNextLoaderView.setVideoJsPlayerElem(this.AudioPlayerData.instance.player.el_);
this.onUpdateMediaAutoPlay();
}
this.refs.AudioElem.parentNode.focus(); // Focus on player.
this.AudioPlayerData.instance.player.one(
'play',
function () {
this.audioStartedPlaying = true;
}.bind(this)
);
if (this.recommendedMedia) {
this.recommendedMedia.initWrappers(this.AudioPlayerData.instance.player.el_);
this.AudioPlayerData.instance.player.one('pause', this.recommendedMedia.init);
this.AudioPlayerData.instance.player.on('fullscreenchange', this.recommendedMedia.onResize);
PageStore.on('window_resize', this.recommendedMedia.onResize);
AudioPlayerStore.on('changed_viewer_mode', this.recommendedMedia.onResize);
}
this.AudioPlayerData.instance.player.one('ended', this.onAudioEnd);
}
}.bind(this),
50
);
}
initialDocumentFocus() {
if (this.refs.AudioElem.parentNode) {
this.refs.AudioElem.parentNode.focus();
setTimeout(
function () {
this.AudioPlayerData.instance.player.play();
}.bind(this),
50
);
}
window.removeEventListener('focus', this.initialDocumentFocus);
this.initialDocumentFocus = null;
}
onClickNextButton() {
const playlistId = MediaPageStore.get('playlist-id');
let nextLink;
if (playlistId) {
nextLink = MediaPageStore.get('playlist-next-media-url');
if (null === nextLink) {
nextLink = MediaPageStore.get('media-data').related_media[0].url;
}
} else if (!this.props.inEmbed) {
nextLink = MediaPageStore.get('media-data').related_media[0].url;
}
window.location.href = nextLink;
}
onClickPreviousButton() {
const playlistId = MediaPageStore.get('playlist-id');
let previousLink;
if (playlistId) {
previousLink = MediaPageStore.get('playlist-previous-media-url');
if (null === previousLink) {
previousLink = MediaPageStore.get('media-data').related_media[0].url;
}
} else if (!this.props.inEmbed) {
previousLink = MediaPageStore.get('media-data').related_media[0].url;
}
window.location.href = previousLink;
}
onUpdateMediaAutoPlay() {
if (this.upNextLoaderView) {
if (PageStore.get('media-auto-play')) {
this.upNextLoaderView.showTimerView(this.AudioPlayerData.instance.isEnded());
} else {
this.upNextLoaderView.hideTimerView();
}
}
}
onAudioPlayerStateUpdate(newState) {
this.updatePlayerVolume(newState.volume, newState.soundMuted);
}
onAudioRestart() {
if (this.recommendedMedia) {
this.recommendedMedia.updateDisplayType('inline');
this.AudioPlayerData.instance.player.one('pause', this.recommendedMedia.init);
this.AudioPlayerData.instance.player.one('ended', this.onAudioEnd);
}
}
onAudioEnd() {
if (this.recommendedMedia) {
this.recommendedMedia.updateDisplayType('full');
this.AudioPlayerData.instance.player.one('playing', this.onAudioRestart);
}
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';
}
if (actionsAnimEl) {
actionsAnimEl.style.display = 'none';
}
window.location.href = nextMediaUrl;
}
this.upNextLoaderView.hideTimerView();
return;
}
if (this.upNextLoaderView) {
if (PageStore.get('media-auto-play')) {
this.upNextLoaderView.startTimer();
this.AudioPlayerData.instance.player.one(
'play',
function () {
this.upNextLoaderView.cancelTimer();
}.bind(this)
);
} else {
this.upNextLoaderView.cancelTimer();
}
}
}
onUpdateMediaAutoPlay() {
if (this.upNextLoaderView) {
if (PageStore.get('media-auto-play')) {
this.upNextLoaderView.showTimerView(this.AudioPlayerData.instance.isEnded());
} else {
this.upNextLoaderView.hideTimerView();
}
}
}
updatePlayerVolume(playerVolume, playerSoundMuted) {
if (AudioPlayerStore.get('player-volume') !== playerVolume) {
AudioPlayerActions.set_player_volume(playerVolume);
}
if (AudioPlayerStore.get('player-sound-muted') !== playerSoundMuted) {
AudioPlayerActions.set_player_sound_muted(playerSoundMuted);
}
}
wrapperClick(ev) {
if (ev.target.parentNode === this.refs.videoPlayerWrap) {
if (!this.AudioPlayerData.instance.player.ended()) {
if (!this.AudioPlayerData.instance.player.hasStarted_ || this.AudioPlayerData.instance.player.paused()) {
this.AudioPlayerData.instance.player.play();
} else {
this.AudioPlayerData.instance.player.pause();
}
}
}
}
render() {
return (
<div className="player-container audio-player-container">
<div className="player-container-inner">
<div className="video-player" ref="videoPlayerWrap" onClick={this.wrapperClick}>
<audio tabIndex="1" ref="AudioElem" className="video-js vjs-mediacms native-dimensions"></audio>
</div>
</div>
</div>
);
}
}
AudioViewer.defaultProps = {
inEmbed: false,
};
AudioViewer.propTypes = {
inEmbed: PropTypes.bool,
};

View File

@@ -1,4 +0,0 @@
.player-container {
overflow: hidden;
background: #000;
}

View File

@@ -30,7 +30,7 @@
}
.page-header {
z-index: +6;
z-index: 9999;
position: fixed;
top: 0;
left: 0;

View File

@@ -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: {},
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,213 +0,0 @@
import React, { useState, useEffect, useContext } from 'react';
import PropTypes from 'prop-types';
import UrlParse from 'url-parse';
import { ApiUrlContext, SiteContext } from '../../utils/contexts/';
import { formatInnerLink, getRequest } from '../../utils/helpers/';
import { BrowserCache } from '../../utils/classes/';
import { orderedSupportedVideoFormats, videoAvailableCodecsAndResolutions, extractDefaultVideoResolution } from '../media-viewer/VideoViewer/functions';
import { VideoPlayer } from './VideoPlayer';
export function VideoPlayerByPageLink(props) {
const apiUrl = useContext(ApiUrlContext);
const site = useContext(SiteContext);
const [errorType, setErrorType] = useState(null);
const [errorMessage, setErrorMessage] = useState(null);
const [videoPoster, setVideoPoster] = useState(null);
const [videoSources, setVideoSources] = useState([]);
const [videoResolutions, setVideoResolutions] = useState({});
const [subtitlesInfo, setSubtitlesInfo] = useState([]);
const [previewSprite, setPreviewSprite] = useState({});
// Keep cache data "fresh" for one day.
const browserCache = new BrowserCache(site.id, 86400);
const playerStates = {
videoQuality: browserCache.get('video-quality'),
};
playerStates.videoQuality = null !== playerStates.videoQuality ? playerStates.videoQuality : 'Auto';
let apiRequestUrl = null;
let data = null;
let videoId = null;
let urlParams = (function () {
let ret = new UrlParse(props.pageLink).query;
if (!ret) {
ret = [];
} else {
ret = ret.substring(1);
ret.split('&');
ret = ret.length ? ret.split('=') : [];
}
return ret;
})();
if (urlParams.length) {
let i = 0;
while (i < urlParams.length) {
if ('m' === urlParams[i]) {
// NOTE: "m" => media id/token.
videoId = urlParams[i + 1];
}
i += 2;
}
}
if (null !== videoId) {
apiRequestUrl = apiUrl.media + '/' + videoId;
}
function onApiResponse(response) {
if (void 0 === response || !!!response || void 0 === response.data || !!!response.data) {
return;
}
data = response.data;
let srcUrl, k;
const videoSources = [];
let videoPoster = null;
let videoInfo = videoAvailableCodecsAndResolutions(data.encodings_info, data.hls_info);
let errorType = null;
let errorMessage = null;
if ('string' === typeof data.poster_url) {
videoPoster = formatInnerLink(data.poster_url, site.url);
} else if ('string' === typeof data.thumbnail_url) {
videoPoster = formatInnerLink(data.thumbnail_url, site.url);
}
const resolutionsKeys = Object.keys(videoInfo);
if (!resolutionsKeys.length) {
videoInfo = null;
} else {
const supportedFormats = orderedSupportedVideoFormats();
let defaultResolution = playerStates.videoQuality;
if (null === defaultResolution || ('Auto' === defaultResolution && void 0 === videoInfo['Auto'])) {
defaultResolution = 720; // Default resolution.
}
let defaultVideoResolution = extractDefaultVideoResolution(defaultResolution, videoInfo);
if ('Auto' === defaultResolution && void 0 !== videoInfo['Auto']) {
videoSources.push({ src: videoInfo['Auto'].url[0] });
}
k = 0;
while (k < videoInfo[defaultVideoResolution].format.length) {
if ('hls' === videoInfo[defaultVideoResolution].format[k]) {
videoSources.push({ src: videoInfo[defaultVideoResolution].url[k] });
break;
}
k += 1;
}
for (k in data.encodings_info[defaultVideoResolution]) {
if (data.encodings_info[defaultVideoResolution].hasOwnProperty(k)) {
if (supportedFormats.support[k]) {
srcUrl = data.encodings_info[defaultVideoResolution][k].url;
if (!!srcUrl) {
// NOTE: In some cases, url value is 'null'.
srcUrl = formatInnerLink(srcUrl, site.url);
videoSources.push({
src: srcUrl,
encodings_status: data.encodings_info[defaultVideoResolution][k].status,
});
}
}
}
}
}
if (1 === videoSources.length && 'running' === videoSources[0].encodings_status) {
errorType = 'encodingRunning';
errorMessage = 'Media encoding is currently running. Try again in few minutes.';
}
if (null !== errorType) {
switch (errorType) {
case 'encodingRunning':
case 'encodingPending':
case 'encodingFailed':
break;
default:
console.warn('VIDEO DEBUG:', "Video files don't exist");
}
}
setErrorType(errorType);
setErrorMessage(errorMessage);
setVideoPoster(videoPoster);
setVideoSources(videoSources);
setVideoResolutions(videoInfo);
setSubtitlesInfo(data.subtitles_info);
setPreviewSprite(
!!data.sprites_url
? { url: formatInnerLink(data.sprites_url, site.url), frame: { width: 160, height: 90, seconds: 10 } }
: null
);
const featuredItemDescrContent = document.querySelector('.feat-first-item .item .item-description > div');
if (featuredItemDescrContent) {
// featuredItemDescrContent.innerHTML = data.summary + '<br/><br/>' + data.description;
featuredItemDescrContent.innerHTML = data.summary;
}
}
function onApiResponseFail(response) {
if (void 0 === response || void 0 === response.type) {
return;
}
switch (response.type) {
case 'network':
case 'private':
case 'unavailable':
setErrorType(response.type);
setErrorMessage(
void 0 !== response.message ? response.message : "Αn error occurred while loading the media's data"
);
break;
}
}
useEffect(() => {
if (null !== apiRequestUrl) {
getRequest(apiRequestUrl, false, onApiResponse, onApiResponseFail);
}
}, []);
return videoSources.length ? (
<div className="video-player">
<VideoPlayer
siteId={site.id}
siteUrl={site.url}
info={videoResolutions}
sources={videoSources}
poster={videoPoster}
previewSprite={previewSprite}
subtitlesInfo={subtitlesInfo}
enableAutoplay={false}
inEmbed={false}
hasTheaterMode={false}
hasNextLink={false}
hasPreviousLink={false}
errorMessage={errorMessage}
/>
</div>
) : null;
}
VideoPlayerByPageLink.propTypes = {
pageLink: PropTypes.string.isRequired,
};