From eac08a51a80bfe8773fbf1c663bdc9129eeccd8d Mon Sep 17 00:00:00 2001 From: Yiannis Christodoulou Date: Wed, 7 Jan 2026 13:03:57 +0200 Subject: [PATCH] feat: add linkTitle options to embed player - Added 'linkTitle' to toggle between clickable and --- .../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 | 19 +- .../media-viewer/VideoViewer/index.js | 3 + frontend/src/static/js/pages/EmbedPage.tsx | 10 +- static/video_js/video-js.js | 260 +++++++++--------- static/video_js/video-js.js.map | 2 +- 9 files changed, 181 insertions(+), 138 deletions(-) diff --git a/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js b/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js index 1ebbcaa2..07732cc5 100644 --- a/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js +++ b/frontend-tools/video-js/src/components/overlays/EmbedInfoOverlay.js @@ -17,6 +17,7 @@ class EmbedInfoOverlay extends Component { this.showTitle = options.showTitle !== undefined ? options.showTitle : true; this.showRelated = options.showRelated !== undefined ? options.showRelated : true; this.showUserAvatar = options.showUserAvatar !== undefined ? options.showUserAvatar : true; + this.linkTitle = options.linkTitle !== undefined ? options.linkTitle : true; // Initialize after player is ready this.player().ready(() => { @@ -136,7 +137,7 @@ class EmbedInfoOverlay extends Component { overflow: hidden; `; - if (this.videoUrl) { + if (this.videoUrl && this.linkTitle) { const titleLink = document.createElement('a'); titleLink.href = this.videoUrl; titleLink.target = '_blank'; 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 744aeb64..bf8df28c 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, showUserAvatar = true }) { +function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelated = true, showUserAvatar = true, linkTitle = true }) { const videoRef = useRef(null); const playerRef = useRef(null); // Track the player instance const userPreferences = useRef(new UserPreferences()); // User preferences instance @@ -221,10 +221,23 @@ function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelate return showUserAvatar; }, [isEmbedPlayer, showUserAvatar]); + // Read linkTitle from URL parameter if available (for embed players) + const getLinkTitleFromURL = useMemo(() => { + if (isEmbedPlayer && typeof window !== 'undefined') { + const urlParams = new URLSearchParams(window.location.search); + const urlLinkTitle = urlParams.get('linkTitle'); + if (urlLinkTitle !== null) { + return urlLinkTitle === '1' || urlLinkTitle === 'true'; + } + } + return linkTitle; + }, [isEmbedPlayer, linkTitle]); + // 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; + const finalLinkTitle = isEmbedPlayer ? getLinkTitleFromURL : linkTitle; // Utility function to detect touch devices const isTouchDevice = useMemo(() => { @@ -1332,6 +1345,7 @@ function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelate goToNextVideo, showRelated: finalShowRelated, showUserAvatar: finalShowUserAvatar, + linkTitle: finalLinkTitle, }); customComponents.current.endScreenHandler = endScreenHandler; // Store for cleanup @@ -2254,6 +2268,7 @@ function VideoJSPlayer({ videoId = 'default-video', showTitle = true, showRelate showTitle: finalShowTitle, showRelated: finalShowRelated, showUserAvatar: finalShowUserAvatar, + linkTitle: finalLinkTitle, }); } // 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 d4ebe3b7..7b01598c 100644 --- a/frontend-tools/video-js/src/utils/EndScreenHandler.js +++ b/frontend-tools/video-js/src/utils/EndScreenHandler.js @@ -72,6 +72,7 @@ export class EndScreenHandler { goToNextVideo, showRelated, showUserAvatar, + linkTitle, } = 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 65910ac1..e2f38d32 100644 --- a/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx +++ b/frontend/src/static/js/components/VideoJS/VideoJSEmbed.jsx @@ -36,6 +36,7 @@ const VideoJSEmbed = ({ showTitle, showRelated, showUserAvatar, + linkTitle, hasTheaterMode, hasNextLink, nextLink, @@ -69,6 +70,7 @@ const VideoJSEmbed = ({ const urlMuted = getUrlParameter('muted'); const urlShowRelated = getUrlParameter('showRelated'); const urlShowUserAvatar = getUrlParameter('showUserAvatar'); + const urlLinkTitle = getUrlParameter('linkTitle'); window.MEDIA_DATA = { data: data || {}, @@ -93,6 +95,7 @@ const VideoJSEmbed = ({ showTitle: showTitle || false, showRelated: showRelated !== undefined ? showRelated : (urlShowRelated === '1' || urlShowRelated === 'true' || urlShowRelated === null), showUserAvatar: showUserAvatar !== undefined ? showUserAvatar : (urlShowUserAvatar === '1' || urlShowUserAvatar === 'true' || urlShowUserAvatar === null), + linkTitle: linkTitle !== undefined ? linkTitle : (urlLinkTitle === '1' || urlLinkTitle === 'true' || urlLinkTitle === null), hasTheaterMode: hasTheaterMode || false, hasNextLink: hasNextLink || false, nextLink: nextLink || null, @@ -104,6 +107,7 @@ const VideoJSEmbed = ({ urlMuted: urlMuted === '1', urlShowRelated: urlShowRelated === '1' || urlShowRelated === 'true', urlShowUserAvatar: urlShowUserAvatar === '1' || urlShowUserAvatar === 'true', + urlLinkTitle: urlLinkTitle === '1' || urlLinkTitle === '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 c3d78400..91f5b904 100644 --- a/frontend/src/static/js/components/media-actions/MediaShareEmbed.jsx +++ b/frontend/src/static/js/components/media-actions/MediaShareEmbed.jsx @@ -22,6 +22,7 @@ export function MediaShareEmbed(props) { const [showTitle, setShowTitle] = useState(false); const [showRelated, setShowRelated] = useState(true); const [showUserAvatar, setShowUserAvatar] = useState(true); + const [linkTitle, setLinkTitle] = useState(true); const [aspectRatio, setAspectRatio] = useState('16:9'); const [embedWidthValue, setEmbedWidthValue] = useState(embedVideoDimensions.width); const [embedWidthUnit, setEmbedWidthUnit] = useState(embedVideoDimensions.widthUnit); @@ -107,6 +108,10 @@ export function MediaShareEmbed(props) { setShowUserAvatar(!showUserAvatar); } + function onLinkTitleChange() { + setLinkTitle(!linkTitle); + } + function onAspectRatioChange() { const newVal = aspectRatioValueRef.current.value; @@ -152,8 +157,8 @@ export function MediaShareEmbed(props) {
{(site) => <> - {/* */} - + {/* */} + }
@@ -188,6 +193,7 @@ export function MediaShareEmbed(props) { 'showTitle=' + (showTitle ? '1' : '0') + '&showRelated=' + (showRelated ? '1' : '0') + '&showUserAvatar=' + (showUserAvatar ? '1' : '0') + + '&linkTitle=' + (linkTitle ? '1' : '0') + '" frameborder="0" allowfullscreen>' } > @@ -209,6 +215,15 @@ export function MediaShareEmbed(props) { + {showTitle && ( +
+ +
+ )} +