22/* eslint-disable jsx-a11y/click-events-have-key-events */
33// TODO fix in https://github.com/gravity-ui/page-constructor/issues/965
44
5- import React , { useCallback , useEffect , useRef , useState } from 'react' ;
5+ import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
66
77import { PlayFill } from '@gravity-ui/icons' ;
88import { Icon } from '@gravity-ui/uikit' ;
@@ -28,10 +28,13 @@ export const AUTOPLAY_ATTRIBUTES = {
2828 autoplay : 1 ,
2929 mute : 1 ,
3030} ;
31+ const NO_AUTOPLAY_ATTRIBUTES = {
32+ autoplay : 0 ,
33+ } ;
3134
3235const b = block ( 'VideoBlock' ) ;
3336
34- function getVideoSrc ( stream ?: string , record ?: string ) {
37+ function getYoutubeVideoSrc ( stream ?: string , record ?: string ) {
3538 if ( ! stream && ! record ) {
3639 return null ;
3740 }
@@ -57,6 +60,7 @@ export interface VideoBlockProps extends AnalyticsEventsBase {
5760 id ?: string ;
5861 stream ?: string ;
5962 record ?: string ;
63+ videoIframe ?: string ;
6064 attributes ?: Record < string , string > ;
6165 className ?: string ;
6266 previewImg ?: string ;
@@ -71,6 +75,7 @@ const VideoBlock = (props: VideoBlockProps) => {
7175 const {
7276 stream,
7377 record,
78+ videoIframe,
7479 attributes,
7580 className,
7681 id,
@@ -84,25 +89,29 @@ const VideoBlock = (props: VideoBlockProps) => {
8489 } = props ;
8590 const handleAnalytics = useAnalytics ( DefaultEventNames . VideoPreview ) ;
8691
87- const src = getVideoSrc ( stream , record ) ;
92+ const src = videoIframe ? videoIframe : getYoutubeVideoSrc ( stream , record ) ;
8893 const ref = useRef < HTMLDivElement > ( null ) ;
89- const iframeRef = useRef < HTMLIFrameElement > ( ) ;
9094 const [ hidePreview , setHidePreview ] = useState ( false ) ;
91- const norender = ( ! stream && ! record ) || ! src ;
9295 const [ currentHeight , setCurrentHeight ] = useState ( height || undefined ) ;
93- const fullId = id || uuidv4 ( ) ;
96+ const fullId = useMemo ( ( ) => id || uuidv4 ( ) , [ id ] ) ;
97+
98+ const [ isPlaying , setIsPlaying ] = useState ( ! previewImg ) ;
99+
100+ const iframeSrc =
101+ src && isPlaying
102+ ? `${ src } ?${ getPageSearchParams ( {
103+ ...( attributes || { } ) ,
104+ ...( autoplay ? AUTOPLAY_ATTRIBUTES : NO_AUTOPLAY_ATTRIBUTES ) ,
105+ } ) } `
106+ : undefined ;
107+
94108 const onPreviewClick = useCallback ( ( ) => {
95109 handleAnalytics ( analyticsEvents ) ;
96110
97- if ( iframeRef . current ) {
98- iframeRef . current . src = `${ src } ?${ getPageSearchParams ( {
99- ...AUTOPLAY_ATTRIBUTES ,
100- ...( attributes || { } ) ,
101- } ) } `;
102- }
111+ setIsPlaying ( true ) ;
103112
104113 setTimeout ( ( ) => setHidePreview ( true ) , AUTOPLAY_DELAY ) ;
105- } , [ handleAnalytics , analyticsEvents , src , attributes ] ) ;
114+ } , [ handleAnalytics , analyticsEvents ] ) ;
106115
107116 useEffect ( ( ) => {
108117 const updateSize = debounce ( ( ) => {
@@ -118,44 +127,33 @@ const VideoBlock = (props: VideoBlockProps) => {
118127 } ;
119128 } , [ height ] ) ;
120129
121- useEffect ( ( ) => {
122- if ( norender ) {
123- return ;
124- }
125-
126- if ( ref . current && ! iframeRef . current ) {
127- const iframe = document . createElement ( 'iframe' ) ;
128- iframe . id = fullId ;
129-
130- if ( ! previewImg ) {
131- iframe . src = `${ src } ?${ getPageSearchParams ( {
132- ...( attributes || { } ) ,
133- ...( autoplay ? AUTOPLAY_ATTRIBUTES : { } ) ,
134- } ) } `;
135- }
136-
137- iframe . width = '100%' ;
138- iframe . height = '100%' ;
139- iframe . title = i18n ( 'iframe-title' ) ;
140- iframe . frameBorder = '0' ;
141- iframe . setAttribute ( 'allowfullscreen' , 'true' ) ;
142- iframe . setAttribute ( 'allow' , 'autoplay' ) ;
143- iframe . setAttribute ( 'loading' , 'lazy' ) ;
144- ref . current . appendChild ( iframe ) ;
145- iframeRef . current = iframe ;
146- }
147- } , [ stream , record , norender , src , fullId , attributes , iframeRef , previewImg , autoplay ] ) ;
130+ const iframeContent = useMemo ( ( ) => {
131+ return (
132+ < iframe
133+ id = { fullId }
134+ src = { iframeSrc }
135+ width = "100%"
136+ height = "100%"
137+ title = { i18n ( 'iframe-title' ) }
138+ frameBorder = "0"
139+ allowFullScreen = { true }
140+ allow = "autoplay; fullscreen; encrypted-media; accelerometer; gyroscope; picture-in-picture; clipboard-write; web-share; screen-wake-lock"
141+ loading = "lazy"
142+ />
143+ ) ;
144+ } , [ fullId , iframeSrc ] ) ;
148145
149146 useEffect ( ( ) => {
150147 setHidePreview ( false ) ;
151- } , [ src , setHidePreview ] ) ;
148+ } , [ src ] ) ;
152149
153- if ( norender ) {
150+ if ( ! src ) {
154151 return null ;
155152 }
156153
157154 return (
158- < div className = { b ( null , className ) } ref = { ref } style = { { height : currentHeight } } >
155+ < div className = { b ( null , className ) } style = { { height : currentHeight } } ref = { ref } >
156+ { iframeContent }
159157 { previewImg && ! hidePreview && ! fullscreen && (
160158 < div className = { b ( 'preview' ) } onClick = { onPreviewClick } >
161159 < Image
0 commit comments