import { useState, useEffect, useRef, useCallback } from "react"; import { THEME, EXAMPLE_VIDEOS } from "../constants"; import type { VideoSourceType, VideoSource } from "../types"; type ExampleVideo = (typeof EXAMPLE_VIDEOS)[number]; interface SourceSelectorProps { onSourceSelected: (source: VideoSource) => void; onBack?: () => void; } interface SourceCardProps { icon: React.ReactNode; title: string; description: string; onClick: () => void; isActive?: boolean; isLoading?: boolean; badge?: string; } function SourceCard({ icon, title, description, onClick, isActive, isLoading, badge }: SourceCardProps) { return ( ); } function ExampleVideoCard({ video, onClick, isSelected }: { video: ExampleVideo; onClick: () => void; isSelected: boolean }) { return ( ); } export default function SourceSelector({ onSourceSelected, onBack }: SourceSelectorProps) { const [mounted, setMounted] = useState(false); const [activeSource, setActiveSource] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [selectedExample, setSelectedExample] = useState(null); const [showExamples, setShowExamples] = useState(false); const fileInputRef = useRef(null); useEffect(() => { setMounted(true); }, []); const handleWebcam = useCallback(async () => { setActiveSource("webcam"); setIsLoading(true); setError(null); try { const stream = await navigator.mediaDevices.getUserMedia({ video: { width: { ideal: 1920, max: 1920 }, height: { ideal: 1080, max: 1080 }, facingMode: "user", }, }); onSourceSelected({ type: "webcam", stream }); } catch (err) { setError(err instanceof Error ? err.message : "Failed to access webcam"); setActiveSource(null); } finally { setIsLoading(false); } }, [onSourceSelected]); const handleScreenShare = useCallback(async () => { setActiveSource("screen"); setIsLoading(true); setError(null); try { const stream = await navigator.mediaDevices.getDisplayMedia({ video: { width: { ideal: 1920 }, height: { ideal: 1080 }, }, }); // Handle stream end (user stops sharing) stream.getVideoTracks()[0].onended = () => { // This will be handled by the parent component }; onSourceSelected({ type: "screen", stream }); } catch (err) { if ((err as Error).name !== "AbortError") { setError(err instanceof Error ? err.message : "Failed to start screen sharing"); } setActiveSource(null); } finally { setIsLoading(false); } }, [onSourceSelected]); const handleFileUpload = useCallback(() => { fileInputRef.current?.click(); }, []); const handleFileChange = useCallback((e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { setActiveSource("upload"); const url = URL.createObjectURL(file); onSourceSelected({ type: "upload", url, name: file.name }); } }, [onSourceSelected]); const handleExampleSelect = useCallback((video: ExampleVideo) => { setSelectedExample(video.id); setActiveSource("example"); onSourceSelected({ type: "example", url: video.url, name: video.name }); }, [onSourceSelected]); const toggleExamples = useCallback(() => { setShowExamples(prev => !prev); }, []); return (
{/* Header Bar */}
{/* Back Button */} {onBack && ( )} {/* Header */}

Choose Video Source

Select how you want to provide video for analysis

{/* Error Message */} {error && (
{error}
)} {/* Source Options Grid */}
} title="Webcam" description="Use your camera for real-time video analysis" onClick={handleWebcam} isActive={activeSource === "webcam"} isLoading={isLoading && activeSource === "webcam"} badge="Live" /> } title="Screen Share" description="Capture your screen, window, or browser tab" onClick={handleScreenShare} isActive={activeSource === "screen"} isLoading={isLoading && activeSource === "screen"} /> } title="Upload Video" description="Select a video file from your device" onClick={handleFileUpload} isActive={activeSource === "upload"} /> } title="Examples" description="Try with pre-loaded sample videos" onClick={toggleExamples} isActive={showExamples || activeSource === "example"} />
{/* Example Videos Section */} {showExamples && (

Sample Videos

{EXAMPLE_VIDEOS.map((video) => ( handleExampleSelect(video)} isSelected={selectedExample === video.id} /> ))}
)} {/* Footer */}

All processing happens locally in your browser

); }