Show 3D hall loading overlay during canvas and texture boot.

Display Loading gallery and Loading paintings in the canvas area while the WebGL scene initializes and wall textures resolve, and document the behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Danila Khodjaef
2026-07-08 15:18:16 +03:00
co-authored by Cursor
parent 21e3e41e48
commit aa6635803d
3 changed files with 21 additions and 11 deletions
+16 -10
View File
@@ -1711,6 +1711,7 @@ export default function VirtualGallery(props: Props) {
const [nearPassage, setNearPassage] = useState(false);
const [isLooking, setIsLooking] = useState(false);
const [texturesPending, setTexturesPending] = useState(0);
const [canvasReady, setCanvasReady] = useState(false);
const [glEpoch, setGlEpoch] = useState(0);
const [glLost, setGlLost] = useState(false);
@@ -1722,15 +1723,12 @@ export default function VirtualGallery(props: Props) {
[]
);
useEffect(() => {
setTexturesPending(0);
}, [hallKey, glEpoch]);
const handleCanvasCreated = useCallback((state: { gl: THREE.WebGLRenderer }) => {
const canvas = state.gl.domElement;
// A freshly created canvas has a healthy context, so clear any lingering
// "restoring" state from a previous loss/remount.
setGlLost(false);
setCanvasReady(true);
const onLost = (event: Event) => {
// Prevent the default so the browser can restore the context, and
// force a clean remount to obtain a fresh WebGL context if it does not.
@@ -1798,6 +1796,14 @@ export default function VirtualGallery(props: Props) {
return buildHallLayout(paintings, periods);
}, [isMovement, movementHalls, hallIndex, paintings, periods]);
const gallerySceneLoading = active && !glLost && (!canvasReady || texturesPending > 0);
const galleryLoadingMessage = !canvasReady
? 'Loading gallery…'
: texturesPending > 0
? 'Loading paintings…'
: 'Loading gallery…';
const computedWindows = useMemo(() => {
if (!isMovement || !interiorStyle || !('hallIndex' in layout)) return undefined;
return computeSideWallWindows(layout as MovementHallLayout, interiorStyle);
@@ -2069,10 +2075,13 @@ export default function VirtualGallery(props: Props) {
onPointerLeave={endCanvasDrag}
onPointerCancel={endCanvasDrag}
>
{active && texturesPending > 0 && (
<GalleryLoadingMarker overlay message="Loading paintings…" />
{active && (gallerySceneLoading || glLost) && (
<GalleryLoadingMarker
overlay
message={glLost ? 'Restoring gallery…' : galleryLoadingMessage}
/>
)}
{syncStatus && texturesPending === 0 && (
{syncStatus && !gallerySceneLoading && !glLost && (
<div className="gallery-loading-overlay gallery-sync-badge">
<p>{syncStatus}</p>
</div>
@@ -2080,9 +2089,6 @@ export default function VirtualGallery(props: Props) {
{!showExitNav && (
<div className="gallery-exit-hint">{exitHint}</div>
)}
{glLost && (
<GalleryLoadingMarker overlay message="Restoring gallery…" />
)}
<Canvas
key={`${hallKey}-${glEpoch}`}
shadows