import type { ForwardRefRenderFunction, SyntheticEvent } from 'react' import { useEffect, useState, useRef, } from 'react' import isUndefined from 'lodash/isUndefined' import isNumber from 'lodash/isNumber' import { useProgressChange } from './useProgressChange' type Ref = Parameters>[1] export type Props = { className?: string, crossOrigin?: string, height?: string, hidden?: boolean, isFullscreen?: boolean, muted?: boolean, onDurationChange?: (durationMs: number) => void, onEnded?: (e: SyntheticEvent) => void, onError?: (e?: SyntheticEvent) => void, onLoadedProgress?: (loadedMs: number) => void, onPause?: (e: SyntheticEvent) => void, onPlayedProgress?: (playedMs: number) => void, onReady?: () => void, playing?: boolean, ref?: Ref, seek?: number | null, src: string, volume?: number, width?: string, } const useVideoRef = (ref?: Ref) => { const videoRef = useRef(null) if (ref && typeof ref === 'object') return ref return videoRef } export const useVideoPlayer = ({ isFullscreen, onDurationChange, onError, onLoadedProgress, onPlayedProgress, onReady, playing, ref, seek = null, src, volume, }: Props) => { const [ready, setReady] = useState(false) const videoRef = useVideoRef(ref) const handleReady = () => { setReady(true) onReady?.() } const handleDurationChange = () => { onDurationChange?.(videoRef.current?.duration || 0) } useEffect(() => { const video = videoRef.current if (!video || !src) return video.src = src video.load() }, [src, videoRef]) useEffect(() => { const video = videoRef.current if (video && isNumber(seek)) { video.currentTime = seek } }, [seek, videoRef]) useEffect(() => { const video = videoRef.current if (!video?.src || !ready || isUndefined(playing)) return if (playing) { // автовоспроизведение со звуком иногда может не сработать // https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#new-behaviors video.play().catch(onError) } else { video.pause() } }, [ ready, playing, src, videoRef, onError, ]) useEffect(() => { const video = videoRef.current if (video) { video.volume = volume ?? 1 } }, [volume, videoRef]) // Todo this logic is responsible for scrolling to the player, delete if not required // useEffect(() => { // videoRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' }) // }, [isFullscreen, videoRef]) return { handleDurationChange, handleReady, videoRef, ...useProgressChange({ onLoadedProgress, onPlayedProgress, videoRef, }), } }