2023-01-08 22:29:38 +01:00
|
|
|
import { useCallback, useEffect, useRef, useState } from "react";
|
2023-01-08 17:51:38 +01:00
|
|
|
import { useVideoPlayerState } from "../VideoContext";
|
|
|
|
|
|
|
|
export function ProgressControl() {
|
|
|
|
const { videoState } = useVideoPlayerState();
|
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
2023-01-08 22:29:38 +01:00
|
|
|
const [mouseDown, setMouseDown] = useState<boolean>(false);
|
|
|
|
const [progress, setProgress] = useState<number>(0);
|
2023-01-08 17:51:38 +01:00
|
|
|
|
2023-01-08 22:29:38 +01:00
|
|
|
let watchProgress = `${(
|
2023-01-08 17:51:38 +01:00
|
|
|
(videoState.time / videoState.duration) *
|
|
|
|
100
|
|
|
|
).toFixed(2)}%`;
|
2023-01-08 22:29:38 +01:00
|
|
|
if (mouseDown) watchProgress = `${progress}%`;
|
|
|
|
|
2023-01-08 17:51:38 +01:00
|
|
|
const bufferProgress = `${(
|
|
|
|
(videoState.buffered / videoState.duration) *
|
|
|
|
100
|
|
|
|
).toFixed(2)}%`;
|
|
|
|
|
2023-01-08 22:29:38 +01:00
|
|
|
useEffect(() => {
|
|
|
|
function mouseMove(ev: MouseEvent) {
|
|
|
|
if (!mouseDown || !ref.current) return;
|
|
|
|
const rect = ref.current.getBoundingClientRect();
|
|
|
|
const pos = ((ev.pageX - rect.left) / ref.current.offsetWidth) * 100;
|
|
|
|
setProgress(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mouseUp(ev: MouseEvent) {
|
|
|
|
if (!mouseDown) return;
|
|
|
|
setMouseDown(false);
|
|
|
|
document.body.removeAttribute("data-no-select");
|
|
|
|
|
2023-01-08 17:51:38 +01:00
|
|
|
if (!ref.current) return;
|
|
|
|
const rect = ref.current.getBoundingClientRect();
|
2023-01-08 22:29:38 +01:00
|
|
|
const pos = (ev.pageX - rect.left) / ref.current.offsetWidth;
|
2023-01-08 17:51:38 +01:00
|
|
|
videoState.setTime(pos * videoState.duration);
|
2023-01-08 22:29:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
document.addEventListener("mousemove", mouseMove);
|
|
|
|
document.addEventListener("mouseup", mouseUp);
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
document.removeEventListener("mousemove", mouseMove);
|
|
|
|
document.removeEventListener("mouseup", mouseUp);
|
|
|
|
};
|
|
|
|
}, [mouseDown, videoState]);
|
|
|
|
|
|
|
|
const handleMouseDown = useCallback(() => {
|
|
|
|
setMouseDown(true);
|
|
|
|
document.body.setAttribute("data-no-select", "true");
|
|
|
|
}, []);
|
2023-01-08 17:51:38 +01:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
ref={ref}
|
|
|
|
className="relative m-1 my-4 h-4 w-48 overflow-hidden rounded-full border border-white bg-denim-100"
|
2023-01-08 22:29:38 +01:00
|
|
|
onMouseDown={handleMouseDown}
|
2023-01-08 17:51:38 +01:00
|
|
|
>
|
|
|
|
<div
|
|
|
|
className="absolute inset-y-0 left-0 bg-denim-700 opacity-50"
|
|
|
|
style={{
|
|
|
|
width: bufferProgress,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
<div
|
|
|
|
className="absolute inset-y-0 left-0 bg-denim-700"
|
|
|
|
style={{
|
|
|
|
width: watchProgress,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|