Files
automaker/apps/ui/src/components/views/terminal-view/terminal-error-boundary.tsx
SuperComboGamer 195b98e688 feat: enhance terminal functionality and settings
- Added new endpoints for terminal settings: GET and PUT /settings to retrieve and update terminal configurations.
- Implemented session limit checks during session creation, returning a 429 status when the limit is reached.
- Introduced a new TerminalSection in settings view for customizing terminal appearance and behavior, including font family, default font size, line height, and screen reader mode.
- Added support for new terminal features such as search functionality and improved error handling with a TerminalErrorBoundary component.
- Updated terminal layout persistence to include session IDs for reconnection and enhanced terminal state management.
- Introduced new keyboard shortcuts for terminal actions, including creating new terminal tabs.
- Enhanced UI with scrollbar theming for terminal components.
2025-12-20 22:56:25 -05:00

95 lines
2.8 KiB
TypeScript

import React, { Component, ErrorInfo } from "react";
import { AlertCircle, RefreshCw } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface Props {
children: React.ReactNode;
sessionId: string;
onRestart?: () => void;
}
interface State {
hasError: boolean;
error: Error | null;
}
/**
* BUG-06 fix: Error boundary for terminal components
* Catches xterm.js errors (WebGL context loss, canvas errors, etc.)
* and displays a friendly recovery UI instead of crashing the app.
*/
export class TerminalErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("[TerminalErrorBoundary] Terminal crashed:", {
sessionId: this.props.sessionId,
error: error.message,
stack: error.stack,
componentStack: errorInfo.componentStack,
});
}
handleRestart = () => {
this.setState({ hasError: false, error: null });
this.props.onRestart?.();
};
render() {
if (this.state.hasError) {
return (
<div
className={cn(
"flex flex-col items-center justify-center h-full w-full",
"bg-background/95 backdrop-blur-sm",
"p-6 text-center gap-4"
)}
>
<div className="w-12 h-12 rounded-full bg-destructive/10 flex items-center justify-center">
<AlertCircle className="w-6 h-6 text-destructive" />
</div>
<div className="space-y-2">
<h3 className="text-lg font-semibold text-foreground">
Terminal Crashed
</h3>
<p className="text-sm text-muted-foreground max-w-sm">
{this.state.error?.message?.includes("WebGL")
? "WebGL context was lost. This can happen with GPU driver issues."
: "An unexpected error occurred in the terminal."}
</p>
</div>
<Button
variant="outline"
size="sm"
onClick={this.handleRestart}
className="gap-2"
>
<RefreshCw className="w-4 h-4" />
Restart Terminal
</Button>
{this.state.error && (
<details className="text-xs text-muted-foreground max-w-md">
<summary className="cursor-pointer hover:text-foreground">
Technical details
</summary>
<pre className="mt-2 p-2 bg-muted/50 rounded text-left overflow-auto max-h-32">
{this.state.error.message}
</pre>
</details>
)}
</div>
);
}
return this.props.children;
}
}