Add error boundary

This commit is contained in:
Philipp Heckel 2022-03-10 15:37:50 -05:00
parent 840cb5b182
commit ccb9da9333
17 changed files with 13649 additions and 18020 deletions

View file

@ -1,27 +1,64 @@
import * as React from "react";
import StackTrace from "stacktrace-js";
import {CircularProgress} from "@mui/material";
import Button from "@mui/material/Button";
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { error: null, info: null };
this.state = { error: null, info: null, stack: null };
}
componentDidCatch(error, info) {
this.setState({ error, info });
console.error("[ErrorBoundary] A horrible error occurred", info);
console.error("[ErrorBoundary] Error caught", error, info);
StackTrace.fromError(error).then(stack => {
console.error("[ErrorBoundary] Stacktrace fetched", stack);
const stackStr = stack.map( el => {
return ` at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})\n`;
})
this.setState({ stack: stackStr })
});
}
static getDerivedStateFromError(error) {
return { error: true, errorMessage: error.toString() }
copyStack() {
let stack = "";
if (this.state.stack) {
stack += `Stack trace:\n${this.state.error}\n${this.state.stack}\n\n`;
}
stack += `Original stack trace:\n${this.state.error}\n${this.state.info.componentStack}\n\n`;
navigator.clipboard.writeText(stack);
}
render() {
if (this.state.info) {
return (
<div>
<h2>Something went wrong.</h2>
<pre>{this.state.error && this.state.error.toString()}</pre>
<pre>{this.state.info.componentStack}</pre>
<div style={{margin: '20px'}}>
<h2>Oh no, ntfy crashed 😮</h2>
<p>
This should obviously not happen. Very sorry about this.<br/>
If you have a minute, please <a href="https://github.com/binwiederhier/ntfy/issues">report this on GitHub</a>, or let us
know via <a href="https://discord.gg/cT7ECsZj9w">Discord</a> or <a href="https://matrix.to/#/#ntfy:matrix.org">Matrix</a>.
</p>
<p>
<Button variant="outlined" onClick={() => this.copyStack()}>Copy stack trace</Button>
</p>
<h3>Stack trace</h3>
{this.state.stack
?
<pre>
{this.state.error && this.state.error.toString()}{"\n"}
{this.state.stack}
</pre>
:
<>
<CircularProgress size="20px" sx={{verticalAlign: "text-bottom"}}/> Gather more info ...
</>
}
<pre>
{this.state.error && this.state.error.toString()}
{this.state.info.componentStack}
</pre>
</div>
);
}