Add graphics error handling and notification for WebGL issues

This commit is contained in:
Ross
2026-03-16 10:53:26 +00:00
parent ef62ffac9f
commit 8dc4bb0aaa
+70
View File
@@ -434,6 +434,45 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
const [stackOrderModified, setStackOrderModified] = useState(false);
const [loadingState, setLoadingState] = useState<null | "annotations" | "viewerState">(null);
// Show a warning when a WebGL/graphics resource error (e.g. releaseGraphicsResources) occurs
const [graphicsErrorVisible, setGraphicsErrorVisible] = useState(false);
const [graphicsErrorMessage, setGraphicsErrorMessage] = useState<string | null>(null);
useEffect(() => {
const onError = (ev: ErrorEvent) => {
try {
const msg = ev && ev.message ? String(ev.message) : '';
if (msg.includes('releaseGraphicsResources') || msg.includes('openGLTexture')) {
console.error('Detected graphics resource error:', ev);
setGraphicsErrorMessage(msg || null);
setGraphicsErrorVisible(true);
}
} catch (e) {
// ignore
}
};
const onRejection = (ev: PromiseRejectionEvent) => {
try {
const reason = (ev && (ev as any).reason) || '';
const text = typeof reason === 'string' ? reason : (reason && reason.message) ? reason.message : String(reason);
if (text.includes('releaseGraphicsResources') || text.includes('openGLTexture')) {
console.error('Detected graphics resource rejection:', ev);
setGraphicsErrorMessage(text || null);
setGraphicsErrorVisible(true);
}
} catch (e) {
// ignore
}
};
window.addEventListener('error', onError as EventListener);
window.addEventListener('unhandledrejection', onRejection as EventListener);
return () => {
window.removeEventListener('error', onError as EventListener);
window.removeEventListener('unhandledrejection', onRejection as EventListener);
};
}, []);
// Load annotations and viewer state from props if provided
useEffect(() => {
let didCancel = false;
@@ -3578,6 +3617,37 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
</div>
)}
{/* Graphics error banner (shows when we detect a problematic WebGL release error) */}
{graphicsErrorVisible && (
<div
style={{
position: 'fixed',
top: 12,
left: 12,
right: 12,
zIndex: 10000,
background: '#fff3cd',
color: '#856404',
border: '1px solid #ffeeba',
padding: '10px 14px',
borderRadius: 6,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 12,
}}
>
<div style={{ flex: 1, fontSize: 14 }}>
<strong>Graphics error:</strong> The viewer encountered a WebGL/graphics error and may be unstable. Please reload the page.
{graphicsErrorMessage ? (<div style={{ marginTop: 6, fontSize: 12, color: '#6b4f00' }}>{graphicsErrorMessage}</div>) : null}
</div>
<div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
<button onClick={() => window.location.reload()} style={{ padding: '6px 10px' }}>Reload</button>
<button onClick={() => setGraphicsErrorVisible(false)} style={{ padding: '6px 10px' }}>Dismiss</button>
</div>
</div>
)}
{/* top stack bar removed; use right-side panel instead */}
{/* Right-side stack panel is implemented in the main content flex container below */}