Update app.css and ViewportCanvas.tsx for WebGL fallback handling
This commit is contained in:
@@ -290,6 +290,27 @@ button:disabled {
|
|||||||
height: 100%;
|
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 {
|
.status-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import type { WorldSettings } from "../document/scene-document";
|
import type { WorldSettings } from "../document/scene-document";
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ interface ViewportCanvasProps {
|
|||||||
export function ViewportCanvas({ world }: ViewportCanvasProps) {
|
export function ViewportCanvas({ world }: ViewportCanvasProps) {
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const hostRef = useRef<ViewportHost | null>(null);
|
const hostRef = useRef<ViewportHost | null>(null);
|
||||||
|
const [viewportMessage, setViewportMessage] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
@@ -19,19 +20,46 @@ export function ViewportCanvas({ world }: ViewportCanvasProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewportHost = new ViewportHost();
|
const testCanvas = document.createElement("canvas");
|
||||||
hostRef.current = viewportHost;
|
const hasWebGl =
|
||||||
viewportHost.mount(container);
|
testCanvas.getContext("webgl2") !== null ||
|
||||||
|
testCanvas.getContext("webgl") !== null ||
|
||||||
|
testCanvas.getContext("experimental-webgl") !== null;
|
||||||
|
|
||||||
return () => {
|
if (!hasWebGl) {
|
||||||
viewportHost.dispose();
|
setViewportMessage("WebGL is unavailable in this browser environment. The viewport shell is visible, but rendering is disabled.");
|
||||||
hostRef.current = null;
|
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(() => {
|
useEffect(() => {
|
||||||
hostRef.current?.updateWorld(world);
|
hostRef.current?.updateWorld(world);
|
||||||
}, [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>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user