'use client'; import { useState, useEffect, useRef } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { useCameraStore } from '@/stores/camera-store'; import { useTranslation } from '@/lib/i18n'; import { cn } from '@/lib/utils'; interface SourceSelectorProps { deviceId: string; } export function SourceSelector({ deviceId }: SourceSelectorProps) { const { t } = useTranslation(); const { cameras, isStreaming, sourceType, sourceFilename, isUploading, startPipeline, stopPipeline, uploadImage, uploadVideo, uploadBatchImages, startFromUrl, } = useCameraStore(); const [mounted, setMounted] = useState(false); const hasCameras = cameras.length > 0; const [cameraDisabled, setCameraDisabled] = useState(false); const [activeTab, setActiveTab] = useState<'camera' | 'image' | 'video'>('camera'); useEffect(() => { setMounted(true); }, []); // After mount, check if cameras are available and switch tab if needed useEffect(() => { if (!hasCameras) { setCameraDisabled(true); if (activeTab === 'camera') { setActiveTab('image'); } } else { setCameraDisabled(false); } }, [hasCameras, activeTab]); const [videoMode, setVideoMode] = useState<'file' | 'url'>('file'); const [videoUrl, setVideoUrl] = useState(''); const [isDragging, setIsDragging] = useState(false); const imageFileRef = useRef(null); const videoFileRef = useRef(null); const handleImageSelect = async (e: React.ChangeEvent) => { const files = Array.from(e.target.files || []); if (files.length === 0) return; if (files.length === 1) { await uploadImage(files[0], deviceId); } else { await uploadBatchImages(files, deviceId); } if (imageFileRef.current) imageFileRef.current.value = ''; }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }; const handleDragLeave = () => setIsDragging(false); const handleDrop = async (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); const files = Array.from(e.dataTransfer.files).filter((f) => ['.jpg', '.jpeg', '.png'].some((ext) => f.name.toLowerCase().endsWith(ext)) ); if (files.length === 0) return; if (files.length === 1) { await uploadImage(files[0], deviceId); } else { await uploadBatchImages(files, deviceId); } }; const handleVideoSelect = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; await uploadVideo(file, deviceId); if (videoFileRef.current) videoFileRef.current.value = ''; }; const handleUrlSubmit = async () => { if (!videoUrl.trim()) return; await startFromUrl(videoUrl.trim(), deviceId); setVideoUrl(''); }; const sourceLabel = sourceType === 'camera' ? t('camera.camera') : sourceType === 'image' ? t('camera.image') : sourceType === 'batch_image' ? t('camera.batchImages') : t('camera.video'); if (!mounted) return null; return (
setActiveTab(v as typeof activeTab)} > {t('camera.camera')} {t('camera.image')} {t('camera.video')}
{isStreaming ? ( <> {sourceFilename && ( {sourceFilename} )} ) : ( <> {activeTab === 'camera' && ( hasCameras ? ( ) : (

{t('camera.noCameraDetected')}

) )} {activeTab === 'image' && (
{t('camera.jpgPngMultiple')}
{isDragging && (

{t('camera.dropImagesHere')}

)}
)} {activeTab === 'video' && (
{videoMode === 'file' ? (
{t('camera.mp4AviMov')}
) : (
setVideoUrl(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') handleUrlSubmit(); }} className="flex-1" />

{t('camera.urlHelpText')}

)}
)} )}
); }