Add a fallback interface for when the 3D scene cannot be rendered
Updates Scene.tsx to include a fallback UI with realm selection when WebGL is not available, and fixes TypeScript errors in TitleBar.tsx. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 893e1048-aa5f-4dea-8907-56a7ccad680b Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/c8LGG4t Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
82de4d9b41
commit
a2805ea740
4 changed files with 173 additions and 5 deletions
4
.replit
4
.replit
|
|
@ -52,6 +52,10 @@ externalPort = 80
|
|||
localPort = 8044
|
||||
externalPort = 3003
|
||||
|
||||
[[ports]]
|
||||
localPort = 35519
|
||||
externalPort = 3002
|
||||
|
||||
[[ports]]
|
||||
localPort = 38557
|
||||
externalPort = 3000
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { Canvas, useFrame, useThree } from "@react-three/fiber";
|
||||
import { Grid, OrbitControls, Text } from "@react-three/drei";
|
||||
import * as THREE from "three";
|
||||
import { MathUtils, Vector3 } from "three";
|
||||
import React, { useMemo, useRef, useState } from "react";
|
||||
import React, { useMemo, useRef, useState, useEffect } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
|
||||
type Gateway = {
|
||||
label: string;
|
||||
|
|
@ -241,7 +242,145 @@ function SceneContent() {
|
|||
);
|
||||
}
|
||||
|
||||
function FallbackUI() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
background: "linear-gradient(135deg, #030712 0%, #0f172a 50%, #1e1b4b 100%)",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontFamily: "Inter, sans-serif",
|
||||
color: "#e5e7eb",
|
||||
padding: 20,
|
||||
}}
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
style={{ textAlign: "center", marginBottom: 40 }}
|
||||
>
|
||||
<h1 style={{ fontSize: 48, fontWeight: 700, marginBottom: 8, letterSpacing: "0.05em" }}>
|
||||
AeThex OS
|
||||
</h1>
|
||||
<p style={{ fontSize: 16, opacity: 0.7, letterSpacing: "0.1em" }}>
|
||||
Select Your Realm
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
|
||||
gap: 16,
|
||||
maxWidth: 900,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
{gateways.map((gw, i) => (
|
||||
<motion.div
|
||||
key={gw.label}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.4, delay: i * 0.1 }}
|
||||
>
|
||||
<Link
|
||||
to={gw.route}
|
||||
style={{
|
||||
display: "block",
|
||||
padding: "24px 20px",
|
||||
borderRadius: 16,
|
||||
border: `2px solid ${gw.color}40`,
|
||||
background: `${gw.color}10`,
|
||||
textDecoration: "none",
|
||||
color: "#e5e7eb",
|
||||
textAlign: "center",
|
||||
transition: "all 0.3s ease",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.borderColor = gw.color;
|
||||
e.currentTarget.style.transform = "translateY(-4px)";
|
||||
e.currentTarget.style.boxShadow = `0 8px 30px ${gw.color}30`;
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.borderColor = `${gw.color}40`;
|
||||
e.currentTarget.style.transform = "translateY(0)";
|
||||
e.currentTarget.style.boxShadow = "none";
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 18,
|
||||
fontWeight: 600,
|
||||
letterSpacing: "0.1em",
|
||||
color: gw.color,
|
||||
}}
|
||||
>
|
||||
{gw.label}
|
||||
</div>
|
||||
</Link>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.6, delay: 0.5 }}
|
||||
style={{ marginTop: 40 }}
|
||||
>
|
||||
<Link
|
||||
to="/login"
|
||||
style={{
|
||||
padding: "12px 24px",
|
||||
borderRadius: 10,
|
||||
border: "1px solid #38bdf8",
|
||||
background: "rgba(14, 165, 233, 0.12)",
|
||||
color: "#e0f2fe",
|
||||
fontWeight: 600,
|
||||
textDecoration: "none",
|
||||
backdropFilter: "blur(6px)",
|
||||
}}
|
||||
>
|
||||
Connect Passport
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function checkWebGLSupport(): boolean {
|
||||
try {
|
||||
const canvas = document.createElement("canvas");
|
||||
const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
||||
return !!gl;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default function Scene() {
|
||||
const [webglSupported, setWebglSupported] = useState<boolean | null>(null);
|
||||
const [webglError, setWebglError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setWebglSupported(checkWebGLSupport());
|
||||
}, []);
|
||||
|
||||
if (webglSupported === null) {
|
||||
return (
|
||||
<div style={{ width: "100vw", height: "100vh", background: "#030712" }} />
|
||||
);
|
||||
}
|
||||
|
||||
if (!webglSupported || webglError) {
|
||||
return <FallbackUI />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
|
|
@ -299,6 +438,11 @@ export default function Scene() {
|
|||
shadows
|
||||
camera={{ position: [0, 3, 12], fov: 50, near: 0.1, far: 100 }}
|
||||
gl={{ antialias: true }}
|
||||
onCreated={({ gl }) => {
|
||||
gl.domElement.addEventListener("webglcontextlost", () => {
|
||||
setWebglError(true);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<SceneContent />
|
||||
</Canvas>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from "react";
|
||||
import { useState, CSSProperties } from "react";
|
||||
|
||||
export default function TitleBar() {
|
||||
const [pinned, setPinned] = useState(false);
|
||||
|
|
@ -19,11 +19,12 @@ export default function TitleBar() {
|
|||
padding: "0 12px",
|
||||
background: "#050814",
|
||||
color: "#9ca3af",
|
||||
// @ts-ignore - Electron-specific property
|
||||
WebkitAppRegion: "drag",
|
||||
borderBottom: "1px solid #0f172a",
|
||||
letterSpacing: "0.08em",
|
||||
fontSize: 12,
|
||||
}}
|
||||
} as CSSProperties}
|
||||
>
|
||||
<div style={{ fontFamily: "Space Mono, monospace" }}>AeThex Terminal</div>
|
||||
<div
|
||||
|
|
@ -31,8 +32,9 @@ export default function TitleBar() {
|
|||
marginLeft: "auto",
|
||||
display: "flex",
|
||||
gap: 8,
|
||||
// @ts-ignore - Electron-specific property
|
||||
WebkitAppRegion: "no-drag",
|
||||
}}
|
||||
} as CSSProperties}
|
||||
>
|
||||
<button
|
||||
onClick={() => call("togglePin")}
|
||||
|
|
|
|||
18
replit.md
18
replit.md
|
|
@ -142,6 +142,24 @@ https://supabase.aethex.tech/auth/v1/callback
|
|||
- `https://aethex.foundation/**`
|
||||
- `https://supabase.aethex.tech/auth/v1/callback`
|
||||
|
||||
## Recent Changes (December 5, 2025)
|
||||
- ✅ **Electron Desktop App Support**: Added desktop application framework
|
||||
- `electron/main.js` - Main Electron process with window management
|
||||
- `electron/preload.js` - Secure IPC bridge for frontend communication
|
||||
- `electron-builder.yml` - Build configuration for packaging
|
||||
- `client/components/DesktopShell.tsx` - Desktop wrapper with title bar
|
||||
- `client/components/TitleBar.tsx` - Custom title bar with pin/minimize/maximize/close
|
||||
- `client/pages/Overlay.tsx` - File watcher overlay for development tools
|
||||
- ✅ **3D Scene Landing Page**: New immersive realm selector
|
||||
- `client/components/Scene.tsx` - Three.js/React Three Fiber 3D scene
|
||||
- Animated gateway meshes for each realm (Nexus, GameForge, Foundation, Labs, Corp)
|
||||
- Camera rig with smooth transitions on realm selection
|
||||
- WebGL fallback UI when 3D rendering isn't available
|
||||
- ✅ **Utility Services**: New backend services
|
||||
- `services/pii-scrub.js` - PII scrubbing utility for privacy
|
||||
- `services/watcher.js` - File watcher for development workflow
|
||||
- ✅ **TypeScript Fixes**: Fixed THREE namespace import and WebkitAppRegion typing
|
||||
|
||||
## Recent Changes (December 4, 2025)
|
||||
- ✅ **RealmSwitcher Alignment Fix**: Fixed realm IDs to match ARMS taxonomy
|
||||
- Old IDs (`game_developer`, `client`, `community_member`, `customer`) replaced with ARMS IDs (`labs`, `gameforge`, `corp`, `foundation`, `devlink`, `nexus`, `staff`)
|
||||
|
|
|
|||
Loading…
Reference in a new issue