import { useState, useEffect, useCallback, useRef } from "react"; import GlassContainer from "./GlassContainer"; import GlassButton from "./GlassButton"; import { GLASS_EFFECTS } from "../constants"; interface VideoScrubberProps { videoRef: React.RefObject; isVisible: boolean; } export default function VideoScrubber({ videoRef, isVisible }: VideoScrubberProps) { const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [isDragging, setIsDragging] = useState(false); const [isHovered, setIsHovered] = useState(false); const [isPlaying, setIsPlaying] = useState(false); const scrubberRef = useRef(null); const formatTime = useCallback((seconds: number) => { if (!isFinite(seconds) || isNaN(seconds)) { return "0:00"; } const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins}:${secs.toString().padStart(2, '0')}`; }, []); const updateProgress = useCallback(() => { const video = videoRef.current; if (video && !isDragging) { const time = isFinite(video.currentTime) ? video.currentTime : 0; const dur = isFinite(video.duration) ? video.duration : 0; setCurrentTime(time); setDuration(dur); setIsPlaying(!video.paused); } }, [videoRef, isDragging]); const togglePlayPause = useCallback(() => { const video = videoRef.current; if (video) { if (video.paused) { video.play(); } else { video.pause(); } } }, [videoRef]); const handleSeek = useCallback((newTime: number) => { const video = videoRef.current; if (video && !isNaN(newTime)) { video.currentTime = newTime; setCurrentTime(newTime); } }, [videoRef]); const handleScrubberChange = useCallback((event: React.ChangeEvent) => { const newTime = parseFloat(event.target.value); handleSeek(newTime); }, [handleSeek]); const handleMouseDown = useCallback(() => { setIsDragging(true); }, []); const handleMouseUp = useCallback(() => { setIsDragging(false); }, []); useEffect(() => { const video = videoRef.current; if (!video) return; const handleLoadedMetadata = () => { const dur = isFinite(video.duration) ? video.duration : 0; const time = isFinite(video.currentTime) ? video.currentTime : 0; setDuration(dur); setCurrentTime(time); }; const handleTimeUpdate = () => { updateProgress(); }; const handlePlay = () => setIsPlaying(true); const handlePause = () => setIsPlaying(false); video.addEventListener('loadedmetadata', handleLoadedMetadata); video.addEventListener('timeupdate', handleTimeUpdate); video.addEventListener('play', handlePlay); video.addEventListener('pause', handlePause); // Update immediately if metadata is already loaded if (video.readyState >= 1) { handleLoadedMetadata(); } return () => { video.removeEventListener('loadedmetadata', handleLoadedMetadata); video.removeEventListener('timeupdate', handleTimeUpdate); video.removeEventListener('play', handlePlay); video.removeEventListener('pause', handlePause); }; }, [videoRef, updateProgress]); useEffect(() => { if (isDragging) { document.addEventListener('mouseup', handleMouseUp); return () => { document.removeEventListener('mouseup', handleMouseUp); }; } }, [isDragging, handleMouseUp]); if (!isVisible) { return null; } const progressPercentage = duration > 0 && isFinite(duration) && isFinite(currentTime) ? Math.min((currentTime / duration) * 100, 100) : 0; return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} style={{ pointerEvents: 'auto' }} >
{/* Play/Pause Button */} {isPlaying ? ( ) : ( )} {/* Current Time */}
{formatTime(currentTime)}
{/* Timeline Scrubber */}
{/* Duration */}
{formatTime(duration)}
); }