-
-
+
{renderTimeout(message, true)} timeout remaining
diff --git a/src/plugins/showTimeoutDuration/styles.css b/src/plugins/showTimeoutDuration/styles.css
index 70a826e10..a6f830c38 100644
--- a/src/plugins/showTimeoutDuration/styles.css
+++ b/src/plugins/showTimeoutDuration/styles.css
@@ -2,3 +2,7 @@
display: flex;
align-items: center;
}
+
+.vc-std-wrapper [class*="communicationDisabled"] {
+ margin-right: 0;
+}
diff --git a/src/plugins/startupTimings/index.tsx b/src/plugins/startupTimings/index.tsx
index cf366df38..5051fdf4a 100644
--- a/src/plugins/startupTimings/index.tsx
+++ b/src/plugins/startupTimings/index.tsx
@@ -28,7 +28,7 @@ export default definePlugin({
patches: [{
find: "Messages.ACTIVITY_SETTINGS",
replacement: {
- match: /(?<=}\)([,;])(\i\.settings)\.forEach.+?(\i)\.push.+}\))/,
+ match: /(?<=}\)([,;])(\i\.settings)\.forEach.+?(\i)\.push.+}\)}\))/,
replace: (_, commaOrSemi, settings, elements) => "" +
`${commaOrSemi}${settings}?.[0]==="CHANGELOG"` +
`&&${elements}.push({section:"StartupTimings",label:"Startup Timings",element:$self.StartupTimingPage})`
diff --git a/src/plugins/vcDoubleClick/index.ts b/src/plugins/vcDoubleClick/index.ts
index a55ac7b67..8d4cae6a9 100644
--- a/src/plugins/vcDoubleClick/index.ts
+++ b/src/plugins/vcDoubleClick/index.ts
@@ -48,7 +48,7 @@ export default definePlugin({
})),
{
// channel mentions
- find: ".shouldCloseDefaultModals",
+ find: 'className:"channelMention",children',
replacement: {
match: /onClick:(\i)(?=,.{0,30}className:"channelMention".+?(\i)\.inContent)/,
replace: (_, onClick, props) => ""
diff --git a/src/plugins/viewIcons/index.tsx b/src/plugins/viewIcons/index.tsx
index f71777ad7..359365ee4 100644
--- a/src/plugins/viewIcons/index.tsx
+++ b/src/plugins/viewIcons/index.tsx
@@ -36,6 +36,10 @@ interface GuildContextProps {
guild?: Guild;
}
+interface GroupDMContextProps {
+ channel: Channel;
+}
+
const settings = definePluginSettings({
format: {
type: OptionType.SELECT,
@@ -145,10 +149,27 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon
));
};
+const GroupDMContext: NavContextMenuPatchCallback = (children, { channel }: GroupDMContextProps) => {
+ if (!channel) return;
+
+ children.splice(-1, 0, (
+
+
+ openImage(IconUtils.getChannelIconURL(channel)!)
+ }
+ icon={ImageIcon}
+ />
+
+ ));
+};
+
export default definePlugin({
name: "ViewIcons",
- authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz],
- description: "Makes avatars and banners in user profiles clickable, and adds View Icon/Banner entries in the user and server context menu",
+ authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz, Devs.nyx],
+ description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.",
tags: ["ImageUtilities"],
settings,
@@ -157,11 +178,12 @@ export default definePlugin({
contextMenus: {
"user-context": UserContext,
- "guild-context": GuildContext
+ "guild-context": GuildContext,
+ "gdm-context": GroupDMContext
},
patches: [
- // Make pfps clickable
+ // Profiles Modal pfp
{
find: "User Profile Modal - Context Menu",
replacement: {
@@ -169,7 +191,7 @@ export default definePlugin({
replace: "{src:$1,onClick:()=>$self.openImage($1)"
}
},
- // Make banners clickable
+ // Banners
{
find: ".NITRO_BANNER,",
replacement: {
@@ -180,12 +202,37 @@ export default definePlugin({
'onClick:ev=>$1&&ev.target.style.backgroundImage&&$self.openImage($2),style:{cursor:$1?"pointer":void 0,'
}
},
+ // User DMs "User Profile" popup in the right
{
find: ".avatarPositionPanel",
replacement: {
match: /(?<=avatarWrapperNonUserBot.{0,50})onClick:(\i\|\|\i)\?void 0(?<=,avatarSrc:(\i).+?)/,
replace: "style:($1)?{cursor:\"pointer\"}:{},onClick:$1?()=>{$self.openImage($2)}"
}
+ },
+ // Group DMs top small & large icon
+ {
+ find: /\.recipients\.length>=2(?!
`${m},onClick:()=>$self.openImage(${iconUrl})`
+ }
+ },
+ // User DMs top small icon
+ {
+ find: ".cursorPointer:null,children",
+ replacement: {
+ match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
+ replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})`
+ }
+ },
+ // User Dms top large icon
+ {
+ find: 'experimentLocation:"empty_messages"',
+ replacement: {
+ match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
+ replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})`
+ }
}
]
});
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 86cbbba9e..130c46956 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -422,6 +422,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "Av32000",
id: 593436735380127770n,
},
+ Noxillio: {
+ name: "Noxillio",
+ id: 138616536502894592n,
+ },
Kyuuhachi: {
name: "Kyuuhachi",
id: 236588665420251137n,
@@ -447,6 +451,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "newwares",
id: 421405303951851520n
},
+ JohnyTheCarrot: {
+ name: "JohnyTheCarrot",
+ id: 132819036282159104n
+ },
puv: {
name: "puv",
id: 469441552251355137n
@@ -495,6 +503,18 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "ScattrdBlade",
id: 678007540608532491n
},
+ Moxxie: {
+ name: "Moxxie",
+ id: 712653921692155965n,
+ },
+ Ethan: {
+ name: "Ethan",
+ id: 721717126523781240n,
+ },
+ nyx: {
+ name: "verticalsync",
+ id: 328165170536775680n
+ },
} satisfies Record);
// iife so #__PURE__ works correctly
diff --git a/src/utils/index.ts b/src/utils/index.ts
index ea4adce4a..62f3f6e96 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -23,9 +23,11 @@ export * from "./constants";
export * from "./discord";
export * from "./guards";
export * from "./lazy";
+export * from "./lazyReact";
export * from "./localStorage";
export * from "./Logger";
export * from "./margins";
+export * from "./mergeDefaults";
export * from "./misc";
export * from "./modal";
export * from "./onlyOnce";
diff --git a/src/utils/patches.ts b/src/utils/patches.ts
index 99f0595d6..87f3ce78c 100644
--- a/src/utils/patches.ts
+++ b/src/utils/patches.ts
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { PatchReplacement, ReplaceFn } from "./types";
+import { Patch, PatchReplacement, ReplaceFn } from "./types";
export function canonicalizeMatch(match: T): T {
if (typeof match === "string") return match;
@@ -55,3 +55,9 @@ export function canonicalizeReplacement(replacement: Pick SettingsRouter = m);
export const { Permissions: PermissionsBits } = findLazy(m => typeof m.Permissions?.ADMINISTRATOR === "bigint") as { Permissions: t.PermissionsBits; };
-export const zustandCreate: typeof import("zustand").default = findByCodeLazy("will be removed in v4");
+export const zustandCreate = findByCodeLazy("will be removed in v4");
const persistFilter = filters.byCode("[zustand persist middleware]");
-export const { persist: zustandPersist }: typeof import("zustand/middleware") = findLazy(m => m.persist && persistFilter(m.persist));
+export const { persist: zustandPersist } = findLazy(m => m.persist && persistFilter(m.persist));
export const MessageActions = findByPropsLazy("editMessage", "sendMessage");
export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");
diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts
index c7e424671..f891e38df 100644
--- a/src/webpack/patchWebpack.ts
+++ b/src/webpack/patchWebpack.ts
@@ -122,7 +122,7 @@ Object.defineProperty(Function.prototype, "m", {
// When using react devtools or other extensions, we may also catch their webpack here.
// This ensures we actually got the right one
const { stack } = new Error();
- if (stack?.includes("discord.com") || stack?.includes("discordapp.com")) {
+ if ((stack?.includes("discord.com") || stack?.includes("discordapp.com")) && !Array.isArray(v)) {
logger.info("Found Webpack module factory", stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? "");
patchFactories(v);
}
diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts
index 8ea6713d0..0bee08f32 100644
--- a/src/webpack/webpack.ts
+++ b/src/webpack/webpack.ts
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { proxyLazy } from "@utils/lazy";
+import { makeLazy, proxyLazy } from "@utils/lazy";
import { LazyComponent } from "@utils/lazyReact";
import { Logger } from "@utils/Logger";
import { canonicalizeMatch } from "@utils/patches";
@@ -462,7 +462,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def
export function extractAndLoadChunksLazy(code: string[], matcher = DefaultExtractAndLoadChunksRegex) {
if (IS_DEV) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]);
- return () => extractAndLoadChunks(code, matcher);
+ return makeLazy(() => extractAndLoadChunks(code, matcher));
}
/**
diff --git a/tsconfig.json b/tsconfig.json
index 96c904766..8db0ab3c1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -29,7 +29,15 @@
"@webpack/types": ["./webpack/common/types"],
"@webpack/common": ["./webpack/common"],
"@webpack": ["./webpack/webpack"]
- }
+ },
+
+ "plugins": [
+ // Transform paths in output .d.ts files (Include this line if you output declarations files)
+ {
+ "transform": "typescript-transform-paths",
+ "afterDeclarations": true
+ }
+ ]
},
"include": ["src/**/*", "browser/**/*", "scripts/**/*"]
}