diff --git a/frontend/src/features/streaming/ChannelPlayer.tsx b/frontend/src/features/streaming/ChannelPlayer.tsx index 9581811..96cc7a6 100644 --- a/frontend/src/features/streaming/ChannelPlayer.tsx +++ b/frontend/src/features/streaming/ChannelPlayer.tsx @@ -21,6 +21,33 @@ export function ChannelPlayer({ const [playing, setPlaying] = useState(false) const [muted, setMuted] = useState(true) const [volume, setVolume] = useState(1) + const [controlsVisible, setControlsVisible] = useState(true) + const hideTimerRef = useRef(null) + const overControlsRef = useRef(false) + + const clearHideTimer = useCallback(() => { + if (hideTimerRef.current !== null) { + window.clearTimeout(hideTimerRef.current) + hideTimerRef.current = null + } + }, []) + + // Прячем панель и курсор после бездействия — но не когда курсор на панели или видео на паузе. + const scheduleHide = useCallback(() => { + clearHideTimer() + hideTimerRef.current = window.setTimeout(() => { + if (!overControlsRef.current && videoRef.current && !videoRef.current.paused) { + setControlsVisible(false) + } + }, 2500) + }, [clearHideTimer]) + + const revealControls = useCallback(() => { + setControlsVisible(true) + scheduleHide() + }, [scheduleHide]) + + useEffect(() => clearHideTimer, [clearHideTimer]) const seekToLiveEdge = useCallback(() => { const video = videoRef.current @@ -110,7 +137,14 @@ export function ChannelPlayer({ return (
{ + clearHideTimer() + if (videoRef.current && !videoRef.current.paused) setControlsVisible(false) + }} + className={`relative aspect-video w-full overflow-hidden rounded-md border border-border bg-black ${ + controlsVisible ? '' : 'cursor-none' + }`} >