ErrorBoundary.tsx raw
1 import { Button } from '@/components/ui/button'
2 import { RotateCw } from 'lucide-react'
3 import React, { Component, ReactNode } from 'react'
4
5 interface ErrorBoundaryProps {
6 children: ReactNode
7 }
8
9 interface ErrorBoundaryState {
10 hasError: boolean
11 error?: Error
12 }
13
14 export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
15 constructor(props: ErrorBoundaryProps) {
16 super(props)
17 this.state = { hasError: false }
18 }
19
20 static getDerivedStateFromError(error: Error) {
21 return { hasError: true, error }
22 }
23
24 componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
25 console.error('ErrorBoundary caught an error:', error, errorInfo)
26 }
27
28 render() {
29 if (this.state.hasError) {
30 return (
31 <div className="w-screen h-screen flex flex-col items-center justify-center p-4 gap-4">
32 <h1 className="text-2xl font-bold">Oops, something went wrong.</h1>
33 <p className="text-lg text-center max-w-md">
34 Sorry for the inconvenience. If you don't mind helping, you can{' '}
35 <a
36 href="https://git.mleku.dev/mleku/smesh/issues/new"
37 target="_blank"
38 rel="noopener noreferrer"
39 className="text-primary underline"
40 >
41 submit an issue
42 </a>{' '}
43 with the error details, or{' '}
44 <a
45 href="https://smesh.mleku.dev/npub1syjmjy0dp62dhccq3g97fr87tngvpvzey08llyt6ul58m2zqpzps9wf6wl"
46 target="_blank"
47 rel="noopener noreferrer"
48 className="text-primary underline"
49 >
50 mention me
51 </a>
52 . Thank you for your support!
53 </p>
54 {this.state.error?.message && (
55 <>
56 <Button
57 onClick={() => {
58 navigator.clipboard.writeText(this.state.error!.message)
59 }}
60 variant="secondary"
61 >
62 Copy Error Message
63 </Button>
64 <pre className="bg-destructive/10 text-destructive p-2 rounded text-wrap break-words whitespace-pre-wrap">
65 Error: {this.state.error.message}
66 </pre>
67 </>
68 )}
69 <Button onClick={() => window.location.reload()} className="mt-2">
70 <RotateCw />
71 Reload Page
72 </Button>
73 </div>
74 )
75 }
76 return this.props.children
77 }
78 }
79