From 1b0a494c1d2a55c36d1493d0be553be6ebc0e8ca Mon Sep 17 00:00:00 2001 From: sirpiglr <49359077-sirpiglr@users.noreply.replit.com> Date: Sun, 21 Dec 2025 04:09:30 +0000 Subject: [PATCH] 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 --- client/index.html | 5 + client/public/manifest.json | 20 +++ client/public/opengraph.jpg | Bin 11714 -> 10628 bytes client/src/pages/os.tsx | 327 ++++++++++++++++++++++++++++++------ 4 files changed, 300 insertions(+), 52 deletions(-) create mode 100644 client/public/manifest.json diff --git a/client/index.html b/client/index.html index d36e27c..1237aee 100644 --- a/client/index.html +++ b/client/index.html @@ -15,6 +15,11 @@ + + + + + diff --git a/client/public/manifest.json b/client/public/manifest.json new file mode 100644 index 0000000..ad6d847 --- /dev/null +++ b/client/public/manifest.json @@ -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 +} diff --git a/client/public/opengraph.jpg b/client/public/opengraph.jpg index 747b745d2a2dee143235337d723a253535d6549a..dd895df0f89ac6fd1b8b65c9a3cea1099ce4677e 100644 GIT binary patch delta 4847 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 diff --git a/client/src/pages/os.tsx b/client/src/pages/os.tsx index fab6f5c..07c7deb 100644 --- a/client/src/pages/os.tsx +++ b/client/src/pages/os.tsx @@ -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 ; - case 'passport': return ; + case 'passport': return ; case 'files': return ; case 'network': return ; case 'metrics': return ; @@ -607,12 +613,13 @@ export default function AeThexOS() { case 'chat': return ; case 'music': return ; case 'pitch': return setLocation('/pitch')} />; - case 'networkneighborhood': return ; - case 'foundry': return ; - case 'devtools': return ; + case 'networkneighborhood': return ; + case 'foundry': return ; + case 'devtools': return ; case 'mission': return ; case 'intel': return ; - case 'drives': return ; + case 'drives': return ; + case 'iframe': return null; case 'settings': return { 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: , + 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 (
@@ -807,6 +841,32 @@ export default function AeThexOS() { ))}
+ {isDesktopLocked && windows.length === 0 && ( + +
+
+ +
+

Desktop Locked

+

Sign in with your Passport to continue

+ +
+
+ )} + {windows.filter(w => !w.minimized && w.desktopId === currentDesktop).map((window) => ( 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 ? ( +