diff --git a/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx b/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx new file mode 100644 index 00000000..74cb034e --- /dev/null +++ b/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx @@ -0,0 +1,116 @@ +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: + * + */ + +const VideoJSEmbed = ({ + data, + playerVolume, + playerSoundMuted, + videoQuality, + videoPlaybackSpeed, + inTheaterMode, + siteId, + siteUrl, + info, + cornerLayers, + sources, + poster, + previewSprite, + subtitlesInfo, + enableAutoplay, + inEmbed, + hasTheaterMode, + hasNextLink, + hasPreviousLink, + errorMessage, + onClickNextCallback, + onClickPreviousCallback, + onStateUpdateCallback, + onPlayerInitCallback, +}) => { + const containerRef = useRef(null); + const assetsLoadedRef = useRef(false); + + useEffect(() => { + // Set the global MEDIA_DATA that the video js expects + if (typeof window !== 'undefined') { + window.MEDIA_DATA = { + data: data || {}, // TODO: Check if this is needed + playerVolume: playerVolume || 0.5, + playerSoundMuted: playerSoundMuted || false, + 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 || false, + inEmbed: inEmbed || false, + hasTheaterMode: hasTheaterMode || false, + hasNextLink: hasNextLink || false, + hasPreviousLink: hasPreviousLink || false, + errorMessage: errorMessage || '', + onClickNextCallback: onClickNextCallback || null, + onClickPreviousCallback: onClickPreviousCallback || null, + onStateUpdateCallback: onStateUpdateCallback || null, + onPlayerInitCallback: onPlayerInitCallback || null, + }; + } + + // Load assets only once + if (!assetsLoadedRef.current) { + loadVideoJSAssets(); + assetsLoadedRef.current = true; + } + }, [data, siteUrl]); + + 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 ( +
+
+
+ ); +}; + +VideoJSEmbed.defaultProps = { + data: {}, + siteUrl: '', +}; + +export default VideoJSEmbed;