From 0bacc8a2f10cc0aef3bdd1b6870f4c4883b3faff Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Fri, 18 Jul 2025 01:16:44 +0700 Subject: [PATCH] feat(plugins): add `error-boundary` --- .../components/ErrorBoundaryScreen.tsx | 244 ++++++++++++++++++ src/plugins/start/error-boundary/index.tsx | 63 +++++ 2 files changed, 307 insertions(+) create mode 100644 src/plugins/start/error-boundary/components/ErrorBoundaryScreen.tsx create mode 100644 src/plugins/start/error-boundary/index.tsx diff --git a/src/plugins/start/error-boundary/components/ErrorBoundaryScreen.tsx b/src/plugins/start/error-boundary/components/ErrorBoundaryScreen.tsx new file mode 100644 index 0000000..6ad117b --- /dev/null +++ b/src/plugins/start/error-boundary/components/ErrorBoundaryScreen.tsx @@ -0,0 +1,244 @@ +import { styles } from '@revenge-mod/components/_' +import { Tokens } from '@revenge-mod/discord/common' +import { Design } from '@revenge-mod/discord/design' +import { ClientInfoModule } from '@revenge-mod/discord/native' +import { Clipboard } from '@revenge-mod/externals/react-native-clipboard' +import { getErrorStack } from '@revenge-mod/utils/error' +import { SafeAreaView, ScrollView, StyleSheet, View } from 'react-native' +import { FullVersion } from '~/constants' +import type { ComponentProps } from 'react' + +const { createStyles, Button, Card, Stack, Text } = Design + +const useErrorBoundaryStyles = createStyles({ + view: { + backgroundColor: Tokens.default.colors.BG_BASE_SECONDARY, + paddingHorizontal: 16, + paddingVertical: 24, + flex: 1, + gap: 16, + }, +}) + +const additionalStyles = StyleSheet.create({ + headerContainer: { + gap: 4, + }, + scrollView: { + gap: 8, + flex: 1, + }, + stackTrace: { + fontFamily: 'monospace', + fontWeight: 'bold', + marginBottom: 8, + }, +}) + +interface RenderError extends Error { + componentStack?: string +} + +export default function ErrorBoundaryScreen({ + error, + rerender, + reload, +}: { + error: RenderError | unknown + rerender: () => void + reload: () => void +}) { + const errorBoundaryStyles = useErrorBoundaryStyles() + const Client = ClientInfoModule.getConstants() + + return ( + + + Error! + + An error was thrown while rendering components. This could + be caused by plugins, Revenge or Discord. + + + {Client.Version} ({Client.Build}) • {FullVersion} + + + + {String(error)} + {error instanceof Error && error.stack && ( + + {parseStackTrace( + error.stack?.slice(String(error).length + 1), + ).map(({ at, file, line, column }) => ( + // biome-ignore lint/correctness/useJsxKeyInIterable: This never gets rerendered + + {at} + {'\n'} + + {file} + { + <> + :{line}:{column} + + } + + + ))} + + )} + + {error instanceof Error && + (error as RenderError).componentStack && ( + + + {...parseStackTrace( + (error as RenderError).componentStack!.slice(1), + ).map(({ at }) => [ + '<', + // biome-ignore lint/correctness/useJsxKeyInIterable: This never gets rerendered + {at}, + '/>\n', + ])} + + + )} + +