import React, { Component, StatelessComponent, ReactNode, ErrorInfo, } from "react"; import { captureException } from "@sentry/browser"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBomb } from "@fortawesome/free-solid-svg-icons/faBomb"; interface InternalErrorProps { message: ReactNode; secondsLeft: number; progressLeft: number; } const InternalError: StatelessComponent = (props) => (

Internal error

{props.message}

This page will auto refresh in {props.secondsLeft}s

); interface ErrorBoundaryProps { children: React.ReactNode; } interface ErrorBoundaryState { cachedError: Error | null; reloadSeconds: number; } class ErrorBoundary extends Component { timer: ReturnType | null; state: Readonly = { cachedError: null, reloadSeconds: 60, }; constructor(props: ErrorBoundaryProps) { super(props); this.timer = null; } reloadApp = (): void => { if (this.state.reloadSeconds <= 1) { window.location.reload(); } else { this.setState({ reloadSeconds: this.state.reloadSeconds - 1 }); } }; componentDidCatch(error: Error, { componentStack }: ErrorInfo): void { if (this.state.cachedError === null) { this.setState({ cachedError: error }); captureException(error, { contexts: { react: { componentStack } } }); } // reload after 60s, this is to fix wall monitors automatically // but only if the timer isn't set yet if (this.timer === null) { this.timer = setInterval(this.reloadApp, 1000); } } render(): ReactNode { if (this.state.cachedError !== null) { return ( ); } return this.props.children; } } export { ErrorBoundary, InternalError };