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,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);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue