Update app.css and ViewportCanvas.tsx for WebGL fallback handling

This commit is contained in:
2026-03-31 01:38:24 +02:00
parent f13c5852b8
commit d2e45e525b
2 changed files with 58 additions and 9 deletions

View File

@@ -290,6 +290,27 @@ button:disabled {
height: 100%;
}
.viewport-canvas__fallback {
position: absolute;
inset: 18px;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 8px;
padding: 18px;
color: #f3e8da;
background: linear-gradient(180deg, rgba(8, 10, 14, 0.12) 0%, rgba(8, 10, 14, 0.58) 100%);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 18px;
}
.viewport-canvas__fallback-title {
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.status-bar {
display: flex;
align-items: center;

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import type { WorldSettings } from "../document/scene-document";
@@ -11,6 +11,7 @@ interface ViewportCanvasProps {
export function ViewportCanvas({ world }: ViewportCanvasProps) {
const containerRef = useRef<HTMLDivElement | null>(null);
const hostRef = useRef<ViewportHost | null>(null);
const [viewportMessage, setViewportMessage] = useState<string | null>(null);
useEffect(() => {
const container = containerRef.current;
@@ -19,19 +20,46 @@ export function ViewportCanvas({ world }: ViewportCanvasProps) {
return;
}
const viewportHost = new ViewportHost();
hostRef.current = viewportHost;
viewportHost.mount(container);
const testCanvas = document.createElement("canvas");
const hasWebGl =
testCanvas.getContext("webgl2") !== null ||
testCanvas.getContext("webgl") !== null ||
testCanvas.getContext("experimental-webgl") !== null;
return () => {
viewportHost.dispose();
hostRef.current = null;
};
if (!hasWebGl) {
setViewportMessage("WebGL is unavailable in this browser environment. The viewport shell is visible, but rendering is disabled.");
return;
}
try {
const viewportHost = new ViewportHost();
hostRef.current = viewportHost;
viewportHost.mount(container);
setViewportMessage(null);
return () => {
viewportHost.dispose();
hostRef.current = null;
};
} catch (error) {
const message = error instanceof Error ? error.message : "Viewport initialization failed.";
setViewportMessage(`Viewport initialization failed: ${message}`);
return;
}
}, []);
useEffect(() => {
hostRef.current?.updateWorld(world);
}, [world]);
return <div ref={containerRef} className="viewport-canvas" data-testid="viewport-shell" aria-label="Editor viewport" />;
return (
<div ref={containerRef} className="viewport-canvas" data-testid="viewport-shell" aria-label="Editor viewport">
{viewportMessage === null ? null : (
<div className="viewport-canvas__fallback" role="status">
<div className="viewport-canvas__fallback-title">Viewport Unavailable</div>
<div>{viewportMessage}</div>
</div>
)}
</div>
);
}