8
8
submitComponentEvent ,
9
9
} from '../client/ophan/ophan' ;
10
10
import { getZIndex } from '../lib/getZIndex' ;
11
+ import { generateImageURL } from '../lib/image' ;
11
12
import { useIsInView } from '../lib/useIsInView' ;
12
13
import { useShouldAdapt } from '../lib/useShouldAdapt' ;
13
14
import type { CustomPlayEventDetail } from '../lib/video' ;
@@ -60,13 +61,24 @@ const dispatchOphanAttentionEvent = (
60
61
document . dispatchEvent ( event ) ;
61
62
} ;
62
63
64
+ const getOptimisedPosterImage = ( mainImage : string ) : string => {
65
+ const resolution = window . devicePixelRatio >= 2 ? 'high' : 'low' ;
66
+
67
+ return generateImageURL ( {
68
+ mainImage,
69
+ imageWidth : 940 , // The widest a looping video can be: Flexible special, giga-boosted
70
+ resolution,
71
+ aspectRatio : '5:4' ,
72
+ } ) ;
73
+ } ;
74
+
63
75
type Props = {
64
76
src : string ;
65
77
atomId : string ;
66
78
uniqueId : string ;
67
- width : number ;
68
79
height : number ;
69
- image : string ;
80
+ width : number ;
81
+ posterImage : string ;
70
82
fallbackImage : CardPictureProps [ 'mainImage' ] ;
71
83
fallbackImageSize : CardPictureProps [ 'imageSize' ] ;
72
84
fallbackImageLoading : CardPictureProps [ 'loading' ] ;
@@ -78,9 +90,9 @@ export const LoopVideo = ({
78
90
src,
79
91
atomId,
80
92
uniqueId,
81
- width,
82
93
height,
83
- image,
94
+ width,
95
+ posterImage,
84
96
fallbackImage,
85
97
fallbackImageSize,
86
98
fallbackImageLoading,
@@ -94,9 +106,7 @@ export const LoopVideo = ({
94
106
const [ isMuted , setIsMuted ] = useState ( true ) ;
95
107
const [ showPlayIcon , setShowPlayIcon ] = useState ( false ) ;
96
108
const [ preloadPartialData , setPreloadPartialData ] = useState ( false ) ;
97
- const [ posterImage , setPosterImage ] = useState < string | undefined > (
98
- undefined ,
99
- ) ;
109
+ const [ showPosterImage , setShowPosterImage ] = useState < boolean > ( false ) ;
100
110
const [ currentTime , setCurrentTime ] = useState ( 0 ) ;
101
111
const [ playerState , setPlayerState ] =
102
112
useState < ( typeof PLAYER_STATES ) [ number ] > ( 'NOT_STARTED' ) ;
@@ -135,11 +145,11 @@ export const LoopVideo = ({
135
145
. catch ( ( error : Error ) => {
136
146
// Autoplay failed
137
147
logAndReportError ( src , error ) ;
138
- setPosterImage ( image ) ;
148
+ setShowPosterImage ( true ) ;
139
149
setPlayerState ( 'PAUSED_BY_BROWSER' ) ;
140
150
} ) ;
141
151
}
142
- } , [ src , image ] ) ;
152
+ } , [ src ] ) ;
143
153
144
154
const pauseVideo = (
145
155
reason : Extract <
@@ -381,9 +391,9 @@ export const LoopVideo = ({
381
391
isAutoplayAllowed === false ||
382
392
( isInView === false && ! hasBeenInView )
383
393
) {
384
- setPosterImage ( image ) ;
394
+ setShowPosterImage ( true ) ;
385
395
}
386
- } , [ isAutoplayAllowed , isInView , hasBeenInView , image ] ) ;
396
+ } , [ isAutoplayAllowed , isInView , hasBeenInView ] ) ;
387
397
388
398
/**
389
399
* We almost always want to preload some of the video data. If a user has prefers-reduced-motion
@@ -506,6 +516,10 @@ export const LoopVideo = ({
506
516
507
517
const AudioIcon = isMuted ? SvgAudioMute : SvgAudio ;
508
518
519
+ const optimisedPosterImage = showPosterImage
520
+ ? getOptimisedPosterImage ( posterImage )
521
+ : undefined ;
522
+
509
523
return (
510
524
< figure
511
525
ref = { setNode }
@@ -519,7 +533,7 @@ export const LoopVideo = ({
519
533
uniqueId = { uniqueId }
520
534
width = { width }
521
535
height = { height }
522
- posterImage = { posterImage }
536
+ posterImage = { optimisedPosterImage }
523
537
FallbackImageComponent = { FallbackImageComponent }
524
538
currentTime = { currentTime }
525
539
setCurrentTime = { setCurrentTime }
0 commit comments