@@ -6,7 +6,7 @@ import type {RefObject} from 'react';
66import React , { useCallback , useEffect , useLayoutEffect , useMemo , useRef , useState } from 'react' ;
77import type { GestureResponderEvent } from 'react-native' ;
88import { View } from 'react-native' ;
9- import { useAnimatedStyle , useSharedValue , withTiming } from 'react-native-reanimated' ;
9+ import { cancelAnimation , useAnimatedStyle , useSharedValue , withTiming } from 'react-native-reanimated' ;
1010import { scheduleOnRN } from 'react-native-worklets' ;
1111import AttachmentOfflineIndicator from '@components/AttachmentOfflineIndicator' ;
1212import Hoverable from '@components/Hoverable' ;
@@ -74,6 +74,8 @@ function BaseVideoPlayer({
7474 const controlsAnimatedStyle = useAnimatedStyle ( ( ) => ( {
7575 opacity : controlsOpacity . get ( ) ,
7676 } ) ) ;
77+ const [ isSeeking , setIsSeeking ] = useState ( false ) ;
78+ const allowSharedAutoPlayRef = useRef ( true ) ;
7779
7880 /* eslint-disable no-param-reassign */
7981 // According to the library docs, the player is configured by mutating the provided instance
@@ -183,20 +185,29 @@ function BaseVideoPlayer({
183185 }
184186
185187 if ( isEnded && currentTime >= duration ) {
188+ allowSharedAutoPlayRef . current = true ;
186189 replayVideo ( ) ;
187190 return ;
188191 }
189192
193+ allowSharedAutoPlayRef . current = true ;
190194 playVideo ( ) ;
191195 } , [ isCurrentlyURLSet , isLoading , isEnded , currentTime , duration , playVideo , updateCurrentURLAndReportID , url , reportID , pauseVideo , replayVideo ] ) ;
192196
193197 const hideControl = useCallback ( ( ) => {
194- if ( isEnded ) {
198+ if ( isEnded || isSeeking ) {
195199 return ;
196200 }
197201
198- controlsOpacity . set ( withTiming ( 0 , { duration : 500 } , ( ) => scheduleOnRN ( setControlStatusState , CONST . VIDEO_PLAYER . CONTROLS_STATUS . HIDE ) ) ) ;
199- } , [ controlsOpacity , isEnded ] ) ;
202+ controlsOpacity . set (
203+ withTiming ( 0 , { duration : 500 } , ( finished ) => {
204+ if ( ! finished ) {
205+ return ;
206+ }
207+ scheduleOnRN ( setControlStatusState , CONST . VIDEO_PLAYER . CONTROLS_STATUS . HIDE ) ;
208+ } ) ,
209+ ) ;
210+ } , [ controlsOpacity , isEnded , isSeeking ] ) ;
200211 const debouncedHideControl = useMemo ( ( ) => debounce ( hideControl , 1500 ) , [ hideControl ] ) ;
201212
202213 useEffect ( ( ) => {
@@ -216,13 +227,13 @@ function BaseVideoPlayer({
216227 if ( controlStatusState !== CONST . VIDEO_PLAYER . CONTROLS_STATUS . SHOW ) {
217228 return ;
218229 }
219- if ( ! isPlaying || isPopoverVisible ) {
230+ if ( ! isPlaying || isPopoverVisible || isSeeking ) {
220231 debouncedHideControl . cancel ( ) ;
221232 return ;
222233 }
223234
224235 debouncedHideControl ( ) ;
225- } , [ isPlaying , debouncedHideControl , controlStatusState , isPopoverVisible , canUseTouchScreen ] ) ;
236+ } , [ isPlaying , debouncedHideControl , controlStatusState , isPopoverVisible , canUseTouchScreen , isSeeking ] ) ;
226237
227238 useEffect ( ( ) => {
228239 if ( ! onTap || ! controlStatusState ) {
@@ -232,6 +243,14 @@ function BaseVideoPlayer({
232243 onTap ( shouldShowArrows ) ;
233244 } , [ controlStatusState , onTap ] ) ;
234245
246+ const restartAutoHide = useCallback ( ( ) => {
247+ debouncedHideControl . cancel ( ) ;
248+ if ( ! canUseTouchScreen || ! isPlaying || isPopoverVisible || controlStatusState !== CONST . VIDEO_PLAYER . CONTROLS_STATUS . SHOW ) {
249+ return ;
250+ }
251+ debouncedHideControl ( ) ;
252+ } , [ canUseTouchScreen , controlStatusState , debouncedHideControl , isPlaying , isPopoverVisible ] ) ;
253+
235254 const stopWheelPropagation = useCallback ( ( ev : WheelEvent ) => ev . stopPropagation ( ) , [ ] ) ;
236255
237256 const toggleControl = useCallback ( ( ) => {
@@ -398,7 +417,7 @@ function BaseVideoPlayer({
398417 videoViewRef . current ,
399418 videoPlayerElementParentRef . current ,
400419 videoPlayerElementRef . current ,
401- ( isUploading && ! isCurrentlyURLSet ) || isFullScreenRef . current || ! isReadyForDisplayRef . current || hasError ,
420+ ( isUploading && ! isCurrentlyURLSet ) || isFullScreenRef . current || ! isReadyForDisplayRef . current || hasError || isSeeking || ! allowSharedAutoPlayRef . current ,
402421 { shouldUseSharedVideoElement, url, reportID} ,
403422 ) ;
404423 } , [
@@ -413,6 +432,7 @@ function BaseVideoPlayer({
413432 isFullScreenRef ,
414433 hasError ,
415434 isCurrentlyURLSet ,
435+ isSeeking ,
416436 status ,
417437 updatePlayerStatus ,
418438 ] ) ;
@@ -571,7 +591,6 @@ function BaseVideoPlayer({
571591 { shouldShowLoadingIndicator && < LoadingIndicator style = { [ styles . opacity1 , styles . bgTransparent ] } /> }
572592 { shouldShowOfflineIndicator && < AttachmentOfflineIndicator isPreview = { isPreview } /> }
573593 { controlStatusState !== CONST . VIDEO_PLAYER . CONTROLS_STATUS . HIDE &&
574- ! shouldShowLoadingIndicator &&
575594 ! shouldShowOfflineIndicator &&
576595 ! shouldShowErrorIndicator &&
577596 ( isPopoverVisible || isHovered || canUseTouchScreen || isEnded ) && (
@@ -588,6 +607,21 @@ function BaseVideoPlayer({
588607 controlsStatus = { controlStatusState }
589608 showPopoverMenu = { showPopoverMenu }
590609 reportID = { reportID }
610+ onSeekStart = { ( ) => {
611+ allowSharedAutoPlayRef . current = false ;
612+ debouncedHideControl . cancel ( ) ;
613+ cancelAnimation ( controlsOpacity ) ;
614+ controlsOpacity . set ( 1 ) ;
615+ setIsSeeking ( true ) ;
616+ } }
617+ onSeekEnd = { ( shouldResumeAfterSeek ) => {
618+ setIsSeeking ( false ) ;
619+ if ( shouldResumeAfterSeek ) {
620+ allowSharedAutoPlayRef . current = true ;
621+ playVideo ( ) ;
622+ }
623+ restartAutoHide ( ) ;
624+ } }
591625 />
592626 ) }
593627 </ View >
0 commit comments