diff --git a/app/soapbox/components/error_boundary.js b/app/soapbox/components/error_boundary.tsx similarity index 53% rename from app/soapbox/components/error_boundary.js rename to app/soapbox/components/error_boundary.tsx index 9489b0e75..b07bb2733 100644 --- a/app/soapbox/components/error_boundary.js +++ b/app/soapbox/components/error_boundary.tsx @@ -1,43 +1,58 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import { NODE_ENV } from 'soapbox/build_config'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import 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 sourceCode from 'soapbox/utils/code'; -import { getSoapboxConfig } from '../actions/soapbox'; +import type { RootState } from 'soapbox/store'; -const mapStateToProps = (state) => { - const soapboxConfig = getSoapboxConfig(state); +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, - helpLink: soapboxConfig.getIn(['links', 'help']), - supportLink: soapboxConfig.getIn(['links', 'support']), - statusLink: soapboxConfig.getIn(['links', 'status']), + logo, + links, }; }; -@connect(mapStateToProps) -class ErrorBoundary extends React.PureComponent { +type Props = ReturnType; - static propTypes = { - children: PropTypes.node, - siteTitle: PropTypes.string, - supportLink: PropTypes.string, - helpLink: PropTypes.string, - statusLink: PropTypes.string, - }; +type State = { + hasError: boolean, + error: any, + componentStack: any, + browser?: Bowser.Parser.Parser, +} - state = { +class ErrorBoundary extends React.PureComponent { + + state: State = { hasError: false, + error: undefined, componentStack: undefined, + browser: undefined, } - componentDidCatch(error, info) { + textarea: HTMLTextAreaElement | null = null; + + componentDidCatch(error: any, info: any): void { captureException(error); this.setState({ @@ -55,11 +70,11 @@ class ErrorBoundary extends React.PureComponent { .catch(() => {}); } - setTextareaRef = c => { + setTextareaRef: React.RefCallback = c => { this.textarea = c; } - handleCopy = e => { + handleCopy: React.MouseEventHandler = () => { if (!this.textarea) return; this.textarea.select(); @@ -68,25 +83,30 @@ class ErrorBoundary extends React.PureComponent { document.execCommand('copy'); } - getErrorText = () => { + getErrorText = (): string => { const { error, componentStack } = this.state; return error + componentStack; } - clearCookies = e => { + clearCookies: React.MouseEventHandler = (e) => { localStorage.clear(); sessionStorage.clear(); + + if ('serviceWorker' in navigator) { + e.preventDefault(); + unregisterSw().then(goHome).catch(goHome); + } } render() { const { browser, hasError } = this.state; - const { children, siteTitle, helpLink, statusLink, supportLink } = this.props; + const { children, siteTitle, logo, links } = this.props; if (!hasError) { return children; } - const isProduction = NODE_ENV === 'production'; + const isProduction = BuildConfig.NODE_ENV === 'production'; const errorText = this.getErrorText(); @@ -95,7 +115,11 @@ class ErrorBoundary extends React.PureComponent {
- {siteTitle} + {logo ? ( + {siteTitle} + ) : ( + + )}
@@ -105,14 +129,18 @@ class ErrorBoundary extends React.PureComponent {

- We're sorry for the interruption. If the problem persists, please reach out to our support team. You - may also try to - - - {' ' }(this will log you out). + + + + ) }} + />

@@ -144,7 +172,7 @@ class ErrorBoundary extends React.PureComponent { {browser && ( - Browser + {browser.getBrowserName()} {browser.getBrowserVersion()} )} @@ -155,28 +183,28 @@ class ErrorBoundary extends React.PureComponent {