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,60 +72,55 @@ 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(() => {
if (!shouldAttemptRecover) {
try {
showNotification({
color: "#eed202",
title: "Discord has crashed!",
body: "Awn :( Discord has crashed two times rapidly, not attempting to recover.",
noPersist: true,
});
} catch { }
shouldAttemptNextHandle = false; return;
if (++crashCount > 5) {
try {
showNotification({
color: "#eed202",
title: "Discord has crashed!",
body: "Awn :( Discord has crashed more than five times, not attempting to recover.",
noPersist: true,
});
} catch { }
lastCrashTimestamp = Date.now();
return false;
}
setTimeout(() => crashCount--, 60_000);
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 (settings.store.attemptToPreventCrashes) {
this.handlePreventCrash(_this);
return true;
} }
return false; shouldAttemptRecover = false;
} catch (err) { // This is enough to avoid a crash loop
CrashHandlerLogger.error("Failed to handle crash", err); setTimeout(() => shouldAttemptRecover = true, 500);
return false;
} finally { try {
lastCrashTimestamp = Date.now(); 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) {
this.handlePreventCrash(_this);
}
} catch (err) {
CrashHandlerLogger.error("Failed to handle crash", err);
}
}, 1);
}, },
handlePreventCrash(_this: ReactElement & { forceUpdate: () => void; }) { handlePreventCrash(_this: any) {
if (Date.now() - lastCrashTimestamp >= 1_000) { try {
try { showNotification({
showNotification({ color: "#eed202",
color: "#eed202", title: "Discord has crashed!",
title: "Discord has crashed!", body: "Attempting to recover...",
body: "Attempting to recover...", 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);
} }