diff options
author | Claire <claire.github-309c@sitedethib.com> | 2023-02-26 15:06:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-26 15:06:03 +0100 |
commit | 6a4be4e96677eb3e1303ddcab8f8b4bea7298453 (patch) | |
tree | 52627bf6dd64b0a33e280442b2de60b4e802a544 /app/javascript/flavours/glitch/components/error_boundary.jsx | |
parent | 45087c1092143e95dfcc85b6c9abc5c6c0a0a5c2 (diff) | |
parent | b91756fd4d475edff890e460c44b3a7245ad51e2 (diff) |
Merge pull request #2119 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes
Diffstat (limited to 'app/javascript/flavours/glitch/components/error_boundary.jsx')
-rw-r--r-- | app/javascript/flavours/glitch/components/error_boundary.jsx | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/components/error_boundary.jsx b/app/javascript/flavours/glitch/components/error_boundary.jsx new file mode 100644 index 000000000..8518dfc86 --- /dev/null +++ b/app/javascript/flavours/glitch/components/error_boundary.jsx @@ -0,0 +1,134 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; +import { source_url } from 'flavours/glitch/initial_state'; +import { preferencesLink } from 'flavours/glitch/utils/backend_links'; +import StackTrace from 'stacktrace-js'; +import { Helmet } from 'react-helmet'; + +export default class ErrorBoundary extends React.PureComponent { + + static propTypes = { + children: PropTypes.node, + }; + + state = { + hasError: false, + errorMessage: undefined, + stackTrace: undefined, + mappedStackTrace: undefined, + componentStack: undefined, + }; + + componentDidCatch(error, info) { + this.setState({ + hasError: true, + errorMessage: error.toString(), + stackTrace: error.stack, + componentStack: info && info.componentStack, + mappedStackTrace: undefined, + }); + + StackTrace.fromError(error).then((stackframes) => { + this.setState({ + mappedStackTrace: stackframes.map((sf) => sf.toString()).join('\n'), + }); + }).catch(() => { + this.setState({ + mappedStackTrace: undefined, + }); + }); + } + + handleReload(e) { + e.preventDefault(); + window.location.reload(); + } + + render() { + const { hasError, errorMessage, stackTrace, mappedStackTrace, componentStack } = this.state; + + if (!hasError) return this.props.children; + + const likelyBrowserAddonIssue = errorMessage && errorMessage.includes('NotFoundError'); + + let debugInfo = ''; + if (stackTrace) { + debugInfo += 'Stack trace\n-----------\n\n```\n' + errorMessage + '\n' + stackTrace.toString() + '\n```'; + } + if (mappedStackTrace) { + debugInfo += 'Mapped stack trace\n-----------\n\n```\n' + errorMessage + '\n' + mappedStackTrace.toString() + '\n```'; + } + if (componentStack) { + if (debugInfo) { + debugInfo += '\n\n\n'; + } + debugInfo += 'React component stack\n---------------------\n\n```\n' + componentStack.toString() + '\n```'; + } + + let issueTracker = source_url; + if (source_url.match(/^https:\/\/github\.com\/[^/]+\/[^/]+\/?$/)) { + issueTracker = source_url + '/issues'; + } + + return ( + <div tabIndex='-1'> + <div className='error-boundary'> + <h1><FormattedMessage id='web_app_crash.title' defaultMessage="We're sorry, but something went wrong with the Mastodon app." /></h1> + <p> + <FormattedMessage id='web_app_crash.content' defaultMessage='You could try any of the following:' /> + </p> + <ul> + { likelyBrowserAddonIssue && ( + <li> + <FormattedMessage + id='web_app_crash.disable_addons' + defaultMessage='Disable browser add-ons or built-in translation tools' + /> + </li> + ) } + <li> + <FormattedMessage + id='web_app_crash.report_issue' + defaultMessage='Report a bug in the {issuetracker}' + values={{ issuetracker: <a href={issueTracker} rel='noopener noreferrer' target='_blank'><FormattedMessage id='web_app_crash.issue_tracker' defaultMessage='issue tracker' /></a> }} + /> + { debugInfo !== '' && ( + <details> + <summary><FormattedMessage id='web_app_crash.debug_info' defaultMessage='Debug information' /></summary> + <textarea + className='web_app_crash-stacktrace' + value={debugInfo} + rows='10' + readOnly + /> + </details> + )} + </li> + <li> + <FormattedMessage + id='web_app_crash.reload_page' + defaultMessage='{reload} the current page' + values={{ reload: <a href='#' onClick={this.handleReload}><FormattedMessage id='web_app_crash.reload' defaultMessage='Reload' /></a> }} + /> + </li> + { preferencesLink !== undefined && ( + <li> + <FormattedMessage + id='web_app_crash.change_your_settings' + defaultMessage='Change your {settings}' + values={{ settings: <a href={preferencesLink}><FormattedMessage id='web_app_crash.settings' defaultMessage='settings' /></a> }} + /> + </li> + )} + </ul> + </div> + + <Helmet> + <meta name='robots' content='noindex' /> + </Helmet> + </div> + ); + } + +} |