refactor: Remove old custom components and 3rd party plugins of video.js

This commit is contained in:
Yiannis Christodoulou
2025-09-19 13:10:55 +03:00
parent 1c4254ba35
commit f27d41bb6f
83 changed files with 17 additions and 204298 deletions
@@ -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
@@ -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,
};
@@ -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
};
}*/
@@ -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,
};
@@ -1,13 +0,0 @@
import React from 'react';
import AudioViewer from '../components/media-viewer/AudioViewer';
import { _MediaPage } from './_MediaPage';
export class MediaAudioPage extends _MediaPage {
viewerContainerContent() {
return <AudioViewer />;
}
mediaType() {
return 'audio';
}
}
@@ -5,6 +5,7 @@ import { _VideoMediaPage } from './_VideoMediaPage';
export class MediaVideoPage extends _VideoMediaPage {
viewerContainerContent(mediaData) {
return <>Not working anymore?</>; // TODO: check this if this page not working anymore as MediaPage.js do the same work
return <SiteConsumer>{(site) => <VideoViewer data={mediaData} siteUrl={site.url} inEmbed={!1} />}</SiteConsumer>;
}
@@ -1,467 +0,0 @@
import { formatViewsNumber, quickSort, greaterCommonDivision, addClassname, removeClassname } from '../helpers/';
import ItemsInlineSlider from '../../components/item-list/includes/itemLists/ItemsInlineSlider';
import { MediaDurationInfo } from './MediaDurationInfo';
const _MediaDurationInfo = new MediaDurationInfo();
function itemDuration(duration) {
return '<span class="more-media-duration"><span>' + duration + '</span></span>';
}
function itemThumb(img, duration) {
return img
? '<span class="more-media-item-thumb" style="background-image:url(\'' +
img +
'\');">' +
itemDuration(duration) +
'</span>'
: '';
}
function itemTitle(title) {
return '<span class="more-media-title">' + title + '</span>';
}
function itemAuthor(author) {
return '<span class="more-media-author">' + author + '</span>';
}
function itemViews(views, hideViews) {
return hideViews ? '' : '<span class="more-media-views">' + views + '</span>';
}
function itemMeta(author, views, hideViews) {
return '<span class="more-media-meta">' + itemAuthor(author) + itemViews(views, hideViews) + '</span>';
}
function itemContent(title, author, views, hideViews) {
return '<span class="more-media-item-content">' + itemTitle(title) + itemMeta(author, views, hideViews) + '</span>';
}
function generateRatiosGrids(columnsArr, rowsArr, itemsLength, viewportWidth, viewportHeight) {
let i = 0,
j,
rw,
rh,
gcd,
ret = {};
let defaultRatioWidth = 16;
let defaultRatioheight = 9;
while (i < columnsArr.length) {
j = 0;
while (j < rowsArr.length) {
rw = defaultRatioWidth * columnsArr[i];
rh = defaultRatioheight * rowsArr[j];
gcd = greaterCommonDivision(rw, rh);
if (1 < gcd) {
rw = rw / gcd;
rh = rh / gcd;
}
if (columnsArr[i] * (rowsArr[j] - 1) < itemsLength) {
ret[rw + '/' + rh] = ret[rw + '/' + rh] || { val: rw / rh, grid: [] };
ret[rw + '/' + rh].grid.push([columnsArr[i], rowsArr[j]]);
}
j += 1;
}
i += 1;
}
return ret;
}
function matchedRatioGrids(ratios, ww, wh, pw, ph, pr, itemWidthBreakpoint) {
let dist = [],
pntr = {},
ret = [];
let x, k, availableGrids;
if (3 * itemWidthBreakpoint <= pw) {
ret = 1.6 < pr ? [4, 3] : [3, 4];
} else if (1.5 * itemWidthBreakpoint >= pw) {
if (160 >= ph) {
ret = [1, 1];
} else if (320 >= ph) {
ret = [1, 2];
} else if (480 >= ph) {
ret = [1, 3];
} else if (640 >= ph) {
ret = [1, 4];
} else if (800 >= ph) {
ret = [1, 6];
} else {
ret = [1, 6];
}
} else if (2.5 * itemWidthBreakpoint >= pw) {
ret = [2, 1];
if (160 >= ph) {
ret = [2, 1];
} else if (320 >= ph) {
ret = [2, 2];
} else if (480 >= ph) {
ret = [2, 3];
} else if (640 >= ph) {
ret = [2, 4];
} else if (800 >= ph) {
ret = [2, 5];
} else {
ret = [2, 6];
}
}
if (!ret.length) {
for (k in ratios) {
if (ratios.hasOwnProperty(k)) {
x = Math.abs(pr - ratios[k].val);
dist.push(x);
pntr[x] = k;
}
}
availableGrids = ratios[pntr[quickSort(dist, 0, dist.length - 1)[0]]].grid;
if (1 < availableGrids.length) {
dist = [];
pntr = {};
k = 0;
while (k < availableGrids.length) {
x = Math.abs(pw - availableGrids[k][0] * itemWidthBreakpoint);
dist.push(x);
pntr[x] = k;
k += 1;
}
ret = availableGrids[pntr[quickSort(dist, 0, dist.length - 1)[0]]];
} else {
ret = availableGrids[0];
}
if (2 * itemWidthBreakpoint >= pw) {
ret[0] = Math.min(2, ret[0]);
} else if (3 * itemWidthBreakpoint >= pw) {
ret[0] = Math.min(3, ret[0]);
}
if (390 >= ph) {
ret[1] = Math.min(2, ret[1]);
} else if (590 >= ph) {
ret[1] = Math.min(3, ret[1]);
}
}
return ret;
}
function gridClassname(itemsLength, container) {
if (!itemsLength || !container || !container.firstChild) {
return '';
}
const ww = window.outerWidth;
const wh = window.outerHeight;
const child = container.firstChild;
const pw = child.offsetWidth;
const ph = child.offsetHeight;
const pr = pw / ph;
let ret = matchedRatioGrids(
generateRatiosGrids([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], itemsLength, parseInt(ww, 10), parseInt(wh, 10)),
ww,
wh,
pw,
ph,
pr,
250
);
return ret.length ? ' grid-col-' + ret[0] + ' grid-row-' + ret[1] : '';
}
function buildItemsElements(itemsData, items, wrapper, inEmbed, hideViews) {
let i = 0;
while (i < itemsData.length) {
_MediaDurationInfo.update(itemsData[i].duration);
items[i] = document.createElement('div');
items[i].setAttribute('class', 'more-media-item before-more-media-item-load');
items[i].setAttribute('style', '--n: ' + i);
items[i].innerHTML =
'<a href="' +
itemsData[i].url +
'" title="' +
itemsData[i].title +
'"' +
(inEmbed ? 'target="_blank"' : '') +
'>' +
itemThumb(itemsData[i].thumbnail_url, _MediaDurationInfo.toString()) +
itemContent(
itemsData[i].title,
itemsData[i].author_name,
formatViewsNumber(itemsData[i].views) + ' ' + (1 >= itemsData[i].views ? 'view' : 'views'),
hideViews
) +
'</a>';
wrapper.appendChild(items[i]);
i += 1;
}
}
export function PlayerRecommendedMedia(itemsData, inEmbed, hideViews) {
inEmbed = inEmbed || false;
let container = null;
function updateSlider(afterItemsUpdate) {
if (!inlineSlider) {
if (!domElems.contentInner.offsetWidth) {
return;
}
inlineSlider = new ItemsInlineSlider(domElems.contentInner, '.more-media-item');
disableItemsRevealAnim();
}
inlineSlider.updateDataState(itemsData.length, true, true);
updateSliderButtonsView();
}
function disableItemsRevealAnim() {
setTimeout(function () {
let i = 0;
while (i < domElems.items.length) {
domElems.items[i].setAttribute('class', 'more-media-item');
domElems.items[i].setAttribute('style', null);
i += 1;
}
}, domElems.items.length * 75 + 200); // NOTE: 200ms is reveal animation duration and 75ms is reveal animation delay (in CSS, with class selector '.before-more-media-item-load' ).
}
function updateSliderButtonsView() {
domElems.prevSlide.style.display = inlineSlider.hasPreviousSlide() ? '' : 'none';
domElems.nextSlide.style.display = inlineSlider.hasNextSlide() ? '' : 'none';
}
function toggleInlineVisibility(ev) {
ev.preventDefault();
ev.stopPropagation();
state.openInlineMoreMedia = !state.openInlineMoreMedia;
(state.openInlineMoreMedia ? removeClassname : addClassname)(domElems.wrapper, 'hidden-inline-more-media');
updateSlider(false);
}
function clickPreviousBtn(ev) {
ev.preventDefault();
ev.stopPropagation();
inlineSlider.previousSlide();
updateSliderButtonsView();
inlineSlider.scrollToCurrentSlide();
}
function clickNextBtn(ev) {
ev.preventDefault();
ev.stopPropagation();
inlineSlider.nextSlide();
updateSliderButtonsView();
inlineSlider.scrollToCurrentSlide();
}
function wrapperClassname() {
if (null === container) {
return;
}
let ret = 'more-media';
switch (state.displayType) {
case 'full':
ret += ' full-wrapper';
break;
case 'inline-small':
ret += ' inline-slider-small';
break;
case 'inline':
ret += ' inline-slider';
break;
}
ret += state.openInlineMoreMedia ? '' : ' hidden-inline-more-media';
return ret + gridClassname(itemsData.length, container);
}
function updateWrapperParentStyle() {
switch (state.displayType) {
case 'full':
domElems.wrapper.parentNode.style.top = '';
break;
case 'inline-small':
case 'inline':
domElems.wrapper.parentNode.style.top = 'auto';
break;
}
}
function updateWrapperClassname() {
domElems.wrapper.setAttribute('class', wrapperClassname());
}
let inlineSlider;
const domElems = {
wrapper: document.createElement('div'),
title: document.createElement('h2'),
openBtn: document.createElement('button'),
closeBtn: document.createElement('button'),
prevSlide: document.createElement('div'),
nextSlide: document.createElement('div'),
prevSlideBtn: null,
nextSlideBtn: null,
content: document.createElement('div'),
contentInner: document.createElement('div'),
items: [],
};
const state = {
isInited: false,
displayType: 'inline',
openInlineMoreMedia: true,
};
domElems.title.innerHTML = 'More videos';
domElems.openBtn.innerHTML = 'More videos';
domElems.prevSlide.innerHTML =
'<button class="circle-icon-button"><span><span><i class="vjs-icon-navigate-before"></i></span></span></button>';
domElems.nextSlide.innerHTML =
'<button class="circle-icon-button"><span><span><i class="vjs-icon-navigate-next"></i></span></span></button>';
domElems.title.setAttribute('class', 'more-media-wrap-title');
domElems.openBtn.setAttribute('class', 'open-more-videos');
domElems.closeBtn.setAttribute('class', 'close-more-videos vjs-icon-close');
domElems.prevSlide.setAttribute('class', 'prev-slide');
domElems.nextSlide.setAttribute('class', 'next-slide');
domElems.content.appendChild(domElems.contentInner);
domElems.wrapper.appendChild(domElems.title);
domElems.wrapper.appendChild(domElems.openBtn);
domElems.wrapper.appendChild(domElems.closeBtn);
domElems.wrapper.appendChild(domElems.content);
domElems.content.appendChild(domElems.prevSlide);
domElems.content.appendChild(domElems.nextSlide);
domElems.prevSlideBtn = domElems.prevSlide.querySelector('button');
domElems.nextSlideBtn = domElems.nextSlide.querySelector('button');
function bindEvents() {
if (domElems.prevSlideBtn) {
domElems.prevSlideBtn.addEventListener('click', clickPreviousBtn);
}
if (domElems.nextSlideBtn) {
domElems.nextSlideBtn.addEventListener('click', clickNextBtn);
}
domElems.openBtn.addEventListener('click', toggleInlineVisibility);
domElems.closeBtn.addEventListener('click', toggleInlineVisibility);
}
function unbindEvents() {
if (domElems.prevSlideBtn) {
domElems.prevSlideBtn.removeEventListener('click', clickPreviousBtn);
}
if (domElems.nextSlideBtn) {
domElems.nextSlideBtn.removeEventListener('click', clickNextBtn);
}
domElems.openBtn.removeEventListener('click', toggleInlineVisibility);
domElems.closeBtn.removeEventListener('click', toggleInlineVisibility);
}
this.html = function () {
return domElems.wrapper;
};
this.onResize = function () {
updateWrapperClassname();
switch (state.displayType) {
case 'inline':
updateSlider(false);
break;
}
};
this.initWrappers = function (wrapper) {
container = wrapper;
updateWrapperParentStyle();
updateWrapperClassname();
};
this.init = function () {
if (!state.itemsAreBuilt) {
state.itemsAreBuilt = true;
buildItemsElements(itemsData, domElems.items, domElems.contentInner, inEmbed, hideViews);
}
switch (state.displayType) {
case 'inline':
if (inlineSlider) {
updateSlider(false);
disableItemsRevealAnim();
} else {
updateSlider(true);
}
break;
}
};
this.destroy = function () {
unbindEvents();
};
this.updateDisplayType = function (type) {
let newType, i;
switch (type) {
case 'full':
case 'inline':
case 'inline-small':
newType = type;
break;
}
if (newType && newType !== state.displayType) {
state.displayType = newType;
updateWrapperParentStyle();
updateWrapperClassname();
i = 0;
while (i < domElems.items.length) {
domElems.items[i].setAttribute('class', 'more-media-item before-more-media-item-load');
domElems.items[i].setAttribute('style', '--n: ' + i);
i += 1;
}
switch (newType) {
case 'full':
disableItemsRevealAnim();
break;
}
}
};
bindEvents();
}
@@ -1,4 +1,3 @@
export * from './BrowserCache';
export * from './MediaDurationInfo';
export * from './PlayerRecommendedMedia';
export * from './UpNextLoaderView';
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long