mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-17 22:27:19 +00:00
Add system upgrade alert and improve boot sequence
Introduce a system upgrade alert panel and enhance the OS boot sequence with new detection steps and a login prompt. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 279f1558-c0e3-40e4-8217-be7e9f4c6eca Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 62aa9e00-7e50-457e-933e-69d1d1490827 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/b984cb14-1d19-4944-922b-bc79e821ed35/279f1558-c0e3-40e4-8217-be7e9f4c6eca/G7VmUb2 Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
c2a8a3e89c
commit
81a51045cf
1 changed files with 400 additions and 19 deletions
|
|
@ -13,7 +13,7 @@ import {
|
|||
Network, Activity, Code2, Radio, Newspaper, Gamepad2,
|
||||
Users, Trophy, Calculator, StickyNote, Cpu, Camera,
|
||||
Eye, Shield, Zap, Skull, Lock, Unlock, Server, Database,
|
||||
TrendingUp, ArrowUp, ArrowDown, Hash, Key
|
||||
TrendingUp, ArrowUp, ArrowDown, Hash, Key, HardDrive, FolderSearch, AlertTriangle
|
||||
} from "lucide-react";
|
||||
|
||||
interface WindowState {
|
||||
|
|
@ -194,7 +194,7 @@ export default function AeThexOS() {
|
|||
const spotlightRef = useRef<HTMLInputElement>(null);
|
||||
const { user, isAuthenticated, logout } = useAuth();
|
||||
const [, setLocation] = useLocation();
|
||||
const [activeTrayPanel, setActiveTrayPanel] = useState<'wifi' | 'volume' | 'battery' | 'notifications' | null>(null);
|
||||
const [activeTrayPanel, setActiveTrayPanel] = useState<'wifi' | 'volume' | 'battery' | 'notifications' | 'upgrade' | null>(null);
|
||||
const [volume, setVolume] = useState(75);
|
||||
const [isMuted, setIsMuted] = useState(false);
|
||||
const [batteryInfo, setBatteryInfo] = useState<{ level: number; charging: boolean } | null>(null);
|
||||
|
|
@ -249,30 +249,31 @@ export default function AeThexOS() {
|
|||
return () => window.removeEventListener('mousemove', handleMouseMove);
|
||||
}, []);
|
||||
|
||||
const [showLoginPrompt, setShowLoginPrompt] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const bootSequence = async () => {
|
||||
const steps = [
|
||||
{ text: 'BIOS CHECK... OK', progress: 5 },
|
||||
{ text: 'Initializing AeThex OS...', progress: 10 },
|
||||
{ text: 'Loading kernel modules...', progress: 25 },
|
||||
{ text: 'Mounting file systems...', progress: 40 },
|
||||
{ text: 'Starting Aegis security layer...', progress: 55 },
|
||||
{ text: 'Connecting to Nexus network...', progress: 70 },
|
||||
{ text: 'Loading user profile...', progress: 85 },
|
||||
{ text: 'Welcome, Architect.', progress: 100 },
|
||||
{ text: 'Loading kernel modules...', progress: 20 },
|
||||
{ text: 'Mounting file systems...', progress: 30 },
|
||||
{ text: 'INITIATING AETHEX PASSPORT...', progress: 40 },
|
||||
{ text: 'DETECTING CROSS-PLATFORM IDENTITY...', progress: 55 },
|
||||
{ text: 'Starting Aegis security layer...', progress: 65 },
|
||||
{ text: 'STATUS: NEUTRAL LAYER ACTIVE.', progress: 75 },
|
||||
{ text: 'Connecting to Nexus network...', progress: 85 },
|
||||
{ text: 'IDENTITY SYSTEM READY.', progress: 100 },
|
||||
];
|
||||
|
||||
for (const step of steps) {
|
||||
setBootStep(step.text);
|
||||
setBootProgress(step.progress);
|
||||
await new Promise(r => setTimeout(r, 400));
|
||||
await new Promise(r => setTimeout(r, 350));
|
||||
}
|
||||
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
setIsBooting(false);
|
||||
|
||||
const randomTip = DAILY_TIPS[Math.floor(Math.random() * DAILY_TIPS.length)];
|
||||
setDailyTip(randomTip);
|
||||
setTimeout(() => setShowDailyTip(true), 1000);
|
||||
await new Promise(r => setTimeout(r, 400));
|
||||
setShowLoginPrompt(true);
|
||||
};
|
||||
|
||||
bootSequence();
|
||||
|
|
@ -378,6 +379,8 @@ export default function AeThexOS() {
|
|||
{ id: "networkneighborhood", title: "Network Neighborhood", icon: <Network className="w-8 h-8" />, component: "networkneighborhood", defaultWidth: 500, defaultHeight: 450 },
|
||||
{ id: "mission", title: "README.TXT", icon: <FileText className="w-8 h-8" />, component: "mission", defaultWidth: 500, defaultHeight: 500 },
|
||||
{ id: "foundry", title: "FOUNDRY.EXE", icon: <Award className="w-8 h-8" />, component: "foundry", defaultWidth: 450, defaultHeight: 500 },
|
||||
{ id: "intel", title: "INTEL", icon: <FolderSearch className="w-8 h-8" />, component: "intel", defaultWidth: 550, defaultHeight: 450 },
|
||||
{ id: "drives", title: "My Computer", icon: <HardDrive className="w-8 h-8" />, component: "drives", defaultWidth: 450, defaultHeight: 400 },
|
||||
{ id: "chat", title: "AeThex AI", icon: <MessageCircle className="w-8 h-8" />, component: "chat", defaultWidth: 400, defaultHeight: 500 },
|
||||
{ id: "terminal", title: "Terminal", icon: <Terminal className="w-8 h-8" />, component: "terminal", defaultWidth: 750, defaultHeight: 500 },
|
||||
{ id: "metrics", title: "System Status", icon: <Activity className="w-8 h-8" />, component: "metrics", defaultWidth: 750, defaultHeight: 550 },
|
||||
|
|
@ -394,6 +397,8 @@ export default function AeThexOS() {
|
|||
{ id: "networkneighborhood", title: "Network Neighborhood", icon: <Network className="w-8 h-8" />, component: "networkneighborhood", defaultWidth: 500, defaultHeight: 450 },
|
||||
{ id: "mission", title: "README.TXT", icon: <FileText className="w-8 h-8" />, component: "mission", defaultWidth: 500, defaultHeight: 500 },
|
||||
{ id: "foundry", title: "FOUNDRY.EXE", icon: <Award className="w-8 h-8" />, component: "foundry", defaultWidth: 450, defaultHeight: 500 },
|
||||
{ id: "intel", title: "INTEL", icon: <FolderSearch className="w-8 h-8" />, component: "intel", defaultWidth: 550, defaultHeight: 450 },
|
||||
{ id: "drives", title: "My Computer", icon: <HardDrive className="w-8 h-8" />, component: "drives", defaultWidth: 450, defaultHeight: 400 },
|
||||
{ id: "devtools", title: "Dev Tools", icon: <Code2 className="w-8 h-8" />, component: "devtools", defaultWidth: 450, defaultHeight: 400 },
|
||||
{ id: "metrics", title: "System Status", icon: <Activity className="w-8 h-8" />, component: "metrics", defaultWidth: 750, defaultHeight: 550 },
|
||||
{ id: "passport", title: "LOGIN", icon: <Key className="w-8 h-8" />, component: "passport", defaultWidth: 500, defaultHeight: 600 },
|
||||
|
|
@ -606,6 +611,8 @@ export default function AeThexOS() {
|
|||
case 'foundry': return <FoundryApp />;
|
||||
case 'devtools': return <DevToolsApp />;
|
||||
case 'mission': return <MissionApp />;
|
||||
case 'intel': return <IntelApp />;
|
||||
case 'drives': return <DrivesApp />;
|
||||
case 'settings': return <SettingsApp
|
||||
wallpaper={wallpaper}
|
||||
setWallpaper={setWallpaper}
|
||||
|
|
@ -660,6 +667,26 @@ export default function AeThexOS() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleGuestContinue = () => {
|
||||
setShowLoginPrompt(false);
|
||||
setIsBooting(false);
|
||||
const randomTip = DAILY_TIPS[Math.floor(Math.random() * DAILY_TIPS.length)];
|
||||
setDailyTip(randomTip);
|
||||
setTimeout(() => setShowDailyTip(true), 1000);
|
||||
};
|
||||
|
||||
const handleLoginFromBoot = () => {
|
||||
setShowLoginPrompt(false);
|
||||
setIsBooting(false);
|
||||
const randomTip = DAILY_TIPS[Math.floor(Math.random() * DAILY_TIPS.length)];
|
||||
setDailyTip(randomTip);
|
||||
setTimeout(() => {
|
||||
setShowDailyTip(true);
|
||||
const passportApp = apps.find(a => a.id === 'passport');
|
||||
if (passportApp) openApp(passportApp);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
if (isBooting) {
|
||||
return (
|
||||
<div className="h-screen w-screen bg-black flex flex-col items-center justify-center">
|
||||
|
|
@ -687,6 +714,37 @@ export default function AeThexOS() {
|
|||
</div>
|
||||
|
||||
<div className="text-white/30 text-xs mt-4 font-mono">AeThex OS v1.0.0</div>
|
||||
|
||||
<AnimatePresence>
|
||||
{showLoginPrompt && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="mt-8 space-y-4"
|
||||
>
|
||||
<div className="text-green-400 font-mono text-sm mb-6">
|
||||
✓ CROSS-PLATFORM IDENTITY READY
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<button
|
||||
onClick={handleLoginFromBoot}
|
||||
className="px-6 py-3 bg-cyan-500 hover:bg-cyan-400 text-black font-mono font-bold uppercase tracking-wider transition-colors flex items-center justify-center gap-2"
|
||||
data-testid="boot-login-button"
|
||||
>
|
||||
<Key className="w-4 h-4" />
|
||||
Login with Passport
|
||||
</button>
|
||||
<button
|
||||
onClick={handleGuestContinue}
|
||||
className="px-6 py-3 border border-white/30 hover:bg-white/10 text-white/70 font-mono uppercase tracking-wider transition-colors"
|
||||
data-testid="boot-guest-button"
|
||||
>
|
||||
Continue as Guest
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -1279,8 +1337,8 @@ interface TaskbarProps {
|
|||
onDesktopChange: (d: number) => void;
|
||||
clearanceTheme: ClearanceTheme;
|
||||
onSwitchClearance: () => void;
|
||||
activeTrayPanel: 'wifi' | 'volume' | 'battery' | 'notifications' | null;
|
||||
onTrayPanelToggle: (panel: 'wifi' | 'volume' | 'battery' | 'notifications') => void;
|
||||
activeTrayPanel: 'wifi' | 'volume' | 'battery' | 'notifications' | 'upgrade' | null;
|
||||
onTrayPanelToggle: (panel: 'wifi' | 'volume' | 'battery' | 'notifications' | 'upgrade') => void;
|
||||
volume: number;
|
||||
onVolumeChange: (v: number) => void;
|
||||
isMuted: boolean;
|
||||
|
|
@ -1739,6 +1797,19 @@ function Taskbar({ windows, activeWindowId, apps, time, showStartMenu, user, isA
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-1 text-white/60 relative">
|
||||
<button
|
||||
onClick={() => onTrayPanelToggle('upgrade')}
|
||||
className={`p-1.5 rounded transition-colors relative ${activeTrayPanel === 'upgrade' ? 'bg-yellow-500/30 text-yellow-400' : 'hover:bg-yellow-500/20 text-yellow-400'}`}
|
||||
data-testid="tray-upgrade"
|
||||
>
|
||||
<motion.div
|
||||
animate={{ scale: [1, 1.2, 1] }}
|
||||
transition={{ repeat: Infinity, duration: 2 }}
|
||||
>
|
||||
<Zap className="w-4 h-4" />
|
||||
</motion.div>
|
||||
<div className="absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full animate-ping" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onTrayPanelToggle('notifications')}
|
||||
className={`p-1.5 rounded transition-colors relative ${activeTrayPanel === 'notifications' ? 'bg-white/20 text-white' : 'hover:bg-white/10'}`}
|
||||
|
|
@ -1971,6 +2042,57 @@ function Taskbar({ windows, activeWindowId, apps, time, showStartMenu, user, isA
|
|||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{activeTrayPanel === 'upgrade' && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 10 }}
|
||||
className="absolute bottom-10 right-0 w-72 bg-slate-900/95 backdrop-blur-xl border border-yellow-500/50 rounded-lg shadow-2xl overflow-hidden"
|
||||
style={{ zIndex: 9999 }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="p-3 border-b border-yellow-500/30 bg-yellow-500/10">
|
||||
<div className="flex items-center gap-2">
|
||||
<AlertTriangle className="w-4 h-4 text-yellow-400" />
|
||||
<span className="text-yellow-400 text-sm font-mono uppercase">System Alert</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4 space-y-4">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 mx-auto rounded-full bg-yellow-500/20 border-2 border-yellow-500/50 flex items-center justify-center mb-3">
|
||||
<Zap className="w-8 h-8 text-yellow-400" />
|
||||
</div>
|
||||
<div className="text-white font-bold mb-1">Architect Access Available</div>
|
||||
<div className="text-white/60 text-sm">
|
||||
Upgrade your permissions to access the Source Code.
|
||||
</div>
|
||||
</div>
|
||||
<div className="border border-yellow-500/20 bg-yellow-500/5 rounded p-3 text-xs space-y-1">
|
||||
<div className="flex items-center gap-2 text-white/70">
|
||||
<Shield className="w-3 h-3 text-yellow-400" /> Full system access
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-white/70">
|
||||
<Network className="w-3 h-3 text-yellow-400" /> Network directory slot
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-white/70">
|
||||
<Globe className="w-3 h-3 text-yellow-400" /> .aethex namespace
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
href="https://aethex.studio"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block w-full text-center px-4 py-3 bg-yellow-500 hover:bg-yellow-400 text-black font-bold uppercase tracking-wider transition-colors text-sm"
|
||||
>
|
||||
Upgrade Now — $500
|
||||
</a>
|
||||
<div className="text-center text-xs text-white/40">
|
||||
Hint: Check the terminal for promo codes
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3701,8 +3823,8 @@ function NetworkNeighborhoodApp() {
|
|||
|
||||
const reservedSlots = Array.from({ length: Math.max(0, 7 - founders.length) }, (_, i) => ({
|
||||
id: `reserved-${i}`,
|
||||
name: "[RESERVED FOR FOUNDRY]",
|
||||
role: "available",
|
||||
name: "[LOCKED - REQUIRES ARCHITECT ACCESS]",
|
||||
role: "locked",
|
||||
isReserved: true,
|
||||
}));
|
||||
|
||||
|
|
@ -3938,6 +4060,265 @@ function DevToolsApp() {
|
|||
);
|
||||
}
|
||||
|
||||
function IntelApp() {
|
||||
const [selectedFile, setSelectedFile] = useState<string | null>(null);
|
||||
|
||||
const files = [
|
||||
{
|
||||
name: "CROSS_PLATFORM_REPORT.TXT",
|
||||
icon: <FileText className="w-4 h-4" />,
|
||||
content: `// INTERCEPTED REPORT //
|
||||
SOURCE: NAAVIK RESEARCH
|
||||
SUBJECT: THE FUTURE OF CROSS-PLATFORM
|
||||
|
||||
========================================
|
||||
KEY FINDINGS
|
||||
========================================
|
||||
|
||||
1. The "Walled Gardens" (Sony/MSFT) are failing.
|
||||
|
||||
Platform holders are losing grip on exclusive
|
||||
ecosystems. Users demand portability.
|
||||
|
||||
2. Users demand a "Neutral Identity Layer."
|
||||
|
||||
Cross-platform identity is the #1 requested
|
||||
feature among gaming audiences globally.
|
||||
|
||||
3. Developers need "Direct-to-Consumer" infrastructure.
|
||||
|
||||
30% platform cuts are unsustainable. The next
|
||||
generation of creators will build direct.
|
||||
|
||||
========================================
|
||||
AETHEX ANALYSIS
|
||||
========================================
|
||||
|
||||
This validates the AEGIS Protocol.
|
||||
|
||||
The industry is currently seeking the exact
|
||||
solution we have already built:
|
||||
|
||||
- Neutral identity layer ✓ DEPLOYED
|
||||
- Cross-platform passport ✓ DEPLOYED
|
||||
- Direct-to-consumer infra ✓ IN PROGRESS
|
||||
|
||||
========================================
|
||||
STATUS
|
||||
========================================
|
||||
|
||||
- Passport: DEPLOYED
|
||||
- CloudOS: DEPLOYED
|
||||
- Foundry: OPEN FOR ENROLLMENT
|
||||
|
||||
// END TRANSMISSION //`
|
||||
},
|
||||
{
|
||||
name: "MARKET_THESIS.TXT",
|
||||
icon: <TrendingUp className="w-4 h-4" />,
|
||||
content: `// MARKET THESIS //
|
||||
CLASSIFICATION: INTERNAL
|
||||
|
||||
========================================
|
||||
THE OPPORTUNITY
|
||||
========================================
|
||||
|
||||
Total Addressable Market (TAM):
|
||||
$200B+ Metaverse Economy by 2030
|
||||
|
||||
Our Position:
|
||||
Identity & Infrastructure Layer
|
||||
|
||||
========================================
|
||||
COMPETITIVE MOAT
|
||||
========================================
|
||||
|
||||
1. First-mover on neutral identity
|
||||
2. Architect certification network
|
||||
3. .aethex TLD namespace ownership
|
||||
4. Aegis security protocol
|
||||
|
||||
========================================
|
||||
REVENUE MODEL
|
||||
========================================
|
||||
|
||||
- Foundry Certifications: $500/architect
|
||||
- Enterprise Licensing: TBD
|
||||
- Namespace Reservations: TBD
|
||||
|
||||
// END DOCUMENT //`
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="h-full bg-black flex flex-col font-mono">
|
||||
<div className="flex items-center gap-2 p-3 border-b border-amber-500/30 bg-amber-500/5">
|
||||
<FolderSearch className="w-4 h-4 text-amber-400" />
|
||||
<span className="text-amber-400 text-sm uppercase tracking-wider">INTEL</span>
|
||||
<span className="text-amber-500/40 text-xs ml-auto">CLASSIFIED</span>
|
||||
</div>
|
||||
|
||||
{!selectedFile ? (
|
||||
<div className="flex-1 overflow-auto p-3 space-y-2">
|
||||
<div className="text-amber-500/60 text-xs mb-3 border-b border-amber-500/20 pb-2">
|
||||
📁 /intel/market_data/
|
||||
</div>
|
||||
{files.map((file, idx) => (
|
||||
<motion.button
|
||||
key={file.name}
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: idx * 0.1 }}
|
||||
onClick={() => setSelectedFile(file.name)}
|
||||
className="w-full flex items-center gap-3 py-2 px-3 border-l-2 border-amber-500/40 bg-amber-500/5 hover:bg-amber-500/15 transition-colors text-left"
|
||||
>
|
||||
<span className="text-amber-400">{file.icon}</span>
|
||||
<span className="text-white">{file.name}</span>
|
||||
<span className="text-amber-500/40 text-xs ml-auto">OPEN</span>
|
||||
</motion.button>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex-1 flex flex-col overflow-hidden">
|
||||
<div className="flex items-center gap-2 p-2 border-b border-amber-500/20 bg-amber-500/5">
|
||||
<button
|
||||
onClick={() => setSelectedFile(null)}
|
||||
className="text-amber-400 hover:text-amber-300 text-xs uppercase"
|
||||
>
|
||||
← Back
|
||||
</button>
|
||||
<span className="text-white text-sm">{selectedFile}</span>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto p-4">
|
||||
<pre className="text-green-400 text-xs whitespace-pre-wrap leading-relaxed">
|
||||
{files.find(f => f.name === selectedFile)?.content}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DrivesApp() {
|
||||
const [selectedDrive, setSelectedDrive] = useState<string | null>(null);
|
||||
|
||||
const drives = [
|
||||
{ id: 'C', name: 'Local System', size: '128 GB', used: '64 GB', status: 'online', icon: <HardDrive className="w-5 h-5" /> },
|
||||
{ id: 'D', name: '.aethex TLD', size: '∞', used: '0 GB', status: 'not_mounted', icon: <Globe className="w-5 h-5" /> },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="h-full bg-slate-950 flex flex-col font-mono">
|
||||
<div className="flex items-center gap-2 p-3 border-b border-cyan-500/30 bg-cyan-500/5">
|
||||
<HardDrive className="w-4 h-4 text-cyan-400" />
|
||||
<span className="text-cyan-400 text-sm uppercase tracking-wider">My Computer</span>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-auto p-4">
|
||||
<div className="text-white/50 text-xs mb-4 uppercase tracking-wider">Storage Devices</div>
|
||||
<div className="space-y-3">
|
||||
{drives.map((drive) => (
|
||||
<motion.div
|
||||
key={drive.id}
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className={`border rounded-lg p-4 cursor-pointer transition-all ${
|
||||
drive.status === 'online'
|
||||
? 'border-cyan-500/30 bg-cyan-500/5 hover:bg-cyan-500/10'
|
||||
: 'border-red-500/30 bg-red-500/5 hover:bg-red-500/10'
|
||||
}`}
|
||||
onClick={() => setSelectedDrive(drive.id)}
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className={`w-12 h-12 rounded-lg flex items-center justify-center ${
|
||||
drive.status === 'online' ? 'bg-cyan-500/20 text-cyan-400' : 'bg-red-500/20 text-red-400'
|
||||
}`}>
|
||||
{drive.icon}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-white font-bold">({drive.id}:)</span>
|
||||
<span className="text-white/70">{drive.name}</span>
|
||||
</div>
|
||||
<div className="text-xs mt-1">
|
||||
{drive.status === 'online' ? (
|
||||
<span className="text-cyan-400">{drive.used} / {drive.size} used</span>
|
||||
) : (
|
||||
<span className="text-red-400 flex items-center gap-1">
|
||||
<Lock className="w-3 h-3" /> Not Mounted
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`w-2 h-2 rounded-full ${
|
||||
drive.status === 'online' ? 'bg-green-500 animate-pulse' : 'bg-red-500'
|
||||
}`} />
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<AnimatePresence>
|
||||
{selectedDrive === 'D' && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
className="mt-6 border border-red-500/30 bg-red-500/10 rounded-lg p-4"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<AlertTriangle className="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<div className="text-red-400 font-bold mb-1">ERROR: Drive Not Mounted</div>
|
||||
<div className="text-white/70 text-sm mb-3">
|
||||
No .aethex domain detected for this identity.
|
||||
</div>
|
||||
<div className="text-white/50 text-xs mb-4">
|
||||
Join The Foundry to reserve your namespace in the AeThex ecosystem.
|
||||
</div>
|
||||
<a
|
||||
href="https://aethex.studio"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 px-4 py-2 bg-yellow-500 hover:bg-yellow-400 text-black text-sm font-bold uppercase tracking-wider transition-colors"
|
||||
>
|
||||
Join The Foundry <ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
{selectedDrive === 'C' && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
className="mt-6 border border-cyan-500/30 bg-cyan-500/5 rounded-lg p-4"
|
||||
>
|
||||
<div className="text-cyan-400 font-bold mb-2">Local System Storage</div>
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between text-white/70">
|
||||
<span>/system</span><span>32 GB</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-white/70">
|
||||
<span>/apps</span><span>16 GB</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-white/70">
|
||||
<span>/user</span><span>12 GB</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-white/70">
|
||||
<span>/cache</span><span>4 GB</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function MissionApp() {
|
||||
return (
|
||||
<div className="h-full bg-black flex flex-col font-mono">
|
||||
|
|
|
|||
Loading…
Reference in a new issue