Fix CrashHandler failing to recover and showing gray screen instead
This commit is contained in:
parent
cc0d9a90bc
commit
38beb93e5f
1 changed files with 44 additions and 52 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue