Abdullahrasheed45 commited on
Commit
04168d9
·
verified ·
1 Parent(s): 7e7edae

Create LoadingScreen.tsx

Browse files
Files changed (1) hide show
  1. src/components/LoadingScreen.tsx +220 -0
src/components/LoadingScreen.tsx ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useEffect, useState } from "react";
2
+ import { useVLMContext } from "../context/useVLMContext";
3
+ import { THEME } from "../constants";
4
+
5
+ interface LoadingScreenProps {
6
+ onComplete: () => void;
7
+ }
8
+
9
+ export default function LoadingScreen({ onComplete }: LoadingScreenProps) {
10
+ const [progress, setProgress] = useState(0);
11
+ const [currentStep, setCurrentStep] = useState("Initializing environment...");
12
+ const [isError, setIsError] = useState(false);
13
+ const [hasStartedLoading, setHasStartedLoading] = useState(false);
14
+ const [mounted, setMounted] = useState(false);
15
+
16
+ const { loadModel, isLoaded, isLoading } = useVLMContext();
17
+
18
+ useEffect(() => {
19
+ setMounted(true);
20
+ }, []);
21
+
22
+ useEffect(() => {
23
+ // Prevent multiple loading attempts
24
+ if (hasStartedLoading || isLoading || isLoaded) return;
25
+
26
+ const loadModelAndProgress = async () => {
27
+ setHasStartedLoading(true);
28
+
29
+ try {
30
+ setCurrentStep("Checking WebGPU compatibility...");
31
+
32
+ // Check for WebGPU support first
33
+ if (!navigator.gpu) {
34
+ setCurrentStep("WebGPU is not available in this browser context.");
35
+ setIsError(true);
36
+ return;
37
+ }
38
+
39
+ await loadModel((message, percentage) => {
40
+ const cleanMsg = message.replace("...", "");
41
+ setCurrentStep(cleanMsg);
42
+
43
+ if (percentage !== undefined) {
44
+ setProgress(percentage);
45
+ }
46
+ });
47
+
48
+ setCurrentStep("System ready.");
49
+ setProgress(100);
50
+ onComplete();
51
+ } catch (error) {
52
+ console.error("Error loading model:", error);
53
+ setCurrentStep(
54
+ `ERR: ${error instanceof Error ? error.message : String(error)}`,
55
+ );
56
+ setIsError(true);
57
+ }
58
+ };
59
+
60
+ loadModelAndProgress();
61
+ }, [hasStartedLoading, isLoading, isLoaded, loadModel, onComplete]);
62
+
63
+ // Handle case where model is already loaded
64
+ useEffect(() => {
65
+ if (isLoaded && !hasStartedLoading) {
66
+ setProgress(100);
67
+ setCurrentStep("Model cached and ready.");
68
+ setTimeout(onComplete, 500);
69
+ }
70
+ }, [isLoaded, hasStartedLoading, onComplete]);
71
+
72
+ return (
73
+ <>
74
+ <div
75
+ className="absolute inset-0 flex items-center justify-center p-8 z-50"
76
+ style={{
77
+ backgroundColor: THEME.beigeLight,
78
+ backgroundImage: `
79
+ linear-gradient(${THEME.beigeDark} 1px, transparent 1px),
80
+ linear-gradient(90deg, ${THEME.beigeDark} 1px, transparent 1px)
81
+ `,
82
+ backgroundSize: "40px 40px",
83
+ }}
84
+ >
85
+ <div
86
+ className={`max-w-md w-full backdrop-blur-sm rounded-sm border shadow-xl transition-all duration-700 transform ${mounted ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
87
+ style={{
88
+ backgroundColor: `${THEME.beigeLight}F2`,
89
+ borderColor: THEME.beigeDark,
90
+ }}
91
+ >
92
+ {/* Header */}
93
+ <div
94
+ className={`h-1 w-full transition-colors duration-300 ${isError ? "bg-[var(--mistral-red)]" : "bg-[var(--mistral-orange)]"}`}
95
+ ></div>
96
+ <div className="p-8 space-y-8">
97
+ {/* Status Icon Area */}
98
+ <div className="flex justify-center">
99
+ {isError ? (
100
+ <div
101
+ className="w-20 h-20 rounded-full flex items-center justify-center border"
102
+ style={{
103
+ backgroundColor: `${THEME.errorRed}1A`,
104
+ borderColor: `${THEME.errorRed}33`,
105
+ }}
106
+ >
107
+ <svg
108
+ className="w-10 h-10"
109
+ style={{ color: THEME.errorRed }}
110
+ fill="none"
111
+ viewBox="0 0 24 24"
112
+ stroke="currentColor"
113
+ strokeWidth={2}
114
+ >
115
+ <path
116
+ strokeLinecap="round"
117
+ strokeLinejoin="round"
118
+ d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
119
+ />
120
+ </svg>
121
+ </div>
122
+ ) : (
123
+ <div className="relative">
124
+ {/* Spinning Ring */}
125
+ <div
126
+ className="w-20 h-20 border-4 border-t-[var(--mistral-orange)] rounded-full animate-spin"
127
+ style={{
128
+ borderColor: THEME.beigeDark,
129
+ borderTopColor: THEME.mistralOrange,
130
+ }}
131
+ ></div>
132
+ {/* Center Dot */}
133
+ <div className="absolute inset-0 flex items-center justify-center">
134
+ <div
135
+ className="w-2 h-2 rounded-full animate-pulse"
136
+ style={{ backgroundColor: THEME.mistralOrange }}
137
+ ></div>
138
+ </div>
139
+ </div>
140
+ )}
141
+ </div>
142
+ <div className="text-center space-y-2">
143
+ <h2
144
+ className="text-2xl font-bold tracking-tight"
145
+ style={{ color: THEME.textBlack }}
146
+ >
147
+ {isError ? "Initialization Failed" : "Loading Model"}
148
+ </h2>
149
+ <p className="text-sm text-gray-500 font-mono uppercase tracking-widest">
150
+ Ministral-3B-Instruct
151
+ </p>
152
+ </div>
153
+ {/* Progress Section */}
154
+ {!isError && (
155
+ <div className="space-y-4">
156
+ <div className="flex justify-between text-xs font-mono font-bold text-gray-500">
157
+ <span>PROGRESS</span>
158
+ <span>{Math.round(progress)}%</span>
159
+ </div>
160
+ <div
161
+ className="w-full rounded-full h-4 overflow-hidden border"
162
+ style={{
163
+ backgroundColor: `${THEME.beigeDark}80`,
164
+ borderColor: THEME.beigeDark,
165
+ }}
166
+ >
167
+ <div
168
+ className="h-full progress-stripe transition-all duration-500 ease-out"
169
+ style={{
170
+ width: `${progress}%`,
171
+ backgroundColor: THEME.mistralOrange,
172
+ }}
173
+ />
174
+ </div>
175
+ {/* "Terminal" Log Output */}
176
+ <div
177
+ className="bg-white border p-3 rounded-sm"
178
+ style={{ borderColor: THEME.beigeDark }}
179
+ >
180
+ <div className="flex items-center space-x-2">
181
+ <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
182
+ <p className="font-mono text-xs text-gray-600 truncate">
183
+ {`> ${currentStep}`}
184
+ </p>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ )}
189
+ {/* Error Actions */}
190
+ {isError && (
191
+ <div className="space-y-4">
192
+ <div
193
+ className="border p-4 rounded text-left"
194
+ style={{
195
+ backgroundColor: `${THEME.errorRed}0D`,
196
+ borderColor: `${THEME.errorRed}33`,
197
+ }}
198
+ >
199
+ <p
200
+ className="font-mono text-xs break-words"
201
+ style={{ color: THEME.errorRed }}
202
+ >
203
+ {`> Error: ${currentStep}`}
204
+ </p>
205
+ </div>
206
+ <button
207
+ onClick={() => window.location.reload()}
208
+ className="w-full py-3 text-white font-bold transition-colors shadow-lg hover:bg-black"
209
+ style={{ backgroundColor: THEME.textBlack }}
210
+ >
211
+ RELOAD APPLICATION
212
+ </button>
213
+ </div>
214
+ )}
215
+ </div>
216
+ </div>
217
+ </div>
218
+ </>
219
+ );
220
+ }