Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions locales/de/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -2570,6 +2570,16 @@ msgstr ""
msgid "gallery_close_preview"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine di copertina
msgid "gallery_preview_image"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine mostrata in anteprima al posto della copertina di default del video.
msgid "gallery_preview_image_description"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Titolo del video
msgid "gallery_video_title"
Expand Down
10 changes: 10 additions & 0 deletions locales/en/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,16 @@ msgstr "Image gallery"
msgid "gallery_close_preview"
msgstr "Close preview"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine di copertina
msgid "gallery_preview_image"
msgstr "Gallery preview image"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine mostrata in anteprima al posto della copertina di default del video.
msgid "gallery_preview_image_description"
msgstr "Image shown in preview instead of the default video cover."

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Titolo del video
msgid "gallery_video_title"
Expand Down
10 changes: 10 additions & 0 deletions locales/es/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,16 @@ msgstr "Galería de imágenes"
msgid "gallery_close_preview"
msgstr "Cerrar vista previa"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine di copertina
msgid "gallery_preview_image"
msgstr "Imagen de portada"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine mostrata in anteprima al posto della copertina di default del video.
msgid "gallery_preview_image_description"
msgstr "Imagen mostrada en la vista previa en lugar de la portada por defecto del video."

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Titolo del video
msgid "gallery_video_title"
Expand Down
10 changes: 10 additions & 0 deletions locales/fr/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -2572,6 +2572,16 @@ msgstr "Galerie d'images"
msgid "gallery_close_preview"
msgstr "Fermer l'aperçu de l'image"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine di copertina
msgid "gallery_preview_image"
msgstr "Image de couverture"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine mostrata in anteprima al posto della copertina di default del video.
msgid "gallery_preview_image_description"
msgstr "Image mostrée dans l'aperçu au lieu de la couverture par défaut de la vidéo."

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Titolo del video
msgid "gallery_video_title"
Expand Down
10 changes: 10 additions & 0 deletions locales/it/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,16 @@ msgstr "Galleria di immagini"
msgid "gallery_close_preview"
msgstr "Chiudi l'anteprima"

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine di copertina
msgid "gallery_preview_image"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine mostrata in anteprima al posto della copertina di default del video.
msgid "gallery_preview_image_description"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Titolo del video
msgid "gallery_video_title"
Expand Down
12 changes: 11 additions & 1 deletion locales/volto.pot
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Plone\n"
"POT-Creation-Date: 2026-05-26T07:34:11.737Z\n"
"POT-Creation-Date: 2026-06-17T10:08:22.559Z\n"
"Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -2557,6 +2557,16 @@ msgstr ""
msgid "gallery_close_preview"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine di copertina
msgid "gallery_preview_image"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Immagine mostrata in anteprima al posto della copertina di default del video.
msgid "gallery_preview_image_description"
msgstr ""

#: components/ItaliaTheme/Blocks/VideoGallery/Sidebar
# defaultMessage: Titolo del video
msgid "gallery_video_title"
Expand Down
16 changes: 10 additions & 6 deletions src/components/ItaliaTheme/Blocks/VideoGallery/Block/ViewBlock.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { Embed } from 'semantic-ui-react';
import { isInternalURL, getParentUrl } from '@plone/volto/helpers';
import { ConditionalEmbed } from 'volto-gdpr-privacy';
import { FontAwesomeIcon } from 'design-comuni-plone-theme/components/ItaliaTheme';
import { videoUrlHelper } from 'design-comuni-plone-theme/helpers';
import {
videoUrlHelper,
useVideoEmbedFocus,
} from 'design-comuni-plone-theme/helpers';
import { useIntl, defineMessages } from 'react-intl';
import config from '@plone/volto/registry';

Expand Down Expand Up @@ -64,11 +67,11 @@ const ViewBlock = ({ data, index, isEditMode = false }) => {
}
}

const ref = React.createRef();
const { wrapperRef, active, activate } = useVideoEmbedFocus();
const onKeyDown = (e) => {
if (e.nativeEvent.keyCode === 13) {
//Enter
ref.current.handleClick();
activate();
}
};

Expand All @@ -83,18 +86,18 @@ const ViewBlock = ({ data, index, isEditMode = false }) => {
<FontAwesomeIcon icon={['fas', 'play']} />
</div>
),
defaultActive: false,
active: active,
autoplay: false,
aspectRatio: '16:9',
placeholder: placeholder,
tabIndex: 0,
onKeyPress: onKeyDown,
ref: ref,
onClick: activate,
'aria-label': intl.formatMessage(messages.loadVideo),
};

return data?.url ? (
<div className="video-wrapper">
<div className="video-wrapper" ref={wrapperRef}>
<ConditionalEmbed url={!isEditMode ? data.url : null}>
{data.url.match('youtu') ? (
<>
Expand Down Expand Up @@ -127,6 +130,7 @@ const ViewBlock = ({ data, index, isEditMode = false }) => {
: data.url
}
controls
poster={placeholder}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

occhio che placeholder può essere null

type="video/mp4"
/>
) : data.allowExternals ? (
Expand Down
42 changes: 42 additions & 0 deletions src/components/ItaliaTheme/Blocks/VideoGallery/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { FormattedMessage, injectIntl } from 'react-intl';
import { Icon, TextWidget, CheckboxWidget } from '@plone/volto/components';
import upSVG from '@plone/volto/icons/up-key.svg';
import downSVG from '@plone/volto/icons/down-key.svg';
import clearSVG from '@plone/volto/icons/clear.svg';
import navTreeSVG from '@plone/volto/icons/nav.svg';
import { defineMessages, useIntl } from 'react-intl';

const messages = defineMessages({
Expand All @@ -30,6 +32,15 @@ const messages = defineMessages({
defaultMessage:
"Non viene mostrato. Serve al redattore per identificare meglio il video all'interno della gallery.",
},
preview_image: {
id: 'gallery_preview_image',
defaultMessage: 'Immagine di copertina',
},
preview_image_description: {
id: 'gallery_preview_image_description',
defaultMessage:
'Immagine mostrata in anteprima al posto della copertina di default del video.',
},
allowExternals: {
id: 'Allow Externals',
defaultMessage: 'Allow Externals',
Expand Down Expand Up @@ -150,6 +161,37 @@ const Sidebar = ({
});
}}
/>

<TextWidget
id="preview_image"
title={intl.formatMessage(messages.preview_image)}
description={intl.formatMessage(
messages.preview_image_description,
)}
required={false}
value={subblock.preview_image?.split('/').slice(-1)[0]}
icon={subblock.preview_image ? clearSVG : navTreeSVG}
iconAction={
subblock.preview_image
? () => {
onChangeSubBlock(index, {
...subblock,
preview_image: '',
});
}
: () =>
openObjectBrowser({
mode: 'image',
onSelectItem: (url) => {
onChangeSubBlock(index, {
...subblock,
preview_image: url,
});
},
})
}
onChange={() => {}}
/>
</Accordion.Content>
</div>
);
Expand Down
16 changes: 11 additions & 5 deletions src/components/ItaliaTheme/View/Commons/EmbeddedVideo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { ConditionalEmbed } from 'volto-gdpr-privacy';
import { Embed } from 'semantic-ui-react';
import { FontAwesomeIcon } from 'design-comuni-plone-theme/components/ItaliaTheme';
import { useVideoEmbedFocus } from 'design-comuni-plone-theme/helpers';
import { defineMessages, injectIntl, useIntl } from 'react-intl';

const messages = defineMessages({
Expand Down Expand Up @@ -34,11 +35,11 @@ const EmbeddedVideo = ({ video_url, title, id }) => {
? video_url.match(/^.*\.be\/(.*)/)?.[1]
: video_url.match(/^.*\?v=(.*)$/)?.[1];

const ref = React.createRef();
const { wrapperRef, active, activate } = useVideoEmbedFocus();
const onKeyDown = (e) => {
if (e.nativeEvent.keyCode === 13) {
//Enter
ref.current.handleClick();
activate();
}
};

Expand All @@ -53,18 +54,23 @@ const EmbeddedVideo = ({ video_url, title, id }) => {
<FontAwesomeIcon icon={['fas', 'play']} />
</div>
),
defaultActive: false,
active: active,
autoplay: false,
aspectRatio: '16:9',
placeholder: 'https://img.youtube.com/vi/' + video_id + '/hqdefault.jpg',
tabIndex: 0,
onKeyPress: onKeyDown,
ref: ref,
onClick: activate,
'aria-label': intl.formatMessage(messages.loadVideo),
};

return video_url ? (
<div key={id} className="embedded-video my4" id={`embedded-video-${id}`}>
<div
key={id}
ref={wrapperRef}
className="embedded-video my4"
id={`embedded-video-${id}`}
>
<ConditionalEmbed url={video_url} key={'embedvideo' + id}>
<Embed
id={video_id}
Expand Down
15 changes: 9 additions & 6 deletions src/customizations/volto/components/manage/Blocks/Video/Body.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
*/

import React from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { Embed, Message } from 'semantic-ui-react';
import cx from 'classnames';
import { isInternalURL, getParentUrl } from '@plone/volto/helpers';
import { videoUrlHelper } from 'design-comuni-plone-theme/helpers';
import {
videoUrlHelper,
useVideoEmbedFocus,
} from 'design-comuni-plone-theme/helpers';
import { ConditionalEmbed } from 'volto-gdpr-privacy';
import { FontAwesomeIcon } from 'design-comuni-plone-theme/components/ItaliaTheme';
import config from '@plone/volto/registry';
Expand Down Expand Up @@ -48,11 +50,11 @@ const Body = ({ data, isEditMode }) => {
placeholder = computedPlaceholder;
}
}
const ref = React.createRef();
const { wrapperRef, active, activate } = useVideoEmbedFocus();
const onKeyDown = (e) => {
if (e.nativeEvent.keyCode === 13) {
//Enter
ref.current.handleClick();
activate();
}
};
const embedSettings = {
Expand All @@ -67,12 +69,12 @@ const Body = ({ data, isEditMode }) => {
<FontAwesomeIcon icon={['fas', 'play']} />
</div>
),
defaultActive: false,
active: active,
autoplay: false,
aspectRatio: '16:9',
tabIndex: 0,
onKeyPress: onKeyDown,
ref: ref,
onClick: activate,
};

let apiPath = config.settings.apiPath;
Expand All @@ -84,6 +86,7 @@ const Body = ({ data, isEditMode }) => {
<>
{data.url && (
<div
ref={wrapperRef}
className={cx('video-inner', {
'full-width': data.align === 'full',
})}
Expand Down
1 change: 1 addition & 0 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export {
videoUrlHelper,
checkIfValidVideoLink,
} from 'design-comuni-plone-theme/helpers/videoUrlHelper';
export { useVideoEmbedFocus } from 'design-comuni-plone-theme/helpers/videoEmbedFocus';
export {
blockIsNotEmptyPlaceholder,
SSRRenderHtml,
Expand Down
39 changes: 39 additions & 0 deletions src/helpers/videoEmbedFocus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useState, useRef, useEffect } from 'react';

/**
* Manage the activation of a semantic-ui Embed video (a fake play button shown
* over a preview/cover image) and move focus to the real video iframe as soon
* as it is rendered.
*
* When a cover image is set, the only focusable element is the fake play button;
* once activated, semantic-ui hides the placeholder and the play icon
* (display: none), which would otherwise drop focus on the <body>. Screen
* reader and keyboard users would then lose the context and not realize a video
* appeared. Controlling the `active` state lets us move focus into the freshly
* mounted iframe instead.
*
* Usage:
* const { wrapperRef, active, activate } = useVideoEmbedFocus();
* <div ref={wrapperRef}>
* <Embed active={active} onClick={activate} ... />
* </div>
*/
export const useVideoEmbedFocus = () => {
const wrapperRef = useRef(null);
const [active, setActive] = useState(false);

useEffect(() => {
if (!active || !wrapperRef.current) {
return;
}
const iframe = wrapperRef.current.querySelector('iframe');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non per forza c'è un tag <iframe>
ci può essere anche un tag

if (iframe) {
iframe.setAttribute('tabindex', '0');
iframe.focus();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

così fa solo il focus sull'iframe sempre, e non lo fa piu sul bottone play dell'embed di youtube?

}
}, [active]);

const activate = () => setActive(true);

return { wrapperRef, active, activate };
};
Loading
Loading