gab-social/app/javascript/gabsocial/components/error_boundary.js

166 lines
4.8 KiB
JavaScript

import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl'
import {
source_url,
version,
} from '../initial_state'
import {
APP_NAME,
DEFAULT_REL,
} from '../constants'
import Button from './button'
import DotTextSeperator from './dot_text_seperator'
import Divider from './divider'
import Icon from './icon'
import Text from './text'
class ErrorBoundary extends React.PureComponent {
state = {
hasError: false,
stackTrace: undefined,
componentStack: undefined,
copied: false,
}
componentDidCatch(error, info) {
this.setState({
hasError: true,
stackTrace: error.stack,
componentStack: info && info.componentStack,
copied: false,
})
}
handleCopyStackTrace = () => {
const { stackTrace } = this.state;
const textarea = document.createElement('textarea');
textarea.textContent = stackTrace;
textarea.style.position = 'fixed';
document.body.appendChild(textarea);
try {
textarea.select();
document.execCommand('copy');
} catch (e) {
//
}
document.body.removeChild(textarea);
this.setState({ copied: true });
setTimeout(() => this.setState({ copied: false }), 700);
}
render() {
const { hasError, copied } = this.state
if (!hasError) return this.props.children
return (
<div className={[_s.d, _s.minH100VH, _s.w100PC, _s.aiCenter, _s.jcCenter].join(' ')}>
<div className={[_s.d, _s.minH53PX, _s.bgBrand, _s.aiCenter, _s.z3, _s.top0, _s.right0, _s.left0, _s.posFixed].join(' ')} >
<div className={[_s.d, _s.flexRow, _s.saveAreaInsetPT, _s.saveAreaInsetPL, _s.saveAreaInsetPR, _s.w1255PX].join(' ')}>
<div className={[_s.d, _s.flexRow].join(' ')}>
<h1 className={[_s.d, _s.mr15].join(' ')}>
<Button href='/' isText aria-label='Gab' className={[_s.d, _s.jcCenter, _s.noSelect, _s.noUnderline, _s.h53PX, _s.cursorPointer, _s.px10, _s.mr15].join(' ')}>
<Icon id='logo' className={_s.fillWhite} />
</Button>
</h1>
</div>
</div>
</div>
<div className={[_s.d, _s.maxW640PX, _s.px15, _s.py10].join(' ')}>
<Icon id='warning' size='28px' className={[_s.d, _s.cSecondary, _s.mb15].join(' ')} />
<Text size='medium' className={_s.pt15}>
<FormattedMessage
id='error.unexpected_crash.explanation'
defaultMessage='Due to a bug in our code or a browser compatibility issue, this page or feature could not be displayed correctly.'
/>
</Text>
<Text size='medium' className={_s.mt10}>
<FormattedMessage
id='error.unexpected_crash.next_steps'
defaultMessage='Try refreshing the page or trying the action again. If that does not help, you may still be able to use Gab Social through a different browser or native app.'
/>
</Text>
<div className={[_s.d, _s.py10, _s.my10].join(' ')}>
<Text>
{APP_NAME} ({version})
</Text>
<div className={[_s.d, _s.flexRow, _s.mt10, _s.aiCenter].join(' ')}>
<Button
isText
href={source_url}
rel={DEFAULT_REL}
target='_blank'
backgroundColor='tertiary'
color='primary'
radiusSmall
className={[_s.py2, _s.px10].join(' ')}
>
<Text color='inherit'>
<FormattedMessage
id='errors.unexpected_crash.report_issue'
defaultMessage='Report issue'
/>
</Text>
</Button>
<DotTextSeperator />
<Button
isText
backgroundColor='tertiary'
color='primary'
onClick={this.handleCopyStackTrace}
radiusSmall
className={[_s.ml5, _s.py2, _s.px10].join(' ')}
>
<Text color='inherit'>
<FormattedMessage
id='errors.unexpected_crash.copy_stacktrace'
defaultMessage='Copy error to clipboard'
/>
</Text>
</Button>
</div>
</div>
<Divider />
<div className={[_s.d, _s.flexRow].join(' ')}>
<Button href='/home'>
<Text align='center' color='inherit'>
<FormattedMessage
id='return_home'
defaultMessage='Return Home'
/>
</Text>
</Button>
</div>
</div>
</div>
)
}
}
ErrorBoundary.propTypes = {
children: PropTypes.node,
}
export default ErrorBoundary