import React from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import * as BuildConfig from 'soapbox/build_config'; import { Text, Stack } from 'soapbox/components/ui'; import SvgIcon from 'soapbox/components/ui/icon/svg-icon'; import { captureException } from 'soapbox/monitoring'; import KVStore from 'soapbox/storage/kv_store'; import sourceCode from 'soapbox/utils/code'; import type { RootState } from 'soapbox/store'; const goHome = () => location.href = '/'; /** Unregister the ServiceWorker */ // https://stackoverflow.com/a/49771828/8811886 const unregisterSw = async() => { if (!navigator.serviceWorker) return; const registrations = await navigator.serviceWorker.getRegistrations(); const unregisterAll = registrations.map(r => r.unregister()); await Promise.all(unregisterAll); }; const mapStateToProps = (state: RootState) => { const { links, logo } = getSoapboxConfig(state); return { siteTitle: state.instance.title, logo, links, }; }; type Props = ReturnType; type State = { hasError: boolean, error: any, componentStack: any, browser?: Bowser.Parser.Parser, } class ErrorBoundary extends React.PureComponent { state: State = { hasError: false, error: undefined, componentStack: undefined, browser: undefined, } textarea: HTMLTextAreaElement | null = null; componentDidCatch(error: any, info: any): void { captureException(error); this.setState({ hasError: true, error, componentStack: info && info.componentStack, }); import(/* webpackChunkName: "error" */'bowser') .then(({ default: Bowser }) => { this.setState({ browser: Bowser.getParser(window.navigator.userAgent), }); }) .catch(() => {}); } setTextareaRef: React.RefCallback = c => { this.textarea = c; } handleCopy: React.MouseEventHandler = () => { if (!this.textarea) return; this.textarea.select(); this.textarea.setSelectionRange(0, 99999); document.execCommand('copy'); } getErrorText = (): string => { const { error, componentStack } = this.state; return error + componentStack; } clearCookies: React.MouseEventHandler = (e) => { localStorage.clear(); sessionStorage.clear(); KVStore.clear(); if ('serviceWorker' in navigator) { e.preventDefault(); unregisterSw().then(goHome).catch(goHome); } } render() { const { browser, hasError } = this.state; const { children, siteTitle, logo, links } = this.props; if (!hasError) { return children; } const isProduction = BuildConfig.NODE_ENV === 'production'; const errorText = this.getErrorText(); return (

) }} />

{sourceCode.displayName}: {' '}{sourceCode.version}
{!isProduction && (
{errorText && (