(value: T): T {
return value;
}
-// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop
-// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device."
-export const isMobile = navigator.userAgent.includes("Mobi");
-
export const isPluginDev = (id: string) => Object.hasOwn(DevsById, id);
export const shouldShowContributorBadge = (id: string) => isPluginDev(id) && DevsById[id].badge !== false;
diff --git a/src/utils/native.ts b/src/utils/native.ts
index d84ed16f..f797a816 100644
--- a/src/utils/native.ts
+++ b/src/utils/native.ts
@@ -19,13 +19,8 @@
export function relaunch() {
if (IS_DISCORD_DESKTOP)
window.DiscordNative.app.relaunch();
- else
+ else if (IS_VESKTOP)
window.VesktopNative.app.relaunch();
-}
-
-export function showItemInFolder(path: string) {
- if (IS_DISCORD_DESKTOP)
- window.DiscordNative.fileManager.showItemInFolder(path);
else
- window.VesktopNative.fileManager.showItemInFolder(path);
+ location.reload();
}
diff --git a/src/utils/react.tsx b/src/utils/react.tsx
index 8963bdf5..f283c2a8 100644
--- a/src/utils/react.tsx
+++ b/src/utils/react.tsx
@@ -17,7 +17,7 @@
*/
import { React, useEffect, useMemo, useReducer, useState } from "@webpack/common";
-import { ActionDispatch, ReactNode } from "react";
+import type { ActionDispatch, ReactNode } from "react";
import { checkIntersecting } from "./misc";
diff --git a/src/utils/text.ts b/src/utils/text.ts
index a48c140d..220b3129 100644
--- a/src/utils/text.ts
+++ b/src/utils/text.ts
@@ -16,8 +16,6 @@
* along with this program. If not, see .
*/
-import { moment } from "@webpack/common";
-
// Utils for readable text transformations eg: `toTitle(fromKebab())`
// Case style to words
@@ -54,6 +52,7 @@ function getUnitStr(unit: Units, isOne: boolean, short: boolean) {
* @param short Whether to use short units like "d" instead of "days"
*/
export function formatDuration(time: number, unit: Units, short: boolean = false) {
+ const { moment } = require("@webpack/common") as typeof import("@webpack/common");
const dur = moment.duration(time, unit);
let unitsAmounts = units.map(unit => ({ amount: dur[unit](), unit }));
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 2d21eaff..12cc2d31 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -16,17 +16,17 @@
* along with this program. If not, see .
*/
-import { ProfileBadge } from "@api/Badges";
-import { ChatBarButtonFactory } from "@api/ChatButtons";
-import { NavContextMenuPatchCallback } from "@api/ContextMenu";
-import { MemberListDecoratorFactory } from "@api/MemberListDecorators";
-import { MessageAccessoryFactory } from "@api/MessageAccessories";
-import { MessageDecorationFactory } from "@api/MessageDecorations";
-import { MessageClickListener, MessageEditListener, MessageSendListener } from "@api/MessageEvents";
-import { MessagePopoverButtonFactory } from "@api/MessagePopover";
-import { Command, FluxEvents } from "@vencord/discord-types";
-import { ReactNode } from "react";
-import { LiteralUnion } from "type-fest";
+import type { ProfileBadge } from "@api/Badges";
+import type { ChatBarButtonFactory } from "@api/ChatButtons";
+import type { NavContextMenuPatchCallback } from "@api/ContextMenu";
+import type { MemberListDecoratorFactory } from "@api/MemberListDecorators";
+import type { MessageAccessoryFactory } from "@api/MessageAccessories";
+import type { MessageDecorationFactory } from "@api/MessageDecorations";
+import type { MessageClickListener, MessageEditListener, MessageSendListener } from "@api/MessageEvents";
+import type { MessagePopoverButtonFactory } from "@api/MessagePopover";
+import type { Command, FluxEvents } from "@vencord/discord-types";
+import type { ReactNode } from "react";
+import type { LiteralUnion } from "type-fest";
// exists to export default definePlugin({...})
export default function definePlugin(p: P & Record) {
diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts
index 725b8092..1bad480b 100644
--- a/src/webpack/common/stores.ts
+++ b/src/webpack/common/stores.ts
@@ -85,6 +85,7 @@ waitForStore("VoiceStateStore", m => VoiceStateStore = m);
waitForStore("StreamerModeStore", m => StreamerModeStore = m);
waitForStore("ThemeStore", m => {
ThemeStore = m;
- // Importing this directly can easily cause circular imports. For this reason, use a non import access here.
- Vencord.QuickCss.initQuickCssThemeStore();
+ // Importing this directly causes all webpack commons to be imported, which can easily cause circular dependencies.
+ // For this reason, use a non import access here.
+ Vencord.Api.Themes.initQuickCssThemeStore(m);
});
diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts
index cae1ecd5..0223c2e7 100644
--- a/src/webpack/common/utils.ts
+++ b/src/webpack/common/utils.ts
@@ -22,8 +22,9 @@ import { _resolveReady, filters, findByCodeLazy, findByPropsLazy, findLazy, mapM
export let FluxDispatcher: t.FluxDispatcher;
waitFor(["dispatch", "subscribe"], m => {
FluxDispatcher = m;
- // Non import access to avoid circular dependency
- Vencord.Plugins.subscribeAllPluginsFluxEvents(m);
+ // Importing this directly causes all webpack commons to be imported, which can easily cause circular dependencies.
+ // For this reason, use a non import access here.
+ Vencord.Api.PluginManager.subscribeAllPluginsFluxEvents(m);
const cb = () => {
m.unsubscribe("CONNECTION_OPEN", cb);
diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts
index 767fa20d..2e2a793e 100644
--- a/src/webpack/patchWebpack.ts
+++ b/src/webpack/patchWebpack.ts
@@ -538,7 +538,7 @@ function patchFactory(moduleId: PropertyKey, originalFactory: AnyModuleFactory):
const previousFactory = originalFactory;
let markedAsPatched = false;
- // We change all patch.replacement to array in plugins/index
+ // We change all patch.replacement to array in PluginManager
for (const replacement of patch.replacement as PatchReplacement[]) {
if (
shouldCheckBuildNumber &&
diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts
index 2fadffe1..a37eb1d0 100644
--- a/src/webpack/webpack.ts
+++ b/src/webpack/webpack.ts
@@ -20,12 +20,11 @@ import { makeLazy, proxyLazy } from "@utils/lazy";
import { LazyComponent } from "@utils/lazyReact";
import { Logger } from "@utils/Logger";
import { canonicalizeMatch } from "@utils/patches";
-import { FluxStore } from "@vencord/discord-types";
-import { ModuleExports, WebpackRequire } from "@vencord/discord-types/webpack";
+import type { FluxStore } from "@vencord/discord-types";
+import type { ModuleExports, WebpackRequire } from "@vencord/discord-types/webpack";
import { traceFunction } from "../debug/Tracer";
-import { Flux } from "./common";
-import { AnyModuleFactory, AnyWebpackRequire } from "./types";
+import type { AnyModuleFactory, AnyWebpackRequire } from "./types";
const logger = new Logger("Webpack");
@@ -39,7 +38,7 @@ export const onceReady = new Promise(r => _resolveReady = r);
export let wreq: WebpackRequire;
export let cache: WebpackRequire["c"];
-export const fluxStores: Record = {};
+export const fluxStores = new Map();
export type FilterFn = (mod: any) => boolean;
@@ -75,7 +74,7 @@ export const filters = {
componentByCode: (...code: CodeFilter): FilterFn => {
const byCodeFilter = filters.byCode(...code);
- const filter = m => {
+ const filter = (m: any) => {
let inner = m;
while (inner != null) {
@@ -455,55 +454,50 @@ export function findByCodeLazy(...code: CodeFilter) {
return proxyLazy(() => findByCode(...code));
}
+function populateFluxStoreMap() {
+ const { Flux } = require("./common") as typeof import("./common");
+
+ Flux.Store.getAll?.().forEach(store =>
+ fluxStores.set(store.getName(), store)
+ );
+
+ try {
+ const getLibdiscore = findByCode("libdiscoreWasm is not initialized");
+ const libdiscoreExports = getLibdiscore();
+
+ for (const libdiscoreExportName in libdiscoreExports) {
+ if (!libdiscoreExportName.endsWith("Store")) {
+ continue;
+ }
+
+ const storeName = libdiscoreExportName;
+ const store = libdiscoreExports[storeName];
+
+ fluxStores.set(storeName, store);
+ }
+ } catch { }
+}
+
/**
* Find a store by its displayName
*/
export function findStore(name: StoreNameFilter) {
- let res = fluxStores[name] as any;
- if (res == null) {
- for (const store of Flux.Store.getAll?.() ?? []) {
- const storeName = store.getName();
-
- if (storeName === name) {
- res = store;
- }
-
- if (fluxStores[storeName] == null) {
- fluxStores[storeName] = store;
- }
- }
-
- try {
- const getLibdiscore = findByCode("libdiscoreWasm is not initialized");
- const libdiscoreExports = getLibdiscore();
-
- for (const libdiscoreExportName in libdiscoreExports) {
- if (!libdiscoreExportName.endsWith("Store")) {
- continue;
- }
-
- const storeName = libdiscoreExportName;
- const store = libdiscoreExports[storeName];
-
- if (storeName === name) {
- res = store;
- }
-
- if (fluxStores[storeName] == null) {
- fluxStores[storeName] = store;
- }
- }
-
- } catch { }
-
- if (res == null) {
- res = find(filters.byStoreName(name), { isIndirect: true });
- }
+ if (!fluxStores.has(name)) {
+ populateFluxStoreMap();
}
- if (!res)
- handleModuleNotFound("findStore", name);
- return res;
+ if (fluxStores.has(name)) {
+ return fluxStores.get(name);
+ }
+
+ const res = find(filters.byStoreName(name), { isIndirect: true });
+ if (res) {
+ fluxStores.set(name, res);
+ return res;
+ }
+
+ handleModuleNotFound("findStore", name);
+ return null;
}
/**
diff --git a/tsconfig.json b/tsconfig.json
index 0123021c..c5bac7b1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -26,8 +26,10 @@
"@api/*": ["./api/*"],
"@components/*": ["./components/*"],
"@utils/*": ["./utils/*"],
+ "@plugins/*": ["./plugins/*"],
"@shared/*": ["./shared/*"],
"@webpack/common": ["./webpack/common"],
+ "@webpack/common/*": ["./webpack/common/*"],
"@webpack": ["./webpack/webpack"],
"@webpack/patcher": ["./webpack/patchWebpack"],
"@webpack/wreq.d": ["./webpack/wreq.d"],