Duffer Derek
"use client";
import React, { Component, ErrorInfo, ReactNode } from "react";
import { IOSErrorFallback } from "./IOSErrorFallback";
import { isIOSDevice } from "@/lib/iosPWAUtils";
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
errorInfo?: ErrorInfo;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
// Update state so the next render will show the fallback UI
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// Log error details
console.error("ErrorBoundary caught an error:", error, errorInfo);
// Store error info in state
this.setState({
error,
errorInfo,
});
// Log to external service if needed
this.logErrorToService(error, errorInfo);
}
private logErrorToService = (error: Error, errorInfo: ErrorInfo) => {
// Enhanced error logging for iOS PWA issues
const errorDetails = {
message: error.message,
stack: error.stack,
componentStack: errorInfo.componentStack,
userAgent: navigator.userAgent,
isIOS: /iPhone|iPad|iPod/.test(navigator.userAgent),
isPWA:
window.matchMedia("(display-mode: standalone)").matches ||
(window.navigator as any).standalone === true,
timestamp: new Date().toISOString(),
url: window.location.href,
};
console.error("Detailed error information:", errorDetails);
// Special handling for Notification API errors
if (error.message.includes("Can't find variable: Notification")) {
console.warn(
"Notification API error detected - this is expected on some iOS Safari versions"
);
// Reset error state for this specific case
this.setState({ hasError: false, error: undefined, errorInfo: undefined });
return;
}
// You can send this to your error tracking service
// Example: Sentry, LogRocket, etc.
};
private handleRetry = () => {
this.setState({ hasError: false, error: undefined, errorInfo: undefined });
};
private handleReload = () => {
window.location.reload();
};
render() {
if (this.state.hasError) {
// Custom fallback UI
if (this.props.fallback) {
return this.props.fallback;
}
// iOS-specific error UI
if (isIOSDevice()) {
return (
<IOSErrorFallback
error={this.state.error}
onRetry={this.handleRetry}
onReload={this.handleReload}
/>
);
}
// Default error UI
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
minHeight: "100vh",
padding: "20px",
textAlign: "center",
backgroundColor: "#f5f5f5",
fontFamily: "system-ui, -apple-system, sans-serif",
}}
>
<div
style={{
backgroundColor: "white",
padding: "30px",
borderRadius: "8px",
boxShadow: "0 2px 10px rgba(0,0,0,0.1)",
maxWidth: "500px",
width: "100%",
}}
>
<h1 style={{ color: "#e30613", marginBottom: "20px" }}>Something went wrong</h1>
<p style={{ marginBottom: "20px", color: "#666" }}>
We're sorry, but something unexpected happened. This might be a temporary issue.
</p>
{/* Show error details in development */}
{process.env.NODE_ENV === "development" && this.state.error && (
<details
style={{
marginBottom: "20px",
textAlign: "left",
backgroundColor: "#f8f8f8",
padding: "15px",
borderRadius: "4px",
border: "1px solid #ddd",
}}
>
<summary style={{ cursor: "pointer", fontWeight: "bold" }}>
Error Details (Development)
</summary>
<pre
style={{
fontSize: "12px",
overflow: "auto",
marginTop: "10px",
whiteSpace: "pre-wrap",
}}
>
{this.state.error.message}
{this.state.error.stack && `\n\nStack:\n${this.state.error.stack}`}
</pre>
</details>
)}
<div style={{ display: "flex", gap: "10px", justifyContent: "center" }}>
<button
onClick={this.handleRetry}
style={{
backgroundColor: "#e30613",
color: "white",
border: "none",
padding: "10px 20px",
borderRadius: "4px",
cursor: "pointer",
fontSize: "14px",
}}
>
Try Again
</button>
<button
onClick={this.handleReload}
style={{
backgroundColor: "#666",
color: "white",
border: "none",
padding: "10px 20px",
borderRadius: "4px",
cursor: "pointer",
fontSize: "14px",
}}
>
Reload Page
</button>
</div>
{/* iOS-specific help */}
{/iPhone|iPad|iPod/.test(navigator.userAgent) && (
<div
style={{
marginTop: "20px",
padding: "15px",
backgroundColor: "#fff3cd",
border: "1px solid #ffeaa7",
borderRadius: "4px",
fontSize: "14px",
}}
>
<strong>iOS Users:</strong> If this error persists, try:
<ul style={{ textAlign: "left", marginTop: "10px" }}>
<li>Close and reopen the app</li>
<li>Clear Safari cache in Settings</li>
<li>Update to the latest iOS version</li>
</ul>
</div>
)}
</div>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists