From 4b06cabf935f3fa4df38de807cad7d9bb2e277df Mon Sep 17 00:00:00 2001 From: Yiannis Christodoulou Date: Wed, 7 Jan 2026 12:54:43 +0200 Subject: [PATCH] feat: add showUserAvatar option to video player and embed UI - Added 'showUserAvatar' parameter to control author avatar visibility in embed info overlay - Implemented UI toggle in MediaShareEmbed for the 'showUserAvatar' option - Propagated 'showUserAvatar' through EmbedPage, VideoViewer, and VideoJSEmbed - Updated test iframe index with all 8 combinations of showTitle, showRelated, and showUserAvatar --- .../components/overlays/EmbedInfoOverlay.js | 3 +- .../components/video-player/VideoJSPlayer.jsx | 17 +- .../video-js/src/utils/EndScreenHandler.js | 1 + .../js/components/VideoJS/VideoJSEmbed.jsx | 4 + .../media-actions/MediaShareEmbed.jsx | 17 +- .../media-viewer/VideoViewer/index.js | 7 + frontend/src/static/js/pages/EmbedPage.tsx | 2 + static/video_js/video-js.js | 286 +++++++++--------- static/video_js/video-js.js.map | 2 +- 9 files changed, 191 insertions(+), 148 deletions(-) diff --git a/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js b/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js index d29bfc70..1ebbcaa2 100644 --- a/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js +++ b/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js @@ -16,6 +16,7 @@ class EmbedInfoOverlay extends Component { this.videoUrl = options.videoUrl || ''; this.showTitle = options.showTitle !== undefined ? options.showTitle : true; this.showRelated = options.showRelated !== undefined ? options.showRelated : true; + this.showUserAvatar = options.showUserAvatar !== undefined ? options.showUserAvatar : true; // Initialize after player is ready this.player().ready(() => { @@ -59,7 +60,7 @@ class EmbedInfoOverlay extends Component { `; // Create avatar container - if (this.authorThumbnail) { + if (this.authorThumbnail && this.showUserAvatar) { const avatarContainer = document.createElement('div'); avatarContainer.className = 'embed-avatar-container'; avatarContainer.style.cssText = ` diff --git a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx index 19edad3a..744aeb64 100644 --- a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx +++ b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx @@ -170,7 +170,7 @@ const enableStandardButtonTooltips = (player) => { }, 500); // Delay to ensure all components are ready }; -function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelated = true }) { +function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelated = true, showUserAvatar = true }) { const videoRef = useRef(null); const playerRef = useRef(null); // Track the player instance const userPreferences = useRef(new UserPreferences()); // User preferences instance @@ -209,9 +209,22 @@ function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelate return showRelated; }, [isEmbedPlayer, showRelated]); + // Read showUserAvatar from URL parameter if available (for embed players) + const getShowUserAvatarFromURL = useMemo(() => { + if (isEmbedPlayer && typeof window !== 'undefined') { + const urlParams = new URLSearchParams(window.location.search); + const urlShowUserAvatar = urlParams.get('showUserAvatar'); + if (urlShowUserAvatar !== null) { + return urlShowUserAvatar === '1' || urlShowUserAvatar === 'true'; + } + } + return showUserAvatar; + }, [isEmbedPlayer, showUserAvatar]); + // Use URL parameter value if available, otherwise use prop value const finalShowTitle = isEmbedPlayer ? getShowTitleFromURL : showTitle; const finalShowRelated = isEmbedPlayer ? getShowRelatedFromURL : showRelated; + const finalShowUserAvatar = isEmbedPlayer ? getShowUserAvatarFromURL : showUserAvatar; // Utility function to detect touch devices const isTouchDevice = useMemo(() => { @@ -1318,6 +1331,7 @@ function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelate relatedVideos, goToNextVideo, showRelated: finalShowRelated, + showUserAvatar: finalShowUserAvatar, }); customComponents.current.endScreenHandler = endScreenHandler; // Store for cleanup @@ -2239,6 +2253,7 @@ function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelate videoUrl: currentVideo.url, showTitle: finalShowTitle, showRelated: finalShowRelated, + showUserAvatar: finalShowUserAvatar, }); } // END: Add Embed Info Overlay Component diff --git a/frontend-tools/video-js/src/utils/EndScreenHandler.js b/frontend-tools/video-js/src/utils/EndScreenHandler.js index 473efb0a..d4ebe3b7 100644 --- a/frontend-tools/video-js/src/utils/EndScreenHandler.js +++ b/frontend-tools/video-js/src/utils/EndScreenHandler.js @@ -71,6 +71,7 @@ export class EndScreenHandler { relatedVideos, goToNextVideo, showRelated, + showUserAvatar, } = this.options; // For embed players, show big play button when video ends diff --git a/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx b/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx index a367131c..65910ac1 100644 --- a/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx +++ b/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx @@ -35,6 +35,7 @@ const VideoJSEmbed = ({ inEmbed, showTitle, showRelated, + showUserAvatar, hasTheaterMode, hasNextLink, nextLink, @@ -67,6 +68,7 @@ const VideoJSEmbed = ({ const urlAutoplay = getUrlParameter('autoplay'); const urlMuted = getUrlParameter('muted'); const urlShowRelated = getUrlParameter('showRelated'); + const urlShowUserAvatar = getUrlParameter('showUserAvatar'); window.MEDIA_DATA = { data: data || {}, @@ -90,6 +92,7 @@ const VideoJSEmbed = ({ inEmbed: inEmbed || false, showTitle: showTitle || false, showRelated: showRelated !== undefined ? showRelated : (urlShowRelated === '1' || urlShowRelated === 'true' || urlShowRelated === null), + showUserAvatar: showUserAvatar !== undefined ? showUserAvatar : (urlShowUserAvatar === '1' || urlShowUserAvatar === 'true' || urlShowUserAvatar === null), hasTheaterMode: hasTheaterMode || false, hasNextLink: hasNextLink || false, nextLink: nextLink || null, @@ -100,6 +103,7 @@ const VideoJSEmbed = ({ urlAutoplay: urlAutoplay === '1', urlMuted: urlMuted === '1', urlShowRelated: urlShowRelated === '1' || urlShowRelated === 'true', + urlShowUserAvatar: urlShowUserAvatar === '1' || urlShowUserAvatar === 'true', onClickNextCallback: onClickNextCallback || null, onClickPreviousCallback: onClickPreviousCallback || null, onStateUpdateCallback: onStateUpdateCallback || null, diff --git a/frontend/src/static/js/components/media-actions/MediaShareEmbed.jsx b/frontend/src/static/js/components/media-actions/MediaShareEmbed.jsx index b5943b7c..c3d78400 100644 --- a/frontend/src/static/js/components/media-actions/MediaShareEmbed.jsx +++ b/frontend/src/static/js/components/media-actions/MediaShareEmbed.jsx @@ -21,6 +21,7 @@ export function MediaShareEmbed(props) { const [keepAspectRatio, setKeepAspectRatio] = useState(false); const [showTitle, setShowTitle] = useState(false); const [showRelated, setShowRelated] = useState(true); + const [showUserAvatar, setShowUserAvatar] = useState(true); const [aspectRatio, setAspectRatio] = useState('16:9'); const [embedWidthValue, setEmbedWidthValue] = useState(embedVideoDimensions.width); const [embedWidthUnit, setEmbedWidthUnit] = useState(embedVideoDimensions.widthUnit); @@ -102,6 +103,10 @@ export function MediaShareEmbed(props) { setShowRelated(!showRelated); } + function onShowUserAvatarChange() { + setShowUserAvatar(!showUserAvatar); + } + function onAspectRatioChange() { const newVal = aspectRatioValueRef.current.value; @@ -147,8 +152,8 @@ export function MediaShareEmbed(props) {
{(site) => <> - {/* */} - + {/* */} + }
@@ -182,6 +187,7 @@ export function MediaShareEmbed(props) { (links.embed.includes('?') ? '&' : '?') + 'showTitle=' + (showTitle ? '1' : '0') + '&showRelated=' + (showRelated ? '1' : '0') + + '&showUserAvatar=' + (showUserAvatar ? '1' : '0') + '" frameborder="0" allowfullscreen>' } > @@ -210,6 +216,13 @@ export function MediaShareEmbed(props) { +
+ +
+