File size: 5,083 Bytes
be54278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
140
141
import { useVoxtral } from "./VoxtralContext";
import { THEME } from "../constants";
import {
  AppGridBackground,
  ErrorMessageBox,
  useMountedTransition,
} from "./SharedUI";

export const LoadingPage = () => {
  const { loadingProgress, loadingMessage, error } = useVoxtral();
  const mounted = useMountedTransition();
  const progressClamped = Math.min(100, Math.max(0, loadingProgress));
  const isError = !!error;

  return (
    <AppGridBackground className="min-h-screen flex items-center justify-center p-8">
      <div
        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"}`}
        style={{
          backgroundColor: `${THEME.beigeLight}F2`,
          borderColor: THEME.beigeDark,
        }}
      >
        <div
          className={`h-1 w-full transition-colors duration-300 ${isError ? "bg-[var(--mistral-red)]" : "bg-[var(--mistral-orange)]"}`}
        />

        <div className="p-8 space-y-8">
          <div className="flex justify-center">
            {isError ? (
              <div
                className="w-20 h-20 rounded-full flex items-center justify-center border"
                style={{
                  backgroundColor: `${THEME.errorRed}1A`,
                  borderColor: `${THEME.errorRed}33`,
                }}
              >
                <svg
                  className="w-10 h-10"
                  style={{ color: THEME.errorRed }}
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  strokeWidth={2}
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"
                  />
                </svg>
              </div>
            ) : (
              <div className="relative">
                <div
                  className="w-20 h-20 border-4 rounded-full animate-spin"
                  style={{
                    borderColor: THEME.beigeDark,
                    borderTopColor: THEME.mistralOrange,
                  }}
                />
                <div className="absolute inset-0 flex items-center justify-center">
                  <div
                    className="w-2 h-2 rounded-full animate-pulse"
                    style={{ backgroundColor: THEME.mistralOrange }}
                  />
                </div>
              </div>
            )}
          </div>

          <div className="text-center space-y-2">
            <h2
              className="text-2xl font-bold tracking-tight"
              style={{ color: THEME.textBlack }}
            >
              {isError ? "Initialization Failed" : "Loading Model"}
            </h2>
            <p className="text-sm text-gray-500 font-mono uppercase tracking-widest">
              {isError ? "Voxtral-Mini-4B-Realtime" : loadingMessage}
            </p>
          </div>

          {!isError && (
            <div className="space-y-4">
              <div className="flex justify-between text-xs font-mono font-bold text-gray-500">
                <span>PROGRESS</span>
                <span>{Math.round(progressClamped)}%</span>
              </div>

              <div
                className="w-full rounded-full h-4 overflow-hidden border"
                style={{
                  backgroundColor: `${THEME.beigeDark}80`,
                  borderColor: THEME.beigeDark,
                }}
              >
                <div
                  className="h-full progress-stripe transition-all duration-500 ease-out"
                  style={{
                    width: `${progressClamped}%`,
                    backgroundColor: THEME.mistralOrange,
                  }}
                />
              </div>

              <div
                className="bg-white border p-3 rounded-sm"
                style={{ borderColor: THEME.beigeDark }}
              >
                <div className="flex items-center space-x-2">
                  <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
                  <p className="font-mono text-xs text-gray-600 truncate">
                    {`> ${loadingMessage}`}
                  </p>
                </div>
              </div>
            </div>
          )}

          {isError && (
            <div className="space-y-4">
              <ErrorMessageBox
                className="border p-4 rounded text-left"
                message={error}
              />
              <button
                onClick={() => window.location.reload()}
                className="w-full py-3 text-white font-bold transition-colors shadow-lg hover:bg-black cursor-pointer"
                style={{ backgroundColor: THEME.textBlack }}
              >
                RELOAD APPLICATION
              </button>
            </div>
          )}
        </div>
      </div>
    </AppGridBackground>
  );
};