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 [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 */}
|
||||
|
||||
Reference in New Issue
Block a user