Spaces:
Running
Running
| import { useState, useEffect } from "react"; | |
| import { Loader2 } from "lucide-react"; | |
| import { useLLM } from "../hooks/useLLM"; | |
| import { ChatApp } from "./ChatApp"; | |
| export function AppShell() { | |
| const { status } = useLLM(); | |
| const isReady = status.state === "ready"; | |
| const [showChat, setShowChat] = useState(false); | |
| useEffect(() => { | |
| if (isReady) { | |
| const timeoutId = setTimeout(() => setShowChat(true), 300); | |
| return () => clearTimeout(timeoutId); | |
| } | |
| }, [isReady]); | |
| return ( | |
| <> | |
| <div | |
| className={`absolute inset-0 z-20 flex flex-col items-center justify-center transition-opacity duration-1000 ease-in-out ${ | |
| showChat ? "opacity-0 pointer-events-none" : "opacity-100" | |
| }`} | |
| > | |
| <Loader2 className="h-10 w-10 animate-spin text-[#76b900]" /> | |
| <p className="mt-4 text-base text-white/80"> | |
| {status.state === "loading" | |
| ? (status.message ?? "Loading model…") | |
| : status.state === "error" | |
| ? "Error" | |
| : "Preparing Nemotron-3-Nano…"} | |
| </p> | |
| <div className="mt-3 h-1.5 w-72 overflow-hidden rounded-full bg-white/20"> | |
| <div | |
| className="h-full rounded-full bg-[#76b900] transition-[width] duration-300 ease-out" | |
| style={{ | |
| width: `${ | |
| status.state === "ready" | |
| ? 100 | |
| : status.state === "loading" | |
| ? (status.progress ?? 0) | |
| : 0 | |
| }%`, | |
| }} | |
| /> | |
| </div> | |
| {status.state === "error" && ( | |
| <p className="mt-2 text-sm text-red-300">{status.error}</p> | |
| )} | |
| </div> | |
| <div | |
| className={`absolute inset-0 z-30 bg-[#0a0a0a] transition-opacity duration-1000 ease-in-out ${ | |
| showChat ? "opacity-100" : "opacity-0 pointer-events-none" | |
| }`} | |
| > | |
| <ChatApp /> | |
| </div> | |
| </> | |
| ); | |
| } | |