import React, { type ErrorInfo, useRef, useState } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { FormattedMessage } from 'react-intl'; import { NODE_ENV } from 'soapbox/build-config'; import { HStack, Text, Stack, Textarea } from 'soapbox/components/ui'; import { useSoapboxConfig } from 'soapbox/hooks'; import { captureSentryException } from 'soapbox/sentry'; import KVStore from 'soapbox/storage/kv-store'; import sourceCode from 'soapbox/utils/code'; import { unregisterSW } from 'soapbox/utils/sw'; import SentryFeedbackForm from './sentry-feedback-form'; import SiteLogo from './site-logo'; interface ISiteErrorBoundary { children: React.ReactNode; } /** Application-level error boundary. Fills the whole screen. */ const SiteErrorBoundary: React.FC = ({ children }) => { const { links, sentryDsn } = useSoapboxConfig(); const textarea = useRef(null); const [error, setError] = useState(); const [componentStack, setComponentStack] = useState(); const [browser, setBrowser] = useState(); const [sentryEventId, setSentryEventId] = useState(); const sentryEnabled = Boolean(sentryDsn); const isProduction = NODE_ENV === 'production'; const errorText = String(error) + componentStack; const clearCookies: React.MouseEventHandler = (e) => { localStorage.clear(); sessionStorage.clear(); KVStore.clear(); if ('serviceWorker' in navigator) { e.preventDefault(); unregisterSW().then(goHome).catch(goHome); } }; const handleCopy: React.MouseEventHandler = () => { if (!textarea.current) return; textarea.current.select(); textarea.current.setSelectionRange(0, 99999); document.execCommand('copy'); }; function handleError(error: Error, info: ErrorInfo) { setError(error); setComponentStack(info.componentStack); captureSentryException(error, { tags: { // Allow page crashes to be easily searched in Sentry. ErrorBoundary: 'yes', }, }) .then((eventId) => setSentryEventId(eventId)) .catch(console.error); import('bowser') .then(({ default: Bowser }) => setBrowser(Bowser.getParser(window.navigator.userAgent))) .catch(() => {}); } function goHome() { location.href = '/'; } const fallback = (

), }} />

{sourceCode.displayName}: {' '}{sourceCode.version}
{(isProduction) ? ( (sentryEnabled && sentryEventId) && ( ) ) : ( <> {errorText && (