You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
1.6 KiB
57 lines
1.6 KiB
import React, { Component, ReactNode } from 'react' |
|
import { AlertTriangle } from 'lucide-react' |
|
import logger from '@/lib/logger' |
|
|
|
interface MediaErrorBoundaryProps { |
|
children: ReactNode |
|
fallback?: ReactNode |
|
onError?: (error: Error) => void |
|
} |
|
|
|
interface MediaErrorBoundaryState { |
|
hasError: boolean |
|
error?: Error |
|
} |
|
|
|
export class MediaErrorBoundary extends Component<MediaErrorBoundaryProps, MediaErrorBoundaryState> { |
|
constructor(props: MediaErrorBoundaryProps) { |
|
super(props) |
|
this.state = { hasError: false } |
|
} |
|
|
|
static getDerivedStateFromError(error: Error): MediaErrorBoundaryState { |
|
return { hasError: true, error } |
|
} |
|
|
|
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { |
|
// Don't log expected media errors |
|
if (error.name === 'AbortError' || |
|
error.message.includes('play() request was interrupted') || |
|
error.message.includes('The play() request was interrupted')) { |
|
return |
|
} |
|
|
|
// Log unexpected errors |
|
logger.warn('Media error boundary caught error', { error, errorInfo }) |
|
this.props.onError?.(error) |
|
} |
|
|
|
render() { |
|
if (this.state.hasError) { |
|
if (this.props.fallback) { |
|
return this.props.fallback |
|
} |
|
|
|
return ( |
|
<div className="flex items-center justify-center p-4 bg-muted/50 rounded-lg border border-dashed"> |
|
<div className="flex items-center gap-2 text-muted-foreground"> |
|
<AlertTriangle className="w-4 h-4" /> |
|
<span className="text-sm">Media unavailable</span> |
|
</div> |
|
</div> |
|
) |
|
} |
|
|
|
return this.props.children |
|
} |
|
}
|
|
|