diff --git a/package.json b/package.json index 9b441eb3..03e23070 100644 --- a/package.json +++ b/package.json @@ -146,6 +146,7 @@ "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", + "stacktrace-js": "^2.0.2", "styled-components": "^5.3.0", "typescript": "^4.4.2", "ulid": "^2.3.0", diff --git a/src/lib/ErrorBoundary.tsx b/src/lib/ErrorBoundary.tsx new file mode 100644 index 00000000..ff6b4a35 --- /dev/null +++ b/src/lib/ErrorBoundary.tsx @@ -0,0 +1,63 @@ +import axios from "axios"; +import * as stackTrace from "stacktrace-js"; +import styled from "styled-components"; + +import { useEffect, useErrorBoundary } from "preact/hooks"; + +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; +} + +const ERROR_URL = "https://reporting.revolt.chat"; + +export default function ErrorBoundary({ children }: Props) { + const [error, ignoreError] = useErrorBoundary(); + + useEffect(() => { + if (error) { + stackTrace.fromError(error).then((stackframes) => + axios.post(ERROR_URL, { + stackframes, + rawStackTrace: error.stack, + origin: window.origin, + commitSHA: GIT_REVISION, + userAgent: navigator.userAgent, + }), + ); + } + }, [error]); + + if (error) { + return ( + +

Client Crash Report

+ + +
+                    {error?.stack}
+                
+
This error has been automatically reported.
+
+ ); + } + + return <>{children}; +} diff --git a/src/pages/app.tsx b/src/pages/app.tsx index c09679c5..f3d7c8a4 100644 --- a/src/pages/app.tsx +++ b/src/pages/app.tsx @@ -2,6 +2,8 @@ import { Route, Switch } from "react-router-dom"; import { lazy, Suspense } from "preact/compat"; +import ErrorBoundary from "../lib/ErrorBoundary"; + import Context from "../context"; import { CheckAuth } from "../context/revoltjs/CheckAuth"; @@ -15,33 +17,35 @@ const RevoltApp = lazy(() => import("./RevoltApp")); export function App() { return ( - - - {/* - // @ts-expect-error typings mis-match between preact... and preact? */} - }> - - - - - - - - - - - - + + + + {/* + // @ts-expect-error typings mis-match between preact... and preact? */} + }> + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + ); } diff --git a/src/pages/developer/Developer.tsx b/src/pages/developer/Developer.tsx index ddf50ea9..d64cf5f6 100644 --- a/src/pages/developer/Developer.tsx +++ b/src/pages/developer/Developer.tsx @@ -15,6 +15,7 @@ export default function Developer() { const client = useContext(AppContext); const userPermission = client.user!.permission; const [ping, setPing] = useState(client.websocket.ping); + const [crash, setCrash] = useState(false); useEffect(() => { const timer = setInterval( @@ -44,6 +45,8 @@ export default function Developer() { />
+ setCrash(true)}>click to crash app + {crash && (window as any).sus.sus()} {/* Voice Status: {VoiceStatus[voice.status]} diff --git a/yarn.lock b/yarn.lock index 228c87ec..374ca4ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2106,6 +2106,13 @@ entities@~2.1.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== +error-stack-parser@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2: version "1.18.5" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19" @@ -3962,6 +3969,11 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -3994,6 +4006,35 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +stack-generator@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36" + integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q== + dependencies: + stackframe "^1.1.1" + +stackframe@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== + +stacktrace-gps@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a" + integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg== + dependencies: + source-map "0.5.6" + stackframe "^1.1.1" + +stacktrace-js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"