"use client";
import { useEffect, useRef } from "react";
import { newEvent } from "@/lib/newEvent";
import { usePlayer, usePlayerSelector } from "@/registry/react/PlayerProvider";
export function ProgressBar() {
const player = usePlayer();
const currentTime = usePlayerSelector((p) => p.currentTime);
const duration = usePlayerSelector((p) => p.duration);
const progress = duration > 0 ? Math.max(0, Math.min(currentTime / duration, 1)) : 0;
const barRef = useRef(null);
const mouseDownRef = useRef(false);
const getMouseRatio = (event) => {
const clientX = event.clientX ?? event.touches?.[0]?.clientX ?? 0;
const { x, width } = barRef.current.getBoundingClientRect();
return Math.max(0, Math.min(1, (clientX - x) / width));
};
const handleMouseDown = (event) => {
mouseDownRef.current = true;
player.onEvent(
newEvent({
type: "PressedProgressBar",
description: "The progress bar was pressed at some ratio.",
initiatedBy: "user",
ratio: getMouseRatio(event),
}),
);
};
useEffect(() => {
const handleMouseMove = (event) => {
if (!mouseDownRef.current) return;
if (!barRef.current) {
handleMouseUp();
return;
}
player.onEvent(
newEvent({
type: "ScrubbedProgressBar",
description: "The user pressed on the progress bar then dragged.",
initiatedBy: "user",
ratio: getMouseRatio(event),
}),
);
};
const handleMouseUp = () => {
if (!mouseDownRef.current) return;
mouseDownRef.current = false;
player.onEvent(
newEvent({
type: "FinishedScrubbingProgressBar",
description: "The user let go after scrubbing the progress bar.",
initiatedBy: "user",
}),
);
};
window.addEventListener("mouseup", handleMouseUp);
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("touchend", handleMouseUp);
window.addEventListener("touchmove", handleMouseMove);
return () => {
window.removeEventListener("mouseup", handleMouseUp);
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("touchend", handleMouseUp);
window.removeEventListener("touchmove", handleMouseMove);
};
}, [player]);
return (
<div
ref={barRef}
className="relative isolate h-2 grow cursor-pointer overflow-hidden rounded"
onMouseDown={handleMouseDown}
onTouchStart={handleMouseDown}
>
<div className="absolute inset-0 cursor-pointer bg-[rgba(0,0,0,0.8)] opacity-15" />
<div className="pointer-events-none h-2 rounded bg-[rgba(0,0,0,0.8)]" style={{ width: `${progress * 100}%` }} />
</div>
);
}