@@ -26,6 +26,7 @@ const Icons = {
2626
2727const VideoComparisonSlider : React . FC < { item : ComparisonItem } > = ( { item } ) => {
2828 const [ position , setPosition ] = useState ( 50 ) ;
29+ const [ isLoading , setIsLoading ] = useState ( true ) ;
2930 const containerRef = useRef < HTMLDivElement > ( null ) ;
3031 const videoLeftRef = useRef < HTMLVideoElement > ( null ) ;
3132 const videoRightRef = useRef < HTMLVideoElement > ( null ) ;
@@ -39,25 +40,49 @@ const VideoComparisonSlider: React.FC<{ item: ComparisonItem }> = ({ item }) =>
3940 setPosition ( percentage ) ;
4041 } ;
4142
43+ // Reset loading state when item changes
44+ useEffect ( ( ) => {
45+ setIsLoading ( true ) ;
46+ } , [ item . id ] ) ;
47+
4248 // Sync video playback - ensure both videos play together
4349 useEffect ( ( ) => {
4450 const leftVideo = videoLeftRef . current ;
4551 const rightVideo = videoRightRef . current ;
4652
4753 if ( leftVideo && rightVideo ) {
54+ // Reset videos when item changes
55+ leftVideo . load ( ) ;
56+ rightVideo . load ( ) ;
57+
4858 // Start playing both videos
4959 const playBoth = async ( ) => {
5060 try {
5161 await Promise . all ( [
5262 leftVideo . play ( ) ,
5363 rightVideo . play ( )
5464 ] ) ;
65+ setIsLoading ( false ) ;
5566 } catch ( error ) {
5667 console . log ( 'Autoplay prevented, user interaction needed' ) ;
68+ setIsLoading ( false ) ;
5769 }
5870 } ;
5971
60- playBoth ( ) ;
72+ // Wait for both videos to be ready
73+ const handleCanPlay = ( ) => {
74+ if ( leftVideo . readyState >= 3 && rightVideo . readyState >= 3 ) {
75+ playBoth ( ) ;
76+ }
77+ } ;
78+
79+ leftVideo . addEventListener ( 'canplay' , handleCanPlay ) ;
80+ rightVideo . addEventListener ( 'canplay' , handleCanPlay ) ;
81+
82+ // Try to play immediately if already loaded
83+ if ( leftVideo . readyState >= 3 && rightVideo . readyState >= 3 ) {
84+ playBoth ( ) ;
85+ }
6186
6287 const syncVideos = ( ) => {
6388 if ( Math . abs ( leftVideo . currentTime - rightVideo . currentTime ) > 0.1 ) {
@@ -73,12 +98,14 @@ const VideoComparisonSlider: React.FC<{ item: ComparisonItem }> = ({ item }) =>
7398 leftVideo . addEventListener ( 'timeupdate' , syncVideos ) ;
7499
75100 return ( ) => {
101+ leftVideo . removeEventListener ( 'canplay' , handleCanPlay ) ;
102+ rightVideo . removeEventListener ( 'canplay' , handleCanPlay ) ;
76103 leftVideo . removeEventListener ( 'play' , handlePlay ) ;
77104 leftVideo . removeEventListener ( 'pause' , handlePause ) ;
78105 leftVideo . removeEventListener ( 'timeupdate' , syncVideos ) ;
79106 } ;
80107 }
81- } , [ ] ) ;
108+ } , [ item . id ] ) ;
82109
83110 return (
84111 < div className = "mb-4" >
@@ -89,15 +116,23 @@ const VideoComparisonSlider: React.FC<{ item: ComparisonItem }> = ({ item }) =>
89116 onTouchMove = { handleMove }
90117 onClick = { handleMove }
91118 >
119+ { /* Loading indicator */ }
120+ { isLoading && (
121+ < div className = "absolute inset-0 flex items-center justify-center z-30 bg-black/50" >
122+ < div className = "w-10 h-10 border-4 border-white border-t-transparent rounded-full animate-spin" > </ div >
123+ </ div >
124+ ) }
125+
92126 { /* Right Video (Ours - Background) */ }
93127 < video
128+ key = { `ours-${ item . id } ` }
94129 ref = { videoRightRef }
95130 src = { item . videoOurs }
96131 className = "absolute inset-0 w-full h-full object-cover"
97132 loop
98133 muted
99134 playsInline
100- autoPlay
135+ preload = "auto"
101136 />
102137
103138 { /* Left Video (Baseline - Clipped overlay) */ }
@@ -106,13 +141,14 @@ const VideoComparisonSlider: React.FC<{ item: ComparisonItem }> = ({ item }) =>
106141 style = { { clipPath : `inset(0 ${ 100 - position } % 0 0)` } }
107142 >
108143 < video
144+ key = { `baseline-${ item . id } ` }
109145 ref = { videoLeftRef }
110146 src = { item . videoBaseline }
111147 className = "absolute inset-0 w-full h-full object-cover"
112148 loop
113149 muted
114150 playsInline
115- autoPlay
151+ preload = "auto"
116152 />
117153 </ div >
118154
0 commit comments