File size: 6,327 Bytes
70348ce 1dfcfc7 70348ce 1dfcfc7 70348ce | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | import { useState } from 'react';
import type { AnalysisResult, AppState } from './types';
import { API_BASE } from './api';
import Background from './components/Background';
import RadioNav from './components/RadioNav';
import HeroSection from './components/HeroSection';
import UploadSection from './components/UploadSection';
import ProcessingSection from './components/ProcessingSection';
import ResultSection from './components/ResultSection';
import ErrorSection from './components/ErrorSection';
import Modal from './components/Modal';
const AGENTS = [
{ name: 'MetadataAgent', desc: 'Scans C2PA signatures and AI tool metadata in the first 512KB of the file.' },
{ name: 'FrameAnalyzerAgent', desc: 'Extracts up to 40 frames uniformly across the video duration.' },
{ name: 'FaceDetectorAgent', desc: 'Uses MediaPipe to detect and crop facial regions with 20% padding.' },
{ name: 'DecisionAgent (ViT)', desc: 'Ensemble of two ViT models (99.3% + 92.1% accuracy) with early exit.' },
{ name: 'AudioAuthenticator', desc: 'Wav2Vec2-based audio analysis with librosa heuristics for AV mismatch.' },
{ name: 'ReportGeneratorAgent',desc: 'Adaptive threshold + confidence calibration to produce the final verdict.' },
];
export default function App() {
const [state, setState] = useState<AppState>('hero');
const [result, setResult] = useState<AnalysisResult | null>(null);
const [error, setError] = useState('');
const [modal, setModal] = useState<string | null>(null);
async function handleAnalyze(file: File) {
setState('processing');
const fd = new FormData();
fd.append('file', file);
try {
const res = await fetch(`${API_BASE}/analyze`, { method: 'POST', body: fd });
if (!res.ok) {
const e = await res.json().catch(() => ({}));
throw new Error((e as { detail?: string }).detail || `Server error ${res.status}`);
}
const data: AnalysisResult = await res.json();
setResult(data);
setState('result');
} catch (err: unknown) {
setError(err instanceof Error ? err.message : 'Connection to analysis engine failed.');
setState('error');
}
}
const activeNav =
state === 'hero' ? 'dashboard' :
state === 'upload' ? 'analyze' :
state === 'processing' ? 'analyze' :
state === 'result' ? 'analyze' : 'dashboard';
const handleNav = (id: string) => {
if (id === 'dashboard') setState('hero');
else if (id === 'analyze') setState('upload');
else if (id === 'pricing') window.location.href = '/pricing';
else if (id === 'agents') setModal('agents');
else if (id === 'settings') setModal('network');
};
return (
<div className="min-h-screen flex flex-col relative overflow-x-hidden">
<Background />
<RadioNav active={activeNav} onNavigate={handleNav} />
{state === 'hero' && <HeroSection onAnalyze={() => setState('upload')} />}
{state === 'upload' && <UploadSection onAnalyze={handleAnalyze} onBack={() => setState('hero')} />}
{state === 'processing' && <ProcessingSection />}
{state === 'result' && result && <ResultSection result={result} onReset={() => setState('upload')} />}
{state === 'error' && <ErrorSection message={error} onRetry={() => setState('upload')} />}
{/* Agents Modal */}
{modal === 'agents' && (
<Modal title="Detection Agents" onClose={() => setModal(null)}>
<div className="flex flex-col gap-4">
{AGENTS.map((ag, i) => (
<div key={i} className="flex items-start gap-4 p-4 rounded-lg"
style={{ background: 'rgba(30,15,50,0.6)', border: '1px solid rgba(124,58,237,0.2)' }}>
<div className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 text-xs font-bold"
style={{ background: 'rgba(124,58,237,0.15)', border: '1px solid rgba(168,85,247,0.3)', color: '#a855f7' }}>
{i}
</div>
<div>
<div className="text-sm font-semibold mb-1" style={{ color: '#c084fc' }}>{ag.name}</div>
<div className="text-xs text-purple-300/50">{ag.desc}</div>
</div>
</div>
))}
</div>
</Modal>
)}
{/* Logs Modal */}
{modal === 'logs' && (
<Modal title="System Logs" onClose={() => setModal(null)}>
<div className="rounded-lg p-4 font-mono text-xs space-y-1 max-h-80 overflow-y-auto"
style={{ background: 'rgba(8,4,18,0.9)', color: '#a855f7' }}>
{[
'[BOOT] Authrix AI v2.2.0 initialized',
'[SYS] ViT ensemble models loaded',
'[SYS] MediaPipe face detector ready',
'[SYS] Wav2Vec2 audio model ready',
'[SYS] C2PA metadata scanner active',
'[NET] FastAPI server listening on :8000',
'[AUTH] API key validation enabled',
'[CACHE] SHA256 result cache initialized',
].map((line, i) => (
<div key={i} className="opacity-70">{line}</div>
))}
</div>
</Modal>
)}
{/* Network Modal */}
{modal === 'network' && (
<Modal title="Network Status" onClose={() => setModal(null)}>
<div className="grid grid-cols-2 gap-4">
{[
{ label: 'API Endpoint', value: window.location.origin },
{ label: 'HF Space', value: 'aarav13-authrix.hf.space' },
{ label: 'Max File Size', value: '100 MB' },
{ label: 'Request Timeout', value: '120s' },
{ label: 'Capture Duration', value: '8s' },
{ label: 'Cache', value: 'SHA256 (1MB)' },
].map(({ label, value }) => (
<div key={label} className="rounded-lg p-4"
style={{ background: 'rgba(20,10,35,0.6)', border: '1px solid rgba(88,28,135,0.25)' }}>
<div className="text-[10px] uppercase tracking-widest mb-1 text-purple-500/50">{label}</div>
<div className="text-sm font-bold font-mono" style={{ color: '#c084fc' }}>{value}</div>
</div>
))}
</div>
</Modal>
)}
</div>
);
}
|