1
0
Fork 0
mirror of https://github.com/sussy-code/smov.git synced 2024-12-22 14:57:40 +01:00
smov/src/components/video/controls/BackdropControl.tsx

87 lines
2.8 KiB
TypeScript
Raw Normal View History

2023-01-10 19:53:55 +01:00
import React, { useCallback, useEffect, useRef, useState } from "react";
2023-01-08 22:29:38 +01:00
import { useVideoPlayerState } from "../VideoContext";
interface BackdropControlProps {
children?: React.ReactNode;
2023-01-10 19:53:55 +01:00
onBackdropChange?: (showing: boolean) => void;
2023-01-08 22:29:38 +01:00
}
export function BackdropControl(props: BackdropControlProps) {
const { videoState } = useVideoPlayerState();
const [moved, setMoved] = useState(false);
const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);
2023-01-09 21:51:24 +01:00
const clickareaRef = useRef<HTMLDivElement>(null);
2023-01-08 22:29:38 +01:00
const handleMouseMove = useCallback(() => {
if (!moved) setMoved(true);
2023-01-08 22:29:38 +01:00
if (timeout.current) clearTimeout(timeout.current);
timeout.current = setTimeout(() => {
if (moved) setMoved(false);
2023-01-08 22:29:38 +01:00
timeout.current = null;
}, 3000);
}, [setMoved, moved]);
2023-01-08 22:29:38 +01:00
2023-01-09 21:51:24 +01:00
const handleMouseLeave = useCallback(() => {
setMoved(false);
}, [setMoved]);
const handleClick = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
if (!clickareaRef.current || clickareaRef.current !== e.target) return;
if (videoState.isPlaying) videoState.pause();
else videoState.play();
},
[videoState, clickareaRef]
);
2023-01-10 19:53:55 +01:00
const handleDoubleClick = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
if (!clickareaRef.current || clickareaRef.current !== e.target) return;
if (!videoState.isFullscreen) videoState.enterFullscreen();
else videoState.exitFullscreen();
},
[videoState, clickareaRef]
);
2023-01-08 22:29:38 +01:00
const lastBackdropValue = useRef<boolean | null>(null);
2023-01-10 19:53:55 +01:00
useEffect(() => {
const currentValue = moved || videoState.isPaused;
if (currentValue !== lastBackdropValue.current) {
lastBackdropValue.current = currentValue;
props.onBackdropChange?.(currentValue);
}
2023-01-10 19:53:55 +01:00
}, [videoState, moved, props]);
2023-01-08 22:29:38 +01:00
const showUI = moved || videoState.isPaused;
return (
<div
className={`absolute inset-0 ${!showUI ? "cursor-none" : ""}`}
onMouseMove={handleMouseMove}
2023-01-09 21:51:24 +01:00
onMouseLeave={handleMouseLeave}
ref={clickareaRef}
2023-01-08 22:29:38 +01:00
onClick={handleClick}
2023-01-10 19:53:55 +01:00
onDoubleClick={handleDoubleClick}
2023-01-08 22:29:38 +01:00
>
<div
2023-01-09 21:51:24 +01:00
className={`pointer-events-none absolute inset-0 bg-black bg-opacity-20 transition-opacity duration-200 ${
2023-01-08 22:29:38 +01:00
!showUI ? "!opacity-0" : ""
}`}
/>
<div
2023-01-10 00:27:04 +01:00
className={`pointer-events-none absolute inset-x-0 bottom-0 h-[20%] bg-gradient-to-t from-black to-transparent transition-opacity duration-200 ${
2023-01-08 22:29:38 +01:00
!showUI ? "!opacity-0" : ""
}`}
/>
<div
2023-01-10 00:27:04 +01:00
className={`pointer-events-none absolute inset-x-0 top-0 h-[20%] bg-gradient-to-b from-black to-transparent transition-opacity duration-200 ${
2023-01-08 22:29:38 +01:00
!showUI ? "!opacity-0" : ""
}`}
/>
2023-01-09 21:51:24 +01:00
<div className="pointer-events-none absolute inset-0">
2023-01-10 19:53:55 +01:00
{props.children}
2023-01-09 21:51:24 +01:00
</div>
2023-01-08 22:29:38 +01:00
</div>
);
}