diff --git a/.storybook/stories/documentation/Types.mdx b/.storybook/stories/documentation/Types.mdx index ab47d0472..602acb01f 100644 --- a/.storybook/stories/documentation/Types.mdx +++ b/.storybook/stories/documentation/Types.mdx @@ -55,6 +55,7 @@ import { Meta } from '@storybook/blocks'; - `parallax?: boolean` — Enable/disable the parallax effect - [`video?: Video` — Video](#Video) - `youtube?: url` — Link to a video on YouTube +- `videoIframe?: url` — Link to a video iframe - `height?: number` — Block height - `previewImg?: string` - `dataLens?: string |` [DataLens](#DataLens) diff --git a/src/components/Media/Media.tsx b/src/components/Media/Media.tsx index 2418e5140..601000468 100644 --- a/src/components/Media/Media.tsx +++ b/src/components/Media/Media.tsx @@ -2,7 +2,7 @@ import React, {ReactElement, useMemo, useState} from 'react'; import {MediaProps, QAProps} from '../../models'; import {block, getQaAttrubutes} from '../../utils'; -import YoutubeBlock from '../VideoBlock/VideoBlock'; +import IframeVideoBlock from '../VideoBlock/VideoBlock'; import DataLens from './DataLens/DataLens'; import FullscreenVideo from './FullscreenVideo/FullscreenVideo'; @@ -26,6 +26,7 @@ export const Media = (props: MediaAllProps) => { image, video, youtube, + videoIframe, dataLens, color, height, @@ -99,11 +100,12 @@ export const Media = (props: MediaAllProps) => { } } - if (youtube) { + if (youtube || videoIframe) { result = ( - { }, [ image, video, + videoIframe, youtube, dataLens, iframe, diff --git a/src/components/VideoBlock/VideoBlock.tsx b/src/components/VideoBlock/VideoBlock.tsx index 8664e0f9c..f51a08422 100644 --- a/src/components/VideoBlock/VideoBlock.tsx +++ b/src/components/VideoBlock/VideoBlock.tsx @@ -2,7 +2,7 @@ /* eslint-disable jsx-a11y/click-events-have-key-events */ // TODO fix in https://github.com/gravity-ui/page-constructor/issues/965 -import React, {useCallback, useEffect, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {PlayFill} from '@gravity-ui/icons'; import {Icon} from '@gravity-ui/uikit'; @@ -28,10 +28,13 @@ export const AUTOPLAY_ATTRIBUTES = { autoplay: 1, mute: 1, }; +const NO_AUTOPLAY_ATTRIBUTES = { + autoplay: 0, +}; const b = block('VideoBlock'); -function getVideoSrc(stream?: string, record?: string) { +function getYoutubeVideoSrc(stream?: string, record?: string) { if (!stream && !record) { return null; } @@ -57,6 +60,7 @@ export interface VideoBlockProps extends AnalyticsEventsBase { id?: string; stream?: string; record?: string; + videoIframe?: string; attributes?: Record; className?: string; previewImg?: string; @@ -71,6 +75,7 @@ const VideoBlock = (props: VideoBlockProps) => { const { stream, record, + videoIframe, attributes, className, id, @@ -84,25 +89,29 @@ const VideoBlock = (props: VideoBlockProps) => { } = props; const handleAnalytics = useAnalytics(DefaultEventNames.VideoPreview); - const src = getVideoSrc(stream, record); + const src = videoIframe ? videoIframe : getYoutubeVideoSrc(stream, record); const ref = useRef(null); - const iframeRef = useRef(); const [hidePreview, setHidePreview] = useState(false); - const norender = (!stream && !record) || !src; const [currentHeight, setCurrentHeight] = useState(height || undefined); - const fullId = id || uuidv4(); + const fullId = useMemo(() => id || uuidv4(), [id]); + + const [isPlaying, setIsPlaying] = useState(!previewImg); + + const iframeSrc = + src && isPlaying + ? `${src}?${getPageSearchParams({ + ...(attributes || {}), + ...(autoplay ? AUTOPLAY_ATTRIBUTES : NO_AUTOPLAY_ATTRIBUTES), + })}` + : undefined; + const onPreviewClick = useCallback(() => { handleAnalytics(analyticsEvents); - if (iframeRef.current) { - iframeRef.current.src = `${src}?${getPageSearchParams({ - ...AUTOPLAY_ATTRIBUTES, - ...(attributes || {}), - })}`; - } + setIsPlaying(true); setTimeout(() => setHidePreview(true), AUTOPLAY_DELAY); - }, [handleAnalytics, analyticsEvents, src, attributes]); + }, [handleAnalytics, analyticsEvents]); useEffect(() => { const updateSize = debounce(() => { @@ -118,44 +127,33 @@ const VideoBlock = (props: VideoBlockProps) => { }; }, [height]); - useEffect(() => { - if (norender) { - return; - } - - if (ref.current && !iframeRef.current) { - const iframe = document.createElement('iframe'); - iframe.id = fullId; - - if (!previewImg) { - iframe.src = `${src}?${getPageSearchParams({ - ...(attributes || {}), - ...(autoplay ? AUTOPLAY_ATTRIBUTES : {}), - })}`; - } - - iframe.width = '100%'; - iframe.height = '100%'; - iframe.title = i18n('iframe-title'); - iframe.frameBorder = '0'; - iframe.setAttribute('allowfullscreen', 'true'); - iframe.setAttribute('allow', 'autoplay'); - iframe.setAttribute('loading', 'lazy'); - ref.current.appendChild(iframe); - iframeRef.current = iframe; - } - }, [stream, record, norender, src, fullId, attributes, iframeRef, previewImg, autoplay]); + const iframeContent = useMemo(() => { + return ( +