mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-01-20 07:12:58 -05:00
feat: add showTitle option for embed videos
- Add showTitle prop support to EmbedInfoOverlay to conditionally show/hide title overlay - Add showTitle checkbox option in MediaShareEmbed dialog with URL parameter support - Update embed code generation to include showTitle parameter - Add copy-url and copy-embed visual feedback icons to SeekIndicator - Support showTitle prop in VideoJSEmbed component
This commit is contained in:
@@ -204,6 +204,54 @@ class SeekIndicator extends Component {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
textEl.textContent = 'Pause';
|
textEl.textContent = 'Pause';
|
||||||
|
} else if (direction === 'copy-url') {
|
||||||
|
iconEl.innerHTML = `
|
||||||
|
<div style="display: flex; align-items: center; justify-content: center; animation: youtubeSeekPulse 0.3s ease-out;">
|
||||||
|
<div style="
|
||||||
|
width: ${circleSize};
|
||||||
|
height: ${circleSize};
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
">
|
||||||
|
<svg viewBox="0 0 24 24" width="${iconSize}" height="${iconSize}" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style="filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));">
|
||||||
|
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
|
||||||
|
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
textEl.textContent = '';
|
||||||
|
} else if (direction === 'copy-embed') {
|
||||||
|
iconEl.innerHTML = `
|
||||||
|
<div style="display: flex; align-items: center; justify-content: center; animation: youtubeSeekPulse 0.3s ease-out;">
|
||||||
|
<div style="
|
||||||
|
width: ${circleSize};
|
||||||
|
height: ${circleSize};
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
">
|
||||||
|
<svg viewBox="0 0 24 24" width="${iconSize}" height="${iconSize}" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style="filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));">
|
||||||
|
<path d="M16 18l6-6-6-6"/>
|
||||||
|
<path d="M8 6l-6 6 6 6"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
textEl.textContent = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear any text content in the text element
|
// Clear any text content in the text element
|
||||||
@@ -239,6 +287,11 @@ class SeekIndicator extends Component {
|
|||||||
this.showTimeout = setTimeout(() => {
|
this.showTimeout = setTimeout(() => {
|
||||||
this.hide();
|
this.hide();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
} else if (direction === 'copy-url' || direction === 'copy-embed') {
|
||||||
|
// Copy operations: 500ms (same as play/pause)
|
||||||
|
this.showTimeout = setTimeout(() => {
|
||||||
|
this.hide();
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,19 @@ class EmbedInfoOverlay extends Component {
|
|||||||
this.authorThumbnail = options.authorThumbnail || '';
|
this.authorThumbnail = options.authorThumbnail || '';
|
||||||
this.videoTitle = options.videoTitle || 'Video';
|
this.videoTitle = options.videoTitle || 'Video';
|
||||||
this.videoUrl = options.videoUrl || '';
|
this.videoUrl = options.videoUrl || '';
|
||||||
|
this.showTitle = options.showTitle !== undefined ? options.showTitle : true;
|
||||||
|
|
||||||
// Initialize after player is ready
|
// Initialize after player is ready
|
||||||
this.player().ready(() => {
|
this.player().ready(() => {
|
||||||
this.createOverlay();
|
if (this.showTitle) {
|
||||||
|
this.createOverlay();
|
||||||
|
} else {
|
||||||
|
// Hide overlay element if showTitle is false
|
||||||
|
const overlay = this.el();
|
||||||
|
overlay.style.display = 'none';
|
||||||
|
overlay.style.opacity = '0';
|
||||||
|
overlay.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,10 +195,16 @@ class EmbedInfoOverlay extends Component {
|
|||||||
const player = this.player();
|
const player = this.player();
|
||||||
const overlay = this.el();
|
const overlay = this.el();
|
||||||
|
|
||||||
|
// If showTitle is false, ensure overlay is hidden
|
||||||
|
if (!this.showTitle) {
|
||||||
|
overlay.style.display = 'none';
|
||||||
|
overlay.style.opacity = '0';
|
||||||
|
overlay.style.visibility = 'hidden';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Sync overlay visibility with control bar visibility
|
// Sync overlay visibility with control bar visibility
|
||||||
const updateOverlayVisibility = () => {
|
const updateOverlayVisibility = () => {
|
||||||
const controlBar = player.getChild('controlBar');
|
|
||||||
|
|
||||||
if (!player.hasStarted()) {
|
if (!player.hasStarted()) {
|
||||||
// Show overlay when video hasn't started (poster is showing) - like before
|
// Show overlay when video hasn't started (poster is showing) - like before
|
||||||
overlay.style.opacity = '1';
|
overlay.style.opacity = '1';
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const VideoJSEmbed = ({
|
|||||||
subtitlesInfo,
|
subtitlesInfo,
|
||||||
enableAutoplay,
|
enableAutoplay,
|
||||||
inEmbed,
|
inEmbed,
|
||||||
|
showTitle,
|
||||||
hasTheaterMode,
|
hasTheaterMode,
|
||||||
hasNextLink,
|
hasNextLink,
|
||||||
nextLink,
|
nextLink,
|
||||||
@@ -220,7 +221,14 @@ const VideoJSEmbed = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="video-js-wrapper" ref={containerRef}>
|
<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" />}
|
{inEmbed ? (
|
||||||
|
<div
|
||||||
|
id="video-js-root-embed"
|
||||||
|
className="video-js-root-embed"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div id="video-js-root-main" className="video-js-root-main" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export function MediaShareEmbed(props) {
|
|||||||
|
|
||||||
const [maxHeight, setMaxHeight] = useState(window.innerHeight - 144 + 56);
|
const [maxHeight, setMaxHeight] = useState(window.innerHeight - 144 + 56);
|
||||||
const [keepAspectRatio, setKeepAspectRatio] = useState(false);
|
const [keepAspectRatio, setKeepAspectRatio] = useState(false);
|
||||||
|
const [showTitle, setShowTitle] = useState(false);
|
||||||
const [aspectRatio, setAspectRatio] = useState('16:9');
|
const [aspectRatio, setAspectRatio] = useState('16:9');
|
||||||
const [embedWidthValue, setEmbedWidthValue] = useState(embedVideoDimensions.width);
|
const [embedWidthValue, setEmbedWidthValue] = useState(embedVideoDimensions.width);
|
||||||
const [embedWidthUnit, setEmbedWidthUnit] = useState(embedVideoDimensions.widthUnit);
|
const [embedWidthUnit, setEmbedWidthUnit] = useState(embedVideoDimensions.widthUnit);
|
||||||
@@ -92,6 +93,10 @@ export function MediaShareEmbed(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onShowTitleChange() {
|
||||||
|
setShowTitle(!showTitle);
|
||||||
|
}
|
||||||
|
|
||||||
function onAspectRatioChange() {
|
function onAspectRatioChange() {
|
||||||
const newVal = aspectRatioValueRef.current.value;
|
const newVal = aspectRatioValueRef.current.value;
|
||||||
|
|
||||||
@@ -136,7 +141,10 @@ export function MediaShareEmbed(props) {
|
|||||||
<div className="on-left">
|
<div className="on-left">
|
||||||
<div className="media-embed-wrap">
|
<div className="media-embed-wrap">
|
||||||
<SiteConsumer>
|
<SiteConsumer>
|
||||||
{(site) => <VideoViewer data={MediaPageStore.get('media-data')} siteUrl={site.url} inEmbed={true} />}
|
{(site) => <>
|
||||||
|
{/* <VideoViewer key={`embed-${showTitle}`} data={MediaPageStore.get('media-data')} siteUrl={site.url} inEmbed={true} showTitle={showTitle} /> */}
|
||||||
|
<iframe width="100%" height="480px" src={`${links.embed + MediaPageStore.get('media-id')}&showTitle=${showTitle ? '1' : '0'}`} frameborder="0" allowfullscreen></iframe>
|
||||||
|
</>}
|
||||||
</SiteConsumer>
|
</SiteConsumer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -166,6 +174,7 @@ export function MediaShareEmbed(props) {
|
|||||||
'" src="' +
|
'" src="' +
|
||||||
links.embed +
|
links.embed +
|
||||||
MediaPageStore.get('media-id') +
|
MediaPageStore.get('media-id') +
|
||||||
|
(showTitle ? (links.embed.includes('?') ? '&showTitle=1' : '?showTitle=1') : '') +
|
||||||
'" frameborder="0" allowfullscreen></iframe>'
|
'" frameborder="0" allowfullscreen></iframe>'
|
||||||
}
|
}
|
||||||
></textarea>
|
></textarea>
|
||||||
@@ -180,6 +189,13 @@ export function MediaShareEmbed(props) {
|
|||||||
|
|
||||||
<div className="option-content">
|
<div className="option-content">
|
||||||
<div className="ratio-options">
|
<div className="ratio-options">
|
||||||
|
<div className="options-group">
|
||||||
|
<label style={{ minHeight: '36px' }}>
|
||||||
|
<input type="checkbox" checked={showTitle} onChange={onShowTitleChange} />
|
||||||
|
Show title
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="options-group">
|
<div className="options-group">
|
||||||
<label style={{ minHeight: '36px' }}>
|
<label style={{ minHeight: '36px' }}>
|
||||||
<input type="checkbox" checked={keepAspectRatio} onChange={onKeepAspectRatioChange} />
|
<input type="checkbox" checked={keepAspectRatio} onChange={onKeepAspectRatioChange} />
|
||||||
|
|||||||
Reference in New Issue
Block a user