mirror of
https://github.com/excalidraw/excalidraw.git
synced 2024-11-10 11:35:52 +01:00
d6cd8b78f1
* feat: decouple package deps and introduce yarn workspaces * update root directory * fix * fix scripts * fix lint * update path in scripts * remove yarn.lock files from packages * ignore workspace * dummy * dummy * remove comment check * revert workflow changes * ignore ws when installing gh actions * remove log * update path * fix * fix typo
145 lines
4.1 KiB
TypeScript
145 lines
4.1 KiB
TypeScript
import React from "react";
|
||
import * as Sentry from "@sentry/browser";
|
||
import { t } from "../../packages/excalidraw/i18n";
|
||
import Trans from "../../packages/excalidraw/components/Trans";
|
||
|
||
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) {
|
||
const _localStorage: any = {};
|
||
for (const [key, value] of Object.entries({ ...localStorage })) {
|
||
try {
|
||
_localStorage[key] = JSON.parse(value);
|
||
} catch (error: any) {
|
||
_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: any) {
|
||
console.error(error);
|
||
}
|
||
|
||
window.open(
|
||
`https://github.com/excalidraw/excalidraw/issues/new?body=${body}`,
|
||
);
|
||
}
|
||
|
||
private errorSplash() {
|
||
return (
|
||
<div className="ErrorSplash excalidraw">
|
||
<div className="ErrorSplash-messageContainer">
|
||
<div className="ErrorSplash-paragraph bigger align-center">
|
||
<Trans
|
||
i18nKey="errorSplash.headingMain"
|
||
button={(el) => (
|
||
<button onClick={() => window.location.reload()}>{el}</button>
|
||
)}
|
||
/>
|
||
</div>
|
||
<div className="ErrorSplash-paragraph align-center">
|
||
<Trans
|
||
i18nKey="errorSplash.clearCanvasMessage"
|
||
button={(el) => (
|
||
<button
|
||
onClick={() => {
|
||
try {
|
||
localStorage.clear();
|
||
window.location.reload();
|
||
} catch (error: any) {
|
||
console.error(error);
|
||
}
|
||
}}
|
||
>
|
||
{el}
|
||
</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", {
|
||
eventId: this.state.sentryEventId,
|
||
})}
|
||
</div>
|
||
<div className="ErrorSplash-paragraph">
|
||
<Trans
|
||
i18nKey="errorSplash.openIssueMessage"
|
||
button={(el) => (
|
||
<button onClick={() => this.createGithubIssue()}>{el}</button>
|
||
)}
|
||
/>
|
||
</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>
|
||
);
|
||
}
|
||
}
|