Implement control visibility logic in ChannelPlayer: add functionality to hide and reveal controls based on user interaction, enhancing the user experience during video playback. This includes managing visibility on mouse movements and video play/pause events.
This commit is contained in:
@@ -21,6 +21,33 @@ export function ChannelPlayer({
|
|||||||
const [playing, setPlaying] = useState(false)
|
const [playing, setPlaying] = useState(false)
|
||||||
const [muted, setMuted] = useState(true)
|
const [muted, setMuted] = useState(true)
|
||||||
const [volume, setVolume] = useState(1)
|
const [volume, setVolume] = useState(1)
|
||||||
|
const [controlsVisible, setControlsVisible] = useState(true)
|
||||||
|
const hideTimerRef = useRef<number | null>(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 seekToLiveEdge = useCallback(() => {
|
||||||
const video = videoRef.current
|
const video = videoRef.current
|
||||||
@@ -110,7 +137,14 @@ export function ChannelPlayer({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className="group relative aspect-video w-full overflow-hidden rounded-md border border-border bg-black"
|
onMouseMove={revealControls}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
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'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<video
|
<video
|
||||||
ref={videoRef}
|
ref={videoRef}
|
||||||
@@ -119,11 +153,31 @@ export function ChannelPlayer({
|
|||||||
className="h-full w-full"
|
className="h-full w-full"
|
||||||
onClick={togglePlay}
|
onClick={togglePlay}
|
||||||
onDoubleClick={toggleFullscreen}
|
onDoubleClick={toggleFullscreen}
|
||||||
onPlay={() => setPlaying(true)}
|
onPlay={() => {
|
||||||
onPause={() => setPlaying(false)}
|
setPlaying(true)
|
||||||
|
scheduleHide()
|
||||||
|
}}
|
||||||
|
onPause={() => {
|
||||||
|
setPlaying(false)
|
||||||
|
clearHideTimer()
|
||||||
|
setControlsVisible(true)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="absolute inset-x-0 bottom-0 flex items-center gap-3 bg-gradient-to-t from-black/70 to-transparent px-3 py-2 text-white opacity-0 transition-opacity group-hover:opacity-100">
|
<div
|
||||||
|
onMouseEnter={() => {
|
||||||
|
overControlsRef.current = true
|
||||||
|
clearHideTimer()
|
||||||
|
setControlsVisible(true)
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
overControlsRef.current = false
|
||||||
|
scheduleHide()
|
||||||
|
}}
|
||||||
|
className={`absolute inset-x-0 bottom-0 flex items-center gap-3 bg-gradient-to-t from-black/70 to-transparent px-3 py-2 text-white transition-opacity ${
|
||||||
|
controlsVisible ? 'opacity-100' : 'pointer-events-none opacity-0'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<button type="button" onClick={togglePlay} aria-label="play/pause">
|
<button type="button" onClick={togglePlay} aria-label="play/pause">
|
||||||
{playing ? <Pause className="h-5 w-5" /> : <Play className="h-5 w-5" />}
|
{playing ? <Pause className="h-5 w-5" /> : <Play className="h-5 w-5" />}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user