Add graphics error handling and notification for WebGL issues
This commit is contained in:
@@ -434,6 +434,45 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
|
|
||||||
const [stackOrderModified, setStackOrderModified] = useState(false);
|
const [stackOrderModified, setStackOrderModified] = useState(false);
|
||||||
const [loadingState, setLoadingState] = useState<null | "annotations" | "viewerState">(null);
|
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
|
// Load annotations and viewer state from props if provided
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let didCancel = false;
|
let didCancel = false;
|
||||||
@@ -3578,6 +3617,37 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
|||||||
</div>
|
</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 */}
|
{/* top stack bar removed; use right-side panel instead */}
|
||||||
|
|
||||||
{/* Right-side stack panel is implemented in the main content flex container below */}
|
{/* Right-side stack panel is implemented in the main content flex container below */}
|
||||||
|
|||||||
Reference in New Issue
Block a user