diff --git a/.replit b/.replit index 76d2fa09..5a7efd43 100644 --- a/.replit +++ b/.replit @@ -52,6 +52,10 @@ externalPort = 80 localPort = 8044 externalPort = 3003 +[[ports]] +localPort = 35519 +externalPort = 3002 + [[ports]] localPort = 38557 externalPort = 3000 diff --git a/client/components/Scene.tsx b/client/components/Scene.tsx index c97e25e8..612900c5 100644 --- a/client/components/Scene.tsx +++ b/client/components/Scene.tsx @@ -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 ( +
+ +

+ AeThex OS +

+

+ Select Your Realm +

+
+ +
+ {gateways.map((gw, i) => ( + + { + 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"; + }} + > +
+ {gw.label} +
+ +
+ ))} +
+ + + + Connect Passport + + +
+ ); +} + +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(null); + const [webglError, setWebglError] = useState(false); + + useEffect(() => { + setWebglSupported(checkWebGLSupport()); + }, []); + + if (webglSupported === null) { + return ( +
+ ); + } + + if (!webglSupported || webglError) { + return ; + } + return (
{ + gl.domElement.addEventListener("webglcontextlost", () => { + setWebglError(true); + }); + }} > diff --git a/client/components/TitleBar.tsx b/client/components/TitleBar.tsx index 362424e3..db68e46d 100644 --- a/client/components/TitleBar.tsx +++ b/client/components/TitleBar.tsx @@ -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} >
AeThex Terminal