@@ -4,6 +4,7 @@ import {PlayFill} from '@gravity-ui/icons';
44import { Icon } from '@gravity-ui/uikit' ;
55import debounce from 'lodash/debounce' ;
66import _ReactPlayer from 'react-player' ;
7+ import type { ReactPlayerProps } from 'react-player' ;
78
89import { MobileContext } from '../../context/mobileContext' ;
910import { VideoContext } from '../../context/videoContext' ;
@@ -41,11 +42,10 @@ const ReactPlayer =
4142 : _ReactPlayer ;
4243
4344export interface ReactPlayerBlockProps
44- extends Omit < MediaVideoProps , 'loop' | ' src' | 'ref' > ,
45+ extends Omit < MediaVideoProps , 'src' | 'ref' > ,
4546 ClassNameProps {
4647 src : string | string [ ] ;
4748 previewImgUrl ?: string ;
48- loop ?: boolean ;
4949 customBarControlsClassName ?: string ;
5050 showPreview ?: boolean ;
5151 onClickPreview ?: ( ) => void ;
@@ -57,6 +57,7 @@ export interface ReactPlayerBlockProps
5757
5858interface PlayerPropgress {
5959 played : number ;
60+ playedSeconds : number ;
6061}
6162
6263// eslint-disable-next-line react/display-name
@@ -108,6 +109,7 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
108109 const [ isPlaying , setIsPlaying ] = React . useState ( autoPlay ) ;
109110 const [ playedPercent , setPlayedPercent ] = React . useState < number > ( 0 ) ;
110111 const [ currentHeight , setCurrentHeight ] = React . useState ( height ) ;
112+ const [ duration , setDuration ] = React . useState < null | number > ( null ) ;
111113 const [ width , setWidth ] = React . useState < number > ( 0 ) ;
112114 const [ actualRatio , setActualRatio ] = React . useState < number > ( ) ;
113115 const [ muted , setMuted ] = React . useState < boolean > ( mute ) ;
@@ -325,26 +327,36 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
325327 }
326328 } , [ ] ) ;
327329
328- const onProgress = React . useCallback ( ( progress : PlayerPropgress ) => {
329- setPlayedPercent ( progress . played ) ;
330+ const onProgress : ReactPlayerProps [ 'onProgress' ] = React . useCallback (
331+ ( { played, playedSeconds} : PlayerPropgress ) => {
332+ setPlayedPercent ( played ) ;
330333
331- if ( progress . played === 1 ) {
332- setMuted ( true ) ;
333- }
334+ if ( loop ) {
335+ const { start = 0 , end = duration } = typeof loop === 'boolean' ? { } : loop ;
336+
337+ // Youtube videos not muted after finishing playing and start again.
338+ // 'onEnded' does not fire when 'loop' is set to true.
339+ // It is custom loop with muted sound after finishing playing and start again.
340+ if ( end !== null && playedSeconds >= end ) {
341+ setIsPlaying ( true ) ;
342+ playerRef ?. seekTo ( start ) ;
343+ }
344+ }
345+
346+ if ( played === 1 ) {
347+ setMuted ( true ) ;
348+ }
349+ } ,
350+ [ duration , loop , playerRef ] ,
351+ ) ;
352+
353+ const onDuration = React . useCallback ( ( currentDuration : number ) => {
354+ setDuration ( currentDuration ) ;
334355 } , [ ] ) ;
335356
336357 const onEnded = React . useCallback ( ( ) => {
337- // Youtube videos not muted after finishing playing and start again.
338- // 'onEnded' does not fire when 'loop' is set to true.
339- // It is custom loop with muted sound after finishing playing and start again.
340- if ( loop ) {
341- setPlayedPercent ( 0 ) ;
342- setIsPlaying ( true ) ;
343- playerRef ?. seekTo ( 0 ) ;
344- }
345-
346358 setEnded ( true ) ;
347- } , [ loop , playerRef ] ) ;
359+ } , [ ] ) ;
348360
349361 const onPlayClick = React . useCallback ( ( ) => {
350362 if ( isPlaying ) {
@@ -422,6 +434,7 @@ export const ReactPlayerBlock = React.forwardRef<ReactPlayerBlockHandler, ReactP
422434 } // to prevent pause icon flickering when autoplayed video ends
423435 onProgress = { onProgress }
424436 onEnded = { onEnded }
437+ onDuration = { onDuration }
425438 aria-label = { ariaLabel }
426439 previewTabIndex = { - 1 }
427440 config = { {
0 commit comments