From a7ccbcfca4f181790b86199a7f31d1ae19e0253f Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 31 Aug 2022 20:47:07 +0200 Subject: Refactor webpack; Add ErrorBoundary --- src/components/ErrorBoundary.tsx | 71 ++++++++++++++++++++++++++++++++++++++++ src/components/Settings.tsx | 52 ++++++++++------------------- 2 files changed, 89 insertions(+), 34 deletions(-) create mode 100644 src/components/ErrorBoundary.tsx (limited to 'src/components') diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..ae52838 --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,71 @@ +import Logger from "../utils/logger"; +import { Card, React } from "../webpack/common"; + +interface Props { + fallback?: React.ComponentType>; + onError?(error: Error, errorInfo: React.ErrorInfo): void; +} + +const color = "#e78284"; + +const logger = new Logger("React ErrorBoundary", color); + +const NO_ERROR = {}; + +export default class ErrorBoundary extends React.Component> { + static wrap(Component: React.ComponentType): (props: T) => React.ReactElement { + return (props) => ( + + + + ); + } + + state = { + error: NO_ERROR as any, + message: "" + }; + + static getDerivedStateFromError(error: any) { + + return { + error: error?.stack?.replace(/https:\/\/\S+\/assets\//g, "") || error?.message || String(error) + }; + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { + this.props.onError?.(error, errorInfo); + logger.error("A component threw an Error\n", error); + logger.error("Component Stack", errorInfo.componentStack); + } + + render() { + if (this.state.error === NO_ERROR) return this.props.children; + + if (this.props.fallback) + return ; + + return ( + +

Oh no!

+

+ An error occurred while rendering this Component. More info can be found below + and in your console. +

+ +
{this.state.error}
+                    
+
+
+ ); + } +} \ No newline at end of file diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index 4499c9f..19f6dd2 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -1,66 +1,50 @@ -import { lazy, LazyComponent, useAwaiter } from "../utils/misc"; -import { findByDisplayName, Forms } from '../webpack'; +import { useAwaiter } from "../utils/misc"; import Plugins from 'plugins'; import { useSettings } from "../api/settings"; -import { findByProps } from '../webpack/index'; import IpcEvents from "../utils/IpcEvents"; -// Lazy spam because this is ran before React is a thing. Todo: Fix that and clean this up lmao +import { Button, ButtonProps, Flex, Switch, Forms } from "../webpack/common"; +import ErrorBoundary from "./ErrorBoundary"; -const SwitchItem = LazyComponent void; - note?: string; - tooltipNote?: string; - disabled?: boolean; -}>>(() => findByDisplayName("SwitchItem").default); - -const getButton = lazy(() => findByProps("ButtonLooks", "default")); -const Button = LazyComponent(() => getButton().default); -const getFlex = lazy(() => findByDisplayName("Flex")); -const Flex = LazyComponent(() => getFlex().default); -const FlexChild = LazyComponent(() => getFlex().default.Child); -const getMargins = lazy(() => findByProps("marginTop8", "marginBottom8")); - -export default function Settings(props) { - const settingsDir = useAwaiter(() => VencordNative.ipc.invoke(IpcEvents.GET_SETTINGS_DIR), "Loading..."); +export default ErrorBoundary.wrap(function Settings(props) { + const [settingsDir, , settingsDirPending] = useAwaiter(() => VencordNative.ipc.invoke(IpcEvents.GET_SETTINGS_DIR), "Loading..."); const settings = useSettings(); return ( SettingsDir: {settingsDir} - - + + - - + + - + Settings - settings.unsafeRequire = v} note="Enables VencordNative.require. Useful for testing, very bad for security. Leave this off unless you need it." > Enable Ensafe Require - + Plugins {Plugins.map(p => ( - {p.name} - + )) } ); -} \ No newline at end of file +}); \ No newline at end of file -- cgit