excalidraw/src/components/TopErrorBoundary.tsx
Aakansha Doshi 4a26845395
enable code splitting and add chunk names to dynamic import and create separate chunk vendor for all node modules (#2245)
* build: increase Limit chunk to enable code splitting add chunk names to dynamic import

* Remove limitchunkcount and have separate chunk for each node module so we dnt have any unnamed id.js chunks

* fix

* create one chunk for all node modules

* Add caret to peer deps

* extra space
2020-10-18 19:36:25 +02:00

139 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import * as Sentry from "@sentry/browser";
import { resetCursor } from "../utils";
import { t } from "../i18n";
interface TopErrorBoundaryState {
hasError: boolean;
sentryEventId: string;
localStorage: string;
}
export class TopErrorBoundary extends React.Component<
any,
TopErrorBoundaryState
> {
state: TopErrorBoundaryState = {
hasError: false,
sentryEventId: "",
localStorage: "",
};
render() {
return this.state.hasError ? this.errorSplash() : this.props.children;
}
componentDidCatch(error: Error, errorInfo: any) {
resetCursor();
const _localStorage: any = {};
for (const [key, value] of Object.entries({ ...localStorage })) {
try {
_localStorage[key] = JSON.parse(value);
} catch (error) {
_localStorage[key] = value;
}
}
Sentry.withScope((scope) => {
scope.setExtras(errorInfo);
const eventId = Sentry.captureException(error);
this.setState((state) => ({
hasError: true,
sentryEventId: eventId,
localStorage: JSON.stringify(_localStorage),
}));
});
}
private selectTextArea(event: React.MouseEvent<HTMLTextAreaElement>) {
if (event.target !== document.activeElement) {
event.preventDefault();
(event.target as HTMLTextAreaElement).select();
}
}
private async createGithubIssue() {
let body = "";
try {
const templateStrFn = (
await import(
/* webpackChunkName: "bug-issue-template" */ "../bug-issue-template"
)
).default;
body = encodeURIComponent(templateStrFn(this.state.sentryEventId));
} catch (error) {
console.error(error);
}
window.open(
`https://github.com/excalidraw/excalidraw/issues/new?body=${body}`,
);
}
private errorSplash() {
return (
<div className="ErrorSplash">
<div className="ErrorSplash-messageContainer">
<div className="ErrorSplash-paragraph bigger align-center">
{t("errorSplash.headingMain_pre")}
<button onClick={() => window.location.reload()}>
{t("errorSplash.headingMain_button")}
</button>
</div>
<div className="ErrorSplash-paragraph align-center">
{t("errorSplash.clearCanvasMessage")}
<button
onClick={() => {
try {
localStorage.clear();
window.location.reload();
} catch (error) {
console.error(error);
}
}}
>
{t("errorSplash.clearCanvasMessage_button")}
</button>
<br />
<div className="smaller">
<span role="img" aria-label="warning">
</span>
{t("errorSplash.clearCanvasCaveat")}
<span role="img" aria-hidden="true">
</span>
</div>
</div>
<div>
<div className="ErrorSplash-paragraph">
{t("errorSplash.trackedToSentry_pre")}
{this.state.sentryEventId}
{t("errorSplash.trackedToSentry_post")}
</div>
<div className="ErrorSplash-paragraph">
{t("errorSplash.openIssueMessage_pre")}
<button onClick={() => this.createGithubIssue()}>
{t("errorSplash.openIssueMessage_button")}
</button>
{t("errorSplash.openIssueMessage_post")}
</div>
<div className="ErrorSplash-paragraph">
<div className="ErrorSplash-details">
<label>{t("errorSplash.sceneContent")}</label>
<textarea
rows={5}
onPointerDown={this.selectTextArea}
readOnly={true}
value={this.state.localStorage}
/>
</div>
</div>
</div>
</div>
</div>
);
}
}