diff --git a/src/patcher.ts b/src/patcher.ts
index c25505a2..4f724cbb 100644
--- a/src/patcher.ts
+++ b/src/patcher.ts
@@ -23,6 +23,7 @@ import { dirname, join } from "path";
import { initIpc } from "./ipcMain";
import { installExt } from "./ipcMain/extensions";
import { readSettings } from "./ipcMain/index";
+import { onceDefined } from "./utils/onceDefined";
console.log("[Vencord] Starting up...");
@@ -74,15 +75,9 @@ require.cache[electronPath]!.exports = {
};
// Patch appSettings to force enable devtools
-Object.defineProperty(global, "appSettings", {
- set: (v: typeof global.appSettings) => {
- v.set("DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING", true);
- // @ts-ignore
- delete global.appSettings;
- global.appSettings = v;
- },
- configurable: true
-});
+onceDefined(global, "appSettings", s =>
+ s.set("DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING", true)
+);
process.env.DATA_DIR = join(app.getPath("userData"), "..", "Vencord");
diff --git a/src/utils/index.ts b/src/utils/index.ts
index d818e886..22504ce2 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -24,4 +24,6 @@ export { default as IpcEvents } from "./IpcEvents";
export { default as Logger } from "./logger";
export * from "./misc";
export * as Modals from "./modal";
+export * from "./onceDefined";
export * from "./proxyLazy";
+export * from "./Queue";
diff --git a/src/utils/onceDefined.ts b/src/utils/onceDefined.ts
new file mode 100644
index 00000000..4ee8fa65
--- /dev/null
+++ b/src/utils/onceDefined.ts
@@ -0,0 +1,47 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2022 Vendicated and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+import type { LiteralUnion } from "type-fest";
+
+/**
+ * Wait for a property to be defined on the target, then call the callback with
+ * the value
+ * @param target Object
+ * @param property Property to be defined
+ * @param callback Callback
+ *
+ * @example onceDefined(window, "webpackChunkdiscord_app", wpInstance => wpInstance.push(...));
+ */
+export function onceDefined>(
+ target: T, property: P, callback: (v: P extends keyof T ? T[P] : any) => void
+): void {
+ const propertyAsAny = property as any;
+
+ if (property in target)
+ return void callback(target[propertyAsAny]);
+
+ Object.defineProperty(target, property, {
+ set(v) {
+ delete target[propertyAsAny];
+ target[propertyAsAny] = v;
+ callback(v);
+ },
+ configurable: true,
+ enumerable: false
+ });
+}
diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts
index ba2d5591..4f78f738 100644
--- a/src/webpack/webpack.ts
+++ b/src/webpack/webpack.ts
@@ -66,6 +66,14 @@ export function _initWebpack(instance: typeof window.webpackChunkdiscord_app) {
instance.pop();
}
+if (IS_DEV && !IS_WEB) {
+ var devToolsOpen = false;
+ // At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed
+ setTimeout(() => {
+ DiscordNative/* just to make sure */?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false);
+ }, 0);
+}
+
export function find(filter: FilterFn, getDefault = true, isWaitFor = false) {
if (typeof filter !== "function")
throw new Error("Invalid filter. Expected a function got " + typeof filter);
@@ -92,10 +100,12 @@ export function find(filter: FilterFn, getDefault = true, isWaitFor = false) {
if (!isWaitFor) {
const err = new Error("Didn't find module matching this filter");
if (IS_DEV) {
- // Strict behaviour in DevBuilds to fail early and make sure the issue is found
- throw err;
+ if (!devToolsOpen)
+ // Strict behaviour in DevBuilds to fail early and make sure the issue is found
+ throw err;
+ } else {
+ logger.warn(err);
}
- logger.warn(err);
}
return null;
@@ -196,10 +206,12 @@ export function bulk(...filterFns: FilterFn[]) {
if (found !== length) {
const err = new Error(`Got ${length} filters, but only found ${found} modules!`);
if (IS_DEV) {
- // Strict behaviour in DevBuilds to fail early and make sure the issue is found
- throw err;
+ if (!devToolsOpen)
+ // Strict behaviour in DevBuilds to fail early and make sure the issue is found
+ throw err;
+ } else {
+ logger.warn(err);
}
- logger.warn(err);
}
return results;
@@ -219,10 +231,12 @@ export function findModuleId(code: string) {
const err = new Error("Didn't find module with code:\n" + code);
if (IS_DEV) {
- // Strict behaviour in DevBuilds to fail early and make sure the issue is found
- throw err;
+ if (!devToolsOpen)
+ // Strict behaviour in DevBuilds to fail early and make sure the issue is found
+ throw err;
+ } else {
+ logger.warn(err);
}
- logger.warn(err);
return null;
}