From 587f40dae6ac0c320c6d12587dcf2fa50b8847b5 Mon Sep 17 00:00:00 2001 From: sadan <117494111+sadan4@users.noreply.github.com> Date: Tue, 25 Aug 2026 19:28:34 -0400 Subject: [PATCH 1/5] FakeNitro: fix emojis (#4547) --- src/plugins/_core/settings.tsx | 11 +++++------ src/plugins/fakeNitro/index.tsx | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 3cf75676e..990472cf3 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -110,10 +110,9 @@ export default definePlugin({ find: "#{intl::COPY_VERSION}", replacement: [ { - match: /"text-xxs\/normal".{0,300}?(?=null!=(\i)&&(.{0,20}\i\.\i.{0,200}?,children:).{0,15}?("span"),({className:\i\.\i,children:\["Build Override: ",\1\.id\]\})\)\}\))/, - replace: (m, _buildOverride, makeRow, component, props) => { - props = props.replace(/children:\[.+\]/, ""); - return `${m},$self.makeInfoElements(${component},${props}).map(e=>${makeRow}e})),`; + match: /"text-xxs\/normal".{0,300}?(?=null!=(\i)&&(.{0,20}\i\.\i.{0,200}?,children:).{0,15}?("span"),{className:(\i\.\i),children:\["Build Override: ",\1\.id,\i\]\}\)\}\))/, + replace: (m, _buildOverride, makeRow, component, className) => { + return `${m},$self.makeInfoElements(${component},${className}).map(e=>${makeRow}e})),`; } }, { @@ -304,9 +303,9 @@ export default definePlugin({ return "\n" + this.getInfoRows().join("\n"); }, - makeInfoElements(Component: ComponentType, props: PropsWithChildren) { + makeInfoElements(Component: ComponentType>, className: string) { return this.getInfoRows().map((text, i) => - {text} + {text} ); } }); diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 754375be3..ce8837f35 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -259,8 +259,8 @@ export default definePlugin({ }, { // Disallow the emoji for premium locked if the intention doesn't allow it - match: /!(\i\.\i\.canUseEmojisEverywhere\(\i\))/, - replace: m => `(${m}&&!${IS_BYPASSEABLE_INTENTION})` + match: /(?<=!\(\i\|\|)\i\.\i\.canUseEmojisEverywhere\(\i\)/, + replace: check => `(${check}&&!${IS_BYPASSEABLE_INTENTION})` }, { // Allow animated emojis to be used if the intention allows it From bf68eee20d00a89fa64e40fa3de81b1f99ac03b9 Mon Sep 17 00:00:00 2001 From: thororen <78185467+thororen1234@users.noreply.github.com> Date: Tue, 25 Aug 2026 19:35:43 -0400 Subject: [PATCH 2/5] MessageLinkEmbeds: prefer attachment proxyURL (#4543) --- src/plugins/messageLinkEmbeds/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index bdf283104..dd7501920 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -356,7 +356,7 @@ function AutomodEmbedAccessory(props: MessageEmbedProps): JSX.Element | null { const { width, height } = computeWidthAndHeight(a.width, a.height); return (
- +
); })} From 985b41a5c162d05993266003b1ba7b68fad16609 Mon Sep 17 00:00:00 2001 From: Davri <42148912+Davr1@users.noreply.github.com> Date: Wed, 26 Aug 2026 01:41:43 +0200 Subject: [PATCH 3/5] improve MutualGroupDMs ui (#4550) --- src/plugins/mutualGroupDMs/index.tsx | 59 ++++++++++++++-------------- src/plugins/mutualGroupDMs/style.css | 10 +++++ 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index 632d1f882..fd3ba13b3 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -23,14 +23,14 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { isNonNullish } from "@utils/guards"; import { Logger } from "@utils/Logger"; +import { classes } from "@utils/misc"; import definePlugin from "@utils/types"; import { Channel, User } from "@vencord/discord-types"; import { findByPropsLazy, findCssClassesLazy } from "@webpack"; -import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, Text, useMemo, UserStore } from "@webpack/common"; +import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, useMemo, UsernameUtils, UserStore } from "@webpack/common"; import { ComponentType, JSX } from "react"; const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel"); -const UserUtils = findByPropsLazy("getGlobalName"); const ProfileListClasses = findCssClassesLazy("empty", "textContainer", "connectionIcon"); const TabBarClasses = findCssClassesLazy("tabPanelScroller", "tabBarPanel"); @@ -38,12 +38,14 @@ const MutualsListClasses = findCssClassesLazy("row", "icon", "name", "details"); let ExpandableList: ComponentType = () => null; +const logger = new Logger("MutualGroupDMs"); + function getGroupDMName(channel: Channel) { return channel.name || channel.recipients .map(UserStore.getUser) .filter(isNonNullish) - .map(c => RelationshipStore.getNickname(c.id) || UserUtils.getName(c)) + .map(c => RelationshipStore.getNickname(c.id) || UsernameUtils.getName(c)) .join(", "); } @@ -58,13 +60,13 @@ function getMutualGDMCountText(user: User) { return `${count === 0 ? "No" : count} Mutual Group${count !== 1 ? "s" : ""}`; } -function renderClickableGDMs(mutualDms: Channel[], onClose: () => void) { +function renderClickableGDMs(mutualDms: Channel[], onClose?: () => void) { return mutualDms.map(c => ( { - onClose(); + onClose?.(); SelectedChannelActionCreators.selectPrivateChannel(c.id); }} > @@ -76,14 +78,12 @@ function renderClickableGDMs(mutualDms: Channel[], onClose: () => void) {
{getGroupDMName(c)}
- {c.recipients.length + 1} Members + {c.recipients.length + 1} Members
)); } -const IS_PATCHED = Symbol("MutualGroupDMs.Patched"); - export default definePlugin({ name: "MutualGroupDMs", description: "Shows mutual group dms in profiles", @@ -91,17 +91,17 @@ export default definePlugin({ authors: [Devs.amia], patches: [ - // User Profile Modal + // Legacy User Profile Modal { find: ".BOT_DATA_ACCESS?(", replacement: [ { - match: /\i\.useEffect.{0,100}(\i)\[0\]\.section/, - replace: "$self.pushSection($1,arguments[0].user);$&" + match: /(?<=initialSection:\i=\i\.\i\.USER_INFO,onClose:\i\}=)(\i)/, + replace: "$self.getProps($1)" }, { match: /\(0,\i\.jsx\)\(\i,\{items:\i,section:(\i)/, - replace: "$1==='MUTUAL_GDMS'?$self.renderMutualGDMs(arguments[0]):$&" + replace: "$1==='MUTUAL_GDMS'?$self.renderMutualGDMs({...arguments[0],isLegacy:true}):$&" }, // Discord adds spacing between each item which pushes our tab off screen. // set the gap to zero to ensure ours stays on screen @@ -116,12 +116,12 @@ export default definePlugin({ find: ".WIDGETS?", replacement: [ { - match: /items:(\i),initialSection:\i,onClose:\i\}=\i.{0,200}?(?=return.{0,30}?\(0,\i\.jsxs?\)\()/, - replace: "$&$self.pushSection($1,arguments[0].user);" + match: /(?<=items:\i,initialSection:\i,onClose:\i\}=)(\i)/, + replace: "$self.getProps($1)" }, { match: /children:(?=.{0,100}?component:.+?section:(\i))/, - replace: "$&$1==='MUTUAL_GDMS'?$self.renderMutualGDMs(arguments[0]):" + replace: "$&$1.section==='MUTUAL_GDMS'?$self.renderMutualGDMs(arguments[0]):" }, // Make the gap between each item smaller so our tab can fit. { @@ -130,6 +130,7 @@ export default definePlugin({ }, ] }, + // Legacy DM Sidebar { find: 'section:"MUTUAL_FRIENDS"', replacement: [ @@ -158,33 +159,33 @@ export default definePlugin({ try { return getMutualGroupDms(userId); } catch (e) { - new Logger("MutualGroupDMs").error("Failed to get mutual group dms:", e); + logger.error("Failed to get mutual group dms:", e); } return []; }, - pushSection(sections: any[], user: User) { + getProps(props: { user: User, items: any[]; }) { try { - if (isBotOrSelf(user) || sections[IS_PATCHED]) return; + if (isBotOrSelf(props.user)) return props; - sections[IS_PATCHED] = true; - sections.push({ - text: getMutualGDMCountText(user), - section: "MUTUAL_GDMS", - }); - } catch (e) { - new Logger("MutualGroupDMs").error("Failed to push mutual group dms section:", e); + const section = { text: getMutualGDMCountText(props.user), section: "MUTUAL_GDMS" }; + return { ...props, items: [...props.items, section] }; } + catch (e) { + logger.error("Failed to append mutual group dms section:", e); + } + + return props; }, - renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => { + renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose, isLegacy }: { user: User, onClose: () => void; isLegacy: boolean; }) => { const mutualGDms = useMemo(() => getMutualGroupDms(user.id), [user.id]); const entries = renderClickableGDMs(mutualGDms, onClose); return ( @@ -210,10 +211,10 @@ export default definePlugin({ <> {hasDivider && Divider} { })} + items={renderClickableGDMs(mutualGDms)} /> ); diff --git a/src/plugins/mutualGroupDMs/style.css b/src/plugins/mutualGroupDMs/style.css index b6d992ad0..ca547f4c7 100644 --- a/src/plugins/mutualGroupDMs/style.css +++ b/src/plugins/mutualGroupDMs/style.css @@ -5,3 +5,13 @@ .vc-mutual-gdms-modal-v2-tab-bar { --space-xl: 16px; } + +.vc-mutual-gdms-scroller { + gap: 12px; + margin-inline-start: -12px; +} + +.vc-mutual-gdms-dm-page-list { + gap: 0; + margin-inline-start: -8px; +} \ No newline at end of file From dccf58453ca7bd2e464b44732d88ab4d9c0bef85 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 26 Aug 2026 01:43:41 +0200 Subject: [PATCH 4/5] v1.15.3 --- package.json | 2 +- src/utils/TTLMap.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 090f0c104..3892f016b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.15.2", + "version": "1.15.3", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { diff --git a/src/utils/TTLMap.ts b/src/utils/TTLMap.ts index 2217fb477..62e3e3624 100644 --- a/src/utils/TTLMap.ts +++ b/src/utils/TTLMap.ts @@ -15,6 +15,10 @@ export class TTLMap extends Map { } public set(key: K, value: V) { + if (this._timers.has(key)) { + clearTimeout(this._timers.get(key)); + } + const timeoutId = setTimeout(() => { this.delete(key); this.onExpire?.(key, value); From ada5cfeb805e77853bde5b04ba4b248a338de66f Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 26 Aug 2026 01:58:01 +0200 Subject: [PATCH 5/5] FakeNitro: ACTUALLY fix emojis --- src/plugins/fakeNitro/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index ce8837f35..b280a14d1 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -260,7 +260,7 @@ export default definePlugin({ { // Disallow the emoji for premium locked if the intention doesn't allow it match: /(?<=!\(\i\|\|)\i\.\i\.canUseEmojisEverywhere\(\i\)/, - replace: check => `(${check}&&!${IS_BYPASSEABLE_INTENTION})` + replace: check => `(${check}||${IS_BYPASSEABLE_INTENTION})` }, { // Allow animated emojis to be used if the intention allows it