Enhance platform security and user experience with locked desktop and app management

Introduce a locked desktop state, preventing app access until login, and add a manifest.json file for progressive web app capabilities. Refactor the openApp function to handle locked states and ensure consistent use of appToOpen. Modify PassportApp to accept login success callbacks and add iframe support for specific applications.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 279f1558-c0e3-40e4-8217-be7e9f4c6eca
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 6153830e-2a7f-4460-a370-8b1f26cbfd29
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/b984cb14-1d19-4944-922b-bc79e821ed35/279f1558-c0e3-40e4-8217-be7e9f4c6eca/KKo8ABE
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sirpiglr 2025-12-21 04:09:30 +00:00
parent 0c40ae53b7
commit 1b0a494c1d
4 changed files with 300 additions and 52 deletions

View file

@ -15,6 +15,11 @@
<meta name="twitter:image" content="https://replit.com/public/images/opengraph.png" />
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#06B6D4" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="AeThex OS" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Importing Oxanium (Tech/Display) and JetBrains Mono (Code/UI) and Share Tech Mono -->

View file

@ -0,0 +1,20 @@
{
"name": "AeThex OS",
"short_name": "AeThex",
"description": "The Operating System for the Metaverse. Cross-platform identity and certification.",
"start_url": "/",
"display": "standalone",
"background_color": "#0F172A",
"theme_color": "#06B6D4",
"orientation": "any",
"icons": [
{
"src": "/favicon.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
}
],
"categories": ["productivity", "utilities", "developer"],
"prefer_related_applications": false
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -30,6 +30,7 @@ interface WindowState {
zIndex: number;
accentColor?: string;
desktopId: number;
iframeUrl?: string;
}
interface Toast {
@ -250,6 +251,7 @@ export default function AeThexOS() {
}, []);
const [showLoginPrompt, setShowLoginPrompt] = useState(false);
const [isDesktopLocked, setIsDesktopLocked] = useState(true);
useEffect(() => {
const bootSequence = async () => {
@ -461,14 +463,18 @@ export default function AeThexOS() {
}, [clearanceMode, addToast, playSound]);
const openApp = useCallback((app: DesktopApp) => {
const appToOpen = (isDesktopLocked && app.id !== 'passport')
? apps.find(a => a.id === 'passport') || app
: app;
playSound('open');
const existingWindow = windows.find(w => w.id === app.id);
const existingWindow = windows.find(w => w.id === appToOpen.id);
if (existingWindow) {
setWindows(prev => prev.map(w =>
w.id === app.id ? { ...w, minimized: false, zIndex: maxZIndex + 1, desktopId: currentDesktop } : w
w.id === appToOpen.id ? { ...w, minimized: false, zIndex: maxZIndex + 1, desktopId: currentDesktop } : w
));
setMaxZIndex(prev => prev + 1);
setActiveWindowId(app.id);
setActiveWindowId(appToOpen.id);
return;
}
@ -476,14 +482,14 @@ export default function AeThexOS() {
const offsetY = (windows.length % 5) * 40 + 50;
const newWindow: WindowState = {
id: app.id,
title: app.title,
icon: app.icon,
component: app.component,
id: appToOpen.id,
title: appToOpen.title,
icon: appToOpen.icon,
component: appToOpen.component,
x: offsetX,
y: offsetY,
width: app.defaultWidth,
height: app.defaultHeight,
width: appToOpen.defaultWidth,
height: appToOpen.defaultHeight,
minimized: false,
maximized: false,
zIndex: maxZIndex + 1,
@ -492,9 +498,9 @@ export default function AeThexOS() {
setWindows(prev => [...prev, newWindow]);
setMaxZIndex(prev => prev + 1);
setActiveWindowId(app.id);
setActiveWindowId(appToOpen.id);
setShowStartMenu(false);
}, [windows, maxZIndex, playSound, currentDesktop]);
}, [windows, maxZIndex, playSound, currentDesktop, isDesktopLocked, apps]);
const closeWindow = useCallback((id: string) => {
playSound('close');
@ -590,7 +596,7 @@ export default function AeThexOS() {
const renderAppContent = (component: string) => {
switch (component) {
case 'terminal': return <TerminalApp />;
case 'passport': return <PassportApp />;
case 'passport': return <PassportApp onLoginSuccess={unlockDesktop} isDesktopLocked={isDesktopLocked} />;
case 'files': return <FilesApp />;
case 'network': return <NetworkMapApp />;
case 'metrics': return <MetricsDashboardApp />;
@ -607,12 +613,13 @@ export default function AeThexOS() {
case 'chat': return <ChatApp />;
case 'music': return <MusicApp />;
case 'pitch': return <PitchApp onNavigate={() => setLocation('/pitch')} />;
case 'networkneighborhood': return <NetworkNeighborhoodApp />;
case 'foundry': return <FoundryApp />;
case 'devtools': return <DevToolsApp />;
case 'networkneighborhood': return <NetworkNeighborhoodApp openIframeWindow={openIframeWindow} />;
case 'foundry': return <FoundryApp openIframeWindow={openIframeWindow} />;
case 'devtools': return <DevToolsApp openIframeWindow={openIframeWindow} />;
case 'mission': return <MissionApp />;
case 'intel': return <IntelApp />;
case 'drives': return <DrivesApp />;
case 'drives': return <DrivesApp openIframeWindow={openIframeWindow} />;
case 'iframe': return null;
case 'settings': return <SettingsApp
wallpaper={wallpaper}
setWallpaper={setWallpaper}
@ -670,6 +677,7 @@ export default function AeThexOS() {
const handleGuestContinue = () => {
setShowLoginPrompt(false);
setIsBooting(false);
setIsDesktopLocked(false);
const randomTip = DAILY_TIPS[Math.floor(Math.random() * DAILY_TIPS.length)];
setDailyTip(randomTip);
setTimeout(() => setShowDailyTip(true), 1000);
@ -678,6 +686,7 @@ export default function AeThexOS() {
const handleLoginFromBoot = () => {
setShowLoginPrompt(false);
setIsBooting(false);
// Keep desktop locked until login succeeds
const randomTip = DAILY_TIPS[Math.floor(Math.random() * DAILY_TIPS.length)];
setDailyTip(randomTip);
setTimeout(() => {
@ -687,6 +696,31 @@ export default function AeThexOS() {
}, 500);
};
const unlockDesktop = () => {
setIsDesktopLocked(false);
};
const openIframeWindow = (url: string, title: string) => {
const windowId = `iframe-${Date.now()}`;
setWindows(prev => [...prev, {
id: windowId,
title,
icon: <Globe className="w-4 h-4" />,
component: 'iframe',
x: 100 + Math.random() * 100,
y: 100 + Math.random() * 100,
width: 900,
height: 600,
minimized: false,
maximized: false,
zIndex: maxZIndex + 1,
desktopId: currentDesktop,
iframeUrl: url
}]);
setMaxZIndex(prev => prev + 1);
setActiveWindowId(windowId);
};
if (isBooting) {
return (
<div className="h-screen w-screen bg-black flex flex-col items-center justify-center">
@ -807,6 +841,32 @@ export default function AeThexOS() {
))}
</div>
{isDesktopLocked && windows.length === 0 && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="absolute inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50"
>
<div className="text-center">
<div className="w-20 h-20 mx-auto rounded-full bg-gradient-to-br from-cyan-500 to-purple-600 flex items-center justify-center mb-4">
<Lock className="w-10 h-10 text-white" />
</div>
<h2 className="text-xl font-display text-white uppercase tracking-wider mb-2">Desktop Locked</h2>
<p className="text-white/60 text-sm font-mono mb-6">Sign in with your Passport to continue</p>
<button
onClick={() => {
const passportApp = apps.find(a => a.id === 'passport');
if (passportApp) openApp(passportApp);
}}
className="px-6 py-3 bg-cyan-500 hover:bg-cyan-400 text-black font-mono font-bold uppercase tracking-wider transition-colors"
data-testid="unlock-desktop-btn"
>
Open Passport
</button>
</div>
</motion.div>
)}
<AnimatePresence>
{windows.filter(w => !w.minimized && w.desktopId === currentDesktop).map((window) => (
<Window
@ -820,7 +880,14 @@ export default function AeThexOS() {
onMove={(x, y) => setWindows(prev => prev.map(w => w.id === window.id ? { ...w, x, y } : w))}
onResize={(width, height) => setWindows(prev => prev.map(w => w.id === window.id ? { ...w, width, height } : w))}
onSnap={(x, y) => handleWindowSnap(window.id, x, y, window.width, window.height)}
content={renderAppContent(window.component)}
content={window.component === 'iframe' && window.iframeUrl ? (
<iframe
src={window.iframeUrl}
className="w-full h-full border-0"
title={window.title}
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
/>
) : renderAppContent(window.component)}
/>
))}
</AnimatePresence>
@ -883,6 +950,7 @@ export default function AeThexOS() {
onClearNotification={(idx) => setNotifications(prev => prev.filter((_, i) => i !== idx))}
onClearAllNotifications={() => setNotifications([])}
desktopWindowCounts={[0, 1, 2, 3].map(d => windows.filter(w => w.desktopId === d).length)}
openIframeWindow={openIframeWindow}
/>
<AnimatePresence>
@ -1347,6 +1415,7 @@ interface TaskbarProps {
onClearNotification: (index: number) => void;
onClearAllNotifications: () => void;
desktopWindowCounts: number[];
openIframeWindow?: (url: string, title: string) => void;
}
function Skeleton({ className = "", animate = true }: { className?: string; animate?: boolean }) {
@ -1554,7 +1623,7 @@ function OnboardingTour({ step, onNext, onClose }: { step: number; onNext: () =>
);
}
function Taskbar({ windows, activeWindowId, apps, time, showStartMenu, user, isAuthenticated, notifications, showNotifications, onToggleStartMenu, onToggleNotifications, onWindowClick, onAppClick, onLogout, onNavigate, currentDesktop, onDesktopChange, clearanceTheme, onSwitchClearance, activeTrayPanel, onTrayPanelToggle, volume, onVolumeChange, isMuted, onMuteToggle, batteryInfo, onClearNotification, onClearAllNotifications, desktopWindowCounts }: TaskbarProps) {
function Taskbar({ windows, activeWindowId, apps, time, showStartMenu, user, isAuthenticated, notifications, showNotifications, onToggleStartMenu, onToggleNotifications, onWindowClick, onAppClick, onLogout, onNavigate, currentDesktop, onDesktopChange, clearanceTheme, onSwitchClearance, activeTrayPanel, onTrayPanelToggle, volume, onVolumeChange, isMuted, onMuteToggle, batteryInfo, onClearNotification, onClearAllNotifications, desktopWindowCounts, openIframeWindow }: TaskbarProps) {
return (
<>
<AnimatePresence>
@ -2079,14 +2148,12 @@ function Taskbar({ windows, activeWindowId, apps, time, showStartMenu, user, isA
<Globe className="w-3 h-3 text-yellow-400" /> .aethex namespace
</div>
</div>
<a
href="https://aethex.studio"
target="_blank"
rel="noopener noreferrer"
<button
onClick={() => openIframeWindow?.('https://aethex.studio', 'The Foundry')}
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>
</button>
<div className="text-center text-xs text-white/40">
Hint: Check the terminal for promo codes
</div>
@ -2725,9 +2792,16 @@ function TerminalApp() {
);
}
function PassportApp() {
const { user, isAuthenticated } = useAuth();
const { data: profile, isLoading } = useQuery({
function PassportApp({ onLoginSuccess, isDesktopLocked }: { onLoginSuccess?: () => void; isDesktopLocked?: boolean }) {
const { user, isAuthenticated, login, signup, logout } = useAuth();
const [mode, setMode] = useState<'view' | 'login' | 'signup'>('view');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [username, setUsername] = useState('');
const [error, setError] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const { data: profile } = useQuery({
queryKey: ['os-user-profile'],
queryFn: async () => {
const res = await fetch('/api/metrics');
@ -2736,6 +2810,143 @@ function PassportApp() {
enabled: true,
});
useEffect(() => {
if (isAuthenticated && isDesktopLocked && onLoginSuccess) {
onLoginSuccess();
}
}, [isAuthenticated, isDesktopLocked, onLoginSuccess]);
useEffect(() => {
if (!isAuthenticated && isDesktopLocked) {
setMode('login');
}
}, [isAuthenticated, isDesktopLocked]);
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setIsSubmitting(true);
try {
await login(email, password);
setMode('view');
if (onLoginSuccess) onLoginSuccess();
} catch (err: any) {
setError(err.message || 'Login failed');
} finally {
setIsSubmitting(false);
}
};
const handleSignup = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setIsSubmitting(true);
try {
await signup(email, password, username || undefined);
setMode('login');
setError('Account created! Please sign in.');
} catch (err: any) {
setError(err.message || 'Signup failed');
} finally {
setIsSubmitting(false);
}
};
if (mode === 'login' || mode === 'signup') {
return (
<div className="h-full p-6 bg-gradient-to-b from-slate-900 to-slate-950 overflow-auto">
<div className="border border-cyan-400/30 rounded-lg p-6 bg-slate-900/50 max-w-sm mx-auto">
<div className="text-center mb-6">
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-gradient-to-br from-cyan-500 to-purple-600 mb-4">
<Key className="w-8 h-8 text-white" />
</div>
<h2 className="text-xl font-display text-white uppercase tracking-wider">
{mode === 'login' ? 'Sign In' : 'Create Account'}
</h2>
<p className="text-cyan-400 text-sm font-mono mt-1">AeThex Passport</p>
</div>
<form onSubmit={mode === 'login' ? handleLogin : handleSignup} className="space-y-4">
{mode === 'signup' && (
<div>
<label className="block text-white/50 text-xs mb-1 font-mono">USERNAME</label>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="w-full bg-black/50 border border-cyan-500/30 rounded px-3 py-2 text-white font-mono text-sm focus:border-cyan-400 focus:outline-none"
placeholder="architect_name"
data-testid="passport-username"
/>
</div>
)}
<div>
<label className="block text-white/50 text-xs mb-1 font-mono">EMAIL</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full bg-black/50 border border-cyan-500/30 rounded px-3 py-2 text-white font-mono text-sm focus:border-cyan-400 focus:outline-none"
placeholder="you@example.com"
required
data-testid="passport-email"
/>
</div>
<div>
<label className="block text-white/50 text-xs mb-1 font-mono">PASSWORD</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full bg-black/50 border border-cyan-500/30 rounded px-3 py-2 text-white font-mono text-sm focus:border-cyan-400 focus:outline-none"
placeholder="••••••••"
required
data-testid="passport-password"
/>
</div>
{error && (
<div className={`text-sm font-mono p-2 rounded ${error.includes('created') ? 'text-green-400 bg-green-500/10' : 'text-red-400 bg-red-500/10'}`}>
{error}
</div>
)}
<button
type="submit"
disabled={isSubmitting}
className="w-full py-3 bg-cyan-500 hover:bg-cyan-400 text-black font-mono font-bold uppercase tracking-wider transition-colors disabled:opacity-50"
data-testid="passport-submit"
>
{isSubmitting ? 'Processing...' : mode === 'login' ? 'Sign In' : 'Create Account'}
</button>
</form>
<div className="mt-4 text-center">
<button
onClick={() => { setMode(mode === 'login' ? 'signup' : 'login'); setError(''); }}
className="text-cyan-400 hover:text-cyan-300 text-sm font-mono"
data-testid="passport-toggle-mode"
>
{mode === 'login' ? 'Need an account? Sign up' : 'Already have an account? Sign in'}
</button>
</div>
{isDesktopLocked && (
<div className="mt-4 pt-4 border-t border-white/10 text-center">
<button
onClick={onLoginSuccess}
className="text-white/40 hover:text-white/60 text-xs font-mono"
data-testid="passport-skip-guest"
>
Continue as Guest
</button>
</div>
)}
</div>
</div>
);
}
return (
<div className="h-full p-6 bg-gradient-to-b from-slate-900 to-slate-950 overflow-auto">
<div className="border border-cyan-400/30 rounded-lg p-6 bg-slate-900/50">
@ -2770,6 +2981,26 @@ function PassportApp() {
)}
</div>
<div className="mt-6 space-y-3">
{!isAuthenticated ? (
<button
onClick={() => setMode('login')}
className="w-full py-2 bg-cyan-500 hover:bg-cyan-400 text-black font-mono font-bold uppercase tracking-wider transition-colors text-sm"
data-testid="passport-signin-btn"
>
Sign In
</button>
) : (
<button
onClick={() => logout()}
className="w-full py-2 border border-red-500/50 text-red-400 hover:bg-red-500/10 font-mono uppercase tracking-wider transition-colors text-sm"
data-testid="passport-logout-btn"
>
Sign Out
</button>
)}
</div>
<div className="mt-6 pt-4 border-t border-white/10 text-center text-xs text-white/30">
Issued by Codex Certification Authority
</div>
@ -3811,7 +4042,7 @@ function ProfilesApp() {
);
}
function NetworkNeighborhoodApp() {
function NetworkNeighborhoodApp({ openIframeWindow }: { openIframeWindow?: (url: string, title: string) => void }) {
const { data: founders = [], isLoading } = useQuery({
queryKey: ['network-neighborhood'],
queryFn: async () => {
@ -3880,14 +4111,12 @@ function NetworkNeighborhoodApp() {
<span className="text-yellow-500/50 text-xs">[{String(founders.length + idx + 1).padStart(3, '0')}]</span>
<span className="text-yellow-500/70">{slot.name}</span>
</div>
<a
href="https://aethex.studio"
target="_blank"
rel="noopener noreferrer"
<button
onClick={() => openIframeWindow?.('https://aethex.studio', 'The Foundry')}
className="text-xs text-yellow-500 hover:text-yellow-400 transition-colors uppercase tracking-wider flex items-center gap-1"
>
Join <ExternalLink className="w-3 h-3" />
</a>
</button>
</div>
))}
</div>
@ -3898,7 +4127,7 @@ function NetworkNeighborhoodApp() {
);
}
function FoundryApp() {
function FoundryApp({ openIframeWindow }: { openIframeWindow?: (url: string, title: string) => void }) {
const [viewMode, setViewMode] = useState<'info' | 'enroll'>('info');
const [promoCode, setPromoCode] = useState('');
const [promoApplied, setPromoApplied] = useState(false);
@ -4004,17 +4233,15 @@ function FoundryApp() {
)}
</div>
<a
href="https://aethex.studio"
target="_blank"
rel="noopener noreferrer"
<button
onClick={() => openIframeWindow?.('https://aethex.studio', 'The Foundry')}
className="block w-full px-6 py-3 bg-yellow-500 hover:bg-yellow-400 text-black text-center font-bold uppercase tracking-wider transition-colors"
>
Complete Enrollment
</a>
</button>
<p className="text-center text-white/40 text-xs">
Redirects to aethex.studio for payment
Opens enrollment form
</p>
</div>
</div>
@ -4023,7 +4250,7 @@ function FoundryApp() {
);
}
function DevToolsApp() {
function DevToolsApp({ openIframeWindow }: { openIframeWindow?: (url: string, title: string) => void }) {
const tools = [
{ name: "Documentation", desc: "API reference & guides", url: "https://aethex.dev", icon: <FileText className="w-5 h-5" /> },
{ name: "GitHub", desc: "Open source repositories", url: "https://github.com/aethex", icon: <Code2 className="w-5 h-5" /> },
@ -4038,12 +4265,10 @@ function DevToolsApp() {
</div>
<div className="flex-1 overflow-auto p-4 space-y-3">
{tools.map((tool, idx) => (
<a
<button
key={idx}
href={tool.url}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-4 p-4 border border-purple-500/20 bg-purple-500/5 hover:bg-purple-500/10 transition-colors rounded-lg"
onClick={() => tool.url !== '#' && openIframeWindow?.(tool.url, tool.name)}
className="w-full flex items-center gap-4 p-4 border border-purple-500/20 bg-purple-500/5 hover:bg-purple-500/10 transition-colors rounded-lg text-left"
>
<div className="w-10 h-10 rounded-lg bg-purple-500/20 flex items-center justify-center text-purple-400">
{tool.icon}
@ -4053,7 +4278,7 @@ function DevToolsApp() {
<div className="text-purple-400/60 text-sm">{tool.desc}</div>
</div>
<ExternalLink className="w-4 h-4 text-purple-400/40" />
</a>
</button>
))}
</div>
</div>
@ -4200,7 +4425,7 @@ REVENUE MODEL
);
}
function DrivesApp() {
function DrivesApp({ openIframeWindow }: { openIframeWindow?: (url: string, title: string) => void }) {
const [selectedDrive, setSelectedDrive] = useState<string | null>(null);
const drives = [
@ -4277,14 +4502,12 @@ function DrivesApp() {
<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"
<button
onClick={() => openIframeWindow?.('https://aethex.studio', 'The Foundry')}
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>
</button>
</div>
</div>
</motion.div>