import { useEffect, useRef, useState } from "react"; export default function VideoEditor() { // --- State --- const [videoPath, setVideoPath] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [isPlaying, setIsPlaying] = useState(false); const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); // --- Refs --- const videoRef = useRef(null); const canvasRef = useRef(null); // --- Load video path on mount --- useEffect(() => { async function loadVideo() { try { const result = await window.electronAPI.getRecordedVideoPath(); if (result.success && result.path) { setVideoPath(`file://${result.path}`); } else { setError(result.message || 'Failed to load video'); } } catch (err) { setError('Error loading video: ' + String(err)); } finally { setLoading(false); } } loadVideo(); }, []); // --- Canvas drawing and video event listeners --- useEffect(() => { const video = videoRef.current; const canvas = canvasRef.current; if (!video || !canvas) return; let animationId: number; function drawFrame() { if (!video || !canvas) return; if (video.paused || video.ended) return; // Keep canvas size in sync with video if (canvas.width !== video.videoWidth || canvas.height !== video.videoHeight) { canvas.width = video.videoWidth; canvas.height = video.videoHeight; } const ctx = canvas.getContext('2d'); if (ctx) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(video, 0, 0, canvas.width, canvas.height); } animationId = requestAnimationFrame(drawFrame); } function handlePlay() { drawFrame(); } function handlePause() { cancelAnimationFrame(animationId); } video.addEventListener('play', handlePlay); video.addEventListener('pause', handlePause); video.addEventListener('ended', handlePause); return () => { video.removeEventListener('play', handlePlay); video.removeEventListener('pause', handlePause); video.removeEventListener('ended', handlePause); cancelAnimationFrame(animationId); }; }, [videoPath]); // --- Handlers --- function togglePlayPause() { if (!videoRef.current) return; if (isPlaying) { videoRef.current.pause(); } else { videoRef.current.play(); } } function handleSeek(e: React.ChangeEvent) { if (!videoRef.current) return; const newTime = parseFloat(e.target.value); videoRef.current.currentTime = newTime; } function formatTime(seconds: number) { if (!isFinite(seconds) || isNaN(seconds) || seconds < 0) { return '0:00'; } const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins}:${secs.toString().padStart(2, '0')}`; } // --- Early returns for loading/error --- if (loading) { return (
Loading video...
); } if (error) { return (
{error}
); } // --- Main render --- return (
{videoPath && ( <>
{formatTime(currentTime)} {formatTime(duration)}
); }