diff --git a/src/debug/reporterData.ts b/src/debug/reporterData.ts index 09cd318d3..1ed7a9cbf 100644 --- a/src/debug/reporterData.ts +++ b/src/debug/reporterData.ts @@ -13,12 +13,16 @@ import { TypeWebpackSearchHistory } from "@webpack"; interface EvaledPatch extends Patch { id: number | string; } +interface ErroredPatch extends EvaledPatch { + oldModule: string, + newModule: string; +} interface ReporterData { failedPatches: { foundNoModule: Patch[]; hadNoEffect: EvaledPatch[]; undoingPatchGroup: EvaledPatch[]; - erroredPatch: EvaledPatch[]; + erroredPatch: ErroredPatch[]; }; failedWebpack: Record; } diff --git a/src/plugins/devCompanion.dev/index.tsx b/src/plugins/devCompanion.dev/index.tsx index 3c1ccd52e..988f340dc 100644 --- a/src/plugins/devCompanion.dev/index.tsx +++ b/src/plugins/devCompanion.dev/index.tsx @@ -35,9 +35,14 @@ export const settings = definePluginSettings({ default: true }, usePatchedModule: { - description: "On extract requests, reply with the current patched module (if it is patched) instead of the original", - type: OptionType.BOOLEAN, + description: "On extract requests, reply with the current patched module (if it is patched) instead of the original.", default: true, + type: OptionType.BOOLEAN, + }, + reloadAfterToggle: { + description: "Reload after a disable/enable plugin command is recived.", + default: true, + type: OptionType.BOOLEAN } }); @@ -45,8 +50,7 @@ export default definePlugin({ name: "DevCompanion", description: "Dev Companion Plugin", authors: [Devs.Ven, Devs.sadan, Devs.Samwich], - // we need to be reporter testable to run and give the reuslts - reporterTestable: IS_COMPANION_TEST ? undefined : ReporterTestable.None, + reporterTestable: ReporterTestable.None, settings, toolboxActions: { diff --git a/src/plugins/devCompanion.dev/initWs.tsx b/src/plugins/devCompanion.dev/initWs.tsx index 5dcef2eb7..3fee2e150 100644 --- a/src/plugins/devCompanion.dev/initWs.tsx +++ b/src/plugins/devCompanion.dev/initWs.tsx @@ -8,9 +8,10 @@ import { showNotification } from "@api/Notifications"; import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; import { filters, findAll, search, wreq } from "@webpack"; import { reporterData } from "debug/reporterData"; +import { Settings } from "Vencord"; import { logger, PORT, settings } from "."; -import { extractModule, extractOrThrow, FindData, findModuleId, FindType, mkRegexFind, parseNode, PatchData, SendData } from "./util"; +import { extractModule, extractOrThrow, FindData, findModuleId, FindType, mkRegexFind, parseNode, PatchData, SendData, toggleEnabled, } from "./util"; export function stopWs() { socket?.close(1000, "Plugin Stopped"); @@ -117,6 +118,13 @@ export function initWs(isManual = false) { logger.info("Received Message:", type, "\n", data); switch (type) { + case "disable": { + const { enabled, pluginName } = data; + const settings = Settings.plugins[pluginName]; + if (enabled !== settings.enabled) + toggleEnabled(pluginName, reply); + break; + } case "diff": { try { const { extractType, idOrSearch } = data; diff --git a/src/plugins/devCompanion.dev/util.tsx b/src/plugins/devCompanion.dev/util.tsx index 61deb2a3a..f18496aba 100644 --- a/src/plugins/devCompanion.dev/util.tsx +++ b/src/plugins/devCompanion.dev/util.tsx @@ -4,13 +4,17 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { showNotice } from "@api/Notices"; +import { Settings } from "@api/Settings"; import { canonicalizeMatch } from "@utils/patches"; import { CodeFilter, stringMatches, wreq } from "@webpack"; +import { Toasts } from "@webpack/common"; -import { settings } from "."; +import { settings as companionSettings } from "."; type Node = StringNode | RegexNode | FunctionNode; + export interface StringNode { type: "string"; value: string; @@ -64,7 +68,7 @@ export function extractOrThrow(id) { * @param id module id * @param patched return the patched module */ -export function extractModule(id: number, patched = settings.store.usePatchedModule): string { +export function extractModule(id: number, patched = companionSettings.store.usePatchedModule): string { const module = wreq.m[id]; if (!module) throw new Error("No module found for module id:" + id); @@ -104,4 +108,92 @@ export function mkRegexFind(idOrSearch: string): RegExp[] { const flags = idOrSearch.substring(idOrSearch.lastIndexOf("/") + 1); return [canonicalizeMatch(RegExp(regex, flags))]; } +// the next two functions are copied from components/pluginSettings +function showErrorToast(message: string) { + Toasts.show({ + message, + type: Toasts.Type.FAILURE, + id: Toasts.genId(), + options: { + position: Toasts.Position.BOTTOM + } + }); +} +export function toggleEnabled(name: string, beforeReload: () => void) { + let restartNeeded = false; + function onRestartNeeded() { + restartNeeded = true; + } + function beforeReturn() { + if (restartNeeded) { + if (companionSettings.store.reloadAfterToggle) { + beforeReload(); + window.location.reload(); + } + Toasts.show({ + id: Toasts.genId(), + message: "Reload Needed", + type: Toasts.Type.MESSAGE, + options: { + duration: 5000, + position: Toasts.Position.TOP + } + }); + } + } + const plugin = Vencord.Plugins.plugins[name]; + + const settings = Settings.plugins[plugin.name]; + + const isEnabled = () => settings.enabled ?? false; + + const wasEnabled = isEnabled(); + + // If we're enabling a plugin, make sure all deps are enabled recursively. + if (!wasEnabled) { + const { restartNeeded, failures } = Vencord.Plugins.startDependenciesRecursive(plugin); + if (failures.length) { + console.error(`Failed to start dependencies for ${plugin.name}: ${failures.join(", ")}`); + showNotice("Failed to start dependencies: " + failures.join(", "), "Close", () => null); + beforeReturn(); + return; + } else if (restartNeeded) { + // If any dependencies have patches, don't start the plugin yet. + settings.enabled = true; + onRestartNeeded(); + beforeReturn(); + return; + } + } + + // if the plugin has patches, dont use stopPlugin/startPlugin. Wait for restart to apply changes. + if (plugin.patches?.length) { + settings.enabled = !wasEnabled; + onRestartNeeded(); + beforeReturn(); + return; + } + + // If the plugin is enabled, but hasn't been started, then we can just toggle it off. + if (wasEnabled && !plugin.started) { + settings.enabled = !wasEnabled; + beforeReturn(); + return; + } + + const result = wasEnabled ? Vencord.Plugins.stopPlugin(plugin) : Vencord.Plugins.startPlugin(plugin); + + if (!result) { + settings.enabled = false; + + const msg = `Error while ${wasEnabled ? "stopping" : "starting"} plugin ${plugin.name}`; + console.error(msg); + showErrorToast(msg); + beforeReturn(); + return; + } + + settings.enabled = !wasEnabled; + beforeReturn(); +} diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 45c6970de..1aee04822 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -318,6 +318,8 @@ function patchFactories(factories: Record