Fix CrashHandler failing to recover and showing gray screen instead

This commit is contained in:
Nuckyz 2024-02-10 13:42:31 -03:00
parent cc0d9a90bc
commit 38beb93e5f
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9

View file

@ -25,7 +25,6 @@ import definePlugin, { OptionType } from "@utils/types";
import { maybePromptToUpdate } from "@utils/updater"; import { maybePromptToUpdate } from "@utils/updater";
import { filters, findBulk, proxyLazyWebpack } from "@webpack"; import { filters, findBulk, proxyLazyWebpack } from "@webpack";
import { FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; import { FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common";
import type { ReactElement } from "react";
const CrashHandlerLogger = new Logger("CrashHandler"); const CrashHandlerLogger = new Logger("CrashHandler");
const { ModalStack, DraftManager, DraftType, closeExpressionPicker } = proxyLazyWebpack(() => { const { ModalStack, DraftManager, DraftType, closeExpressionPicker } = proxyLazyWebpack(() => {
@ -57,13 +56,12 @@ const settings = definePluginSettings({
} }
}); });
let crashCount: number = 0; let hasCrashedOnce = false;
let lastCrashTimestamp: number = 0; let shouldAttemptRecover = true;
let shouldAttemptNextHandle = false;
export default definePlugin({ export default definePlugin({
name: "CrashHandler", name: "CrashHandler",
description: "Utility plugin for handling and possibly recovering from Crashes without a restart", description: "Utility plugin for handling and possibly recovering from crashes without a restart",
authors: [Devs.Nuckyz], authors: [Devs.Nuckyz],
enabledByDefault: true, enabledByDefault: true,
@ -74,51 +72,47 @@ export default definePlugin({
find: ".Messages.ERRORS_UNEXPECTED_CRASH", find: ".Messages.ERRORS_UNEXPECTED_CRASH",
replacement: { replacement: {
match: /(?=this\.setState\()/, match: /(?=this\.setState\()/,
replace: "$self.handleCrash(this)||" replace: "$self.handleCrash(this);"
} }
} }
], ],
handleCrash(_this: ReactElement & { forceUpdate: () => void; }) { handleCrash(_this: any) {
if (Date.now() - lastCrashTimestamp <= 1_000 && !shouldAttemptNextHandle) return true; // 1 ms timeout to avoid react breaking when re-rendering
setTimeout(() => {
shouldAttemptNextHandle = false; if (!shouldAttemptRecover) {
if (++crashCount > 5) {
try { try {
showNotification({ showNotification({
color: "#eed202", color: "#eed202",
title: "Discord has crashed!", title: "Discord has crashed!",
body: "Awn :( Discord has crashed more than five times, not attempting to recover.", body: "Awn :( Discord has crashed two times rapidly, not attempting to recover.",
noPersist: true, noPersist: true,
}); });
} catch { } } catch { }
lastCrashTimestamp = Date.now(); return;
return false;
} }
setTimeout(() => crashCount--, 60_000); shouldAttemptRecover = false;
// This is enough to avoid a crash loop
setTimeout(() => shouldAttemptRecover = true, 500);
try { try {
if (crashCount === 1) maybePromptToUpdate("Uh oh, Discord has just crashed... but good news, there is a Vencord update available that might fix this issue! Would you like to update now?", true); if (!hasCrashedOnce) {
hasCrashedOnce = true;
maybePromptToUpdate("Uh oh, Discord has just crashed... but good news, there is a Vencord update available that might fix this issue! Would you like to update now?", true);
}
if (settings.store.attemptToPreventCrashes) { if (settings.store.attemptToPreventCrashes) {
this.handlePreventCrash(_this); this.handlePreventCrash(_this);
return true;
} }
return false;
} catch (err) { } catch (err) {
CrashHandlerLogger.error("Failed to handle crash", err); CrashHandlerLogger.error("Failed to handle crash", err);
return false;
} finally {
lastCrashTimestamp = Date.now();
} }
}, 1);
}, },
handlePreventCrash(_this: ReactElement & { forceUpdate: () => void; }) { handlePreventCrash(_this: any) {
if (Date.now() - lastCrashTimestamp >= 1_000) {
try { try {
showNotification({ showNotification({
color: "#eed202", color: "#eed202",
@ -127,7 +121,6 @@ export default definePlugin({
noPersist: true, noPersist: true,
}); });
} catch { } } catch { }
}
try { try {
const channelId = SelectedChannelStore.getChannelId(); const channelId = SelectedChannelStore.getChannelId();
@ -177,8 +170,7 @@ export default definePlugin({
} }
try { try {
shouldAttemptNextHandle = true; _this.setState({ error: null, info: null });
_this.forceUpdate();
} catch (err) { } catch (err) {
CrashHandlerLogger.debug("Failed to update crash handler component.", err); CrashHandlerLogger.debug("Failed to update crash handler component.", err);
} }