hermes-agent/apps/desktop/src/components/error-boundary.tsx
brooklyn! e003c53b06
chore(desktop): zero eslint/typecheck debt + prettier pass (#39100)
- eslint --fix across src/ and electron/ (unused imports, import/prop sort, padding)
- flatten empty catch blocks in electron CJS; drop unused applyUpdatesPosixInApp arg
- add setMutableRef helper for imperative ref writes (react-compiler clean)
- move sidebar cookie persistence into an effect; extract scrollElementToBottom helper
2026-06-04 14:10:38 +00:00

74 lines
2.1 KiB
TypeScript

import { Component, type ErrorInfo, type ReactNode } from 'react'
import { Button } from '@/components/ui/button'
import { ErrorState } from '@/components/ui/error-state'
export interface ErrorBoundaryFallbackProps {
error: Error
reset: () => void
}
interface ErrorBoundaryProps {
children: ReactNode
fallback?: (props: ErrorBoundaryFallbackProps) => ReactNode
label?: string
onError?: (error: Error, info: ErrorInfo) => void
}
interface ErrorBoundaryState {
error: Error | null
}
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
state: ErrorBoundaryState = { error: null }
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { error }
}
componentDidCatch(error: Error, info: ErrorInfo) {
const tag = this.props.label ? `[error-boundary:${this.props.label}]` : '[error-boundary]'
console.error(tag, error, info.componentStack)
this.props.onError?.(error, info)
}
reset = () => {
this.setState({ error: null })
}
render() {
const { error } = this.state
if (!error) {
return this.props.children
}
if (this.props.fallback) {
return this.props.fallback({ error, reset: this.reset })
}
return <RootErrorFallback error={error} reset={this.reset} />
}
}
function RootErrorFallback({ error, reset }: ErrorBoundaryFallbackProps) {
return (
<div className="fixed inset-0 z-[1500] grid place-items-center bg-(--ui-chat-surface-background) p-6">
<ErrorState
className="w-full max-w-[28rem]"
description={error.message || 'The view hit an unexpected error. Your chats and settings are safe.'}
title="Something broke in the interface"
>
<Button className="font-semibold" onClick={reset} size="lg">
Try again
</Button>
<Button onClick={() => window.location.reload()} variant="text">
Reload window
</Button>
<Button onClick={() => void window.hermesDesktop?.revealLogs()?.catch(() => undefined)} variant="text">
Open logs
</Button>
</ErrorState>
</div>
)
}