130 lines
No EOL
4.2 KiB
JavaScript
130 lines
No EOL
4.2 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import AeThexLogo from '@/components/AeThexLogo';
|
|
|
|
const BinaryDigit = () => {
|
|
const [position, setPosition] = useState({
|
|
top: `${Math.random() * 100}%`,
|
|
left: `${Math.random() * 100}%`,
|
|
});
|
|
const duration = Math.random() * 5 + 5; // 5 to 10 seconds
|
|
|
|
return (
|
|
<motion.span
|
|
className="absolute text-primary/20 text-xs font-mono"
|
|
style={{ ...position }}
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: [0, 1, 0] }}
|
|
transition={{ duration, repeat: Infinity, ease: "linear" }}
|
|
>
|
|
{Math.round(Math.random())}
|
|
</motion.span>
|
|
);
|
|
};
|
|
|
|
const DataFallBar = ({ i }) => {
|
|
const height = Math.random() * 24 + 8;
|
|
const duration = Math.random() * 0.5 + 0.8;
|
|
|
|
return (
|
|
<motion.div
|
|
className="w-1.5 bg-gradient-to-t from-primary/50 to-purple-600/50"
|
|
style={{ height: `${height}px`, opacity: 0 }}
|
|
animate={{
|
|
y: [0, 48],
|
|
opacity: [1, 0],
|
|
}}
|
|
transition={{
|
|
duration,
|
|
repeat: Infinity,
|
|
ease: 'linear',
|
|
delay: i * 0.15 + Math.random() * 0.5,
|
|
}}
|
|
/>
|
|
);
|
|
};
|
|
|
|
const LoadingScreen = () => {
|
|
const [progress, setProgress] = useState(0);
|
|
const [text, setText] = useState("Initializing AeThex OS...");
|
|
|
|
useEffect(() => {
|
|
let currentProgress = 0;
|
|
const interval = setInterval(() => {
|
|
currentProgress += 1;
|
|
|
|
if (currentProgress > 98) {
|
|
currentProgress = 98;
|
|
}
|
|
setProgress(currentProgress);
|
|
|
|
if (currentProgress > 60 && currentProgress < 80) {
|
|
setText("Calibrating systems...");
|
|
} else if (currentProgress >= 80) {
|
|
setText("Booting interface...");
|
|
}
|
|
|
|
}, 40);
|
|
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
return (
|
|
<div className="flex items-center justify-center min-h-screen bg-[#06080d] overflow-hidden relative">
|
|
<AnimatePresence>
|
|
<>
|
|
{Array.from({ length: 30 }).map((_, i) => (
|
|
<BinaryDigit key={i} />
|
|
))}
|
|
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
transition={{ duration: 0.5 }}
|
|
className="flex flex-col items-center gap-8 z-10 w-full max-w-sm px-4"
|
|
>
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8, ease: "easeOut" }}
|
|
className="relative"
|
|
>
|
|
<div className="absolute -inset-2 bg-primary/20 rounded-[28px] blur-xl opacity-75"></div>
|
|
<div className="relative w-24 h-24 bg-slate-900/50 rounded-3xl flex items-center justify-center border border-primary/20 backdrop-blur-sm p-4">
|
|
<AeThexLogo className="h-full" hideText />
|
|
</div>
|
|
</motion.div>
|
|
|
|
<div className="flex justify-center items-start h-12 w-24 overflow-hidden relative -mt-4">
|
|
<div className="absolute top-0 flex justify-center items-start gap-1">
|
|
{Array.from({ length: 9 }).map((_, i) => (
|
|
<DataFallBar key={i} i={i} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="w-full max-w-xs -mt-4">
|
|
<div className="h-1.5 bg-slate-800 rounded-full overflow-hidden">
|
|
<motion.div
|
|
className="h-full bg-gradient-to-r from-primary to-purple-500 rounded-full"
|
|
initial={{ width: 0 }}
|
|
animate={{ width: `${progress}%` }}
|
|
transition={{ duration: 0.1, ease: "linear" }}
|
|
/>
|
|
</div>
|
|
<p className="text-center text-sm text-gray-400 font-mono mt-2 tracking-widest">{progress}%</p>
|
|
</div>
|
|
|
|
<div className="text-center font-mono h-16">
|
|
<p className="text-lg text-primary">{text}</p>
|
|
<p className="text-sm text-gray-500 mt-1">Please wait while we prepare your experience...</p>
|
|
</div>
|
|
</motion.div>
|
|
</>
|
|
</AnimatePresence>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LoadingScreen; |