forked from sagnik/Project_Astral
139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
import React, { useEffect, useRef } from 'react';
|
|
import { useDesktopStore } from '@/stores/desktopStore';
|
|
import { NebulaBackground } from '@/components/nebula/NebulaBackground';
|
|
import { VaultDoor } from '@/sections/VaultDoor';
|
|
import { ProjectNexus } from '@/sections/ProjectNexus';
|
|
import { Dock } from '@/components/dock/Dock';
|
|
import { ProductionHub } from '@/components/apps/ProductionHub';
|
|
import { AssetVault } from '@/components/apps/AssetVault';
|
|
import { EngineRoom } from '@/components/apps/EngineRoom';
|
|
import { UserControl } from '@/components/user/UserControl';
|
|
import { SystemPreferencesWindow } from '@/components/settings/SystemPreferencesWindow';
|
|
import { useSettingsStore } from '@/stores/settingsStore';
|
|
|
|
function App() {
|
|
const { currentStage } = useDesktopStore();
|
|
const initializeSettings = useSettingsStore((state) => state.initializeSettings);
|
|
const appRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
const root = appRef.current;
|
|
if (!root) return;
|
|
|
|
const maxShift = 16;
|
|
let targetX = 0;
|
|
let targetY = 0;
|
|
let currentX = 0;
|
|
let currentY = 0;
|
|
let rafId = 0;
|
|
|
|
const onMouseMove = (e: MouseEvent) => {
|
|
const nx = e.clientX / window.innerWidth - 0.5;
|
|
const ny = e.clientY / window.innerHeight - 0.5;
|
|
targetX = nx * maxShift;
|
|
targetY = ny * maxShift;
|
|
};
|
|
|
|
const onMouseLeave = () => {
|
|
targetX = 0;
|
|
targetY = 0;
|
|
};
|
|
|
|
const tick = () => {
|
|
currentX += (targetX - currentX) * 0.08;
|
|
currentY += (targetY - currentY) * 0.08;
|
|
root.style.setProperty('--parallax-x', `${currentX.toFixed(2)}px`);
|
|
root.style.setProperty('--parallax-y', `${currentY.toFixed(2)}px`);
|
|
rafId = requestAnimationFrame(tick);
|
|
};
|
|
|
|
window.addEventListener('mousemove', onMouseMove);
|
|
window.addEventListener('mouseleave', onMouseLeave);
|
|
rafId = requestAnimationFrame(tick);
|
|
|
|
return () => {
|
|
window.removeEventListener('mousemove', onMouseMove);
|
|
window.removeEventListener('mouseleave', onMouseLeave);
|
|
cancelAnimationFrame(rafId);
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
initializeSettings();
|
|
}, [initializeSettings]);
|
|
|
|
return (
|
|
<div ref={appRef} className="relative w-screen h-screen overflow-hidden bg-black">
|
|
{/* Nebula Background - Always visible */}
|
|
<NebulaBackground />
|
|
|
|
{/* Noise Overlay */}
|
|
<div className="noise-overlay parallax-layer-foreground" />
|
|
|
|
{/* Stage 1: Vault Door */}
|
|
{currentStage === 'vault' && <VaultDoor />}
|
|
|
|
{/* Stage 2: Project Nexus */}
|
|
{currentStage === 'nexus' && <ProjectNexus />}
|
|
|
|
{/* Stage 3: Astral Workspace */}
|
|
{currentStage === 'workspace' && <Workspace />}
|
|
|
|
{/* Global Settings Modal */}
|
|
<SystemPreferencesWindow />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Workspace Component (Stage 3)
|
|
const Workspace: React.FC = () => {
|
|
return (
|
|
<div className="fixed inset-0 z-30">
|
|
{/* Status Bar */}
|
|
<StatusBar />
|
|
|
|
{/* App Windows */}
|
|
<ProductionHub />
|
|
<AssetVault />
|
|
<EngineRoom />
|
|
|
|
{/* The Dock */}
|
|
<Dock />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Status Bar Component
|
|
const StatusBar: React.FC = () => {
|
|
const { selectedProject, setStage } = useDesktopStore();
|
|
|
|
return (
|
|
<div className="fixed inset-x-0 top-0 z-[5] pointer-events-none">
|
|
{/* Left - Project Name */}
|
|
<div className="absolute top-8 left-8 flex items-center gap-4 pointer-events-auto">
|
|
<button
|
|
type="button"
|
|
onClick={() => setStage('nexus')}
|
|
className="text-xs font-semibold tracking-[0.15em] uppercase opacity-60 hover:opacity-100 transition-opacity duration-300"
|
|
>
|
|
Astral Suite
|
|
</button>
|
|
{selectedProject && (
|
|
<>
|
|
<span className="text-xs opacity-30">/</span>
|
|
<span className="text-xs font-medium">{selectedProject.name}</span>
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
{/* Right - User Control */}
|
|
<div className="absolute top-6 right-8 pointer-events-auto">
|
|
<UserControl />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default App;
|
|
|