import type { MouseEvent } from 'react' import { useCallback, useState, useRef, } from 'react' import ReactPlayer from 'react-player' import once from 'lodash/once' import throttle from 'lodash/throttle' import { useFullscreen } from './useFullscreen' import { useVolume } from './useVolume' type ProgressState = { loaded: number, loadedSeconds: number, played: number, playedSeconds: number, } export type Props = { onPlayingChange: (playing: boolean) => void, onProgressChange: (seconds: number) => void, url: string, } export const useVideoPlayer = ({ onPlayingChange, onProgressChange: progressChangeCallback, }: Props) => { const [ready, setReady] = useState(false) const [playing, setPlaying] = useState(false) const [duration, setDuration] = useState(0) const [loadedProgress, setLoadedProgress] = useState(0) const [playedProgress, setPlayedProgress] = useState(0) const [playedSeconds, setPlayedSeconds] = useState(0) const wrapperRef = useRef(null) const playerRef = useRef(null) const startPlaying = useCallback(once(() => { setReady(true) setPlaying(true) onPlayingChange(true) }), []) const togglePlaying = () => { if (ready) { setPlaying(!playing) onPlayingChange(!playing) } } const onPlayerClick = (e: MouseEvent) => { if (e.target === playerRef.current?.getInternalPlayer()) { togglePlaying() } } const setPlayerProgress = useCallback( throttle((value: number) => { playerRef.current?.seekTo(value, 'fraction') }, 100), [], ) const onProgressChange = useCallback((progress: number) => { setPlayedProgress(progress * 100) setPlayerProgress(progress) }, [ setPlayedProgress, setPlayerProgress, ]) const setProgress = ({ loaded, played, playedSeconds: seconds, }: ProgressState) => { setLoadedProgress(loaded * 100) setPlayedProgress(played * 100) setPlayedSeconds(seconds) progressChangeCallback(seconds) } return { duration, loadedProgress, onPlayerClick, onProgressChange, playedProgress, playedSeconds, playerRef, playing, setDuration, setProgress, setReady, startPlaying, togglePlaying, wrapperRef, ...useFullscreen(wrapperRef), ...useVolume(), } }