2021-12-25 09:32:28 -05:00
|
|
|
import axios from "axios";
|
2021-12-25 11:41:57 -05:00
|
|
|
import localforage from "localforage";
|
2021-12-25 09:32:28 -05:00
|
|
|
import * as stackTrace from "stacktrace-js";
|
|
|
|
import styled from "styled-components";
|
|
|
|
|
2021-12-25 11:41:57 -05:00
|
|
|
import { useEffect, useErrorBoundary, useState } from "preact/hooks";
|
2021-12-25 09:32:28 -05:00
|
|
|
|
|
|
|
import { GIT_REVISION } from "../revision";
|
|
|
|
import { Children } from "../types/Preact";
|
|
|
|
|
|
|
|
const CrashContainer = styled.div`
|
|
|
|
height: 100%;
|
|
|
|
padding: 12px;
|
|
|
|
|
|
|
|
background: black;
|
|
|
|
color: white;
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
margin: 0;
|
|
|
|
margin-bottom: 12px;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
children: Children;
|
2021-12-25 11:03:05 -05:00
|
|
|
section: "client" | "renderer";
|
2021-12-25 09:32:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
const ERROR_URL = "https://reporting.revolt.chat";
|
|
|
|
|
2021-12-25 11:37:39 -05:00
|
|
|
export function reportError(error: Error, section: string) {
|
|
|
|
stackTrace.fromError(error).then((stackframes) =>
|
|
|
|
axios.post(ERROR_URL, {
|
|
|
|
stackframes,
|
|
|
|
rawStackTrace: error.stack,
|
|
|
|
origin: window.origin,
|
|
|
|
commitSHA: GIT_REVISION,
|
|
|
|
userAgent: navigator.userAgent,
|
|
|
|
section,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-12-25 11:03:05 -05:00
|
|
|
export default function ErrorBoundary({ children, section }: Props) {
|
2021-12-25 09:32:28 -05:00
|
|
|
const [error, ignoreError] = useErrorBoundary();
|
2021-12-25 11:41:57 -05:00
|
|
|
const [confirm, setConfirm] = useState(false);
|
|
|
|
|
|
|
|
async function reset() {
|
|
|
|
if (confirm) {
|
|
|
|
await localforage.clear();
|
|
|
|
location.reload();
|
|
|
|
} else {
|
|
|
|
setConfirm(true);
|
|
|
|
}
|
|
|
|
}
|
2021-12-25 09:32:28 -05:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (error) {
|
2021-12-25 11:37:39 -05:00
|
|
|
reportError(error, section);
|
2021-12-25 09:32:28 -05:00
|
|
|
}
|
|
|
|
}, [error]);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
return (
|
|
|
|
<CrashContainer>
|
2021-12-25 11:03:05 -05:00
|
|
|
{section === "client" ? (
|
|
|
|
<>
|
|
|
|
<h3>Client Crash Report</h3>
|
|
|
|
<button onClick={ignoreError}>
|
|
|
|
Ignore error and try to reload app
|
|
|
|
</button>
|
2021-12-25 11:41:57 -05:00
|
|
|
<button onClick={reset}>
|
|
|
|
{confirm ? "Are you sure?" : "Reset all app data"}
|
|
|
|
</button>
|
2021-12-25 11:03:05 -05:00
|
|
|
<button onClick={() => location.reload()}>
|
|
|
|
Refresh page
|
|
|
|
</button>
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<h3>Component Error</h3>
|
|
|
|
<button onClick={ignoreError}>
|
|
|
|
Ignore error and try render again
|
|
|
|
</button>
|
|
|
|
</>
|
|
|
|
)}
|
2021-12-25 09:32:28 -05:00
|
|
|
<pre>
|
|
|
|
<code>{error?.stack}</code>
|
|
|
|
</pre>
|
|
|
|
<div>This error has been automatically reported.</div>
|
|
|
|
</CrashContainer>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return <>{children}</>;
|
|
|
|
}
|