diff --git a/packages/discord-types/src/classes.d.ts b/packages/discord-types/src/classes.d.ts deleted file mode 100644 index a7260048..00000000 --- a/packages/discord-types/src/classes.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface ButtonWrapperClasses { - hoverScale: string; - buttonWrapper: string; - button: string; - iconMask: string; - buttonContent: string; - icon: string; - pulseIcon: string; - pulseButton: string; - notificationDot: string; - sparkleContainer: string; - sparkleStar: string; - sparklePlus: string; - sparkle: string; - active: string; -} diff --git a/packages/discord-types/src/index.d.ts b/packages/discord-types/src/index.d.ts index fdbd65f1..23ab505d 100644 --- a/packages/discord-types/src/index.d.ts +++ b/packages/discord-types/src/index.d.ts @@ -1,5 +1,4 @@ export * from "./common"; -export * from "./classes"; export * from "./components"; export * from "./flux"; export * from "./fluxEvents"; diff --git a/src/api/ChatButtons.tsx b/src/api/ChatButtons.tsx index c2a1a198..ebb5eb5e 100644 --- a/src/api/ChatButtons.tsx +++ b/src/api/ChatButtons.tsx @@ -11,15 +11,15 @@ import { Logger } from "@utils/Logger"; import { classes } from "@utils/misc"; import { IconComponent } from "@utils/types"; import { Channel } from "@vencord/discord-types"; -import { waitFor } from "@webpack"; -import { ButtonWrapperClasses, Clickable, Menu, Tooltip } from "@webpack/common"; +import { findCssClassesLazy } from "@webpack"; +import { Clickable, Menu, Tooltip } from "@webpack/common"; import { HTMLProps, JSX, MouseEventHandler, ReactNode } from "react"; import { addContextMenuPatch, findGroupChildrenByChildId } from "./ContextMenu"; import { useSettings } from "./Settings"; -let ChannelTextAreaClasses: Record<"button" | "buttonContainer", string>; -waitFor(["buttonContainer", "channelTextArea"], m => ChannelTextAreaClasses = m); +const ButtonWrapperClasses = findCssClassesLazy("button", "buttonWrapper", "notificationDot"); +const ChannelTextAreaClasses = findCssClassesLazy("buttonContainer", "channelTextArea", "button"); export interface ChatBarProps { channel: Channel; @@ -113,11 +113,9 @@ function VencordChatBarButtons(props: ChatBarProps) { } export function _injectButtons(buttons: ReactNode[], props: ChatBarProps) { - if (props.disabled) return; + if (props.disabled || buttons.length === 0) return; buttons.unshift(); - - return buttons; } /** @@ -145,13 +143,13 @@ export const ChatBarButton = ErrorBoundary.wrap((props: ChatBarButtonProps) => { aria-label={props.tooltip} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} - className={classes(ButtonWrapperClasses?.button, ChannelTextAreaClasses?.button)} + className={classes(ButtonWrapperClasses.button, ChannelTextAreaClasses?.button)} onClick={props.onClick} onContextMenu={props.onContextMenu} onAuxClick={props.onAuxClick} {...props.buttonProps} > -
+
{props.children}
diff --git a/src/components/CodeBlock.tsx b/src/components/CodeBlock.tsx index 29b76265..e85e7ed7 100644 --- a/src/components/CodeBlock.tsx +++ b/src/components/CodeBlock.tsx @@ -4,10 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { Parser } from "@webpack/common"; -const CodeContainerClasses = findByPropsLazy("markup", "codeContainer"); +const CodeContainerClasses = findCssClassesLazy("markup", "codeContainer"); /** * Renders code in a Discord codeblock diff --git a/src/plugins/_api/chatButtons.ts b/src/plugins/_api/chatButtons.ts index 5a5969cc..432c66bf 100644 --- a/src/plugins/_api/chatButtons.ts +++ b/src/plugins/_api/chatButtons.ts @@ -16,8 +16,8 @@ export default definePlugin({ { find: '"sticker")', replacement: { - match: /(?<=className:.{0,20}\.buttons.{0,50}children:)(\i)/, - replace: "Vencord.Api.ChatButtons._injectButtons($1,arguments[0])" + match: /let (\i)=\(0,\i\.chain\).{0,150}?;(?=return 0===\1\.length)/, + replace: "$&Vencord.Api.ChatButtons._injectButtons($1,arguments[0]);" } } ] diff --git a/src/plugins/_api/commands.ts b/src/plugins/_api/commands.ts index 3a761936..cca1a686 100644 --- a/src/plugins/_api/commands.ts +++ b/src/plugins/_api/commands.ts @@ -50,10 +50,10 @@ export default definePlugin({ }, // Show plugin name instead of "Built-In" { - find: ".source,children", + find: "#{intl::COMMANDS_OPTIONAL_COUNT}", replacement: { // ...children: p?.name - match: /(?<=:(.{1,3})\.displayDescription\}.{0,200}\.source,children:)[^}]+/, + match: /(?<=:(\i)\.displayDescription\}.{0,200}children:).{0,50}\.name(?=\}\))/, replace: "$1.plugin||($&)" } } diff --git a/src/plugins/_api/dynamicImageModalApi.ts b/src/plugins/_api/dynamicImageModalApi.ts index 114b4836..775cdf03 100644 --- a/src/plugins/_api/dynamicImageModalApi.ts +++ b/src/plugins/_api/dynamicImageModalApi.ts @@ -14,7 +14,7 @@ export default definePlugin({ description: "Allows you to omit either width or height when opening an image modal", patches: [ { - find: ".dimensionlessImage,", + find: ".renderLinkComponent)?", replacement: { // widthAndHeightPassed = w != null && w !== 0 && h == null || h === 0 match: /(?<=\i=)(null!=\i&&0!==\i)&&(null!=\i&&0!==\i)/, diff --git a/src/plugins/_api/memberListDecorators/index.tsx b/src/plugins/_api/memberListDecorators/index.tsx index 90f09d8f..ab0ba590 100644 --- a/src/plugins/_api/memberListDecorators/index.tsx +++ b/src/plugins/_api/memberListDecorators/index.tsx @@ -30,7 +30,7 @@ export default definePlugin({ patches: [ { - find: ".lostPermission)", + find: "#{intl::GUILD_OWNER}),children:", replacement: [ { match: /children:\[(?=.{0,300},lostPermissionTooltipText:)/, diff --git a/src/plugins/_api/messageAccessories.ts b/src/plugins/_api/messageAccessories.ts index 0ba2a031..f0bf4589 100644 --- a/src/plugins/_api/messageAccessories.ts +++ b/src/plugins/_api/messageAccessories.ts @@ -27,8 +27,8 @@ export default definePlugin({ { find: "#{intl::REMOVE_ATTACHMENT_BODY}", replacement: { - match: /(?<=.container\)?,children:)(\[.+?\])/, - replace: "Vencord.Api.MessageAccessories._modifyAccessories($1,this.props)", + match: /children:(\[[^\]]{0,100}?this.renderSuppressConfirmModal[^\]]{0,100}?\])/, + replace: "children:Vencord.Api.MessageAccessories._modifyAccessories($1,this.props)", }, }, ], diff --git a/src/plugins/_api/notices.ts b/src/plugins/_api/notices.ts index 43ef2acc..89aa1a46 100644 --- a/src/plugins/_api/notices.ts +++ b/src/plugins/_api/notices.ts @@ -32,13 +32,6 @@ export default definePlugin({ match: /(?<=!1;)\i=null;(?=.{0,80}getPremiumSubscription\(\))/g, replace: "if(Vencord.Api.Notices.currentNotice)return false;$&" }, - - // FIXME(Bundler minifier change related): Remove the non used compability once enough time has passed - { - match: /(?<=,NOTICE_DISMISS:function\(\i\){)return null!=(\i)/, - replace: (m, notice) => `if(${notice}?.id=="VencordNotice")return(${notice}=null,Vencord.Api.Notices.nextNotice(),true);${m}`, - noWarn: true, - }, { match: /(?<=function (\i)\(\i\){)return null!=(\i)(?=.+?NOTICE_DISMISS:\1)/, replace: (m, _, notice) => `if(${notice}?.id=="VencordNotice")return(${notice}=null,Vencord.Api.Notices.nextNotice(),true);${m}` diff --git a/src/plugins/_api/serverList.ts b/src/plugins/_api/serverList.ts index 89c40796..edbaea69 100644 --- a/src/plugins/_api/serverList.ts +++ b/src/plugins/_api/serverList.ts @@ -27,7 +27,7 @@ export default definePlugin({ { find: "#{intl::DISCODO_DISABLED}", replacement: { - match: /(?<=#{intl::DISCODO_DISABLED}.+?return)(\(.{0,75}?tutorialContainer.+?}\))(?=}function)/, + match: /(?<=#{intl::DISCODO_DISABLED}.+?return)(\(.{0,150}?tutorialId:"friends-list".+?}\))(?=}function)/, replace: "[$1].concat(Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.Above))" } }, diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 052a38ff..d9bcf95f 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -102,17 +102,17 @@ export default definePlugin({ patches: [ { - find: ".versionHash", + find: "#{intl::COPY_VERSION}", replacement: [ { - match: /\.compactInfo.+?(?=null!=(\i)&&(.{0,20}\i\.Text.{0,200}?,children:).{0,15}?("span"),({className:\i\.versionHash,children:\["Build Override: ",\1\.id\]\})\)\}\))/, + match: /"text-xxs\/normal".{0,300}?(?=null!=(\i)&&(.{0,20}\i\.Text.{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: /\.info.+?\[\(0,\i\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, + match: /"text-xs\/normal".{0,300}?\[\(0,\i\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}className:\i.\i,.+?\})\)," "/, replace: (m, component, props) => { props = props.replace(/children:\[.+\]/, ""); return `${m},$self.makeInfoElements(${component},${props})`; @@ -141,8 +141,8 @@ export default definePlugin({ find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}", replacement: { // Skip the check Discord performs to make sure the section being selected in the user settings context menu is valid - match: /(?<=function\((\i),(\i),\i\)\{)(?=let \i=Object.values\(\i\.\i\).+?(\(0,\i\.openUserSettings\))\()/, - replace: (_, settingsPanel, section, openUserSettings) => `${openUserSettings}(${settingsPanel},{section:${section}});return;` + match: /null!=\(\i=Object.values\(\i\.\i\).{0,50}?&&(?=\(0,\i\.openUserSettings\)\(\i,\{section:\i)/, + replace: "" } }, { diff --git a/src/plugins/alwaysAnimate/index.ts b/src/plugins/alwaysAnimate/index.ts index 1635781c..8a057c98 100644 --- a/src/plugins/alwaysAnimate/index.ts +++ b/src/plugins/alwaysAnimate/index.ts @@ -49,9 +49,9 @@ export default definePlugin({ }, { // Guild Banner - find: ".animatedBannerHoverLayer,onMouseEnter:", + find: "#{intl::DISCOVERABLE_GUILD_HEADER_PUBLIC_INFO}", replacement: { - match: /(\.headerContent.+?guildBanner:\i,animate:)\i/, + match: /(guildBanner:\i,animate:)\i(?=}\):null)/, replace: "$1!0" } }, diff --git a/src/plugins/anonymiseFileNames/index.tsx b/src/plugins/anonymiseFileNames/index.tsx index 62cd7796..985fc4a8 100644 --- a/src/plugins/anonymiseFileNames/index.tsx +++ b/src/plugins/anonymiseFileNames/index.tsx @@ -24,7 +24,7 @@ import { CloudUpload } from "@vencord/discord-types"; import { findByCodeLazy } from "@webpack"; import { useState } from "@webpack/common"; -const ActionBarIcon = findByCodeLazy(".actionBarIcon)"); +const ActionBarIcon = findByCodeLazy("Children.map", "isValidElement", "dangerous:"); const enum Methods { Random, diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 5a1754d3..cee1a6d0 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -178,7 +178,7 @@ export default definePlugin({ }, // If we are rendering the Better Folders sidebar, we filter out everything but the Guild List from the Sidebar children { - match: /unreadMentionsFixedFooter\].+?\}\)\]/, + match: /reverse:!0,.{0,150}?barClassName:.+?\}\)\]/, replace: "$&.filter($self.makeGuildsBarSidebarFilter(!!arguments[0]?.isBetterFolders))" } ] @@ -212,7 +212,7 @@ export default definePlugin({ // If we are rendering the normal GuildsBar sidebar, we make Discord think the folder is always collapsed to show better icons (the mini guild icons) and avoid transitions { predicate: () => settings.store.keepIcons, - match: /(?<=let{folderNode:\i,setNodeRef:\i,.+?expanded:(\i),.+?;)(?=let)/, + match: /(?<=let ?(?:\i,)*?{folderNode:\i,setNodeRef:\i,.+?expanded:(\i),.+?;)(?=let)/, replace: (_, isExpanded) => `${isExpanded}=!!arguments[0]?.isBetterFolders&&${isExpanded};` }, // Disable expanding and collapsing folders transition in the normal GuildsBar sidebar @@ -224,20 +224,20 @@ export default definePlugin({ // If we are rendering the normal GuildsBar sidebar, we avoid rendering guilds from folders that are expanded { predicate: () => !settings.store.keepIcons, - match: /folderGroupBackground.+?,(?=\i\(\(\i,\i,\i\)=>{let{key:.{0,70}"ul")(?<=selected:\i,expanded:(\i),.+?)/, + match: /"--custom-folder-color".+?(?=\i\(\(\i,\i,\i\)=>{let{key:.{0,70}"ul")(?<=selected:\i,expanded:(\i),.+?)/, replace: (m, isExpanded) => `${m}$self.shouldRenderContents(arguments[0],${isExpanded})?null:` }, // Decide if we should render the expanded folder background if we are rendering the Better Folders sidebar { predicate: () => settings.store.showFolderIcon !== FolderIconDisplay.Always, - match: /\.isExpanded\].{0,110}children:\[/, + match: /"--custom-folder-color".{0,110}?children:\[/, replace: "$&$self.shouldShowFolderIconAndBackground(!!arguments[0]?.isBetterFolders,arguments[0]?.betterFoldersExpandedIds)&&" }, // Decide if we should render the expanded folder icon if we are rendering the Better Folders sidebar { predicate: () => settings.store.showFolderIcon !== FolderIconDisplay.Always, - match: /(?<=\.folderGroupBackground.*?}\),)(?=\i,)/, - replace: "!$self.shouldShowFolderIconAndBackground(!!arguments[0]?.isBetterFolders,arguments[0]?.betterFoldersExpandedIds)?null:" + match: /"--custom-folder-color".+?className:\i\.\i}\),(?=\i,)/, + replace: "$&!$self.shouldShowFolderIconAndBackground(!!arguments[0]?.isBetterFolders,arguments[0]?.betterFoldersExpandedIds)?null:" } ] }, @@ -252,12 +252,12 @@ export default definePlugin({ // One is for visual refresh, one is not, // and each has a bunch of conditions &&ed in front of it. // Add the betterFolders sidebar to both, keeping the conditions Discord uses. - match: /(?<=[[,])((?:!?\i&&)+)\(.{0,50}({className:\i\.guilds,themeOverride:\i})\)/g, + match: /(?<=[[,])((?:!?\i&&)+)\(.{0,50}({className:\i\.\i,themeOverride:\i})\)/g, replace: (m, conditions, props) => `${m},${conditions}$self.FolderSideBar(${props})` }, { // Add grid styles to fix aligment with other visual refresh elements - match: /(?<=className:)\i\.base(?=,)/, + match: /(?<=className:)\i\.\i(?=,"data-fullscreen")/, replace: `"${GRID_STYLE_NAME} "+$&` } ] diff --git a/src/plugins/betterRoleDot/index.ts b/src/plugins/betterRoleDot/index.ts index 9928a2a4..d2c8d3f3 100644 --- a/src/plugins/betterRoleDot/index.ts +++ b/src/plugins/betterRoleDot/index.ts @@ -29,7 +29,8 @@ export default definePlugin({ patches: [ { - find: ".dotBorderBase", + // Class used in this module is dotBorderBase + find: "M0 4C0 1.79086 1.79086 0 4 0H16C18.2091 0 20 1.79086 20 4V16C20 18.2091 18.2091 20 16 20H4C1.79086 20 0 18.2091 0 16V4Z", replacement: { match: /,viewBox:"0 0 20 20"/, replace: "$&,onClick:()=>$self.copyToClipBoard(arguments[0].color),style:{cursor:'pointer'}", diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index 052b5867..78aea613 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -23,7 +23,7 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; +import { findByPropsLazy, findComponentByCodeLazy, findCssClassesLazy, findStoreLazy } from "@webpack"; import { Constants, React, RestAPI, Tooltip } from "@webpack/common"; import { RenameButton } from "./components/RenameButton"; @@ -33,8 +33,8 @@ import { fetchNamesFromDataStore, getDefaultName, GetOsColor, GetPlatformIcon, s const AuthSessionsStore = findStoreLazy("AuthSessionsStore"); const UserSettingsModal = findByPropsLazy("saveAccountChanges", "open"); -const TimestampClasses = findByPropsLazy("timestamp", "blockquoteContainer"); -const SessionIconClasses = findByPropsLazy("sessionIcon"); +const TimestampClasses = findCssClassesLazy("timestamp", "blockquoteContainer"); +const SessionIconClasses = findCssClassesLazy("sessionIcon"); const BlobMask = findComponentByCodeLazy("!1,lowerBadgeSize:"); @@ -66,17 +66,17 @@ export default definePlugin({ replacement: [ // Replace children with a single label with state { - match: /({variant:"eyebrow",className:\i\.sessionInfoRow,children:).{70,110}{children:"\\xb7"}\),\(0,\i\.\i\)\("span",{children:\i\[\d+\]}\)\]}\)\]/, + match: /({variant:"eyebrow",className:\i\.\i,children:).{70,110}{children:"\\xb7"}\),\(0,\i\.\i\)\("span",{children:\i\[\d+\]}\)\]}\)\]/, replace: "$1$self.renderName(arguments[0])" }, { - match: /({variant:"text-sm\/medium",className:\i\.sessionInfoRow,children:.{70,110}{children:"\\xb7"}\),\(0,\i\.\i\)\("span",{children:)(\i\[\d+\])}/, - replace: "$1$self.renderTimestamp({ ...arguments[0], timeLabel: $2 })}" + match: /({variant:"text-sm\/medium",className:\i\.\i,children:.{70,110}{children:"\\xb7"}\),\(0,\i\.\i\)\("span",{children:)(\i\[\d+\])}/, + replace: "$1$self.renderTimestamp({...arguments[0],timeLabel:$2})}" }, // Replace the icon { - match: /\.legacySession\),children:\[(?<=,icon:(\i)\}.+?)/, - replace: "$& $self.renderIcon({ ...arguments[0], DeviceIcon: $1 }), false &&" + match: /children:\[(?=.{0,125}?width:"32")(?<=,icon:(\i)\}.+?)/, + replace: "children:[$self.renderIcon({...arguments[0],DeviceIcon:$1}),false&&" } ] } diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index c3432ab8..2236d2fd 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -5,12 +5,13 @@ */ import { definePluginSettings } from "@api/Settings"; -import { classNameFactory, disableStyle, enableStyle } from "@api/Styles"; +import { disableStyle, enableStyle } from "@api/Styles"; import { buildPluginMenuEntries, buildThemeMenuEntries } from "@plugins/vencordToolbox/menu"; import { Devs } from "@utils/constants"; +import { classNameFactory } from "@utils/css"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { waitFor } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { ComponentDispatch, FocusLock, Menu, useEffect, useRef } from "@webpack/common"; import type { HTMLAttributes, ReactElement } from "react"; @@ -19,8 +20,7 @@ import fullHeightStyle from "./fullHeightContext.css?managed"; type SettingsEntry = { section: string, label: string; }; const cl = classNameFactory(""); -let Classes: Record; -waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => Classes = m); +const Classes = findCssClassesLazy("animating", "baseLayer", "bg", "layer", "layers"); const settings = definePluginSettings({ disableFade: { @@ -139,8 +139,8 @@ export default definePlugin({ find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}", replacement: [ { - match: /=\[\];if\((\i)(?=\.forEach.{0,100}"logout"!==\i.{0,30}(\i)\.get\(\i\))/, - replace: "=$self.wrapMap([]);if($self.transformSettingsEntries($1,$2)", + match: /=\[\];(\i)(?=\.forEach.{0,100}"logout"!==\i.{0,30}(\i)\.get\(\i\))/, + replace: "=$self.wrapMap([]);$self.transformSettingsEntries($1,$2)", predicate: () => settings.store.organizeMenu }, { @@ -160,7 +160,7 @@ export default definePlugin({ // Thus, we sanity check webpack modules Layer(props: LayerProps) { try { - [FocusLock.$$vencordGetWrappedComponent(), ComponentDispatch, Classes].forEach(e => e.test); + [FocusLock.$$vencordGetWrappedComponent(), ComponentDispatch, Classes.layer].forEach(e => e.test); } catch { new Logger("BetterSettings").error("Failed to find some components"); return props.children; diff --git a/src/plugins/blurNsfw/index.ts b/src/plugins/blurNsfw/index.ts index 958bac57..358c986b 100644 --- a/src/plugins/blurNsfw/index.ts +++ b/src/plugins/blurNsfw/index.ts @@ -46,10 +46,12 @@ export default definePlugin({ patches: [ { find: "}renderEmbeds(", - replacement: [{ - match: /\.container/, - replace: "$&+(this.props.channel.nsfw? ' vc-nsfw-img': '')" - }] + replacement: [ + { + match: /(\.renderReactions\(\i\).+?className:)/, + replace: '$&(this.props?.channel?.nsfw?"vc-nsfw-img ":"")+' + } + ] } ], diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index 188ebe61..c163dd64 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -56,14 +56,14 @@ const define: typeof Object.defineProperty = }; function makeShortcuts() { - function newFindWrapper(filterFactory: (...props: any[]) => Webpack.FilterFn) { + function newFindWrapper(filterFactory: (...props: any[]) => Webpack.FilterFn, topLevelOnly = false) { const cache = new Map(); return function (...filterProps: unknown[]) { const cacheKey = String(filterProps); if (cache.has(cacheKey)) return cache.get(cacheKey); - const matches = findAll(filterFactory(...filterProps)); + const matches = findAll(filterFactory(...filterProps), { topLevelOnly }); const result = (() => { switch (matches.length) { @@ -118,6 +118,7 @@ function makeShortcuts() { findByProps, findAllByProps: (...props: string[]) => findAll(filters.byProps(...props)), findByCode: newFindWrapper(filters.byCode), + findCssClasses: newFindWrapper(filters.byClassNames, true), findAllByCode: (code: string) => findAll(filters.byCode(code)), findComponentByCode: newFindWrapper(filters.componentByCode), findAllComponentsByCode: (...code: string[]) => findAll(filters.componentByCode(...code)), diff --git a/src/plugins/copyFileContents/index.tsx b/src/plugins/copyFileContents/index.tsx index 5bb79515..673a204d 100644 --- a/src/plugins/copyFileContents/index.tsx +++ b/src/plugins/copyFileContents/index.tsx @@ -27,7 +27,7 @@ export default definePlugin({ { find: "#{intl::PREVIEW_BYTES_LEFT}", replacement: { - match: /\.footerGap.+?url:\i,fileName:\i,fileSize:\i}\),(?<=fileContents:(\i),bytesLeft:(\i).+?)/g, + match: /url:\i,fileName:\i,fileSize:\i}\),(?=.{0,25}setLanguage:)(?<=fileContents:(\i),bytesLeft:(\i).+?)/g, replace: "$&$self.addCopyButton({fileContents:$1,bytesLeft:$2})," } } diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx index 18e4bec1..8e3328e8 100644 --- a/src/plugins/customRPC/index.tsx +++ b/src/plugins/customRPC/index.tsx @@ -36,7 +36,7 @@ import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, React, UserStore import { RPCSettings } from "./RpcSettings"; const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color"); -const ActivityView = findComponentByCodeLazy(".party?(0", ".card"); +const ActivityView = findComponentByCodeLazy(".party?(0", "USER_PROFILE_ACTIVITY"); const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!; diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx index 319bc14f..33acebf8 100644 --- a/src/plugins/decor/index.tsx +++ b/src/plugins/decor/index.tsx @@ -47,14 +47,14 @@ export default definePlugin({ }, // Decoration modal module { - find: ".decorationGridItem,", + find: "80,onlyAnimateOnHoverOrFocus:!", replacement: [ { - match: /(?<==)\i=>{var{children.{20,200}decorationGridItem/, + match: /(?<==)\i=>{let{children.{20,200}isSelected:\i=!1\}=\i/, replace: "$self.DecorationGridItem=$&", }, { - match: /(?<==)\i=>{var{user:\i,avatarDecoration/, + match: /(?<==)\i=>{let{user:\i,avatarDecoration/, replace: "$self.DecorationGridDecoration=$&", }, // Remove NEW label from decor avatar decorations @@ -98,7 +98,7 @@ export default definePlugin({ }, ...[ '"Message Username"', // Messages - ".nameplatePreview,{", // Nameplate preview + "#{intl::COLLECTIBLES_NAMEPLATE_PREVIEW_A11Y}", // Nameplate preview "#{intl::ayozFl::raw}", // Avatar preview ].map(find => ({ find, diff --git a/src/plugins/decor/ui/components/DecorSection.tsx b/src/plugins/decor/ui/components/DecorSection.tsx index 3209b435..e25c816c 100644 --- a/src/plugins/decor/ui/components/DecorSection.tsx +++ b/src/plugins/decor/ui/components/DecorSection.tsx @@ -13,7 +13,7 @@ import { openChangeDecorationModal } from "@plugins/decor/ui/modals/ChangeDecora import { findComponentByCodeLazy } from "@webpack"; import { useEffect } from "@webpack/common"; -const CustomizationSection = findComponentByCodeLazy(".customizationSectionBackground"); +const CustomizationSection = findComponentByCodeLazy(".DESCRIPTION", "hasBackground:"); export interface DecorSectionProps { hideTitle?: boolean; diff --git a/src/plugins/decor/ui/components/SectionedGridList.tsx b/src/plugins/decor/ui/components/SectionedGridList.tsx index 4352fadd..0e848e99 100644 --- a/src/plugins/decor/ui/components/SectionedGridList.tsx +++ b/src/plugins/decor/ui/components/SectionedGridList.tsx @@ -6,13 +6,13 @@ import { cl } from "@plugins/decor/ui"; import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { React } from "@webpack/common"; import { JSX } from "react"; import Grid, { GridProps } from "./Grid"; -const ScrollerClasses = findByPropsLazy("managedReactiveScroller"); +const ScrollerClasses = findCssClassesLazy("managedReactiveScroller", "thin"); type Section = SectionT & { items: Array; diff --git a/src/plugins/decor/ui/index.ts b/src/plugins/decor/ui/index.ts index 44e58ecc..a10824c5 100644 --- a/src/plugins/decor/ui/index.ts +++ b/src/plugins/decor/ui/index.ts @@ -5,10 +5,10 @@ */ import { classNameFactory } from "@utils/css"; -import { extractAndLoadChunksLazy, findByPropsLazy } from "@webpack"; +import { extractAndLoadChunksLazy, findCssClassesLazy } from "@webpack"; export const cl = classNameFactory("vc-decor-"); -export const DecorationModalStyles = findByPropsLazy("modalPreview", "modalCloseButton", "spinner", "modal"); +export const DecorationModalClasses = findCssClassesLazy("modalPreview", "modalCloseButton", "spinner", "modal"); export const requireAvatarDecorationModal = extractAndLoadChunksLazy(["initialSelectedDecoration:", /initialSelectedDecoration:\i,.{0,300}\i\.e\(/]); -export const requireCreateStickerModal = extractAndLoadChunksLazy(["stickerInspected]:"]); +export const requireCreateStickerModal = extractAndLoadChunksLazy([".CREATE_STICKER_MODAL,", "isDisplayingIndividualStickers"]); diff --git a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx index f784849e..7c595abc 100644 --- a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx @@ -13,7 +13,7 @@ import { useAuthorizationStore } from "@plugins/decor/lib/stores/AuthorizationSt import { useCurrentUserDecorationsStore } from "@plugins/decor/lib/stores/CurrentUserDecorationsStore"; import { decorationToAvatarDecoration } from "@plugins/decor/lib/utils/decoration"; import { settings } from "@plugins/decor/settings"; -import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "@plugins/decor/ui"; +import { cl, DecorationModalClasses, requireAvatarDecorationModal } from "@plugins/decor/ui"; import { AvatarDecorationModalPreview } from "@plugins/decor/ui/components"; import DecorationGridCreate from "@plugins/decor/ui/components/DecorationGridCreate"; import DecorationGridNone from "@plugins/decor/ui/components/DecorationGridNone"; @@ -139,7 +139,7 @@ function ChangeDecorationModal(props: ModalProps) { return = 49 /* 1*/ && src.charCodeAt(0) <= 57 /* 9*/) { + src = "0,function" + src.substring(src.indexOf("(")); } let i = 0; @@ -203,6 +204,9 @@ function initWs(isManual = false) { case "": results = findAll(parsedArgs[0]); break; + case "CssClasses": + results = findAll(filters.byClassNames(...parsedArgs), { topLevelOnly: true }); + break; case "ByProps": results = findAll(filters.byProps(...parsedArgs)); break; diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index e01e34b8..cb456fc7 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -106,7 +106,7 @@ export default definePlugin({ }, // Enable experiment embed on sent experiment links { - find: ".experimentOverride,children:", + find: '"Clear Treatment "', replacement: [ { match: /\i\.isStaff\(\)/, diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index c117d512..4a943e11 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -183,11 +183,11 @@ export default definePlugin({ makeBypassPatches(), // Patch the emoji picker in voice calls to not be bypassed by fake nitro { - find: "emojiItemDisabled]", + find: '.getByName("fork_and_knife")', predicate: () => settings.store.enableEmojiBypass, replacement: { - match: /CHAT/, - replace: "STATUS" + match: ".CHAT", + replace: ".STATUS" } }, { diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index 19d9b164..6197d0c3 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -10,14 +10,14 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; import definePlugin from "@utils/types"; -import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy, findCssClassesLazy } from "@webpack"; import { RelationshipStore, Text } from "@webpack/common"; -const containerWrapper = findByPropsLazy("memberSinceWrapper"); -const container = findByPropsLazy("memberSince"); +const WrapperClasses = findCssClassesLazy("memberSinceWrapper"); +const ContainerClasses = findCssClassesLazy("memberSince"); const getCreatedAtDate = findByCodeLazy('month:"short",day:"numeric"'); const locale = findByPropsLazy("getLocale"); -const Section = findComponentByCodeLazy("headingVariant:", ".section", ".header"); +const Section = findComponentByCodeLazy("headingVariant:", '"section"', "headingIcon:"); export default definePlugin({ name: "FriendsSince", @@ -34,7 +34,7 @@ export default definePlugin({ }, // User Profile Modal { - find: ".connections,userId:", + find: ",applicationRoleConnection:", replacement: { match: /#{intl::USER_PROFILE_MEMBER_SINCE}\),.{0,100}userId:(\i\.id),.{0,100}}\)}\),/, replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:false})," @@ -77,8 +77,8 @@ export default definePlugin({ headingColor="text-default" className="vc-friendsSince-profile-section" > -
-
+
+
{!!getCurrentChannel()?.guild_id && ( {" "}({getIntlMessage("MESSAGE_EDITED")}) + {" "}({getIntlMessage("MESSAGE_EDITED")})
))} @@ -445,11 +445,11 @@ export default definePlugin({ { // Attachment renderer - find: ".removeMosaicItemHoverButton", + find: "#{intl::REMOVE_ATTACHMENT_TOOLTIP_TEXT}", replacement: [ { - match: /\[\i\.obscured\]:.+?,(?<=item:(\i).+?)/, - replace: '$&"messagelogger-deleted-attachment":$1.originalItem?.deleted,' + match: /\.SPOILER,(?=\[\i\.\i\]:)/, + replace: '$&"messagelogger-deleted-attachment":arguments[0]?.item?.originalItem?.deleted,' } ] }, @@ -471,7 +471,7 @@ export default definePlugin({ find: ".SEND_FAILED,", replacement: { // Render editHistory behind the message content - match: /\.isFailed]:.+?children:\[/, + match: /\]:\i.isUnsupported.{0,20}?,children:\[/, replace: "$&arguments[0]?.message?.editHistory?.length>0&&$self.renderEdits(arguments[0])," } }, @@ -480,8 +480,8 @@ export default definePlugin({ find: "#{intl::MESSAGE_EDITED}", replacement: { // Make edit marker clickable - match: /"span",\{(?=className:\i\.edited,)/, - replace: "$self.EditMarker,{message:arguments[0].message," + match: /(isInline:!1,children:.{0,50}?)"span",\{(?=className:)/, + replace: "$1$self.EditMarker,{message:arguments[0].message," } }, diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index 6909fbd2..63746e06 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -18,22 +18,24 @@ import "./style.css"; +import { BaseText } from "@components/BaseText"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { isNonNullish } from "@utils/guards"; import { Logger } from "@utils/Logger"; import definePlugin from "@utils/types"; import { Channel, User } from "@vencord/discord-types"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByPropsLazy, findComponentByCodeLazy, findCssClassesLazy } from "@webpack"; import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, Text, useMemo, UserStore } from "@webpack/common"; import { JSX } from "react"; const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel"); const UserUtils = findByPropsLazy("getGlobalName"); -const ProfileListClasses = findByPropsLazy("emptyIconFriends", "emptyIconGuilds"); -const MutualsListClasses = findByPropsLazy("row", "icon", "name", "nick"); -const ExpandableList = findComponentByCodeLazy('"PRESS_SECTION"', ".header"); +const ProfileListClasses = findCssClassesLazy("empty", "textContainer", "connectionIcon"); +const TabBarClasses = findCssClassesLazy("tabPanelScroller", "tabBarPanel"); +const MutualsListClasses = findCssClassesLazy("row", "icon", "name", "details"); +const ExpandableList = findComponentByCodeLazy('action:"PRESS_SECTION"', "section"); function getGroupDMName(channel: Channel) { return channel.name || @@ -102,7 +104,7 @@ export default definePlugin({ // Discord adds spacing between each item which pushes our tab off screen. // set the gap to zero to ensure ours stays on screen { - match: /className:\i\.tabBar/, + match: /className:\i\.\i(?=,type:"top")/, replace: '$& + " vc-mutual-gdms-modal-tab-bar"' } ] @@ -116,7 +118,7 @@ export default definePlugin({ replace: "$&$self.pushSection($1,arguments[0].user);" }, { - match: /\.tabBarPanel,.*?children:(?=.+?section:(\i))/, + match: /children:(?=.{0,100}?component:.+?section:(\i))/, replace: "$&$1==='MUTUAL_GDMS'?$self.renderMutualGDMs(arguments[0]):" }, // Make the gap between each item smaller so our tab can fit. @@ -134,7 +136,7 @@ export default definePlugin({ replace: "$&||$self.getMutualGroupDms(arguments[0].user.id).length>0" }, { - match: /\.openUserProfileModal.+?\)}\)}\)(?<=,(\i)&&(\i)&&(\(0,\i\.jsxs?\)\(\i\.\i,{className:(\i)\.divider}\)).+?)/, + match: /\.openUserProfileModal.+?\)}\)}\)(?<=,(\i)&&(\i)&&(\(0,\i\.jsxs?\)\(\i\.\i,{className:(\i)\.\i}\)).{0,50}?"MUTUAL_FRIENDS".+?)/, replace: (m, hasMutualGuilds, hasMutualFriends, Divider, classes) => "" + `${m},$self.renderDMPageList({user:arguments[0].user,hasDivider:${hasMutualGuilds}||${hasMutualFriends},Divider:${Divider},listStyle:${classes}.list})` } @@ -172,7 +174,7 @@ export default definePlugin({ return ( @@ -180,8 +182,9 @@ export default definePlugin({ ? entries : (
-
-
No group dms in common
+
+ You don't have any group chats in common +
) } diff --git a/src/plugins/permissionsViewer/components/UserPermissions.tsx b/src/plugins/permissionsViewer/components/UserPermissions.tsx index 7e0572e5..3b0c1f30 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -22,7 +22,7 @@ import { cl, getGuildPermissionSpecMap, getSortedRolesForMember, sortUserRoles } import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import type { Guild, GuildMember } from "@vencord/discord-types"; -import { filters, findBulk, proxyLazyWebpack } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common"; import { PermissionsSortOrder, settings } from ".."; @@ -37,14 +37,8 @@ interface UserPermission { type UserPermissions = Array; -const { RoleClasses, RoleBorderClasses } = proxyLazyWebpack(() => { - const [RoleClasses, RoleBorderClasses] = findBulk( - filters.byProps("role", "roleCircle", "roleName"), - filters.byProps("roleCircle", "dot", "dotBorderColor") - ) as Record[]; - - return { RoleClasses, RoleBorderClasses }; -}); +const RoleClasses = findCssClassesLazy("role", "roleName", "roleRemoveButton", "roleNameOverflow", "root"); +const RoleBorderClasses = findCssClassesLazy("roleCircle", "dot", "dotBorderColor"); interface FakeRoleProps extends React.HTMLAttributes { text: string; @@ -56,7 +50,7 @@ function FakeRole({ text, color, ...props }: FakeRoleProps) {
diff --git a/src/plugins/permissionsViewer/index.tsx b/src/plugins/permissionsViewer/index.tsx index bcf9e55b..37e68a5f 100644 --- a/src/plugins/permissionsViewer/index.tsx +++ b/src/plugins/permissionsViewer/index.tsx @@ -27,15 +27,14 @@ import { Devs } from "@utils/constants"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; import type { Guild } from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { Button, ChannelStore, Dialog, GuildMemberStore, GuildRoleStore, GuildStore, match, Menu, PermissionsBits, Popout, useRef, UserStore } from "@webpack/common"; import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions"; import UserPermissions from "./components/UserPermissions"; import { getSortedRolesForMember, sortPermissionOverwrites } from "./utils"; -const PopoutClasses = findByPropsLazy("container", "scroller", "list"); -const RoleButtonClasses = findByPropsLazy("button", "icon"); +const PopoutClasses = findCssClassesLazy("container", "scroller", "list"); export const enum PermissionsSortOrder { HighestRole, diff --git a/src/plugins/pictureInPicture/index.tsx b/src/plugins/pictureInPicture/index.tsx index 1d75319a..ff8c00eb 100644 --- a/src/plugins/pictureInPicture/index.tsx +++ b/src/plugins/pictureInPicture/index.tsx @@ -28,9 +28,9 @@ export default definePlugin({ settings, patches: [ { - find: ".removeMosaicItemHoverButton),", + find: '["VIDEO","CLIP","AUDIO"]', replacement: { - match: /(\.nonMediaMosaicItem\]:.{0,40}children:)(\i.slice\(\i\))(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/, + match: /(\[\i>0&&\i\.length>0.{0,150}?children:)(\i.slice\(\i\))(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/, replace: (_, rest, origChildren, showDownload, isVisualMediaType) => `${rest}[${showDownload}&&${isVisualMediaType}&&$self.PictureInPictureButton(),...${origChildren}]` } } diff --git a/src/plugins/pinDms/index.tsx b/src/plugins/pinDms/index.tsx index 53524257..4dfa4dfa 100644 --- a/src/plugins/pinDms/index.tsx +++ b/src/plugins/pinDms/index.tsx @@ -12,7 +12,7 @@ import { Devs } from "@utils/constants"; import { classes } from "@utils/misc"; import definePlugin, { OptionType, StartAt } from "@utils/types"; import { Channel } from "@vencord/discord-types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findCssClassesLazy, findStoreLazy } from "@webpack"; import { Clickable, ContextMenuApi, FluxDispatcher, Menu, React } from "@webpack/common"; import { contextMenus } from "./components/contextMenu"; @@ -26,7 +26,7 @@ interface ChannelComponentProps { selected: boolean; } -const headerClasses = findByPropsLazy("privateChannelsHeaderContainer"); +const headerClasses = findCssClassesLazy("privateChannelsHeaderContainer", "headerText"); export const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { getPrivateChannelIds: () => string[]; }; @@ -72,7 +72,7 @@ export default definePlugin({ patches: [ { - find: ".privateChannelsHeaderContainer,", + find: '"private-channels-".concat(', replacement: [ { // Filter out pinned channels from the private channel list @@ -95,8 +95,8 @@ export default definePlugin({ replace: "$&if($self.isCategoryIndex($1.section))return $self.renderCategory($1);" }, { - match: /(?<=span",{)className:\i\.headerText,/, - replace: "...$self.makeSpanProps(),$&" + match: /"renderSection".{0,300}?"span",{/, + replace: "$&...$self.makeSpanProps()," }, // Fix Row Height diff --git a/src/plugins/plainFolderIcon/index.ts b/src/plugins/plainFolderIcon/index.ts index 8eb87896..d7f0bd62 100644 --- a/src/plugins/plainFolderIcon/index.ts +++ b/src/plugins/plainFolderIcon/index.ts @@ -28,12 +28,12 @@ export default definePlugin({ patches: [ { - find: ".folderPreviewGuildIconError", + find: "#{intl::GUILD_FOLDER_TOOLTIP_A11Y_LABEL}", replacement: [ { // Discord always renders both plain and guild icons folders and uses a css transtion to switch between them - match: /(?<=.folderButtonContent]:(!\i))/, - replace: (_, hasFolderButtonContentClass) => `,"vc-plainFolderIcon-plain":${hasFolderButtonContentClass}` + match: /\.slice\(0,4\).+?\]:(\i),\[\i\.\i\]:!\1/, + replace: (m, hasFolderButtonContent) => `${m},"vc-plainFolderIcon-plain":!${hasFolderButtonContent}` } ] diff --git a/src/plugins/replyTimestamp/index.tsx b/src/plugins/replyTimestamp/index.tsx index dcf70c70..7391153b 100644 --- a/src/plugins/replyTimestamp/index.tsx +++ b/src/plugins/replyTimestamp/index.tsx @@ -10,11 +10,11 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import type { Message } from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { DateUtils, Timestamp } from "@webpack/common"; import type { HTMLAttributes } from "react"; -const MessageClasses = findByPropsLazy("separator", "latin24CompactTimeStamp"); +const MessageClasses = findCssClassesLazy("separator", "latin24CompactTimeStamp"); function Sep(props: HTMLAttributes) { return ; diff --git a/src/plugins/revealAllSpoilers/index.ts b/src/plugins/revealAllSpoilers/index.ts index ad1d89f9..814abb20 100644 --- a/src/plugins/revealAllSpoilers/index.ts +++ b/src/plugins/revealAllSpoilers/index.ts @@ -18,10 +18,10 @@ import { Devs, IS_MAC } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; -const SpoilerClasses = findByPropsLazy("spoilerContent"); -const MessagesClasses = findByPropsLazy("messagesWrapper", "navigationDescription"); +const SpoilerClasses = findCssClassesLazy("spoilerContent", "hidden"); +const MessagesClasses = findCssClassesLazy("messagesWrapper", "navigationDescription"); export default definePlugin({ name: "RevealAllSpoilers", diff --git a/src/plugins/reviewDB/components/MessageButton.tsx b/src/plugins/reviewDB/components/MessageButton.tsx index 9b0b4be1..10c92db8 100644 --- a/src/plugins/reviewDB/components/MessageButton.tsx +++ b/src/plugins/reviewDB/components/MessageButton.tsx @@ -18,10 +18,10 @@ import { DeleteIcon } from "@components/Icons"; import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { Tooltip } from "@webpack/common"; -const iconClasses = findByPropsLazy("button", "wrapper", "disabled", "separator"); +const iconClasses = findCssClassesLazy("button", "wrapper", "disabled", "separator", "dangerous"); export function DeleteButton({ onClick }: { onClick(): void; }) { return ( diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index 2091687f..1b395f69 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -23,10 +23,9 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { NotesIcon, OpenExternalIcon } from "@components/Icons"; import { TooltipContainer } from "@components/TooltipContainer"; import { Devs } from "@utils/constants"; -import { classes } from "@utils/misc"; import definePlugin from "@utils/types"; import { Guild, User } from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { Alerts, Clickable, Menu, Parser } from "@webpack/common"; import { Auth, initAuth, updateAuth } from "./auth"; @@ -36,7 +35,7 @@ import { getCurrentUserInfo, readNotification } from "./reviewDbApi"; import { settings } from "./settings"; import { showToast } from "./utils"; -const BannerButtonClasses = findByPropsLazy("bannerButton"); +const BannerButtonClasses = findCssClassesLazy("bannerButton"); const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => { if (!guild) return; @@ -152,7 +151,7 @@ export default definePlugin({ openReviewsModal(user.id, user.username, ReviewType.User)} - className={classes(BannerButtonClasses.bannerButton)} + className={BannerButtonClasses.bannerButton} > diff --git a/src/plugins/reviewDB/style.css b/src/plugins/reviewDB/style.css index e65275f8..83fa6cf2 100644 --- a/src/plugins/reviewDB/style.css +++ b/src/plugins/reviewDB/style.css @@ -130,4 +130,4 @@ .vc-rdb-block-modal-unblock { cursor: pointer; -} \ No newline at end of file +} diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index bb76af7d..03a71f49 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -91,7 +91,8 @@ export default definePlugin({ }, // Slate { - find: ".userTooltip,children", + // Same find as FullUserInChatbox + find: ':"text":', replacement: [ { match: /let\{id:(\i),guildId:\i,channelId:(\i)[^}]*\}.*?\.\i,{(?=children)/, @@ -105,8 +106,8 @@ export default definePlugin({ find: 'tutorialId:"whos-online', replacement: [ { - match: /(?<=\.roleIcon.{0,15}:null,).{0,150}— ",\i\]\}\)\]/, - replace: "$self.RoleGroupColor(arguments[0])]" + match: /(#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.+}\):null,).{0,100}?— ",\i\]\}\)\]/, + replace: (_, rest) => `${rest}$self.RoleGroupColor(arguments[0])]` }, ], predicate: () => settings.store.memberList @@ -123,20 +124,21 @@ export default definePlugin({ }, // Voice Users { - find: ".usernameSpeaking]:", + find: "#{intl::GUEST_NAME_SUFFIX})]", replacement: [ { - match: /\.usernameSpeaking\]:.+?,(?=children)(?<=guildId:(\i),.+?user:(\i).+?)/, - replace: "$&style:$self.getColorStyle($2.id,$1)," + match: /#{intl::GUEST_NAME_SUFFIX}.{0,50}?""\](?<=guildId:(\i),.{0,50}?user:(\i).+?)/, + replace: "$&,style:$self.getColorStyle($2.id,$1)," } ], predicate: () => settings.store.voiceUsers }, // Reaction List { - find: ".reactionDefault", + find: "MessageReactions.render:", replacement: { - match: /tag:"strong"(?=.{0,50}\i\.name)(?<=onContextMenu:.{0,15}\((\i),(\i),\i\).+?)/, + // FIXME: (?:medium|normal) is for stable compat + match: /tag:"strong",variant:"text-md\/(?:medium|normal)"(?<=onContextMenu:.{0,15}\((\i),(\i),\i\).+?)/, replace: "$&,style:$self.getColorStyle($2?.id,$1?.channel?.id)" }, predicate: () => settings.store.reactorsList, @@ -145,7 +147,7 @@ export default definePlugin({ { find: ",reactionVoteCounts", replacement: { - match: /\.name,(?="aria-label)/, + match: /\.SIZE_32.+?variant:"text-md\/normal",className:\i\.\i,(?="aria-label":)/, replace: "$&style:$self.getColorStyle(arguments[0]?.user?.id,arguments[0]?.channel?.id)," }, predicate: () => settings.store.pollResults @@ -154,7 +156,7 @@ export default definePlugin({ { find: ".SEND_FAILED,", replacement: { - match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/, + match: /(?<=\]:(\i)\.isUnsupported.{0,50}?,)(?=children:\[)/, replace: "style:$self.useMessageColorsStyle($1)," }, predicate: () => settings.store.colorChatMessages diff --git a/src/plugins/serverInfo/GuildInfoModal.tsx b/src/plugins/serverInfo/GuildInfoModal.tsx index 0ed5548c..5e3a23a7 100644 --- a/src/plugins/serverInfo/GuildInfoModal.tsx +++ b/src/plugins/serverInfo/GuildInfoModal.tsx @@ -12,10 +12,10 @@ import { classes } from "@utils/misc"; import { ModalRoot, ModalSize, openModal } from "@utils/modal"; import { useAwaiter } from "@utils/react"; import { Guild, User } from "@vencord/discord-types"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findComponentByCodeLazy, findCssClassesLazy } from "@webpack"; import { FluxDispatcher, Forms, GuildChannelStore, GuildMemberStore, GuildRoleStore, IconUtils, Parser, PresenceStore, RelationshipStore, ScrollerThin, SnowflakeUtils, TabBar, Timestamp, useEffect, UserStore, UserUtils, useState, useStateFromStores } from "@webpack/common"; -const IconClasses = findByPropsLazy("icon", "acronym", "childWrapper"); +const IconClasses = findCssClassesLazy("icon", "acronym", "childWrapper"); const FriendRow = findComponentByCodeLazy("discriminatorClass:", ".isMobileOnline", "getAvatarURL"); const cl = classNameFactory("vc-gp-"); diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index 7dec55ac..bb7a361f 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -25,7 +25,7 @@ import { sortPermissionOverwrites } from "@plugins/permissionsViewer/utils"; import { classes } from "@utils/misc"; import { formatDuration } from "@utils/text"; import type { Channel } from "@vencord/discord-types"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByPropsLazy, findComponentByCodeLazy, findCssClassesLazy } from "@webpack"; import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common"; import { cl, settings } from ".."; @@ -81,8 +81,7 @@ const enum ChannelFlags { } -const ChatScrollClasses = findByPropsLazy("auto", "managedReactiveScroller"); -const ChatClasses = findByPropsLazy("chat", "content", "noChat", "chatContent"); +const ChatScrollClasses = findCssClassesLazy("auto", "managedReactiveScroller", "customTheme"); const ChannelBeginHeader = findComponentByCodeLazy("#{intl::ROLE_REQUIRED_SINGLE_USER_MESSAGE}"); const TagComponent = findComponentByCodeLazy("#{intl::FORUM_TAG_A11Y_FILTER_BY_TAG}"); diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 6d4a4238..484352a1 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -25,15 +25,15 @@ import { classNameFactory } from "@utils/css"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; import type { Channel, Role } from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { ChannelStore, PermissionsBits, PermissionStore, Tooltip } from "@webpack/common"; import HiddenChannelLockScreen from "./components/HiddenChannelLockScreen"; -const ChannelListClasses = findByPropsLazy("modeMuted", "modeSelected", "unread", "icon"); - export const cl = classNameFactory("vc-shc-"); +const ChannelListClasses = findCssClassesLazy("modeSelected", "modeMuted", "unread", "icon"); + const enum ShowMode { LockIcon, HiddenIconWithMutedStyle @@ -106,7 +106,7 @@ export default definePlugin({ replacement: [ { // Do not show confirmation to join a voice channel when already connected to another if clicking on a hidden voice channel - match: /(?<=getIgnoredUsersForVoiceChannel\((\i)\.id\);return\()/, + match: /(?<=getIgnoredUsersForVoiceChannel\((\i)\.id\)[^;]+?;return\()/, replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&` }, { @@ -166,7 +166,7 @@ export default definePlugin({ replacement: [ // Make the channel appear as muted if it's hidden { - match: /\.subtitle,.+?;(?=return\(0,\i\.jsxs?\))(?<={channel:(\i),name:\i,muted:(\i).+?;)/, + match: /Children\.count.+?;(?=return\(0,\i\.jsxs?\)\(\i\.\i,{focusTarget:)(?<={channel:(\i),name:\i,muted:(\i).+?;)/, replace: (m, channel, muted) => `${m}${muted}=$self.isHiddenChannel(${channel})?true:${muted};` }, // Add the hidden eye icon if the channel is hidden @@ -176,7 +176,7 @@ export default definePlugin({ }, // Make voice channels also appear as muted if they are muted { - match: /(?<=\.wrapper:\i\.notInteractive,)(.+?)if\((\i)(?:\)return |\?)(\i\.MUTED)/, + match: /(?<=\?\i\.\i:\i\.\i,)(.{0,150}?)if\((\i)(?:\)return |\?)(\i\.MUTED)/, replace: (_, otherClasses, isMuted, mutedClassExpression) => `${isMuted}?${mutedClassExpression}:"",${otherClasses}if(${isMuted})return ""` } ] @@ -193,7 +193,7 @@ export default definePlugin({ { // Hide unreads predicate: () => settings.store.hideUnreads === true, - match: /\.subtitle,.+?;(?=return\(0,\i\.jsxs?\))(?<={channel:(\i),name:\i,.+?unread:(\i).+?)/, + match: /Children\.count.+?;(?=return\(0,\i\.jsxs?\)\(\i\.\i,{focusTarget:)(?<={channel:(\i),name:\i,.+?unread:(\i).+?)/, replace: (m, channel, unread) => `${m}${unread}=$self.isHiddenChannel(${channel})?false:${unread};` } ] @@ -301,7 +301,7 @@ export default definePlugin({ }, { // Patch the header to only return allowed users and roles if it's a hidden channel or locked channel (Like when it's used on the HiddenChannelLockScreen) - match: /return\(0,\i\.jsxs?\)\(\i\.\i,{channelId:(\i)\.id(?=.+?(\(0,\i\.jsxs?\)\("div",{className:\i\.members.+?\]}\)),)/, + match: /return\(0,\i\.jsxs?\)\(\i\.\i,{channelId:(\i)\.id(?=.+?(\(0,\i\.jsxs?\)\("div",{className:\i\.\i,children:\[.{0,100}\i\.length>0.+?\]}\)),)/, replace: (m, channel, allowedUsersAndRolesComponent) => `if($self.isHiddenChannel(${channel},true)){return${allowedUsersAndRolesComponent};}${m}` }, { @@ -368,7 +368,7 @@ export default definePlugin({ }, { // Disable bad CSS class which mess up hidden voice channels styling - match: /callContainer,(?<=\i\.callContainer,)/, + match: /(?=\i\|\|\i!==\i\.\i\.FULL_SCREEN.{0,100}?this\._callContainerRef)/, replace: '$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel,true)?"":' } ] @@ -408,7 +408,7 @@ export default definePlugin({ }, { // Remove the open chat button for the HiddenChannelLockScreen - match: /(?<=&&)\(0,\i\.jsxs?\).{0,180}\.buttonIcon/, + match: /(?<="participants-list-button"\),!\i&&)\(0,\i\.jsxs?\).{0,280}?iconClassName:/, replace: "!$self.isHiddenChannel(arguments[0]?.channel,true)&&$&" } ] @@ -438,10 +438,10 @@ export default definePlugin({ }, }, { - find: 'className:"channelMention",children', + find: 'className:"channelMention",children:', replacement: { // Show inside voice channel instead of trying to join them when clicking on a channel mention - match: /(?<=getChannel\(\i\);if\(null!=(\i))(?=.{0,100}?selectVoiceChannel)/, + match: /(?<=getChannel\(\i\);null!=(\i))(?=.{0,100}?selectVoiceChannel)/, replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})` } }, @@ -461,7 +461,7 @@ export default definePlugin({ ] }, { - find: ".invitesDisabledTooltip", + find: "GuildTooltip - ", replacement: { // Make GuildChannelStore.getChannels return hidden channels match: /(?<=getChannels\(\i)(?=\))/, diff --git a/src/plugins/showHiddenChannels/style.css b/src/plugins/showHiddenChannels/style.css index c7c70c5c..2aa0e76e 100644 --- a/src/plugins/showHiddenChannels/style.css +++ b/src/plugins/showHiddenChannels/style.css @@ -104,4 +104,4 @@ cursor: not-allowed; margin-left: 6px; z-index: 0; -} \ No newline at end of file +} diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 318e2bc7..b788a8bd 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -72,8 +72,8 @@ export default definePlugin({ find: "#{intl::GUILD_MEMBER_MOD_VIEW_HIGHEST_ROLE}),children:", predicate: () => settings.store.showModView, replacement: { - match: /(?<=\.highestRole\),)role:\i(?<=\[\i\.roles,\i\.highestRoleId,(\i)\].+)/, - replace: "role:$self.getHighestRole(arguments[0],$1)", + match: /(#{intl::GUILD_MEMBER_MOD_VIEW_HIGHEST_ROLE}.{0,80})role:\i(?<=\[\i\.roles,\i\.highestRoleId,(\i)\].+?)/, + replace: (_, rest, roles) => `${rest}role:$self.getHighestRole(arguments[0],${roles})`, } }, // allows you to open mod view on yourself diff --git a/src/plugins/sortFriendRequests/index.tsx b/src/plugins/sortFriendRequests/index.tsx index 8d7b2df6..11a14c15 100644 --- a/src/plugins/sortFriendRequests/index.tsx +++ b/src/plugins/sortFriendRequests/index.tsx @@ -65,7 +65,7 @@ export default definePlugin({ find: "#{intl::FRIEND_REQUEST_CANCEL}", replacement: { predicate: () => settings.store.showDates, - match: /(?<=\.listItemContents,children:\[)\(0,.+?(?=,\(0)(?<=user:(\i).+?)/, + match: /(?<=children:\[)\(0,.{0,100}user:\i,hovered:\i.+?(?=,\(0)(?<=user:(\i).+?)/, replace: (children, user) => `$self.WrapperDateComponent({user:${user},children:${children}})` } }], diff --git a/src/plugins/spotifyControls/index.tsx b/src/plugins/spotifyControls/index.tsx index c7e8c91f..f0c00313 100644 --- a/src/plugins/spotifyControls/index.tsx +++ b/src/plugins/spotifyControls/index.tsx @@ -53,7 +53,7 @@ export default definePlugin({ }, patches: [ { - find: "this.isCopiedStreakGodlike", + find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}", replacement: { // react.jsx)(AccountPanel, { ..., showTaglessAccountPanel: blah }) match: /(?<=\i\.jsxs?\)\()(\i),{(?=[^}]*?userTag:\i,hidePrivateData:)/, diff --git a/src/plugins/superReactionTweaks/index.ts b/src/plugins/superReactionTweaks/index.ts index a8827903..84cd04e9 100644 --- a/src/plugins/superReactionTweaks/index.ts +++ b/src/plugins/superReactionTweaks/index.ts @@ -42,13 +42,6 @@ export default definePlugin({ { find: ",BURST_REACTION_EFFECT_PLAY", replacement: [ - // FIXME(Bundler minifier change related): Remove the non used compability once enough time has passed - { - // if (inlinedCalculatePlayingCount(a,b) >= limit) return; - match: /(BURST_REACTION_EFFECT_PLAY:\i=>{.+?if\()(\(\(\i,\i\)=>.+?\(\i,\i\))>=5+?(?=\))/, - replace: (_, rest, playingCount) => `${rest}!$self.shouldPlayBurstReaction(${playingCount})`, - noWarn: true, - }, { /* * var limit = 5 diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index beb108af..9cb95874 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -29,10 +29,10 @@ export default definePlugin({ // Add data-author-id and data-is-self to all messages { - find: ".messageListItem", + find: "Message must not be a thread starter message", replacement: { - match: /\.messageListItem(?=,"aria)/, - replace: "$&,...$self.getMessageProps(arguments[0])" + match: /"aria-setsize":-1,(?=.{0,150}?#{intl::MESSAGE_A11Y_ROLE_DESCRIPTION})/, + replace: "...$self.getMessageProps(arguments[0]),$&" } }, diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index ecd8c44d..2e7c9cff 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -27,7 +27,7 @@ import definePlugin, { OptionType } from "@utils/types"; import { findComponentByCodeLazy } from "@webpack"; import { GuildMemberStore, RelationshipStore, SelectedChannelStore, Tooltip, TypingStore, UserGuildSettingsStore, UserStore, UserSummaryItem, useStateFromStores } from "@webpack/common"; -const ThreeDots = findComponentByCodeLazy(".dots,", "dotRadius:"); +const ThreeDots = findComponentByCodeLazy("Math.min(1,Math.max(", "dotRadius:"); const enum IndicatorMode { Dots = 1 << 0, diff --git a/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx b/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx index b4c32638..4c380e93 100644 --- a/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx +++ b/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx @@ -21,13 +21,13 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import { Message } from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; +import { findCssClassesLazy } from "@webpack"; import { Tooltip, UserStore } from "@webpack/common"; import { settings } from "./settings"; import { useFormattedPronouns } from "./utils"; -const styles: Record = findByPropsLazy("timestampInline"); +const TimestampClasses = findCssClassesLazy("timestampInline", "timestamp"); const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact")!; const AUTO_MODERATION_ACTION = 24; @@ -49,7 +49,7 @@ function PronounsChatComponent({ message }: { message: Message; }) { {tooltipProps => ( • {pronouns} )} diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index 34201445..71c7e9b0 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -10,18 +10,15 @@ import ShowHiddenChannelsPlugin from "@plugins/showHiddenChannels"; import { classNameFactory } from "@utils/css"; import { classes } from "@utils/misc"; import { Channel } from "@vencord/discord-types"; -import { filters, findByPropsLazy, mapMangledModuleLazy } from "@webpack"; +import { findByPropsLazy, findCssClassesLazy } from "@webpack"; import { ChannelRouter, ChannelStore, Parser, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, UserSummaryItem, useStateFromStores, VoiceStateStore } from "@webpack/common"; import { PropsWithChildren } from "react"; const cl = classNameFactory("vc-uvs-"); const { selectVoiceChannel } = findByPropsLazy("selectVoiceChannel", "selectChannel"); -const { useChannelName } = mapMangledModuleLazy("#{intl::GROUP_DM_ALONE}", { - useChannelName: filters.byCode("()=>null==") -}); -const ActionButtonClasses = findByPropsLazy("actionButton", "highlight"); +const ActionButtonClasses = findCssClassesLazy("actionButton", "highlight"); type IconProps = Omit, "children"> & { size?: number; diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 04b9aa11..039982dd 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -87,7 +87,7 @@ export default definePlugin({ { find: "null!=this.peopleListItemRef.current", replacement: { - match: /\.actions,children:\[(?<=isFocused:(\i).+?)/, + match: /\.isProvisional.{0,50}?className:\i\.\i,children:\[(?<=isFocused:(\i).+?)/, replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true,shouldHighlight:$1})," }, predicate: () => settings.store.showInMemberList diff --git a/src/plugins/vencordToolbox/index.tsx b/src/plugins/vencordToolbox/index.tsx index 1cac4009..22dfd948 100644 --- a/src/plugins/vencordToolbox/index.tsx +++ b/src/plugins/vencordToolbox/index.tsx @@ -28,7 +28,7 @@ import type { PropsWithChildren } from "react"; import { renderPopout } from "./menu"; -const HeaderBarIcon = findComponentByCodeLazy(".HEADER_BAR_BADGE_TOP:", '.iconBadge,"top"'); +const HeaderBarIcon = findComponentByCodeLazy(".HEADER_BAR_BADGE_TOP:", '"aria-haspopup":'); export const settings = definePluginSettings({ showPluginMenu: { diff --git a/src/plugins/viewIcons/index.tsx b/src/plugins/viewIcons/index.tsx index 44bee1e1..891a2c7c 100644 --- a/src/plugins/viewIcons/index.tsx +++ b/src/plugins/viewIcons/index.tsx @@ -197,21 +197,18 @@ export default definePlugin({ patches: [ // Avatar component used in User DMs "User Profile" popup in the right and User Profile Modal pfp { - find: ".overlay:void 0,status:", - replacement: [ - { - match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",.{0,100}className:\i,/, - replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openAvatar($1)},", - } - ], - all: true + find: "imageClassName:null!=", + replacement: { + match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",.{0,100}className:\i,/, + replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openAvatar($1)},", + } }, // Banners { find: 'backgroundColor:"COMPLETE"', replacement: { - match: /(\.banner,.+?),style:{(?=.+?backgroundImage:null!=(\i)\?"url\("\.concat\(\2,)/, - replace: (_, rest, bannerSrc) => `${rest},onClick:()=>${bannerSrc}!=null&&$self.openBanner(${bannerSrc}),style:{cursor:${bannerSrc}!=null?"pointer":void 0,` + match: /(overflow:"visible",.{0,125}?!1\),)style:{(?=.+?backgroundImage:null!=(\i)\?"url\("\.concat\(\2,)/, + replace: (_, rest, bannerSrc) => `${rest}onClick:()=>${bannerSrc}!=null&&$self.openBanner(${bannerSrc}),style:{cursor:${bannerSrc}!=null?"pointer":void 0,` } }, // Group DMs top small & large icon @@ -225,7 +222,7 @@ export default definePlugin({ }, // User DMs top small icon { - find: ".cursorPointer:null,children", + find: ".channel.getRecipientId(),", replacement: { match: /(?=,src:(\i.getAvatarURL\(.+?[)]))/, replace: (_, avatarUrl) => `,onClick:()=>$self.openAvatar(${avatarUrl})` diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx index 571c3d0e..19d0883f 100644 --- a/src/plugins/voiceDownload/index.tsx +++ b/src/plugins/voiceDownload/index.tsx @@ -15,10 +15,10 @@ export default definePlugin({ authors: [Devs.puv], patches: [ { - find: "rippleContainer,children", + find: "#{intl::LgCPMt::raw}", replacement: { - match: /\(0,\i\.jsx\).{0,150},children:.{0,50}\("source",{src:(\i)}\)}\)/, - replace: "[$&, $self.renderDownload($1)]" + match: /(?<=onVolumeHide:\i\}\))/, + replace: ",$self.renderDownload(arguments[0].src)" } } ], diff --git a/src/plugins/voiceDownload/style.css b/src/plugins/voiceDownload/style.css index 4e1379e2..b261bbe1 100644 --- a/src/plugins/voiceDownload/style.css +++ b/src/plugins/voiceDownload/style.css @@ -2,11 +2,10 @@ width: 24px; height: 24px; color: var(--interactive-icon-default); - margin-left: 12px; cursor: pointer; position: relative; } .vc-voice-download:hover { color: var(--interactive-icon-active); -} \ No newline at end of file +} diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index 886ada85..5528aa6f 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -32,7 +32,7 @@ import definePlugin from "@utils/types"; import { chooseFile } from "@utils/web"; import { CloudUpload as TCloudUpload } from "@vencord/discord-types"; import { CloudUploadPlatform } from "@vencord/discord-types/enums"; -import { findByPropsLazy, findLazy, findStoreLazy } from "@webpack"; +import { findCssClassesLazy, findLazy, findStoreLazy } from "@webpack"; import { Button, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; import { ComponentType } from "react"; @@ -43,7 +43,7 @@ import { VoiceRecorderWeb } from "./WebRecorder"; const CloudUpload: typeof TCloudUpload = findLazy(m => m.prototype?.trackUploadFinished); const PendingReplyStore = findStoreLazy("PendingReplyStore"); -const OptionClasses = findByPropsLazy("optionName", "optionIcon", "optionLabel"); +const OptionClasses = findCssClassesLazy("optionName", "optionIcon", "optionLabel"); export const cl = classNameFactory("vc-vmsg-"); export type VoiceRecorder = ComponentType<{ diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index fa9bfab5..72330116 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -23,10 +23,8 @@ import { Queue } from "@utils/Queue"; import { useForceUpdater } from "@utils/react"; import definePlugin from "@utils/types"; import { CustomEmoji, Message, ReactionEmoji, User } from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; import { ChannelStore, Constants, FluxDispatcher, React, RestAPI, useEffect, useLayoutEffect, UserStore, UserSummaryItem } from "@webpack/common"; -const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); let Scroll: any = null; const queue = new Queue(); let reactions: Record; diff --git a/src/webpack/common/classes.ts b/src/webpack/common/classes.ts deleted file mode 100644 index daaf023c..00000000 --- a/src/webpack/common/classes.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 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 * as t from "@vencord/discord-types"; -import { findByPropsLazy } from "@webpack"; - -export const ButtonWrapperClasses: t.ButtonWrapperClasses = findByPropsLazy("buttonWrapper", "buttonContent"); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index e388a8a1..f06f830f 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -26,7 +26,7 @@ import { TooltipContainer as TooltipContainerComponent } from "@components/Toolt import { TooltipFallback } from "@components/TooltipFallback"; import { LazyComponent } from "@utils/lazyReact"; import * as t from "@vencord/discord-types"; -import { filters, mapMangledModuleLazy, waitFor } from "@webpack"; +import { filters, find, findCssClassesLazy, mapMangledCssClasses, mapMangledModuleLazy, proxyLazyWebpack, waitFor } from "@webpack"; import { waitForComponent } from "./internal"; @@ -50,9 +50,7 @@ export const Button = ButtonCompat; /** @deprecated Use FormSwitch from Vencord */ export const Switch = FormSwitchCompat as never; -/** @deprecated Use Card from Vencord */ -export const Card = waitForComponent("Card", filters.componentByCode(".editable),", ".outline:")); -export const Checkbox = waitForComponent("Checkbox", filters.componentByCode(".checkboxWrapperDisabled:")); +export const Checkbox = waitForComponent("Checkbox", filters.componentByCode('"data-toggleable-component":"checkbox')); export const Tooltip = waitForComponent("Tooltip", m => m.prototype?.shouldShowTooltip && m.prototype.render, TooltipFallback); /** @deprecated import from @vencord/components */ @@ -77,19 +75,26 @@ export const UserSummaryItem = waitForComponent("UserSummaryItem", filters.compo export let createScroller: (scrollbarClassName: string, fadeClassName: string, customThemeClassName: string) => t.ScrollerThin; export let createListScroller: (scrollBarClassName: string, fadeClassName: string, someOtherClassIdkMan: string, resizeObserverClass: typeof ResizeObserver) => t.ListScrollerThin; -export let scrollerClasses: Record; -export let listScrollerClasses: Record; + +const listScrollerClassnames = ["thin", "auto", "fade"] as const; +export const scrollerClasses = findCssClassesLazy("thin", "auto", "fade", "customTheme", "none"); + +const isListScroller = filters.byClassNames(...listScrollerClassnames); +const isNotNormalScroller = filters.byClassNames("customTheme"); +export const listScrollerClasses = proxyLazyWebpack(() => { + const mod = find(m => isListScroller(m) && !isNotNormalScroller(m), { topLevelOnly: true }); + if (!mod) return {} as Record; + + return mapMangledCssClasses(mod, listScrollerClassnames); +}); waitFor(filters.byCode('="ltr",orientation:', "customTheme:", "forwardRef"), m => createScroller = m); waitFor(filters.byCode("getScrollerNode:", "resizeObserver:", "sectionHeight:"), m => createListScroller = m); -waitFor(["thin", "auto", "customTheme"], m => scrollerClasses = m); -waitFor(m => m.thin && m.auto && !m.customTheme, m => listScrollerClasses = m); export const ScrollerNone = LazyComponent(() => createScroller(scrollerClasses.none, scrollerClasses.fade, scrollerClasses.customTheme)); export const ScrollerThin = LazyComponent(() => createScroller(scrollerClasses.thin, scrollerClasses.fade, scrollerClasses.customTheme)); export const ScrollerAuto = LazyComponent(() => createScroller(scrollerClasses.auto, scrollerClasses.fade, scrollerClasses.customTheme)); -export const ListScrollerNone = LazyComponent(() => createListScroller(listScrollerClasses.none, listScrollerClasses.fade, "", ResizeObserver)); export const ListScrollerThin = LazyComponent(() => createListScroller(listScrollerClasses.thin, listScrollerClasses.fade, "", ResizeObserver)); export const ListScrollerAuto = LazyComponent(() => createListScroller(listScrollerClasses.auto, listScrollerClasses.fade, "", ResizeObserver)); @@ -107,7 +112,7 @@ waitFor(m => { export const MaskedLink = waitForComponent("MaskedLink", filters.componentByCode("MASKED_LINK)")); export const Timestamp = waitForComponent("Timestamp", filters.componentByCode("#{intl::MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL}")); -export const OAuth2AuthorizeModal = waitForComponent("OAuth2AuthorizeModal", filters.componentByCode(".authorize,children:", ".contentBackground")); +export const OAuth2AuthorizeModal = waitForComponent("OAuth2AuthorizeModal", filters.componentByCode("hasContentBackground", "oauth2_authorize")); export const Animations = mapMangledModuleLazy(".assign({colorNames:", { Transition: filters.componentByCode('["items","children"]', ",null,"), diff --git a/src/webpack/common/index.ts b/src/webpack/common/index.ts index 80223b9a..f75507e9 100644 --- a/src/webpack/common/index.ts +++ b/src/webpack/common/index.ts @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -export * from "./classes"; export * from "./components"; export * from "./menu"; export * from "./react"; diff --git a/src/webpack/common/menu.ts b/src/webpack/common/menu.ts index 7e5447ce..4029877f 100644 --- a/src/webpack/common/menu.ts +++ b/src/webpack/common/menu.ts @@ -41,7 +41,7 @@ waitFor(m => m.name === "MenuCheckboxItem", (_, id) => { }); waitFor(filters.componentByCode('path:["empty"]'), m => Menu.Menu = m); -waitFor(filters.componentByCode("sliderContainer", "slider", "handleSize:16", "=100"), m => Menu.MenuSliderControl = m); +waitFor(filters.componentByCode("SLIDER)", "handleSize:16"), m => Menu.MenuSliderControl = m); waitFor(filters.componentByCode(".SEARCH)", ".focus()", "query:"), m => Menu.MenuSearchControl = m); export const ContextMenuApi: t.ContextMenuApi = mapMangledModuleLazy('type:"CONTEXT_MENU_OPEN', { diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index c23a8e66..c76c3ead 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -148,7 +148,7 @@ export const ApplicationAssetUtils = mapMangledModuleLazy("getAssetImage: size m getAssets: filters.byCode(".assets") }); -export const NavigationRouter: t.NavigationRouter = mapMangledModuleLazy("Transitioning to ", { +export const NavigationRouter: t.NavigationRouter = mapMangledModuleLazy("transitionTo - Transitioning to", { transitionTo: filters.byCode("transitionTo -"), transitionToGuild: filters.byCode("transitionToGuild -"), back: filters.byCode("goBack()"), diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 1dcb43a9..c025a72b 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -256,7 +256,7 @@ export const find = traceFunction("find", function find(filter: FilterFn, { isIn return isWaitFor ? [null, null] : null; }); -export function findAll(filter: FilterFn) { +export function findAll(filter: FilterFn, { topLevelOnly = false }: { topLevelOnly?: boolean; } = {}) { if (typeof filter !== "function") throw new Error("Invalid filter. Expected a function got " + typeof filter); @@ -268,7 +268,7 @@ export function findAll(filter: FilterFn) { if (filter(mod.exports)) ret.push(mod.exports); - if (typeof mod.exports !== "object") + if (typeof mod.exports !== "object" || topLevelOnly) continue; for (const nestedMod in mod.exports) { @@ -389,7 +389,7 @@ export function findModuleFactory(...code: CodeFilter) { return wreq.m[id]; } -export const lazyWebpackSearchHistory = [] as Array<["find" | "findByProps" | "findByCode" | "findStore" | "findComponent" | "findComponentByCode" | "findExportedComponent" | "waitFor" | "waitForComponent" | "waitForStore" | "proxyLazyWebpack" | "LazyComponentWebpack" | "extractAndLoadChunks" | "mapMangledModule", any[]]>; +export const lazyWebpackSearchHistory = [] as Array<["find" | "findByProps" | "findByCode" | "findCssClasses" | "findStore" | "findComponent" | "findComponentByCode" | "findExportedComponent" | "waitFor" | "waitForComponent" | "waitForStore" | "proxyLazyWebpack" | "LazyComponentWebpack" | "extractAndLoadChunks" | "mapMangledModule", any[]]>; /** * This is just a wrapper around {@link proxyLazy} to make our reporter test for your webpack finds. @@ -578,23 +578,32 @@ export function findExportedComponentLazy(...props: Prop }); } -export function findCssClasses(...classes: S[]): Record { - const res = find(filters.byClassNames(...classes), { isIndirect: true, topLevelOnly: true }); - - if (!res) - handleModuleNotFound("findCssClasses", ...classes); - - const values = Object.values(res); +export function mapMangledCssClasses(mappedModule: object, classes: S[] | ReadonlyArray): Record { + const values = Object.values(mappedModule); const mapped = {} as Record; for (const cls of classes) { const re = makeClassNameRegex(cls); mapped[cls] = values.find(v => typeof v === "string" && re.test(v)) as string; + + if (!mapped[cls]) // this should never happen unless this is used manually with invalid input + throw new Error(`mapMangledCssClasses: Invalid input. ${cls} not found in module`); } return mapped; } +export function findCssClasses(...classes: S[]): Record { + const res = find(filters.byClassNames(...classes), { isIndirect: true, topLevelOnly: true }); + + if (!res) { + handleModuleNotFound("findCssClasses", ...classes); + return {} as Record; + } + + return mapMangledCssClasses(res, classes); +} + export function findCssClassesLazy(...classes: S[]) { if (IS_REPORTER) lazyWebpackSearchHistory.push(["findCssClasses", classes]);