@@ -4,8 +4,10 @@ import {
44 type ComponentProps ,
55 useEffect ,
66 useId ,
7+ useContext ,
78} from "react" ;
89import type { Atom } from "nanostores" ;
10+ import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime" ;
911
1012export const defaultTag = "video" ;
1113
@@ -27,116 +29,126 @@ export const Video = forwardRef<
2729 $visible ?: Atom < boolean > ;
2830 $timeline ?: boolean ;
2931 }
30- > ( ( { $progress, $visible, $timeline, children, ...props } , ref ) => {
31- const id = useId ( ) ;
32- const videoIdProps = {
33- [ videoIdAttribute ] : id ,
34- } ;
35-
36- useEffect ( ( ) => {
37- if ( $progress === undefined ) {
38- return ;
39- }
40-
41- if ( $visible === undefined ) {
42- return ;
43- }
44-
45- const video = document . querySelector ( `[${ videoIdAttribute } ="${ id } "]` ) ;
46-
47- if ( video === null ) {
48- return ;
49- }
50-
51- if ( false === video instanceof HTMLVideoElement ) {
52- return ;
53- }
54-
55- // Safari IOS does not seek video without play called at least once
56- // this is in case autoPlay is not set
57- video . play ( ) . catch ( ( ) => {
58- /**/
59- } ) ;
60- video . pause ( ) ;
61-
62- if ( $timeline ) {
63- return $progress . subscribe ( ( progress ) => {
64- if ( video . readyState < READY_STATE . HAVE_METADATA ) {
65- return ;
66- }
32+ > (
33+ (
34+ { $progress, $visible, $timeline, children, src : srcProp , ...props } ,
35+ ref
36+ ) => {
37+ const id = useId ( ) ;
38+ const videoIdProps = {
39+ [ videoIdAttribute ] : id ,
40+ } ;
41+ const { assetBaseUrl } = useContext ( ReactSdkContext ) ;
6742
68- if ( ! video . paused ) {
69- video . pause ( ) ;
70- }
43+ const src = srcProp ?. startsWith ( assetBaseUrl )
44+ ? `/cgi/ video/ ${ srcProp . slice ( assetBaseUrl . length ) } `
45+ : srcProp ;
7146
72- if ( video . seeking ) {
73- return ;
74- }
47+ useEffect ( ( ) => {
48+ if ( $progress === undefined ) {
49+ return ;
50+ }
7551
76- let duration = video . duration ;
52+ if ( $visible === undefined ) {
53+ return ;
54+ }
7755
78- if ( Number . isNaN ( duration ) ) {
79- return ;
80- }
56+ const video = document . querySelector ( `[${ videoIdAttribute } ="${ id } "]` ) ;
8157
82- if ( ! Number . isFinite ( duration ) ) {
83- // Set to 60s on streaming videos
84- duration = 60 ;
85- }
58+ if ( video === null ) {
59+ return ;
60+ }
61+
62+ if ( false === video instanceof HTMLVideoElement ) {
63+ return ;
64+ }
8665
87- video . currentTime = ( progress ?? 0 ) * duration ;
66+ // Safari IOS does not seek video without play called at least once
67+ // this is in case autoPlay is not set
68+ video . play ( ) . catch ( ( ) => {
69+ /**/
8870 } ) ;
89- }
71+ video . pause ( ) ;
72+
73+ if ( $timeline ) {
74+ return $progress . subscribe ( ( progress ) => {
75+ if ( video . readyState < READY_STATE . HAVE_METADATA ) {
76+ return ;
77+ }
78+
79+ if ( ! video . paused ) {
80+ video . pause ( ) ;
81+ }
82+
83+ if ( video . seeking ) {
84+ return ;
85+ }
86+
87+ let duration = video . duration ;
9088
91- let isPlaying = false ;
92- let isVisible = false ;
89+ if ( Number . isNaN ( duration ) ) {
90+ return ;
91+ }
9392
94- const unsubscribeVisible = $visible . subscribe ( ( visible ) => {
95- isVisible = visible ;
93+ if ( ! Number . isFinite ( duration ) ) {
94+ // Set to 60s on streaming videos
95+ duration = 60 ;
96+ }
9697
97- // Seek video only if it's invisible to avoid jumps
98- if ( isVisible === false && isPlaying === false && ! video . loop ) {
99- video . currentTime = 0 ;
98+ video . currentTime = ( progress ?? 0 ) * duration ;
99+ } ) ;
100100 }
101- } ) ;
102101
103- const unsubscribeProgress = $progress . subscribe ( ( progress ) => {
104- if (
105- isPlaying &&
106- ( progress === undefined || progress === 0 || progress === 1 )
107- ) {
108- isPlaying = false ;
109- video . pause ( ) ;
102+ let isPlaying = false ;
103+ let isVisible = false ;
104+
105+ const unsubscribeVisible = $visible . subscribe ( ( visible ) => {
106+ isVisible = visible ;
110107
111108 // Seek video only if it's invisible to avoid jumps
112109 if ( isVisible === false && isPlaying === false && ! video . loop ) {
113110 video . currentTime = 0 ;
114111 }
112+ } ) ;
115113
116- return ;
117- }
114+ const unsubscribeProgress = $progress . subscribe ( ( progress ) => {
115+ if (
116+ isPlaying &&
117+ ( progress === undefined || progress === 0 || progress === 1 )
118+ ) {
119+ isPlaying = false ;
120+ video . pause ( ) ;
121+
122+ // Seek video only if it's invisible to avoid jumps
123+ if ( isVisible === false && isPlaying === false && ! video . loop ) {
124+ video . currentTime = 0 ;
125+ }
118126
119- if ( ! isPlaying ) {
120- isPlaying = true ;
121- if ( ! video . ended ) {
122- video . play ( ) . catch ( ( ) => {
123- /**/
124- } ) ;
127+ return ;
125128 }
126- }
127- } ) ;
128129
129- return ( ) => {
130- unsubscribeProgress ( ) ;
131- unsubscribeVisible ( ) ;
132- } ;
133- } , [ $progress , $timeline , $visible , id ] ) ;
134-
135- return (
136- < video { ...props } { ...videoIdProps } ref = { ref } >
137- { children }
138- </ video >
139- ) ;
140- } ) ;
130+ if ( ! isPlaying ) {
131+ isPlaying = true ;
132+ if ( ! video . ended ) {
133+ video . play ( ) . catch ( ( ) => {
134+ /**/
135+ } ) ;
136+ }
137+ }
138+ } ) ;
139+
140+ return ( ) => {
141+ unsubscribeProgress ( ) ;
142+ unsubscribeVisible ( ) ;
143+ } ;
144+ } , [ $progress , $timeline , $visible , id ] ) ;
145+
146+ return (
147+ < video src = { src } { ...props } { ...videoIdProps } ref = { ref } >
148+ { children }
149+ </ video >
150+ ) ;
151+ }
152+ ) ;
141153
142154Video . displayName = "Video" ;
0 commit comments