Spaces:
Running
Running
File size: 5,260 Bytes
ff324d9 ea25548 ff324d9 ea25548 ff324d9 ea25548 ff324d9 ea25548 ff324d9 ea25548 ff324d9 ea25548 ff324d9 |
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 |
import { useEffect, useState } from "react";
import { useVLMContext } from "../context/useVLMContext";
import GlassContainer from "./GlassContainer";
import { GLASS_EFFECTS } from "../constants";
interface LoadingScreenProps {
onComplete: () => void;
}
export default function LoadingScreen({ onComplete }: LoadingScreenProps) {
const [progress, setProgress] = useState(0);
const [currentStep, setCurrentStep] = useState("Initializing...");
const [isError, setIsError] = useState(false);
const [hasStartedLoading, setHasStartedLoading] = useState(false);
const { loadModel, isLoaded, isLoading } = useVLMContext();
useEffect(() => {
// Prevent multiple loading attempts
if (hasStartedLoading || isLoading || isLoaded) return;
const loadModelAndProgress = async () => {
setHasStartedLoading(true);
try {
setCurrentStep("Checking WebGPU support...");
setProgress(5);
// Check for WebGPU support first
if (!navigator.gpu) {
setCurrentStep("WebGPU not available in this browser");
setIsError(true);
return;
}
// Load the actual AI model
await loadModel((message) => {
setCurrentStep(message);
if (message.includes("Loading processor")) {
setProgress(15);
} else if (message.includes("Processor loaded")) {
setProgress(35);
} else if (message.includes("Loading model")) {
setProgress(50);
} else if (message.includes("Model loaded")) {
setProgress(90);
}
});
setCurrentStep("Ready to start!");
setProgress(100);
// Small delay before completing
await new Promise((resolve) => setTimeout(resolve, 300));
onComplete();
} catch (error) {
console.error("Error loading model:", error);
setCurrentStep(`Error loading model: ${error instanceof Error ? error.message : String(error)}`);
setIsError(true);
}
};
loadModelAndProgress();
}, [hasStartedLoading, isLoading, isLoaded, loadModel, onComplete]);
// Handle case where model is already loaded
useEffect(() => {
if (isLoaded && !hasStartedLoading) {
setProgress(100);
setCurrentStep("Model already loaded!");
setTimeout(onComplete, 300);
}
}, [isLoaded, hasStartedLoading, onComplete]);
return (
<div className="absolute inset-0 text-white flex items-center justify-center p-8" style={{ opacity: 1 }}>
<GlassContainer
className="max-w-md w-full rounded-3xl shadow-2xl"
bgColor={isError ? GLASS_EFFECTS.COLORS.ERROR_BG : GLASS_EFFECTS.COLORS.DEFAULT_BG}
>
<div className="p-8 text-center space-y-8">
<div className="space-y-4">
<div className="w-16 h-16 mx-auto">
{isError ? (
<div className="w-16 h-16 rounded-full bg-red-500/20 flex items-center justify-center">
<svg className="w-8 h-8 text-red-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
clipRule="evenodd"
/>
</svg>
</div>
) : (
<div className="animate-spin rounded-full h-16 w-16 border-4 border-blue-500 border-t-transparent"></div>
)}
</div>
<h2 className="text-2xl font-bold text-gray-100">{isError ? "Loading Failed" : "Loading AI Model"}</h2>
<p className={`${isError ? "text-red-400" : "text-gray-400"}`}>{currentStep}</p>
</div>
{!isError && (
<div className="space-y-3">
<div className="w-full bg-gray-800/50 rounded-full h-4 overflow-hidden backdrop-blur-sm border border-gray-700/30 shadow-inner">
<div
className="h-full bg-gradient-to-r from-blue-500 via-blue-400 to-cyan-400 rounded-full transition-all duration-500 ease-out relative"
style={{ width: `${progress}%` }}
>
<div className="absolute inset-0 bg-white/20 rounded-full animate-pulse" />
</div>
</div>
<div className="flex justify-between items-center text-sm">
<span className="text-gray-400">{Math.round(progress)}% complete</span>
{progress > 0 && progress < 100 && (
<span className="text-blue-400 animate-pulse">●</span>
)}
</div>
</div>
)}
{isError && (
<div className="mt-4">
<button
onClick={() => window.location.reload()}
className="px-6 py-2 bg-red-600 hover:bg-red-700 rounded-lg text-white font-medium transition-colors"
>
Reload Page
</button>
</div>
)}
</div>
</GlassContainer>
</div>
);
}
|