import { __ } from '@wordpress/i18n';
|
import {
|
useBlockProps,
|
InspectorControls,
|
MediaUpload,
|
MediaUploadCheck,
|
InnerBlocks
|
} from '@wordpress/block-editor';
|
import {
|
PanelBody,
|
Button,
|
ToggleControl,
|
BaseControl
|
} from '@wordpress/components';
|
import './editor.scss';
|
|
const ALLOWED_VIDEO_TYPES = ['video/mp4', 'video/webm', 'video/ogg', 'video/ogv'];
|
|
export default function Edit({ attributes, setAttributes }) {
|
const {
|
posterId,
|
posterUrl,
|
videoSources,
|
mobileSources,
|
fadeEffect
|
} = attributes;
|
|
const blockProps = useBlockProps({
|
className: 'video-cover-editor'
|
});
|
|
const onSelectPoster = (media) => {
|
setAttributes({
|
posterId: media.id,
|
posterUrl: media.url
|
});
|
};
|
|
const onSelectVideo = (media, isMobile = false) => {
|
const newSource = {
|
id: media.id,
|
url: media.url,
|
mime: media.mime
|
};
|
|
if (isMobile) {
|
// Check if this format already exists in mobile sources
|
const exists = mobileSources.some(s => s.mime === media.mime);
|
if (!exists) {
|
setAttributes({
|
mobileSources: [...mobileSources, newSource]
|
});
|
}
|
} else {
|
// Check if this format already exists in desktop sources
|
const exists = videoSources.some(s => s.mime === media.mime);
|
if (!exists) {
|
setAttributes({
|
videoSources: [...videoSources, newSource]
|
});
|
}
|
}
|
};
|
|
const removeVideoSource = (index, isMobile = false) => {
|
if (isMobile) {
|
const updated = [...mobileSources];
|
updated.splice(index, 1);
|
setAttributes({ mobileSources: updated });
|
} else {
|
const updated = [...videoSources];
|
updated.splice(index, 1);
|
setAttributes({ videoSources: updated });
|
}
|
};
|
|
const renderVideoSourceList = (sources, isMobile = false) => {
|
if (sources.length === 0) return null;
|
|
return (
|
<ul className="video-source-list">
|
{sources.map((source, index) => (
|
<li key={index} className="video-source-item">
|
<span className="video-source-mime">{source.mime}</span>
|
<Button
|
isDestructive
|
isSmall
|
onClick={() => removeVideoSource(index, isMobile)}
|
>
|
{__('Remove', 'jvb')}
|
</Button>
|
</li>
|
))}
|
</ul>
|
);
|
};
|
|
return (
|
<>
|
<InspectorControls>
|
<PanelBody title={__('Video Settings', 'jvb')} initialOpen={true}>
|
<BaseControl
|
label={__('Poster Image', 'jvb')}
|
help={__('Image shown while video loads', 'jvb')}
|
>
|
<MediaUploadCheck>
|
<MediaUpload
|
onSelect={onSelectPoster}
|
allowedTypes={['image']}
|
value={posterId}
|
render={({ open }) => (
|
<>
|
{posterUrl && (
|
<img
|
src={posterUrl}
|
alt={__('Poster preview', 'jvb')}
|
style={{ maxWidth: '100%', marginBottom: '10px' }}
|
/>
|
)}
|
<Button
|
onClick={open}
|
variant={posterUrl ? 'secondary' : 'primary'}
|
>
|
{posterUrl
|
? __('Change Poster', 'jvb')
|
: __('Select Poster', 'jvb')}
|
</Button>
|
{posterUrl && (
|
<Button
|
isDestructive
|
onClick={() => setAttributes({ posterId: 0, posterUrl: '' })}
|
style={{ marginLeft: '10px' }}
|
>
|
{__('Remove', 'jvb')}
|
</Button>
|
)}
|
</>
|
)}
|
/>
|
</MediaUploadCheck>
|
</BaseControl>
|
|
<BaseControl
|
label={__('Desktop Video Sources', 'jvb')}
|
help={__('Add multiple formats for better browser support', 'jvb')}
|
>
|
{renderVideoSourceList(videoSources, false)}
|
<MediaUploadCheck>
|
<MediaUpload
|
onSelect={(media) => onSelectVideo(media, false)}
|
allowedTypes={ALLOWED_VIDEO_TYPES}
|
render={({ open }) => (
|
<Button
|
onClick={open}
|
variant="secondary"
|
>
|
{__('Add Desktop Video', 'jvb')}
|
</Button>
|
)}
|
/>
|
</MediaUploadCheck>
|
</BaseControl>
|
|
<BaseControl
|
label={__('Mobile Video Sources (Optional)', 'jvb')}
|
help={__('Smaller videos for mobile devices', 'jvb')}
|
>
|
{renderVideoSourceList(mobileSources, true)}
|
<MediaUploadCheck>
|
<MediaUpload
|
onSelect={(media) => onSelectVideo(media, true)}
|
allowedTypes={ALLOWED_VIDEO_TYPES}
|
render={({ open }) => (
|
<Button
|
onClick={open}
|
variant="secondary"
|
>
|
{__('Add Mobile Video', 'jvb')}
|
</Button>
|
)}
|
/>
|
</MediaUploadCheck>
|
</BaseControl>
|
|
<ToggleControl
|
label={__('Fade Effect', 'jvb')}
|
help={__('Add fade class to video element', 'jvb')}
|
checked={fadeEffect}
|
onChange={(value) => setAttributes({ fadeEffect: value })}
|
/>
|
</PanelBody>
|
</InspectorControls>
|
|
<div {...blockProps}>
|
{posterUrl ? (
|
<div className="video-cover-preview">
|
<img src={posterUrl} alt={__('Video poster', 'jvb')} />
|
<div className="video-overlay">
|
<p>
|
{videoSources.length} {__('desktop source(s)', 'jvb')}
|
{mobileSources.length > 0 &&
|
`, ${mobileSources.length} ${__('mobile source(s)', 'jvb')}`
|
}
|
</p>
|
</div>
|
</div>
|
) : (
|
<div className="video-cover-placeholder">
|
<p>{__('Configure video sources in the sidebar →', 'jvb')}</p>
|
</div>
|
)}
|
</div>
|
<div className="inner-blocks">
|
<InnerBlocks />
|
</div>
|
</>
|
);
|
}
|