Download frontend/src/components/InferenceProgress.tsx from vipan-kumar/Audio_Deepfake_Detection: direct link, hf CLI and curl.
- Browser
- Download file 2.61 kB
-
https://huggingface.co/spaces/vipan-kumar/Audio_Deepfake_Detection/resolve/main/frontend/src/components/InferenceProgress.tsx
- Command line
-
hf download hf://spaces/vipan-kumar/Audio_Deepfake_Detection/frontend/src/components/InferenceProgress.tsx
-
curl -L -o InferenceProgress.tsx https://huggingface.co/spaces/vipan-kumar/Audio_Deepfake_Detection/resolve/main/frontend/src/components/InferenceProgress.tsx
2.61 kB
| import { Loader2, CheckCircle2, Circle } from "lucide-react"; | |
| import { motion } from "framer-motion"; | |
| interface Props { | |
| isInferring: boolean; | |
| modelIds: string[]; | |
| completedIds: Set<string>; | |
| } | |
| /** Per-detector progress chips. Smoothly animates from queued → running → done. */ | |
| export default function InferenceProgress({ | |
| isInferring, | |
| modelIds, | |
| completedIds, | |
| }: Props) { | |
| if (!isInferring && completedIds.size === 0) { | |
| return null; | |
| } | |
| const totalDone = completedIds.size; | |
| const totalActive = modelIds.length; | |
| const progressPct = | |
| totalActive > 0 ? (totalDone / totalActive) * 100 : 0; | |
| return ( | |
| <motion.div | |
| initial={{ opacity: 0, y: -4 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| className="panel-alt p-3" | |
| > | |
| <div className="flex items-center justify-between gap-2"> | |
| <div className="flex items-center gap-2"> | |
| {isInferring ? ( | |
| <Loader2 className="h-3.5 w-3.5 animate-spin text-cyber" /> | |
| ) : ( | |
| <CheckCircle2 className="h-3.5 w-3.5 text-cyber" /> | |
| )} | |
| <span className="font-mono text-xs text-ink-dim"> | |
| {isInferring | |
| ? `running ${totalDone}/${totalActive} detectors…` | |
| : `complete · ${totalActive}/${totalActive}`} | |
| </span> | |
| </div> | |
| <span className="font-mono text-[10px] text-ink-mute"> | |
| {progressPct.toFixed(0)}% | |
| </span> | |
| </div> | |
| {/* Overall progress bar */} | |
| <div className="mt-2 h-1 overflow-hidden rounded-full bg-bg/50"> | |
| <motion.div | |
| initial={{ width: 0 }} | |
| animate={{ width: `${progressPct}%` }} | |
| transition={{ duration: 0.3 }} | |
| className="h-full bg-cyber" | |
| /> | |
| </div> | |
| {/* Per-detector chips */} | |
| <div className="mt-2 grid gap-1.5 sm:grid-cols-2 lg:grid-cols-4"> | |
| {modelIds.map((id) => { | |
| const done = completedIds.has(id); | |
| return ( | |
| <div | |
| key={id} | |
| className="flex items-center justify-between gap-2 rounded-md border border-line bg-bg/40 px-2 py-1 font-mono text-[10px]" | |
| > | |
| <span className="truncate text-ink">{id}</span> | |
| {done ? ( | |
| <CheckCircle2 className="h-3 w-3 shrink-0 text-cyber" /> | |
| ) : isInferring ? ( | |
| <Loader2 className="h-3 w-3 shrink-0 animate-spin text-ink-dim" /> | |
| ) : ( | |
| <Circle className="h-3 w-3 shrink-0 text-ink-mute" /> | |
| )} | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| </motion.div> | |
| ); | |
| } | |