From a6e1c7a4627cf0ee0f873ed3bd27f438bf1ef64b Mon Sep 17 00:00:00 2001 From: jax Date: Sat, 18 Jul 2026 13:37:38 -0400 Subject: [PATCH 1/7] PinDMs: fix scrolling issues when using many pins (#4414) very silly math error... --- src/plugins/pinDms/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/pinDms/index.tsx b/src/plugins/pinDms/index.tsx index ebdd8eaee..624d9ded5 100644 --- a/src/plugins/pinDms/index.tsx +++ b/src/plugins/pinDms/index.tsx @@ -212,7 +212,7 @@ export default definePlugin({ const sectionHeaderSizePx = sections.length * 40; // (header heights + DM heights + DEFAULT_CHUNK_SIZE) * 1.5 // we multiply everything by 1.5 so it only gets unmounted after the entire list is off screen - return (sectionHeaderSizePx + sections.reduce((acc, v) => acc += v + 44, 0) + DEFAULT_CHUNK_SIZE) * 1.5; + return (sectionHeaderSizePx + sections.reduce((acc, v) => acc += v * 44, 0) + DEFAULT_CHUNK_SIZE) * 1.5; }, isCategoryIndex(sectionIndex: number) { From 3978889b9b82f0f70c25703dc14109c3442429a0 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 19 Jul 2026 21:13:59 +0200 Subject: [PATCH 2/7] Theme Settings: improve link layout --- .../settings/tabs/themes/LocalThemesTab.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/settings/tabs/themes/LocalThemesTab.tsx b/src/components/settings/tabs/themes/LocalThemesTab.tsx index 2f3a812bc..c2601e3fb 100644 --- a/src/components/settings/tabs/themes/LocalThemesTab.tsx +++ b/src/components/settings/tabs/themes/LocalThemesTab.tsx @@ -10,6 +10,7 @@ import { Card } from "@components/Card"; import { Flex } from "@components/Flex"; import { FolderIcon, PaintbrushIcon, PencilIcon, PlusIcon, RestartIcon } from "@components/Icons"; import { Link } from "@components/Link"; +import { Margins } from "@components/margins"; import { QuickAction, QuickActionCard } from "@components/settings/QuickAction"; import { openPluginModal } from "@components/settings/tabs/plugins/PluginModal"; import { UserThemeHeader } from "@main/themes"; @@ -87,12 +88,10 @@ export function LocalThemesTab() { Find Themes: -
- - BetterDiscord Themes - - GitHub -
+ + – BetterDiscord theme list + – GitHub + If using the BD site, click on "Download" and place the downloaded .theme.css file into your themes folder.
From b07a4cfdc945aefb972cfd971bbdf679d28e3a5d Mon Sep 17 00:00:00 2001 From: theo Date: Sun, 19 Jul 2026 23:01:58 +0100 Subject: [PATCH 3/7] fix MutualGroupDMs (#4415) --- src/plugins/mutualGroupDMs/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index d98519ed9..8b3d29fd0 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -116,7 +116,7 @@ export default definePlugin({ find: ".WIDGETS?", replacement: [ { - match: /items:(\i),.+?(?=return\(0,\i\.jsxs?\)\("div)/, + match: /items:(\i),initialSection:\i,onClose:\i\}=\i.+?(?=return\(0,\i\.jsxs?\)\()/, replace: "$&$self.pushSection($1,arguments[0].user);" }, { From b9e08dc63b27b48ae9e3bd6c9019b05523bc821e Mon Sep 17 00:00:00 2001 From: qrewy <114613848+qrewy@users.noreply.github.com> Date: Mon, 20 Jul 2026 01:19:19 +0300 Subject: [PATCH 4/7] PermissionViewer: fix scrolling behaviour (#4341) --- src/plugins/permissionsViewer/styles.css | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/plugins/permissionsViewer/styles.css b/src/plugins/permissionsViewer/styles.css index 910aee668..24a3c3294 100644 --- a/src/plugins/permissionsViewer/styles.css +++ b/src/plugins/permissionsViewer/styles.css @@ -32,17 +32,22 @@ .vc-permviewer-modal-container { width: 100%; - height: 100%; + height: min(760px, 80vh); + min-height: 0; display: flex; gap: 8px; + overflow: hidden; } .vc-permviewer-modal-list { display: flex; flex-direction: column; gap: 2px; + flex: 0 0 200px; + max-height: 100%; + min-height: 0; + overflow: auto; padding-right: 8px; - width: 200px; } .vc-permviewer-modal-list-item-btn { @@ -98,6 +103,11 @@ .vc-permviewer-modal-perms { display: flex; flex-direction: column; + flex: 1 1 0; + max-height: 100%; + min-width: 0; + min-height: 0; + overflow: auto; padding-right: 8px; } @@ -155,4 +165,4 @@ display: flex; align-items: center; gap: 4px; -} \ No newline at end of file +} From c5f33dd2c8666006e6b8e3783b06c3b70cd0215e Mon Sep 17 00:00:00 2001 From: Vendicated Date: Mon, 20 Jul 2026 00:39:18 +0200 Subject: [PATCH 5/7] BetterSettings: better optimise context menu Co-Authored-By: thororen1234 <78185467+thororen1234@users.noreply.github.com> --- src/plugins/betterSettings/index.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 16a7bac47..ab23b1b44 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -9,11 +9,12 @@ import { disableStyle, enableStyle } from "@api/Styles"; import { buildPluginMenuEntries, buildThemeMenuEntries } from "@plugins/vencordToolbox/menu"; import { Devs } from "@utils/constants"; import { classNameFactory } from "@utils/css"; +import { getIntlMessage } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findCssClassesLazy } from "@webpack"; import { ComponentDispatch, FocusLock, Menu, useEffect, useRef } from "@webpack/common"; -import type { HTMLAttributes, ReactNode } from "react"; +import type { HTMLAttributes, ReactElement, ReactNode } from "react"; import fullHeightStyle from "./fullHeightContext.css?managed"; @@ -177,7 +178,7 @@ export default definePlugin({ return ; }, - transformSettingsEntries(list) { + transformSettingsEntries(list: ReactElement[]): ReactNode[] { const items: ReactNode[] = []; for (const item of list) { @@ -194,9 +195,13 @@ export default definePlugin({ {children} ); - } else if (key.endsWith("_section") && props.label) { + } else if (key === "user_section" || (key?.endsWith("_section") && props.label)) { + const label = key === "user_section" + ? getIntlMessage("USER_SETTINGS") + : props.label; + items.push( - + {this.transformSettingsEntries(props.children)} ); From aa8d348352dd351a2b3fffb697c01c948ac929e6 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Mon, 20 Jul 2026 01:16:02 +0200 Subject: [PATCH 6/7] PermissionViewer/BetterRoleContext: fix 'View Role Members' --- packages/discord-types/src/components.d.ts | 7 ++++++ .../_core/concatenatedComponentExtractor.tsx | 12 +++++++-- src/plugins/betterRoleContext/index.tsx | 25 ++----------------- src/webpack/common/components.ts | 7 ++++-- src/webpack/webpack.ts | 2 +- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/packages/discord-types/src/components.d.ts b/packages/discord-types/src/components.d.ts index a8b181599..5dca0599a 100644 --- a/packages/discord-types/src/components.d.ts +++ b/packages/discord-types/src/components.d.ts @@ -541,3 +541,10 @@ export type ColorPicker = ComponentType<{ label?: ReactNode; onChange(value: number | null): void; }>; + +export type RoleMemberPopout = ComponentType<{ + popoutProps: PopoutProps; + guildId: string; + channelId: string; + roleId: string; +}>; diff --git a/src/plugins/_core/concatenatedComponentExtractor.tsx b/src/plugins/_core/concatenatedComponentExtractor.tsx index 7fd23ff77..288d530b3 100644 --- a/src/plugins/_core/concatenatedComponentExtractor.tsx +++ b/src/plugins/_core/concatenatedComponentExtractor.tsx @@ -6,7 +6,7 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { setColorPicker, setCreateScroller } from "@webpack/common"; +import { setColorPicker, setCreateScroller, setRoleMemberPopout } from "@webpack/common"; export default definePlugin({ name: "ConcatenatedComponentExtractor", @@ -29,9 +29,17 @@ export default definePlugin({ match: /(?=function (\i)\(\i,\i,\i\)\{.{0,20}?return \i\.forwardRef\(function\(\i,\i\)\{let\{[^}]+?="ltr",orientation:)/, replace: "$self.setCreateScroller($1);" } - } + }, + { + find: ".ROLE_MENTION)", + replacement: { + match: /function (\i)(?=.+?renderPopout:.{0,20}\1,\{guildId:\i,channelId:\i)/, + replace: "$self.setRoleMemberPopout($1);$&" + } + }, ], setCreateScroller, setColorPicker, + setRoleMemberPopout, }); diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx index 5344da5b3..53f603dc3 100644 --- a/src/plugins/betterRoleContext/index.tsx +++ b/src/plugins/betterRoleContext/index.tsx @@ -13,10 +13,9 @@ import { getCurrentChannel, getCurrentGuild, getIntlMessage, openImageModal } fr import { isTruthy } from "@utils/guards"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; -import { Guild, PopoutProps, Role } from "@vencord/discord-types"; +import { Guild, Role } from "@vencord/discord-types"; import { findByCodeLazy, findByPropsLazy, findCssClassesLazy } from "@webpack"; -import { ContextMenuApi, GuildRoleStore, Menu, PermissionStore, Popout, useRef } from "@webpack/common"; -import { ComponentType } from "react"; +import { ContextMenuApi, GuildRoleStore, Menu, PermissionStore, Popout, RoleMemberPopout, useRef } from "@webpack/common"; const GuildSettingsActions = findByPropsLazy("open", "selectRole", "updateGuild"); const MenuItemClasses = findCssClassesLazy("item", "labelContainer", "colorDefault", "label", "iconContainer"); @@ -76,15 +75,6 @@ const settings = definePluginSettings({ } }); -interface RoleMemberPopoutProps { - popoutProps: PopoutProps; - guildId: string; - channelId: string; - roleId: string; -} -type RoleMemberPopout = ComponentType; - -let RoleMemberPopout: RoleMemberPopout = () => null; export function buildExtraRoleContextMenuItems(role: Role, guild: Guild, popoutRef?: React.RefObject) { if (!role) return { before: [], after: [] }; @@ -211,13 +201,6 @@ export default definePlugin({ settings, openRoleContextMenu, patches: [ - { - find: ".ROLE_MENTION)", - replacement: { - match: /function (\i)(?=.+?renderPopout:.{0,20}\1,\{guildId:\i,channelId:\i)/, - replace: "$self.RoleMembers=$1;$&" - } - }, // Conflicts with RoleColorEverywhere which changes the code at the end of our match. (and also uses same find & similar match) // However, BetterRoleContext applies first (alphabetic order), so it's not an issue { @@ -234,10 +217,6 @@ export default definePlugin({ DeveloperMode.updateSetting(true); }, - set RoleMembers(component: RoleMemberPopout) { - RoleMemberPopout = component; - }, - contextMenus: { "dev-context"(children, { id }: { id: string; }) { const popoutRef = useRef(null); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index cf11deeae..7cda74590 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -68,14 +68,17 @@ export const TabBar = waitForComponent("TabBar", filters.componentByCode("ref:th // TODO: remake this component export const Clickable = waitForComponent("Clickable", filters.componentByCode("this.context?this.renderNonInteractive():")); export const Avatar = waitForComponent("Avatar", filters.componentByCode(".size-1.375*")); +export const UserSummaryItem = waitForComponent("UserSummaryItem", filters.componentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers")); export let ColorPicker: t.ColorPicker = () => null; export function setColorPicker(component: t.ColorPicker) { ColorPicker = component; } - -export const UserSummaryItem = waitForComponent("UserSummaryItem", filters.componentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers")); +export let RoleMemberPopout: t.RoleMemberPopout = () => null; +export function setRoleMemberPopout(component: t.RoleMemberPopout) { + RoleMemberPopout = component; +} export let createScroller: ((scrollbarClassName: string, fadeClassName: string, customThemeClassName: string) => t.ScrollerThin) | undefined; export function setCreateScroller(cs: NonNullable) { diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 7e420575b..6ccd27a5f 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -55,7 +55,7 @@ export const stringMatches = (s: string, filter: CodeFilter) => ); export function makeClassNameRegex(className: string) { - return new RegExp(`(?:\\b|_)${escapeRegExp(className)}(?:\\b|_)`); + return new RegExp(`(?<=^|\\s)${escapeRegExp(className)}(?:_\\S*)?(?=$|\\s)`); } export const filters = { From 4b9c27d905d6255141617546227a56073916ebd4 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 20 Jul 2026 10:44:54 -0300 Subject: [PATCH 7/7] ViewIcons: fix profile avatars --- src/plugins/viewIcons/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/viewIcons/index.tsx b/src/plugins/viewIcons/index.tsx index d0c430725..267206146 100644 --- a/src/plugins/viewIcons/index.tsx +++ b/src/plugins/viewIcons/index.tsx @@ -201,8 +201,8 @@ export default definePlugin({ { find: "return{avatarProps:{", replacement: { - match: /(?<=avatarProps:(\i),eventHandlers:(\i).{0,100}?)return null==/, - replace: 'Object.assign($2,{style:{cursor:"pointer"},onClick:()=>$self.openAvatar($1.src)});$&', + match: /(?<=avatarProps:(\i),eventHandlers:\i.{0,100}?)return null==(?<=onOpenAvatar:(\i).+?)/, + replace: "$2&&=$self.openAvatar.bind(undefined,$1.src);$&", } }, // Banners