better handling for settings ui errors

This commit is contained in:
Vendicated 2022-11-15 17:29:31 +01:00
parent eabbf7d9bd
commit b30508aef8
No known key found for this signature in database
GPG Key ID: EC781ADFB93EFFA3
5 changed files with 60 additions and 4 deletions

@ -102,11 +102,11 @@ const ErrorBoundary = LazyComponent(() => {
}; };
}) as }) as
React.ComponentType<React.PropsWithChildren<Props>> & { React.ComponentType<React.PropsWithChildren<Props>> & {
wrap<T extends JSX.IntrinsicAttributes = any>(Component: React.ComponentType<T>): React.ComponentType<T>; wrap<T extends JSX.IntrinsicAttributes = any>(Component: React.ComponentType<T>, errorBoundaryProps?: Props): React.ComponentType<T>;
}; };
ErrorBoundary.wrap = Component => props => ( ErrorBoundary.wrap = (Component, errorBoundaryProps) => props => (
<ErrorBoundary> <ErrorBoundary {...errorBoundaryProps}>
<Component {...props} /> <Component {...props} />
</ErrorBoundary> </ErrorBoundary>
); );

@ -31,6 +31,7 @@ import { Alerts, Button, Forms, Margins, Parser, React, Select, Switch, Text, Te
import ErrorBoundary from "../ErrorBoundary"; import ErrorBoundary from "../ErrorBoundary";
import { ErrorCard } from "../ErrorCard"; import { ErrorCard } from "../ErrorCard";
import { Flex } from "../Flex"; import { Flex } from "../Flex";
import { handleComponentFailed } from "../handleComponentFailed";
import PluginModal from "./PluginModal"; import PluginModal from "./PluginModal";
import * as styles from "./styles"; import * as styles from "./styles";
@ -312,6 +313,9 @@ export default ErrorBoundary.wrap(function Settings() {
</div> </div>
</Forms.FormSection > </Forms.FormSection >
); );
}, {
message: "Failed to render the Plugin Settings. If this persists, try using the installer to reinstall!",
onError: handleComponentFailed,
}); });
function makeDependencyList(deps: string[]) { function makeDependencyList(deps: string[]) {

@ -23,6 +23,7 @@ import { useAwaiter } from "../utils/misc";
import { Alerts, Button, Forms, Margins, Parser, React, Switch } from "../webpack/common"; import { Alerts, Button, Forms, Margins, Parser, React, Switch } from "../webpack/common";
import ErrorBoundary from "./ErrorBoundary"; import ErrorBoundary from "./ErrorBoundary";
import { Flex } from "./Flex"; import { Flex } from "./Flex";
import { handleComponentFailed } from "./handleComponentFailed";
export default ErrorBoundary.wrap(function Settings() { export default ErrorBoundary.wrap(function Settings() {
const [settingsDir, , settingsDirPending] = useAwaiter(() => VencordNative.ipc.invoke<string>(IpcEvents.GET_SETTINGS_DIR), "Loading..."); const [settingsDir, , settingsDirPending] = useAwaiter(() => VencordNative.ipc.invoke<string>(IpcEvents.GET_SETTINGS_DIR), "Loading...");
@ -115,4 +116,7 @@ export default ErrorBoundary.wrap(function Settings() {
</Switch>} </Switch>}
</Forms.FormSection > </Forms.FormSection >
); );
}, {
message: "Failed to render the Settings. If this persists, try using the installer to reinstall!",
onError: handleComponentFailed,
}); });

@ -24,6 +24,7 @@ import { Alerts, Button, Card, Forms, Margins, Parser, React, Toasts } from "../
import ErrorBoundary from "./ErrorBoundary"; import ErrorBoundary from "./ErrorBoundary";
import { ErrorCard } from "./ErrorCard"; import { ErrorCard } from "./ErrorCard";
import { Flex } from "./Flex"; import { Flex } from "./Flex";
import { handleComponentFailed } from "./handleComponentFailed";
import { Link } from "./Link"; import { Link } from "./Link";
function withDispatcher(dispatcher: React.Dispatch<React.SetStateAction<boolean>>, action: () => any) { function withDispatcher(dispatcher: React.Dispatch<React.SetStateAction<boolean>>, action: () => any) {
@ -209,4 +210,7 @@ function Updater() {
); );
} }
export default IS_WEB ? null : ErrorBoundary.wrap(Updater); export default IS_WEB ? null : ErrorBoundary.wrap(Updater, {
message: "Failed to render the Updater. If this persists, try using the installer to reinstall!",
onError: handleComponentFailed,
});

@ -0,0 +1,44 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { isOutdated, rebuild, update } from "../utils/updater";
export async function handleComponentFailed() {
if (isOutdated) {
setImmediate(async () => {
const wantsUpdate = confirm(
"Uh Oh! Failed to render this Page." +
" However, there is an update available that might fix it." +
" Would you like to update and restart now?"
);
if (wantsUpdate) {
try {
await update();
await rebuild();
if (IS_WEB)
location.reload();
else
DiscordNative.app.relaunch();
} catch (e) {
console.error(e);
alert("That also failed :( Try updating or reinstalling with the installer!");
}
}
});
}
}