From a6ea03bacc53af38ddeeaec167621d976074deb6 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 24 Oct 2024 07:08:02 -0400 Subject: [PATCH 01/82] ImageZoom: Fix when multiple images with carrousel (#2966) Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com> --- src/plugins/imageZoom/index.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index adb0ab220..0cd63f050 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -179,6 +179,11 @@ export default definePlugin({ { match: /componentWillUnmount\(\){/, replace: "$&$self.unMountMagnifier();" + }, + + { + match: /componentDidUpdate\(\i\){/, + replace: "$&$self.updateMagnifier(this);" } ] } @@ -215,6 +220,11 @@ export default definePlugin({ } }, + updateMagnifier(instance) { + this.unMountMagnifier(); + this.renderMagnifier(instance); + }, + unMountMagnifier() { this.root?.unmount(); this.currentMagnifierElement = null; From 534ab3eb5f0b8180ce5f48c1252cdfc44e3e660a Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 24 Oct 2024 07:09:12 -0400 Subject: [PATCH 02/82] ConsoleJanitor: Brush react-spring deprecation (#2973) --- src/plugins/consoleJanitor/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index b0c8905f7..2d5d60ecf 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -66,6 +66,13 @@ export default definePlugin({ }, patches: [ + { + find: 'react-spring: The "interpolate" function', + replacement: { + match: /,console.warn\('react-spring: The "interpolate" function is deprecated in v10 \(use "to" instead\)'\)/, + replace: "" + } + }, { find: 'console.warn("Window state not initialized"', replacement: { From f5f59be1b665b35a1b07ae094c43abde27df8c0d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 24 Oct 2024 08:10:29 -0300 Subject: [PATCH 03/82] Fix plugins using ImageModals (again) --- src/utils/discord.css | 10 +++++----- src/utils/discord.tsx | 33 +++++++++++++++------------------ src/utils/modal.tsx | 37 ++++++++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/utils/discord.css b/src/utils/discord.css index a7f95fbe6..12d15694b 100644 --- a/src/utils/discord.css +++ b/src/utils/discord.css @@ -7,18 +7,18 @@ **/ .vc-image-modal { - background: transparent!important; - box-shadow: none!important; + background: transparent !important; + box-shadow: none !important; display: flex; justify-content: center; align-items: center; - border-radius: 0 + border-radius: 0; } @media(width <= 485px) { .vc-image-modal { - display:relative; + display: relative; overflow: visible; - overflow: initial + overflow: initial; } } diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 08de22ccd..fed5a5d86 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -21,8 +21,9 @@ import "./discord.css"; import { MessageObject } from "@api/MessageEvents"; import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Channel, Guild, Message, User } from "discord-types/general"; +import { Except } from "type-fest"; -import { ImageModal, ImageModalItem, openModal } from "./modal"; +import { MediaModalItem, MediaModalProps, openMediaModal } from "./modal"; /** * Open the invite modal @@ -111,24 +112,20 @@ export function sendMessage( } /** - * You must specify either height or width + * You must specify either height or width in the item */ -export function openImageModal(props: Omit): string { - return openModal(modalProps => ( - - )); +export function openImageModal(item: Except, mediaModalProps?: Omit) { + return openMediaModal({ + className: "vc-image-modal", + fit: "vc-position-inherit", + shouldAnimateCarousel: true, + items: [{ + type: "IMAGE", + original: item.original ?? item.url, + ...item, + }], + ...mediaModalProps + }); } export async function openUserProfile(id: string) { diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index 7459379ea..a11cb3cc5 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByPropsLazy, findModuleId, proxyLazyWebpack, wreq } from "@webpack"; import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react"; import { LazyComponent } from "./react"; @@ -101,24 +101,39 @@ export const Modals = findByPropsLazy("ModalRoot", "ModalCloseButton") as { }>; }; -export interface ImageModalItem { - type: "IMAGE" | "VIDEO"; +export type MediaModalItem = { url: string; + type: "IMAGE" | "VIDEO"; + original?: string; + alt?: string; width?: number; height?: number; - original?: string; -} + animated?: boolean; + maxWidth?: number; + maxHeight?: number; +} & Record; -export type ImageModal = ComponentType<{ +export type MediaModalProps = { + location?: string; + contextKey?: string; + onCloseCallback?: () => void; className?: string; + items: MediaModalItem[]; + startingIndex?: number; + onIndexChange?: (...args: any[]) => void; fit?: string; - onClose?(): void; + shouldRedactExplicitContent?: boolean; shouldHideMediaOptions?: boolean; - shouldAnimate?: boolean; - items: ImageModalItem[]; -}>; + shouldAnimateCarousel?: boolean; +}; -export const ImageModal = findComponentByCodeLazy(".MEDIA_MODAL_CLOSE") as ImageModal; +export const openMediaModal: (props: MediaModalProps) => void = proxyLazyWebpack(() => { + const mediaModalKeyModuleId = findModuleId('"Zoomed Media Modal"'); + if (mediaModalKeyModuleId == null) return; + + const openMediaModalModule = wreq(findModuleId(mediaModalKeyModuleId, "modalKey:") as any); + return Object.values(openMediaModalModule).find(v => String(v).includes("modalKey:")); +}); export const ModalRoot = LazyComponent(() => Modals.ModalRoot); export const ModalHeader = LazyComponent(() => Modals.ModalHeader); From 88e8fa7e904e525c4c1110d057f0812e4008ff7c Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Fri, 25 Oct 2024 05:48:11 -0400 Subject: [PATCH 04/82] NoPendingCount: Fix hiding offers count (#2975) --- src/plugins/noPendingCount/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/noPendingCount/index.ts b/src/plugins/noPendingCount/index.ts index 84ee8ec19..4b98e6664 100644 --- a/src/plugins/noPendingCount/index.ts +++ b/src/plugins/noPendingCount/index.ts @@ -87,7 +87,7 @@ export default definePlugin({ replacement: { // The two groups inside the first group grab the minified names of the variables, // they are then referenced later to find unviewedTrialCount + unviewedDiscountCount. - match: /(?<=\{unviewedTrialCount:(\i),unviewedDiscountCount:(\i)\}.{0,200}\i=)\1\+\2/, + match: /(?<=\{unviewedTrialCount:(\i),unviewedDiscountCount:(\i)\}.{0,300}\i=)\1\+\2/, replace: "0" } } From d897dab0547309d1408fcb8fbde77145455a011a Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Sat, 26 Oct 2024 06:32:32 -0400 Subject: [PATCH 05/82] ShowHiddenChannels: Fix viewing voice channels (#2979) --- src/plugins/showHiddenChannels/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 31f90242f..d220d0c12 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -103,7 +103,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: /(?<=getBlockedUsersForVoiceChannel\((\i)\.id\);return)/, + match: /(?<=getBlockedUsersForVoiceChannel\((\i)\.id\);return\()/, replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&` }, { From e7e298d2e7fbdcd9c692dd4a2762951f2f541cdb Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 26 Oct 2024 13:48:15 +0200 Subject: [PATCH 06/82] ThemeAttributes: fix freezing when changing avatar --- src/plugins/themeAttributes/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index b80844546..2a613967c 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -55,6 +55,8 @@ export default definePlugin({ ], getAvatarStyles(src: string) { + if (src.startsWith("data:")) return {}; + return Object.fromEntries( [128, 256, 512, 1024, 2048, 4096].map(size => [ `--avatar-url-${size}`, From 5216bcca1eca1b79a5a397e2128414ef653daee7 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 3 Nov 2024 15:47:19 -0300 Subject: [PATCH 07/82] Fix settings & updater for Canary --- src/plugins/_core/settings.tsx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 329c389c4..ffaea15bc 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -57,7 +57,7 @@ export default definePlugin({ ] }, { - find: "Messages.ACTIVITY_SETTINGS", + find: ".SEARCH_NO_RESULTS&&0===", replacement: [ { match: /(?<=section:(.{0,50})\.DIVIDER\}\))([,;])(?=.{0,200}(\i)\.push.{0,100}label:(\i)\.header)/, @@ -148,13 +148,17 @@ export default definePlugin({ if (!header) return; - const names = { - top: i18n.Messages.USER_SETTINGS, - aboveNitro: i18n.Messages.BILLING_SETTINGS, - belowNitro: i18n.Messages.APP_SETTINGS, - aboveActivity: i18n.Messages.ACTIVITY_SETTINGS - }; - return header === names[settingsLocation]; + try { + const names = { + top: i18n.Messages.USER_SETTINGS, + aboveNitro: i18n.Messages.BILLING_SETTINGS, + belowNitro: i18n.Messages.APP_SETTINGS, + aboveActivity: i18n.Messages.ACTIVITY_SETTINGS + }; + return header === names[settingsLocation]; + } catch { + return firstChild === "PREMIUM"; + } }, patchedSettings: new WeakSet(), From 00f82e96bd0472eb4ca83a10ee9a5a22652436b6 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:49:27 -0300 Subject: [PATCH 08/82] Fix all plugins for new i18n lib (#2993) --- package.json | 1 + pnpm-lock.yaml | 8 +++ src/components/Icons.tsx | 5 +- src/debug/loadLazyChunks.ts | 4 +- src/plugins/_api/memberListDecorators.ts | 2 +- src/plugins/_api/messageAccessories.ts | 2 +- src/plugins/_api/messageDecorations.ts | 2 +- src/plugins/_api/messageEvents.ts | 2 +- src/plugins/_api/messagePopover.ts | 4 +- src/plugins/_api/serverList.ts | 8 +-- src/plugins/_core/settings.tsx | 14 ++--- src/plugins/_core/supportHelper.tsx | 4 +- .../accountPanelServerProfile/index.tsx | 2 +- src/plugins/alwaysAnimate/index.ts | 2 +- src/plugins/anonymiseFileNames/index.tsx | 4 +- src/plugins/banger/index.ts | 2 +- src/plugins/betterFolders/index.tsx | 21 +++++--- src/plugins/betterGifAltText/index.ts | 4 +- src/plugins/betterNotes/index.tsx | 4 +- src/plugins/betterRoleDot/index.ts | 2 +- src/plugins/betterSessions/index.tsx | 2 +- src/plugins/betterSettings/PluginsSubmenu.tsx | 5 +- src/plugins/betterSettings/index.tsx | 9 ++-- src/plugins/clientTheme/index.tsx | 2 +- src/plugins/consoleShortcuts/index.ts | 2 + src/plugins/copyFileContents/index.tsx | 2 +- src/plugins/crashHandler/index.ts | 2 +- src/plugins/decor/index.tsx | 2 +- .../ui/components/DecorationGridCreate.tsx | 5 +- .../ui/components/DecorationGridNone.tsx | 5 +- src/plugins/disableCallIdle/index.ts | 2 +- src/plugins/fakeNitro/index.tsx | 6 +-- src/plugins/fakeProfileThemes/index.tsx | 8 +-- src/plugins/forceOwnerCrown/index.ts | 2 +- src/plugins/friendsSince/index.tsx | 4 +- src/plugins/fullSearchContext/index.tsx | 7 +-- src/plugins/gameActivityToggle/index.tsx | 2 +- src/plugins/greetStickerPicker/index.tsx | 2 +- src/plugins/ignoreActivities/index.tsx | 4 +- src/plugins/implicitRelationships/index.ts | 8 +-- src/plugins/invisibleChat.desktop/index.tsx | 2 +- src/plugins/keepCurrentChannel/index.ts | 18 ++++++- src/plugins/loadingQuotes/index.ts | 2 +- src/plugins/memberCount/index.tsx | 2 +- src/plugins/messageLogger/index.tsx | 9 ++-- src/plugins/moreUserTags/index.tsx | 45 +++++++++------- src/plugins/noBlockedMessages/index.ts | 2 +- src/plugins/noOnboardingDelay/index.ts | 2 +- src/plugins/noUnblockToJump/index.ts | 6 +-- src/plugins/normalizeMessageLinks/index.ts | 2 +- src/plugins/pauseInvitesForever/index.tsx | 11 ++-- src/plugins/permissionFreeWill/index.ts | 4 +- .../components/RolesAndUsersPermissions.tsx | 10 ++-- .../components/UserPermissions.tsx | 5 +- src/plugins/permissionsViewer/index.tsx | 2 +- src/plugins/permissionsViewer/utils.ts | 7 +-- .../pinDms/components/CreateCategoryModal.tsx | 2 +- src/plugins/replyTimestamp/index.tsx | 2 +- src/plugins/reverseImageSearch/index.tsx | 2 +- src/plugins/roleColorEverywhere/index.tsx | 4 +- src/plugins/shikiCodeblocks.desktop/index.ts | 2 +- src/plugins/showAllMessageButtons/index.ts | 2 +- src/plugins/showConnections/VerifiedIcon.tsx | 7 +-- .../components/HiddenChannelLockScreen.tsx | 12 ++--- src/plugins/showHiddenChannels/index.tsx | 12 ++--- src/plugins/showHiddenThings/index.ts | 2 +- src/plugins/showTimeoutDuration/index.tsx | 18 +++++-- src/plugins/sortFriendRequests/index.tsx | 2 +- src/plugins/startupTimings/index.tsx | 2 +- src/plugins/themeAttributes/index.ts | 2 +- src/plugins/typingIndicator/index.tsx | 11 ++-- src/plugins/typingTweaks/index.tsx | 4 +- src/plugins/unlockedAvatarZoom/index.ts | 2 +- .../PronounsChatComponent.tsx | 5 +- src/plugins/userVoiceShow/components.tsx | 2 +- src/plugins/userVoiceShow/index.tsx | 4 +- src/plugins/validReply/index.ts | 4 +- src/plugins/viewRaw/index.tsx | 5 +- src/plugins/volumeBooster/index.ts | 2 +- src/plugins/webContextMenus.web/index.ts | 16 +++--- src/utils/discord.tsx | 29 ++++++++++- src/utils/index.ts | 1 + src/utils/intlHash.ts | 52 +++++++++++++++++++ src/utils/patches.ts | 25 +++++++-- src/webpack/common/components.ts | 2 +- src/webpack/common/types/i18nMessages.ts | 24 --------- src/webpack/common/types/index.d.ts | 1 - src/webpack/common/types/utils.d.ts | 14 ----- src/webpack/common/utils.ts | 8 ++- 89 files changed, 351 insertions(+), 238 deletions(-) create mode 100644 src/utils/intlHash.ts delete mode 100644 src/webpack/common/types/i18nMessages.ts diff --git a/package.json b/package.json index 9d5ad3e58..63ff0678b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "testTsc": "tsc --noEmit" }, "dependencies": { + "@intrnl/xxhash64": "^0.1.2", "@sapphi-red/web-noise-suppressor": "0.3.5", "@vap/core": "0.0.12", "@vap/shiki": "0.10.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eaa6b537c..a62c40cd6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ importers: .: dependencies: + '@intrnl/xxhash64': + specifier: ^0.1.2 + version: 0.1.2 '@sapphi-red/web-noise-suppressor': specifier: 0.3.5 version: 0.3.5 @@ -537,6 +540,9 @@ packages: resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} engines: {node: '>=18.18'} + '@intrnl/xxhash64@0.1.2': + resolution: {integrity: sha512-1+lx7j99fdph+uy3EnjQyr39KQZ7LP56+aWOr6finJWpgYpvb7XrhFUqDwnEk/wpPC98nCjAT6RulpW3crWjlg==} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -2939,6 +2945,8 @@ snapshots: '@humanwhocodes/retry@0.3.0': {} + '@intrnl/xxhash64@0.1.2': {} + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx index fa142a18c..d0d2ecbe8 100644 --- a/src/components/Icons.tsx +++ b/src/components/Icons.tsx @@ -18,9 +18,8 @@ import "./iconStyles.css"; -import { getTheme, Theme } from "@utils/discord"; +import { getIntlMessage, getTheme, Theme } from "@utils/discord"; import { classes } from "@utils/misc"; -import { i18n } from "@webpack/common"; import type { PropsWithChildren } from "react"; interface BaseIconProps extends IconProps { @@ -133,7 +132,7 @@ export function InfoIcon(props: IconProps) { export function OwnerCrownIcon(props: IconProps) { return ( (); - // Workaround for a chunk that depends on the ChannelMessage component but may be be force loaded before - // the chunk containing the component - const shouldForceDefer = factoryCode.includes(".Messages.GUILD_FEED_UNFEATURE_BUTTON_TEXT"); + const shouldForceDefer = false; await Promise.all(Array.from(lazyChunks).map(async ([, rawChunkIds, entryPoint]) => { const chunkIds = rawChunkIds ? Array.from(rawChunkIds.matchAll(Webpack.ChunkIdsRegex)).map(m => Number(m[1])) : []; diff --git a/src/plugins/_api/memberListDecorators.ts b/src/plugins/_api/memberListDecorators.ts index 5e3e5ed18..0dba3608f 100644 --- a/src/plugins/_api/memberListDecorators.ts +++ b/src/plugins/_api/memberListDecorators.ts @@ -31,7 +31,7 @@ export default definePlugin({ match: /let\{[^}]*lostPermissionTooltipText:\i[^}]*\}=(\i),/, replace: "$&vencordProps=$1," }, { - match: /\.Messages\.GUILD_OWNER(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/, + match: /#{intl::GUILD_OWNER}(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/, replace: "$&...(typeof vencordProps=='undefined'?[]:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps))," } ] diff --git a/src/plugins/_api/messageAccessories.ts b/src/plugins/_api/messageAccessories.ts index a98fdb32b..0ba2a031d 100644 --- a/src/plugins/_api/messageAccessories.ts +++ b/src/plugins/_api/messageAccessories.ts @@ -25,7 +25,7 @@ export default definePlugin({ authors: [Devs.Cyn], patches: [ { - find: ".Messages.REMOVE_ATTACHMENT_BODY", + find: "#{intl::REMOVE_ATTACHMENT_BODY}", replacement: { match: /(?<=.container\)?,children:)(\[.+?\])/, replace: "Vencord.Api.MessageAccessories._modifyAccessories($1,this.props)", diff --git a/src/plugins/_api/messageDecorations.ts b/src/plugins/_api/messageDecorations.ts index b41ec0be9..fb63a6dde 100644 --- a/src/plugins/_api/messageDecorations.ts +++ b/src/plugins/_api/messageDecorations.ts @@ -27,7 +27,7 @@ export default definePlugin({ { find: '"Message Username"', replacement: { - match: /\.Messages\.GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE.+?}\),\i(?=\])/, + match: /#{intl::GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE}.+?}\),\i(?=\])/, replace: "$&,...Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])" } } diff --git a/src/plugins/_api/messageEvents.ts b/src/plugins/_api/messageEvents.ts index 0347d5445..0101b02c8 100644 --- a/src/plugins/_api/messageEvents.ts +++ b/src/plugins/_api/messageEvents.ts @@ -25,7 +25,7 @@ export default definePlugin({ authors: [Devs.Arjix, Devs.hunt, Devs.Ven], patches: [ { - find: ".Messages.EDIT_TEXTAREA_HELP", + find: "#{intl::EDIT_TEXTAREA_HELP}", replacement: { match: /(?<=,channel:\i\}\)\.then\().+?(?=return \i\.content!==this\.props\.message\.content&&\i\((.+?)\))/, replace: (match, args) => "" + diff --git a/src/plugins/_api/messagePopover.ts b/src/plugins/_api/messagePopover.ts index 57b9b1193..21e5accde 100644 --- a/src/plugins/_api/messagePopover.ts +++ b/src/plugins/_api/messagePopover.ts @@ -24,9 +24,9 @@ export default definePlugin({ description: "API to add buttons to message popovers.", authors: [Devs.KingFish, Devs.Ven, Devs.Nuckyz], patches: [{ - find: "Messages.MESSAGE_UTILITIES_A11Y_LABEL", + find: "#{intl::MESSAGE_UTILITIES_A11Y_LABEL}", replacement: { - match: /\.jsx\)\((\i\.\i),\{label:\i\.\i\.Messages\.MESSAGE_ACTION_REPLY.{0,200}?"reply-self".{0,50}?\}\):null(?=,.+?message:(\i))/, + match: /\.jsx\)\((\i\.\i),\{label:\i\.\i\.string\(\i\.\i#{intl::MESSAGE_ACTION_REPLY}.{0,200}?"reply-self".{0,50}?\}\):null(?=,.+?message:(\i))/, replace: "$&,Vencord.Api.MessagePopover._buildPopoverElements($1,$2)" } }], diff --git a/src/plugins/_api/serverList.ts b/src/plugins/_api/serverList.ts index 7904e78b0..dfd40de74 100644 --- a/src/plugins/_api/serverList.ts +++ b/src/plugins/_api/serverList.ts @@ -25,16 +25,16 @@ export default definePlugin({ description: "Api required for plugins that modify the server list", patches: [ { - find: "Messages.DISCODO_DISABLED", + find: "#{intl::DISCODO_DISABLED}", replacement: { - match: /(?<=Messages\.DISCODO_DISABLED.+?return)(\(.{0,75}?tutorialContainer.+?}\))(?=}function)/, + match: /(?<=#{intl::DISCODO_DISABLED}.+?return)(\(.{0,75}?tutorialContainer.+?}\))(?=}function)/, replace: "[$1].concat(Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.Above))" } }, { - find: "Messages.SERVERS,children", + find: "#{intl::SERVERS}),children", replacement: { - match: /(?<=Messages\.SERVERS,children:)\i\.map\(\i\)/, + match: /(?<=#{intl::SERVERS}\),children:)\i\.map\(\i\)/, replace: "Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.In).concat($&)" } } diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index ffaea15bc..a94e8cfaf 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -25,8 +25,9 @@ import ThemesTab from "@components/VencordSettings/ThemesTab"; import UpdaterTab from "@components/VencordSettings/UpdaterTab"; import VencordTab from "@components/VencordSettings/VencordTab"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; -import { i18n, React } from "@webpack/common"; +import { React } from "@webpack/common"; import gitHash from "~git-hash"; @@ -70,7 +71,7 @@ export default definePlugin({ ] }, { - find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", + find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}", replacement: { match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.\i\).*?(\i\.\i)\.open\()/, replace: "$2.open($1);return;" @@ -150,11 +151,12 @@ export default definePlugin({ try { const names = { - top: i18n.Messages.USER_SETTINGS, - aboveNitro: i18n.Messages.BILLING_SETTINGS, - belowNitro: i18n.Messages.APP_SETTINGS, - aboveActivity: i18n.Messages.ACTIVITY_SETTINGS + top: getIntlMessage("USER_SETTINGS"), + aboveNitro: getIntlMessage("BILLING_SETTINGS"), + belowNitro: getIntlMessage("APP_SETTINGS"), + aboveActivity: getIntlMessage("ACTIVITY_SETTINGS") }; + return header === names[settingsLocation]; } catch { return firstChild === "PREMIUM"; diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index cb8d1d056..1b9ce162b 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -147,9 +147,9 @@ export default definePlugin({ settings, patches: [{ - find: ".BEGINNING_DM.format", + find: "#{intl::BEGINNING_DM}", replacement: { - match: /BEGINNING_DM\.format\(\{.+?\}\),(?=.{0,300}(\i)\.isMultiUserDM)/, + match: /#{intl::BEGINNING_DM},{.+?}\),(?=.{0,300}(\i)\.isMultiUserDM)/, replace: "$& $self.renderContributorDmWarningCard({ channel: $1 })," } }], diff --git a/src/plugins/accountPanelServerProfile/index.tsx b/src/plugins/accountPanelServerProfile/index.tsx index fe5df48ad..fcecffb17 100644 --- a/src/plugins/accountPanelServerProfile/index.tsx +++ b/src/plugins/accountPanelServerProfile/index.tsx @@ -69,7 +69,7 @@ export default definePlugin({ patches: [ { - find: ".Messages.ACCOUNT_SPEAKING_WHILE_MUTED", + find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}", group: true, replacement: [ { diff --git a/src/plugins/alwaysAnimate/index.ts b/src/plugins/alwaysAnimate/index.ts index 20cb4f974..97593990c 100644 --- a/src/plugins/alwaysAnimate/index.ts +++ b/src/plugins/alwaysAnimate/index.ts @@ -41,7 +41,7 @@ export default definePlugin({ }, { // Status emojis - find: ".Messages.GUILD_OWNER,", + find: "#{intl::GUILD_OWNER}", replacement: { match: /(?<=\.activityEmoji,.+?animate:)\i/, replace: "!0" diff --git a/src/plugins/anonymiseFileNames/index.tsx b/src/plugins/anonymiseFileNames/index.tsx index 0e97bc7f8..21f4e5c8a 100644 --- a/src/plugins/anonymiseFileNames/index.tsx +++ b/src/plugins/anonymiseFileNames/index.tsx @@ -86,9 +86,9 @@ export default definePlugin({ } }, { - find: ".Messages.ATTACHMENT_UTILITIES_SPOILER", + find: "#{intl::ATTACHMENT_UTILITIES_SPOILER}", replacement: { - match: /(?<=children:\[)(?=.{10,80}tooltip:.{0,100}\i\.\i\.Messages\.ATTACHMENT_UTILITIES_SPOILER)/, + match: /(?<=children:\[)(?=.{10,80}tooltip:.{0,100}#{intl::ATTACHMENT_UTILITIES_SPOILER})/, replace: "arguments[0].canEdit!==false?$self.renderIcon(arguments[0]):null," }, }, diff --git a/src/plugins/banger/index.ts b/src/plugins/banger/index.ts index eca80f9ee..f13fd3515 100644 --- a/src/plugins/banger/index.ts +++ b/src/plugins/banger/index.ts @@ -36,7 +36,7 @@ export default definePlugin({ settings, patches: [ { - find: "BAN_CONFIRM_TITLE.", + find: "#{intl::BAN_CONFIRM_TITLE}", replacement: { match: /src:\i\("?\d+"?\)/g, replace: "src:$self.source" diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index bb1a67ebb..50dee4f56 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -18,9 +18,10 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findLazy, findStoreLazy } from "@webpack"; -import { FluxDispatcher, i18n, useMemo } from "@webpack/common"; +import { FluxDispatcher, useMemo } from "@webpack/common"; import FolderSideBar from "./FolderSideBar"; @@ -172,7 +173,7 @@ export default definePlugin({ // Disable expanding and collapsing folders transition in the normal GuildsBar sidebar { predicate: () => !settings.store.keepIcons, - match: /(?<=\.Messages\.SERVER_FOLDER_PLACEHOLDER.+?useTransition\)\()/, + match: /(?<=#{intl::SERVER_FOLDER_PLACEHOLDER}.+?useTransition\)\()/, replace: "$self.shouldShowTransition(arguments[0])&&" }, // If we are rendering the normal GuildsBar sidebar, we avoid rendering guilds from folders that are expanded @@ -205,7 +206,7 @@ export default definePlugin({ } }, { - find: ".Messages.DISCODO_DISABLED", + find: "#{intl::DISCODO_DISABLED}", predicate: () => settings.store.closeAllHomeButton, replacement: { // Close all folders when clicking the home button @@ -274,12 +275,16 @@ export default definePlugin({ }, makeGuildsBarGuildListFilter(isBetterFolders: boolean) { - return child => { - if (isBetterFolders) { - return child?.props?.["aria-label"] === i18n.Messages.SERVERS; - } + try { + return child => { + if (isBetterFolders) { + return child?.props?.["aria-label"] === getIntlMessage("SERVERS"); + } + return true; + }; + } catch { return true; - }; + } }, makeGuildsBarTreeFilter(isBetterFolders: boolean) { diff --git a/src/plugins/betterGifAltText/index.ts b/src/plugins/betterGifAltText/index.ts index 55fa22525..5d9b188ea 100644 --- a/src/plugins/betterGifAltText/index.ts +++ b/src/plugins/betterGifAltText/index.ts @@ -34,9 +34,9 @@ export default definePlugin({ }, }, { - find: ".Messages.GIF,", + find: "#{intl::GIF}", replacement: { - match: /alt:(\i)=(\i\.\i\.Messages\.GIF)(?=,[^}]*\}=(\i))/, + match: /alt:(\i)=(\i\.\i\.string\(\i\.\i#{intl::GIF}\))(?=,[^}]*\}=(\i))/, replace: // rename prop so we can always use default value "alt_$$:$1=$self.altify($3)||$2", diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index 63fcf6477..68aa70c61 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -63,9 +63,9 @@ export default definePlugin({ } }, { - find: "Messages.NOTE_PLACEHOLDER", + find: "#{intl::NOTE_PLACEHOLDER}", replacement: { - match: /\.NOTE_PLACEHOLDER,/, + match: /#{intl::NOTE_PLACEHOLDER}\),/, replace: "$&spellCheck:!$self.noSpellCheck," } } diff --git a/src/plugins/betterRoleDot/index.ts b/src/plugins/betterRoleDot/index.ts index a8cadd8b0..3a8a14567 100644 --- a/src/plugins/betterRoleDot/index.ts +++ b/src/plugins/betterRoleDot/index.ts @@ -47,7 +47,7 @@ export default definePlugin({ }, { - find: ".ADD_ROLE_A11Y_LABEL", + find: "#{intl::ADD_ROLE_A11Y_LABEL}", all: true, predicate: () => Settings.plugins.BetterRoleDot.copyRoleColorInProfilePopout && !Settings.plugins.BetterRoleDot.bothStyles, noWarn: true, diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index 598e01042..9347c398c 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -60,7 +60,7 @@ export default definePlugin({ patches: [ { - find: "Messages.AUTH_SESSIONS_SESSION_LOG_OUT", + find: "#{intl::AUTH_SESSIONS_SESSION_LOG_OUT}", replacement: [ // Replace children with a single label with state { diff --git a/src/plugins/betterSettings/PluginsSubmenu.tsx b/src/plugins/betterSettings/PluginsSubmenu.tsx index b22f82a67..ad7ded307 100644 --- a/src/plugins/betterSettings/PluginsSubmenu.tsx +++ b/src/plugins/betterSettings/PluginsSubmenu.tsx @@ -5,8 +5,9 @@ */ import { openPluginModal } from "@components/PluginSettings/PluginModal"; +import { getIntlMessage } from "@utils/discord"; import { isObjectEmpty } from "@utils/misc"; -import { Alerts, i18n, Menu, useMemo, useState } from "@webpack/common"; +import { Alerts, Menu, useMemo, useState } from "@webpack/common"; import Plugins from "~plugins"; @@ -48,7 +49,7 @@ export default function PluginsSubmenu() { query={query} onChange={setQuery} ref={ref} - placeholder={i18n.Messages.SEARCH} + placeholder={getIntlMessage("SEARCH")} /> )} /> diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index f0dd89a7a..2cee85695 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -7,10 +7,11 @@ import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { waitFor } from "@webpack"; -import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common"; +import { ComponentDispatch, FocusLock, Menu, useEffect, useRef } from "@webpack/common"; import type { HTMLAttributes, ReactElement } from "react"; import PluginsSubmenu from "./PluginsSubmenu"; @@ -111,7 +112,7 @@ export default definePlugin({ predicate: () => settings.store.disableFade }, { // Load menu TOC eagerly - find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format", + find: "#{intl::USER_SETTINGS_WITH_BUILD_OVERRIDE}", replacement: { match: /(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?null!=\i&&.{0,100}?(await Promise\.all[^};]*?\)\)).*?,(?=\1\(this)/, replace: "$&(async ()=>$2)()," @@ -119,7 +120,7 @@ export default definePlugin({ predicate: () => settings.store.eagerLoad }, { // Settings cog context menu - find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", + find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}", replacement: [ { match: /(EXPERIMENTS:.+?)(\(0,\i.\i\)\(\))(?=\.filter\(\i=>\{let\{section:\i\}=)/, @@ -159,7 +160,7 @@ export default definePlugin({ if (item.section === "HEADER") { items.push({ label: item.label, items: [] }); } else if (item.section === "DIVIDER") { - items.push({ label: i18n.Messages.OTHER_OPTIONS, items: [] }); + items.push({ label: getIntlMessage("OTHER_OPTIONS"), items: [] }); } else { items.at(-1)!.items.push(item); } diff --git a/src/plugins/clientTheme/index.tsx b/src/plugins/clientTheme/index.tsx index 59f3d5fe2..7e6484276 100644 --- a/src/plugins/clientTheme/index.tsx +++ b/src/plugins/clientTheme/index.tsx @@ -14,7 +14,7 @@ import definePlugin, { OptionType, StartAt } from "@utils/types"; import { findByCodeLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; import { Button, Forms, ThemeStore, useStateFromStores } from "@webpack/common"; -const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); +const ColorPicker = findComponentByCodeLazy("#{intl::USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR}", ".BACKGROUND_PRIMARY)"); const colorPresets = [ "#1E1514", "#172019", "#13171B", "#1C1C28", "#402D2D", diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index 2fdf87356..f10335e3c 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -18,6 +18,7 @@ import { Devs } from "@utils/constants"; import { getCurrentChannel, getCurrentGuild } from "@utils/discord"; +import { runtimeHashMessageKey } from "@utils/intlHash"; import { SYM_LAZY_CACHED, SYM_LAZY_GET } from "@utils/lazy"; import { relaunch } from "@utils/native"; import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches"; @@ -104,6 +105,7 @@ function makeShortcuts() { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement, + runtimeHashMessageKey, fakeRender: (component: ComponentType, props: any) => { const prevWin = fakeRenderWin?.deref(); const win = prevWin?.closed === false diff --git a/src/plugins/copyFileContents/index.tsx b/src/plugins/copyFileContents/index.tsx index 13b649174..28b5bb92d 100644 --- a/src/plugins/copyFileContents/index.tsx +++ b/src/plugins/copyFileContents/index.tsx @@ -25,7 +25,7 @@ export default definePlugin({ authors: [Devs.Obsidian, Devs.Nuckyz], patches: [ { - find: ".Messages.PREVIEW_BYTES_LEFT.format(", + find: "#{intl::PREVIEW_BYTES_LEFT}", replacement: { match: /\.footerGap.+?url:\i,fileName:\i,fileSize:\i}\),(?<=fileContents:(\i),bytesLeft:(\i).+?)/g, replace: "$&$self.addCopyButton({fileContents:$1,bytesLeft:$2})," diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index 221b115f6..f6bc2c8b0 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -67,7 +67,7 @@ export default definePlugin({ patches: [ { - find: ".Messages.ERRORS_UNEXPECTED_CRASH", + find: "#{intl::ERRORS_UNEXPECTED_CRASH}", replacement: { match: /this\.setState\((.+?)\)/, replace: "$self.handleCrash(this,$1);" diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx index 33d1d40b7..69a7a1a59 100644 --- a/src/plugins/decor/index.tsx +++ b/src/plugins/decor/index.tsx @@ -41,7 +41,7 @@ export default definePlugin({ { find: "DefaultCustomizationSections", replacement: { - match: /(?<=USER_SETTINGS_AVATAR_DECORATION},"decoration"\),)/, + match: /(?<=#{intl::USER_SETTINGS_AVATAR_DECORATION}\)},"decoration"\),)/, replace: "$self.DecorSection()," } }, diff --git a/src/plugins/decor/ui/components/DecorationGridCreate.tsx b/src/plugins/decor/ui/components/DecorationGridCreate.tsx index 7699b23d9..09572041a 100644 --- a/src/plugins/decor/ui/components/DecorationGridCreate.tsx +++ b/src/plugins/decor/ui/components/DecorationGridCreate.tsx @@ -5,7 +5,8 @@ */ import { PlusIcon } from "@components/Icons"; -import { i18n, Text } from "@webpack/common"; +import { getIntlMessage } from "@utils/discord"; +import { Text } from "@webpack/common"; import { HTMLProps } from "react"; import { DecorationGridItem } from "."; @@ -24,7 +25,7 @@ export default function DecorationGridCreate(props: DecorationGridCreateProps) { variant="text-xs/normal" color="header-primary" > - {i18n.Messages.CREATE} + {getIntlMessage("CREATE")} ; } diff --git a/src/plugins/decor/ui/components/DecorationGridNone.tsx b/src/plugins/decor/ui/components/DecorationGridNone.tsx index b6114c674..81ebde0bd 100644 --- a/src/plugins/decor/ui/components/DecorationGridNone.tsx +++ b/src/plugins/decor/ui/components/DecorationGridNone.tsx @@ -5,7 +5,8 @@ */ import { NoEntrySignIcon } from "@components/Icons"; -import { i18n, Text } from "@webpack/common"; +import { getIntlMessage } from "@utils/discord"; +import { Text } from "@webpack/common"; import { HTMLProps } from "react"; import { DecorationGridItem } from "."; @@ -24,7 +25,7 @@ export default function DecorationGridNone(props: DecorationGridNoneProps) { variant="text-xs/normal" color="header-primary" > - {i18n.Messages.NONE} + {getIntlMessage("NONE")} ; } diff --git a/src/plugins/disableCallIdle/index.ts b/src/plugins/disableCallIdle/index.ts index c36fce6ca..82ab56f2c 100644 --- a/src/plugins/disableCallIdle/index.ts +++ b/src/plugins/disableCallIdle/index.ts @@ -27,7 +27,7 @@ export default definePlugin({ authors: [Devs.Nuckyz], patches: [ { - find: ".Messages.BOT_CALL_IDLE_DISCONNECT", + find: "#{intl::BOT_CALL_IDLE_DISCONNECT_2}", replacement: { match: /,?(?=\i\(this,"idleTimeout",new \i\.\i\))/, replace: ";return;" diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index ca348c614..087bb5551 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -285,7 +285,7 @@ export default definePlugin({ }, // Remove boost requirements to stream with high quality { - find: "STREAM_FPS_OPTION.format", + find: "#{intl::STREAM_FPS_OPTION}", predicate: () => settings.store.enableStreamQualityBypass, replacement: { match: /guildPremiumTier:\i\.\i\.TIER_\d,?/g, @@ -356,7 +356,7 @@ export default definePlugin({ ] }, { - find: ".Messages.STICKER_POPOUT_UNJOINED_PRIVATE_GUILD_DESCRIPTION.format", + find: "#{intl::STICKER_POPOUT_UNJOINED_PRIVATE_GUILD_DESCRIPTION}", predicate: () => settings.store.transformStickers, replacement: [ { @@ -381,7 +381,7 @@ export default definePlugin({ } }, { - find: ".Messages.EMOJI_POPOUT_UNJOINED_DISCOVERABLE_GUILD_DESCRIPTION", + find: "#{intl::EMOJI_POPOUT_UNJOINED_DISCOVERABLE_GUILD_DESCRIPTION}", predicate: () => settings.store.transformEmojis, replacement: { // Add the fake nitro emoji notice diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index 708c961aa..bfd1cb993 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -108,10 +108,10 @@ interface ProfileModalProps { isTryItOutFlow: boolean; } -const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); +const ColorPicker = findComponentByCodeLazy("#{intl::USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR}", ".BACKGROUND_PRIMARY)"); const ProfileModal = findComponentByCodeLazy("isTryItOutFlow:", "pendingThemeColors:", "pendingAvatarDecoration:", "EDIT_PROFILE_BANNER"); -const requireColorPicker = extractAndLoadChunksLazy(["USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format"], /createPromise:\(\)=>\i\.\i(\("?.+?"?\)).then\(\i\.bind\(\i,"?(.+?)"?\)\)/); +const requireColorPicker = extractAndLoadChunksLazy(["#{intl::USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON}"], /createPromise:\(\)=>\i\.\i(\("?.+?"?\)).then\(\i\.bind\(\i,"?(.+?)"?\)\)/); export default definePlugin({ name: "FakeProfileThemes", @@ -126,9 +126,9 @@ export default definePlugin({ } }, { - find: ".USER_SETTINGS_RESET_PROFILE_THEME", + find: "#{intl::USER_SETTINGS_RESET_PROFILE_THEME}", replacement: { - match: /RESET_PROFILE_THEME}\)(?<=color:(\i),.{0,500}?color:(\i),.{0,500}?)/, + match: /#{intl::USER_SETTINGS_RESET_PROFILE_THEME}\)}\)(?<=color:(\i),.{0,500}?color:(\i),.{0,500}?)/, replace: "$&,$self.addCopy3y3Button({primary:$1,accent:$2})" } } diff --git a/src/plugins/forceOwnerCrown/index.ts b/src/plugins/forceOwnerCrown/index.ts index 444bfab34..b21de4891 100644 --- a/src/plugins/forceOwnerCrown/index.ts +++ b/src/plugins/forceOwnerCrown/index.ts @@ -27,7 +27,7 @@ export default definePlugin({ authors: [Devs.D3SOX, Devs.Nickyux], patches: [ { - find: ".Messages.GUILD_OWNER,", + find: "#{intl::GUILD_OWNER}", replacement: { match: /,isOwner:(\i),/, replace: ",_isOwner:$1=$self.isGuildOwner(e)," diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index cb5634c8e..0f4016ad6 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -26,7 +26,7 @@ export default definePlugin({ { find: ".PANEL}),nicknameIcons", replacement: { - match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id)}\)}\)/, + match: /#{intl::USER_PROFILE_MEMBER_SINCE}\),.{0,100}userId:(\i\.id)}\)}\)/, replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:true})" } }, @@ -34,7 +34,7 @@ export default definePlugin({ { find: "action:\"PRESS_APP_CONNECTION\"", replacement: { - match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id),.{0,100}}\)}\),/, + match: /#{intl::USER_PROFILE_MEMBER_SINCE}\),.{0,100}userId:(\i\.id),.{0,100}}\)}\),/, replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:false})," } } diff --git a/src/plugins/fullSearchContext/index.tsx b/src/plugins/fullSearchContext/index.tsx index 193e69f1a..3f9e82109 100644 --- a/src/plugins/fullSearchContext/index.tsx +++ b/src/plugins/fullSearchContext/index.tsx @@ -19,10 +19,11 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import { NoopComponent } from "@utils/react"; import definePlugin from "@utils/types"; import { filters, findByPropsLazy, waitFor } from "@webpack"; -import { ChannelStore, ContextMenuApi, i18n, UserStore } from "@webpack/common"; +import { ChannelStore, ContextMenuApi, UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; const { useMessageMenu } = findByPropsLazy("useMessageMenu"); @@ -41,7 +42,7 @@ function MessageMenu({ message, channel, onHeightUpdate }) { return useMessageMenu({ navId: "message-actions", - ariaLabel: i18n.Messages.MESSAGE_UTILITIES_A11Y_LABEL, + ariaLabel: getIntlMessage("MESSAGE_UTILITIES_A11Y_LABEL"), message, channel, @@ -72,7 +73,7 @@ const contextMenuPatch: NavContextMenuPatchCallback = (children, props: MessageA const group = findGroupChildrenByChildId("devmode-copy-id", children, true); group?.push( - CopyIdMenuItem({ id: props.message.author.id, label: i18n.Messages.COPY_ID_AUTHOR }) + CopyIdMenuItem({ id: props.message.author.id, label: getIntlMessage("COPY_ID_AUTHOR") }) ); }; diff --git a/src/plugins/gameActivityToggle/index.tsx b/src/plugins/gameActivityToggle/index.tsx index 7aeb470d6..32d72fdbf 100644 --- a/src/plugins/gameActivityToggle/index.tsx +++ b/src/plugins/gameActivityToggle/index.tsx @@ -92,7 +92,7 @@ export default definePlugin({ patches: [ { - find: ".Messages.ACCOUNT_SPEAKING_WHILE_MUTED", + find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}", replacement: { match: /this\.renderNameZone\(\).+?children:\[/, replace: "$&$self.GameActivityToggleButton()," diff --git a/src/plugins/greetStickerPicker/index.tsx b/src/plugins/greetStickerPicker/index.tsx index 438fa40c6..3ab5fca41 100644 --- a/src/plugins/greetStickerPicker/index.tsx +++ b/src/plugins/greetStickerPicker/index.tsx @@ -166,7 +166,7 @@ export default definePlugin({ patches: [ { - find: "Messages.WELCOME_CTA_LABEL", + find: "#{intl::WELCOME_CTA_LABEL}", replacement: { match: /innerClassName:\i\.welcomeCTAButton,(?<={channel:\i,message:\i}=(\i).{0,400}?)/, replace: "$&onContextMenu:(vcEvent)=>$self.pickSticker(vcEvent, $1)," diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx index 19f22e61d..fac83687d 100644 --- a/src/plugins/ignoreActivities/index.tsx +++ b/src/plugins/ignoreActivities/index.tsx @@ -260,9 +260,9 @@ export default definePlugin({ } }, { - find: ".Messages.SETTINGS_GAMES_TOGGLE_OVERLAY", + find: "#{intl::SETTINGS_GAMES_TOGGLE_OVERLAY}", replacement: { - match: /\.Messages\.SETTINGS_GAMES_TOGGLE_OVERLAY.+?}\(\),(?<={overlay:\i,.+?=(\i),.+?)(?=!(\i))/, + match: /#{intl::SETTINGS_GAMES_TOGGLE_OVERLAY}.+?}\(\),(?<={overlay:\i,.+?=(\i),.+?)(?=!(\i))/, replace: (m, props, nowPlaying) => `${m}$self.renderToggleGameActivityButton(${props},${nowPlaying}),` } }, diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 7fefb39b8..1cde814e7 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -32,7 +32,7 @@ export default definePlugin({ patches: [ // Counts header { - find: ".FRIENDS_ALL_HEADER", + find: "#{intl::FRIENDS_ALL_HEADER}", replacement: { match: /toString\(\)\}\);case (\i\.\i)\.BLOCKED/, replace: 'toString()});case $1.IMPLICIT:return "Implicit — "+arguments[1];case $1.BLOCKED' @@ -48,9 +48,9 @@ export default definePlugin({ }, // Sections header { - find: ".FRIENDS_SECTION_ONLINE", + find: "#{intl::FRIENDS_SECTION_ONLINE}", replacement: { - match: /(\(0,\i\.jsx\)\(\i\.TabBar\.Item,\{id:\i\.\i)\.BLOCKED,className:([^\s]+?)\.item,children:\i\.\i\.Messages\.BLOCKED\}\)/, + match: /(\(0,\i\.jsx\)\(\i\.TabBar\.Item,\{id:\i\.\i)\.BLOCKED,className:([^\s]+?)\.item,children:\i\.\i\.string\(\i\.\i#{intl::BLOCKED}\)\}\)/, replace: "$1.IMPLICIT,className:$2.item,children:\"Implicit\"}),$&" }, }, @@ -117,7 +117,7 @@ export default definePlugin({ wrapSort(comparator: Function, row: any) { return row.type === 5 - ? -UserAffinitiesStore.getUserAffinity(row.user.id)?.affinity ?? 0 + ? -(UserAffinitiesStore.getUserAffinity(row.user.id)?.affinity ?? 0) : comparator(row); }, diff --git a/src/plugins/invisibleChat.desktop/index.tsx b/src/plugins/invisibleChat.desktop/index.tsx index c7eb29e7e..1af8f4e5d 100644 --- a/src/plugins/invisibleChat.desktop/index.tsx +++ b/src/plugins/invisibleChat.desktop/index.tsx @@ -111,7 +111,7 @@ export default definePlugin({ patches: [ { // Indicator - find: ".Messages.MESSAGE_EDITED,", + find: "#{intl::MESSAGE_EDITED}", replacement: { match: /let\{className:\i,message:\i[^}]*\}=(\i)/, replace: "try {$1 && $self.INV_REGEX.test($1.message.content) ? $1.content.push($self.indicator()) : null } catch {};$&" diff --git a/src/plugins/keepCurrentChannel/index.ts b/src/plugins/keepCurrentChannel/index.ts index 1e0e742dc..92a389eb4 100644 --- a/src/plugins/keepCurrentChannel/index.ts +++ b/src/plugins/keepCurrentChannel/index.ts @@ -19,7 +19,7 @@ import * as DataStore from "@api/DataStore"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { ChannelRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common"; +import { ChannelRouter, ChannelStore, NavigationRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common"; export interface LogoutEvent { type: "LOGOUT"; @@ -45,6 +45,16 @@ export default definePlugin({ description: "Attempt to navigate to the channel you were in before switching accounts or loading Discord.", authors: [Devs.Nuckyz], + patches: [ + { + find: '"Switching accounts"', + replacement: { + match: /goHomeAfterSwitching:\i/, + replace: "goHomeAfterSwitching:!1" + } + } + ], + flux: { LOGOUT(e: LogoutEvent) { ({ isSwitchingAccount } = e); @@ -55,7 +65,11 @@ export default definePlugin({ isSwitchingAccount = false; if (previousCache?.channelId) { - ChannelRouter.transitionToChannel(previousCache.channelId); + if (ChannelStore.hasChannel(previousCache.channelId)) { + ChannelRouter.transitionToChannel(previousCache.channelId); + } else { + NavigationRouter.transitionToGuild("@me"); + } } }, diff --git a/src/plugins/loadingQuotes/index.ts b/src/plugins/loadingQuotes/index.ts index 7d85cc90b..9bfc88a73 100644 --- a/src/plugins/loadingQuotes/index.ts +++ b/src/plugins/loadingQuotes/index.ts @@ -62,7 +62,7 @@ export default definePlugin({ patches: [ { - find: ".LOADING_DID_YOU_KNOW", + find: "#{intl::LOADING_DID_YOU_KNOW}", replacement: [ { match: /"_loadingText".+?(?=(\i)\[.{0,10}\.random)/, diff --git a/src/plugins/memberCount/index.tsx b/src/plugins/memberCount/index.tsx index 85dcc4b2d..67bbc4ce8 100644 --- a/src/plugins/memberCount/index.tsx +++ b/src/plugins/memberCount/index.tsx @@ -74,7 +74,7 @@ export default definePlugin({ { find: ".invitesDisabledTooltip", replacement: { - match: /\.VIEW_AS_ROLES_MENTIONS_WARNING.{0,100}(?=])/, + match: /#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}.{0,100}(?=])/, replace: "$&,$self.renderTooltip(arguments[0].guild)" }, predicate: () => settings.store.toolTip diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index a08aeccce..3ee9f3fad 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -24,12 +24,13 @@ import { Settings } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy, findByPropsLazy } from "@webpack"; -import { ChannelStore, FluxDispatcher, i18n, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common"; +import { ChannelStore, FluxDispatcher, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common"; import { Message } from "discord-types/general"; import overlayStyle from "./deleteStyleOverlay.css?managed"; @@ -178,7 +179,7 @@ export default definePlugin({ isEdited={true} isInline={false} > - {" "}({i18n.Messages.MESSAGE_EDITED}) + {" "}({getIntlMessage("MESSAGE_EDITED")}) ))} @@ -445,7 +446,7 @@ export default definePlugin({ { // Message content renderer - find: "Messages.MESSAGE_EDITED,\")\"", + find: "#{intl::MESSAGE_EDITED}", replacement: [ { // Render editHistory in the deepest div for message content @@ -497,7 +498,7 @@ export default definePlugin({ }, { // Message group rendering - find: "Messages.NEW_MESSAGES_ESTIMATED_WITH_DATE", + find: "#{intl::NEW_MESSAGES_ESTIMATED_WITH_DATE}", replacement: [ { match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\|\|/, diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 7a56131a5..6c9102d81 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -19,6 +19,7 @@ import { definePluginSettings } from "@api/Settings"; import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy, findLazy } from "@webpack"; @@ -187,13 +188,13 @@ export default definePlugin({ } }, { - find: ".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP_OFFICIAL,", + find: "#{intl::DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP_OFFICIAL}", replacement: [ // make the tag show the right text { - match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=.{0,40}(\i\.\i\.Messages)\.APP_TAG/, - replace: (_, origSwitch, variant, tags, displayedText, strings) => - `${origSwitch}default:{${displayedText} = $self.getTagText(${tags}[${variant}], ${strings})}` + match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=(.{0,40}#{intl::APP_TAG}\))/, + replace: (_, origSwitch, variant, tags, displayedText, originalText) => + `${origSwitch}default:{${displayedText} = $self.getTagText(${tags}[${variant}],${originalText})}` }, // show OP tags correctly { @@ -217,7 +218,7 @@ export default definePlugin({ }, // in the member list { - find: ".Messages.GUILD_OWNER,", + find: "#{intl::GUILD_OWNER}", replacement: { match: /(?\i)=\(null==.{0,100}\.BOT;return null!=(?\i)&&\i\.bot/, replace: "$ = $self.getTag({user: $, channel: arguments[0].channel, origType: $.bot ? 0 : null, location: 'not-chat' }); return typeof $ === 'number'" @@ -232,7 +233,7 @@ export default definePlugin({ } }, { - find: ".Messages.USER_PROFILE_PRONOUNS", + find: "#{intl::USER_PROFILE_PRONOUNS}", replacement: { match: /(?=,hideBotTag:!0)/, replace: ",moreTags_channelId:arguments[0].moreTags_channelId" @@ -295,21 +296,25 @@ export default definePlugin({ isOPTag: (tag: number) => tag === Tag.Types.ORIGINAL_POSTER || tags.some(t => tag === Tag.Types[`${t.name}-OP`]), - getTagText(passedTagName: string, strings: Record) { - if (!passedTagName) return strings.APP_TAG; - const [tagName, variant] = passedTagName.split("-"); - const tag = tags.find(({ name }) => tagName === name); - if (!tag) return strings.APP_TAG; - if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return strings.APP_TAG; + getTagText(passedTagName: string, originalText: string) { + try { + const [tagName, variant] = passedTagName.split("-"); + if (!passedTagName) return getIntlMessage("APP_TAG"); + const tag = tags.find(({ name }) => tagName === name); + if (!tag) return getIntlMessage("APP_TAG"); + if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return getIntlMessage("APP_TAG"); - const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; - switch (variant) { - case "OP": - return `${strings.BOT_TAG_FORUM_ORIGINAL_POSTER} • ${tagText}`; - case "BOT": - return `${strings.APP_TAG} • ${tagText}`; - default: - return tagText; + const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; + switch (variant) { + case "OP": + return `${getIntlMessage("BOT_TAG_FORUM_ORIGINAL_POSTER")} • ${tagText}`; + case "BOT": + return `${getIntlMessage("APP_TAG")} • ${tagText}`; + default: + return tagText; + } + } catch { + return originalText; } }, diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index d3b37b026..7884aa29c 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -37,7 +37,7 @@ export default definePlugin({ authors: [Devs.rushii, Devs.Samu], patches: [ { - find: "Messages.BLOCKED_MESSAGES_HIDE", + find: "#{intl::BLOCKED_MESSAGES_HIDE}", replacement: [ { match: /let\{[^}]*collapsedReason[^}]*\}/, diff --git a/src/plugins/noOnboardingDelay/index.ts b/src/plugins/noOnboardingDelay/index.ts index 6211e97c2..285109761 100644 --- a/src/plugins/noOnboardingDelay/index.ts +++ b/src/plugins/noOnboardingDelay/index.ts @@ -25,7 +25,7 @@ export default definePlugin({ authors: [Devs.nekohaxx], patches: [ { - find: "Messages.ONBOARDING_COVER_WELCOME_SUBTITLE", + find: "#{intl::ONBOARDING_COVER_WELCOME_SUBTITLE}", replacement: { match: "3e3", replace: "0" diff --git a/src/plugins/noUnblockToJump/index.ts b/src/plugins/noUnblockToJump/index.ts index cba6bb9aa..cde0e19e5 100644 --- a/src/plugins/noUnblockToJump/index.ts +++ b/src/plugins/noUnblockToJump/index.ts @@ -28,21 +28,21 @@ export default definePlugin({ { find: '.id,"Search Results"', replacement: { - match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}UNBLOCK_TO_JUMP_TITLE)/, + match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/, replace: "if(false)$1" } }, { find: "renderJumpButton()", replacement: { - match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}UNBLOCK_TO_JUMP_TITLE)/, + match: /if\(.{1,10}\)(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/, replace: "if(false)$1" } }, { find: "flash:!0,returnMessageId", replacement: { - match: /.\?(.{1,10}\.show\({.{1,50}UNBLOCK_TO_JUMP_TITLE)/, + match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/, replace: "false?$1" } } diff --git a/src/plugins/normalizeMessageLinks/index.ts b/src/plugins/normalizeMessageLinks/index.ts index cac36e65c..82076ef20 100644 --- a/src/plugins/normalizeMessageLinks/index.ts +++ b/src/plugins/normalizeMessageLinks/index.ts @@ -13,7 +13,7 @@ export default definePlugin({ authors: [Devs.bb010g], patches: [ { - find: ".Messages.COPY_MESSAGE_LINK,", + find: "#{intl::COPY_MESSAGE_LINK}", replacement: { match: /\.concat\(location\.host\)/, replace: ".concat($self.normalizeHost(location.host))", diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 666f0af8e..23b188bcb 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -18,8 +18,9 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import definePlugin from "@utils/types"; -import { Constants, GuildStore, i18n, RestAPI } from "@webpack/common"; +import { Constants, GuildStore, RestAPI } from "@webpack/common"; function showDisableInvites(guildId: string) { // @ts-ignore @@ -43,15 +44,15 @@ export default definePlugin({ patches: [ { - find: "Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION", + find: "#{intl::GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION}", group: true, replacement: [ { - match: /children:\i\.\i\.\i\.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION/, + match: /children:\i\.\i\.string\(\i\.\i#{intl::GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION}\)/, replace: "children: $self.renderInvitesLabel({guildId:arguments[0].guildId,setChecked})", }, { - match: /\.INVITES_DISABLED\)(?=.+?\.Messages\.INVITES_PERMANENTLY_DISABLED_TIP.+?checked:(\i)).+?\[\1,(\i)\]=\i.useState\(\i\)/, + match: /\.INVITES_DISABLED\)(?=.+?#{intl::INVITES_PERMANENTLY_DISABLED_TIP}.+?checked:(\i)).+?\[\1,(\i)\]=\i.useState\(\i\)/, replace: "$&,setChecked=$2" } ] @@ -61,7 +62,7 @@ export default definePlugin({ renderInvitesLabel: ErrorBoundary.wrap(({ guildId, setChecked }) => { return (
- {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {getIntlMessage("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION")} {showDisableInvites(guildId) && { setChecked(true); disableInvites(guildId); diff --git a/src/plugins/permissionFreeWill/index.ts b/src/plugins/permissionFreeWill/index.ts index 96e110b6a..c45cbff60 100644 --- a/src/plugins/permissionFreeWill/index.ts +++ b/src/plugins/permissionFreeWill/index.ts @@ -32,7 +32,7 @@ export default definePlugin({ patches: [ // Permission lockout, just set the check to true { - find: ".STAGE_CHANNEL_CANNOT_OVERWRITE_PERMISSION", + find: "#{intl::STAGE_CHANNEL_CANNOT_OVERWRITE_PERMISSION}", replacement: [ { match: /case"DENY":.{0,50}if\((?=\i\.\i\.can)/, @@ -43,7 +43,7 @@ export default definePlugin({ }, // Onboarding, same thing but we need to prevent the check { - find: ".ONBOARDING_CHANNEL_THRESHOLD_WARNING", + find: "#{intl::ONBOARDING_CHANNEL_THRESHOLD_WARNING}", replacement: [ { match: /{(\i:function\(\){return \i},?){2}}/, diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx index 82925d610..32dcaf8d6 100644 --- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx +++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx @@ -19,10 +19,10 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { InfoIcon, OwnerCrownIcon } from "@components/Icons"; -import { getUniqueUsername } from "@utils/discord"; +import { getIntlMessage, getUniqueUsername } from "@utils/discord"; import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { findByCodeLazy } from "@webpack"; -import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common"; +import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common"; import { UnicodeEmoji } from "@webpack/types"; import type { Guild, Role, User } from "discord-types/general"; @@ -216,7 +216,7 @@ function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: str > { Clipboard.copy(roleId); }} @@ -225,7 +225,7 @@ function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: str {(settings.store as any).unsafeViewAsRole && ( { const role = GuildStore.getRole(guild.id, roleId); if (!role) return; @@ -257,7 +257,7 @@ function UserContextMenu({ userId }: { userId: string; }) { > { Clipboard.copy(userId); }} diff --git a/src/plugins/permissionsViewer/components/UserPermissions.tsx b/src/plugins/permissionsViewer/components/UserPermissions.tsx index 7c0858f10..720445daa 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -18,9 +18,10 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { ExpandableHeader } from "@components/ExpandableHeader"; +import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import { filters, findBulk, proxyLazyWebpack } from "@webpack"; -import { i18n, PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common"; +import { PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common"; import type { Guild, GuildMember } from "discord-types/general"; import { PermissionsSortOrder, settings } from ".."; @@ -105,7 +106,7 @@ function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { g permissions: Object.values(PermissionsBits).reduce((prev, curr) => prev | curr, 0n) }); - const OWNER = i18n.Messages.GUILD_OWNER || "Server Owner"; + const OWNER = getIntlMessage("GUILD_OWNER") || "Server Owner"; userPermissions.push({ permission: OWNER, roleName: "Owner", diff --git a/src/plugins/permissionsViewer/index.tsx b/src/plugins/permissionsViewer/index.tsx index 7d6572df5..20b0b1910 100644 --- a/src/plugins/permissionsViewer/index.tsx +++ b/src/plugins/permissionsViewer/index.tsx @@ -170,7 +170,7 @@ export default definePlugin({ patches: [ { - find: ".VIEW_ALL_ROLES,", + find: "#{intl::VIEW_ALL_ROLES}", replacement: { match: /\.expandButton,.+?null,/, replace: "$&$self.ViewPermissionsButton(arguments[0])," diff --git a/src/plugins/permissionsViewer/utils.ts b/src/plugins/permissionsViewer/utils.ts index ac7537973..b2015840e 100644 --- a/src/plugins/permissionsViewer/utils.ts +++ b/src/plugins/permissionsViewer/utils.ts @@ -17,8 +17,9 @@ */ import { classNameFactory } from "@api/Styles"; +import { getIntlMessage } from "@utils/discord"; import { wordsToTitle } from "@utils/text"; -import { GuildStore, i18n, Parser } from "@webpack/common"; +import { GuildStore, Parser } from "@webpack/common"; import { Guild, GuildMember, Role } from "discord-types/general"; import type { ReactNode } from "react"; @@ -44,7 +45,7 @@ const PermissionKeyMap = { export function getPermissionString(permission: string) { permission = PermissionKeyMap[permission] || permission; - return i18n.Messages[permission] || + return getIntlMessage(permission) || // shouldn't get here but just in case formatPermissionWithoutMatchingString(permission); } @@ -58,7 +59,7 @@ export function getPermissionDescription(permission: string): ReactNode { else if (permission !== "STREAM") permission = PermissionKeyMap[permission] || permission; - const msg = i18n.Messages[`ROLE_PERMISSIONS_${permission}_DESCRIPTION`] as any; + const msg = getIntlMessage(`ROLE_PERMISSIONS_${permission}_DESCRIPTION`) as any; if (msg?.hasMarkdown) return Parser.parse(msg.message); diff --git a/src/plugins/pinDms/components/CreateCategoryModal.tsx b/src/plugins/pinDms/components/CreateCategoryModal.tsx index 2f1d4d1d5..7c4cf0d07 100644 --- a/src/plugins/pinDms/components/CreateCategoryModal.tsx +++ b/src/plugins/pinDms/components/CreateCategoryModal.tsx @@ -30,7 +30,7 @@ interface ColorPickerWithSwatchesProps { renderCustomButton?: () => React.ReactNode; } -const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); +const ColorPicker = findComponentByCodeLazy("#{intl::USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR}", ".BACKGROUND_PRIMARY)"); const ColorPickerWithSwatches = findExportedComponentLazy("ColorPicker", "CustomColorPicker"); export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\("?.+?"?\).+?\])\).then\(\i\.bind\(\i,"?(.+?)"?\)\).{0,50}"UserSettings"/); diff --git a/src/plugins/replyTimestamp/index.tsx b/src/plugins/replyTimestamp/index.tsx index b0a01addb..dc31dd883 100644 --- a/src/plugins/replyTimestamp/index.tsx +++ b/src/plugins/replyTimestamp/index.tsx @@ -67,7 +67,7 @@ export default definePlugin({ patches: [ { - find: ".REPLY_QUOTE_MESSAGE_BLOCKED", + find: "#{intl::REPLY_QUOTE_MESSAGE_BLOCKED}", replacement: { match: /\.onClickReply,.+?}\),(?=\i,\i,\i\])/, replace: "$&$self.ReplyTimestamp(arguments[0])," diff --git a/src/plugins/reverseImageSearch/index.tsx b/src/plugins/reverseImageSearch/index.tsx index 728156b2b..eb87240c6 100644 --- a/src/plugins/reverseImageSearch/index.tsx +++ b/src/plugins/reverseImageSearch/index.tsx @@ -108,7 +108,7 @@ export default definePlugin({ patches: [ { - find: ".Messages.MESSAGE_ACTIONS_MENU_LABEL,shouldHideMediaOptions", + find: "#{intl::MESSAGE_ACTIONS_MENU_LABEL}", replacement: { match: /favoriteableType:\i,(?<=(\i)\.getAttribute\("data-type"\).+?)/, replace: (m, target) => `${m}reverseImageSearchType:${target}.getAttribute("data-role"),` diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 108ed00c5..204bc0be3 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -104,7 +104,7 @@ export default definePlugin({ predicate: () => settings.store.memberList, }, { - find: ".Messages.THREAD_BROWSER_PRIVATE", + find: "#{intl::THREAD_BROWSER_PRIVATE}", replacement: [ { match: /children:\[\i," — ",\i\]/, @@ -132,7 +132,7 @@ export default definePlugin({ predicate: () => settings.store.reactorsList, }, { - find: '.Messages.MESSAGE_EDITED,")"', + find: "#{intl::MESSAGE_EDITED}", replacement: { match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/, replace: "style:{color:$self.useMessageColor($1)}," diff --git a/src/plugins/shikiCodeblocks.desktop/index.ts b/src/plugins/shikiCodeblocks.desktop/index.ts index e6676a866..1092f89a7 100644 --- a/src/plugins/shikiCodeblocks.desktop/index.ts +++ b/src/plugins/shikiCodeblocks.desktop/index.ts @@ -46,7 +46,7 @@ export default definePlugin({ } }, { - find: ".PREVIEW_NUM_LINES", + find: "#{intl::PREVIEW_NUM_LINES}", replacement: { match: /(?<=function \i\((\i)\)\{)(?=let\{text:\i,language:)/, replace: "return $self.renderHighlighter({lang:$1.language,content:$1.text});" diff --git a/src/plugins/showAllMessageButtons/index.ts b/src/plugins/showAllMessageButtons/index.ts index 44a5741cb..1d6890130 100644 --- a/src/plugins/showAllMessageButtons/index.ts +++ b/src/plugins/showAllMessageButtons/index.ts @@ -26,7 +26,7 @@ export default definePlugin({ patches: [ { - find: ".Messages.MESSAGE_UTILITIES_A11Y_LABEL", + find: "#{intl::MESSAGE_UTILITIES_A11Y_LABEL}", replacement: { match: /isExpanded:\i&&(.+?),/, replace: "isExpanded:$1," diff --git a/src/plugins/showConnections/VerifiedIcon.tsx b/src/plugins/showConnections/VerifiedIcon.tsx index ffdf21e63..d748f326c 100644 --- a/src/plugins/showConnections/VerifiedIcon.tsx +++ b/src/plugins/showConnections/VerifiedIcon.tsx @@ -16,11 +16,12 @@ * along with this program. If not, see . */ +import { getIntlMessage } from "@utils/discord"; import { findComponentByCodeLazy, findLazy } from "@webpack"; -import { i18n, useToken } from "@webpack/common"; +import { useToken } from "@webpack/common"; const ColorMap = findLazy(m => m.colors?.INTERACTIVE_MUTED?.css); -const VerifiedIconComponent = findComponentByCodeLazy(".CONNECTIONS_ROLE_OFFICIAL_ICON_TOOLTIP"); +const VerifiedIconComponent = findComponentByCodeLazy("#{intl::CONNECTIONS_ROLE_OFFICIAL_ICON_TOOLTIP}"); export function VerifiedIcon() { const color = useToken(ColorMap.colors.INTERACTIVE_MUTED).hex(); @@ -31,7 +32,7 @@ export function VerifiedIcon() { color={color} forcedIconColor={forcedIconColor} size={16} - tooltipText={i18n.Messages.CONNECTION_VERIFIED} + tooltipText={getIntlMessage("CONNECTION_VERIFIED")} /> ); } diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index bdb9fee8c..51c984b08 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -19,7 +19,7 @@ import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { formatDuration } from "@utils/text"; -import { findByPropsLazy, findComponentByCodeLazy, findComponentLazy } from "@webpack"; +import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common"; import type { Channel } from "discord-types/general"; @@ -80,14 +80,8 @@ const enum ChannelFlags { const ChatScrollClasses = findByPropsLazy("auto", "managedReactiveScroller"); const ChatClasses = findByPropsLazy("chat", "content", "noChat", "chatContent"); -const ChannelBeginHeader = findComponentByCodeLazy(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE"); -const TagComponent = findComponentLazy(m => { - if (typeof m !== "function") return false; - - const code = Function.prototype.toString.call(m); - // Get the component which doesn't include increasedActivity - return code.includes(".Messages.FORUM_TAG_A11Y_FILTER_BY_TAG") && !code.includes("increasedActivityPill"); -}); +const ChannelBeginHeader = findComponentByCodeLazy("#{intl::ROLE_REQUIRED_SINGLE_USER_MESSAGE}"); +const TagComponent = findComponentByCodeLazy("#{intl::FORUM_TAG_A11Y_FILTER_BY_TAG}"); const EmojiParser = findByPropsLazy("convertSurrogateToName"); const EmojiUtils = findByPropsLazy("getURL", "getEmojiColors"); diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index d220d0c12..ba3675428 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -149,7 +149,7 @@ export default definePlugin({ } }, { - find: ".Messages.CHANNEL_TOOLTIP_DIRECTORY", + find: "#{intl::CHANNEL_TOOLTIP_DIRECTORY}", predicate: () => settings.store.showMode === ShowMode.LockIcon, replacement: { // Lock Icon @@ -274,7 +274,7 @@ export default definePlugin({ } }, { - find: ".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE", + find: "#{intl::ROLE_REQUIRED_SINGLE_USER_MESSAGE}", replacement: [ { // Change the role permission check to CONNECT if the channel is locked @@ -336,7 +336,7 @@ export default definePlugin({ ] }, { - find: ".Messages.CHANNEL_CALL_CURRENT_SPEAKER.format", + find: "#{intl::CHANNEL_CALL_CURRENT_SPEAKER}", replacement: [ { // Remove the divider and the open chat button for the HiddenChannelLockScreen @@ -351,7 +351,7 @@ export default definePlugin({ ] }, { - find: ".Messages.EMBEDDED_ACTIVITIES_DEVELOPER_ACTIVITY_SHELF_FETCH_ERROR", + find: "#{intl::EMBEDDED_ACTIVITIES_DEVELOPER_ACTIVITY_SHELF_FETCH_ERROR}", replacement: [ { // Render our HiddenChannelLockScreen component instead of the main voice channel component @@ -401,7 +401,7 @@ export default definePlugin({ ] }, { - find: ".Messages.STAGE_FULL_MODERATOR_TITLE", + find: "#{intl::STAGE_FULL_MODERATOR_TITLE}", replacement: [ { // Remove the divider and amount of users in stage channel components for the HiddenChannelLockScreen @@ -463,7 +463,7 @@ export default definePlugin({ ] }, { - find: ".Messages.FORM_LABEL_MUTED", + find: "#{intl::FORM_LABEL_MUTED}", replacement: { // Make GuildChannelStore.getChannels return hidden channels match: /(?<=getChannels\(\i)(?=\))/, diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index bab0b3032..8fd6ef82e 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -68,7 +68,7 @@ export default definePlugin({ }, // fixes a bug where Members page must be loaded to see highest role, why is Discord depending on MemberSafetyStore.getEnhancedMember for something that can be obtained here? { - find: "Messages.GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL,allowOverflow", + find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}", predicate: () => settings.store.showModView, replacement: { match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/, diff --git a/src/plugins/showTimeoutDuration/index.tsx b/src/plugins/showTimeoutDuration/index.tsx index bfe806802..fa2ef4312 100644 --- a/src/plugins/showTimeoutDuration/index.tsx +++ b/src/plugins/showTimeoutDuration/index.tsx @@ -9,13 +9,16 @@ import "./styles.css"; import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; +import { canonicalizeMatch } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; import { findComponentLazy } from "@webpack"; -import { ChannelStore, GuildMemberStore, i18n, Text, Tooltip } from "@webpack/common"; +import { ChannelStore, GuildMemberStore, Text, Tooltip } from "@webpack/common"; import { Message } from "discord-types/general"; import { FunctionComponent, ReactNode } from "react"; -const CountDown = findComponentLazy(m => m.prototype?.render?.toString().includes(".MAX_AGE_NEVER")); +const countDownFilter = canonicalizeMatch("#{intl::MAX_AGE_NEVER}"); +const CountDown = findComponentLazy(m => m.prototype?.render?.toString().includes(countDownFilter)); const enum DisplayStyle { Tooltip = "tooltip", @@ -48,9 +51,14 @@ function renderTimeout(message: Message, inline: boolean) { /> ); + getIntlMessage("GUILD_ENABLE_COMMUNICATION_TIME_REMAINING", { + username: message.author.username, + countdown + }); + return inline ? countdown() - : i18n.Messages.GUILD_ENABLE_COMMUNICATION_TIME_REMAINING.format({ + : getIntlMessage("GUILD_ENABLE_COMMUNICATION_TIME_REMAINING", { username: message.author.username, countdown }); @@ -65,10 +73,10 @@ export default definePlugin({ patches: [ { - find: ".GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY", + find: "#{intl::GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY}", replacement: [ { - match: /(\i)\.Tooltip,{(text:.{0,30}\.Messages\.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY)/, + match: /(\i)\.Tooltip,{(text:.{0,30}#{intl::GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY}\))/, replace: "$self.TooltipWrapper,{message:arguments[0].message,$2" } ] diff --git a/src/plugins/sortFriendRequests/index.tsx b/src/plugins/sortFriendRequests/index.tsx index 64eb13fe5..6ce1af14d 100644 --- a/src/plugins/sortFriendRequests/index.tsx +++ b/src/plugins/sortFriendRequests/index.tsx @@ -45,7 +45,7 @@ export default definePlugin({ replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()" } }, { - find: ".Messages.FRIEND_REQUEST_CANCEL", + find: "#{intl::FRIEND_REQUEST_CANCEL}", replacement: { predicate: () => settings.store.showDates, match: /subText:(\i)(?<=user:(\i).+?)/, diff --git a/src/plugins/startupTimings/index.tsx b/src/plugins/startupTimings/index.tsx index 5051fdf4a..aabc786a4 100644 --- a/src/plugins/startupTimings/index.tsx +++ b/src/plugins/startupTimings/index.tsx @@ -26,7 +26,7 @@ export default definePlugin({ description: "Adds Startup Timings to the Settings menu", authors: [Devs.Megu], patches: [{ - find: "Messages.ACTIVITY_SETTINGS", + find: "#{intl::ACTIVITY_SETTINGS}", replacement: { match: /(?<=}\)([,;])(\i\.settings)\.forEach.+?(\i)\.push.+}\)}\))/, replace: (_, commaOrSemi, settings, elements) => "" + diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index 2a613967c..8e1e022b9 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -38,7 +38,7 @@ export default definePlugin({ // add --avatar-url- css variable to avatar img elements // popout profiles { - find: ".LABEL_WITH_ONLINE_STATUS", + find: "#{intl::LABEL_WITH_ONLINE_STATUS}", replacement: { match: /src:null!=\i\?(\i).{1,50}"aria-hidden":!0/, replace: "$&,style:$self.getAvatarStyles($1)" diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index 6df3f4b80..e23cf49d2 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -21,9 +21,10 @@ import "./style.css"; import { definePluginSettings, Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { findComponentByCodeLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildMemberStore, i18n, RelationshipStore, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; +import { ChannelStore, GuildMemberStore, RelationshipStore, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; import { buildSeveralUsers } from "../typingTweaks"; @@ -75,21 +76,21 @@ function TypingIndicator({ channelId }: { channelId: string; }) { switch (typingUsersArray.length) { case 0: break; case 1: { - tooltipText = i18n.Messages.ONE_USER_TYPING.format({ a: getDisplayName(guildId, typingUsersArray[0]) }); + tooltipText = getIntlMessage("ONE_USER_TYPING", { a: getDisplayName(guildId, typingUsersArray[0]) }); break; } case 2: { - tooltipText = i18n.Messages.TWO_USERS_TYPING.format({ a: getDisplayName(guildId, typingUsersArray[0]), b: getDisplayName(guildId, typingUsersArray[1]) }); + tooltipText = getIntlMessage("TWO_USERS_TYPING", { a: getDisplayName(guildId, typingUsersArray[0]), b: getDisplayName(guildId, typingUsersArray[1]) }); break; } case 3: { - tooltipText = i18n.Messages.THREE_USERS_TYPING.format({ a: getDisplayName(guildId, typingUsersArray[0]), b: getDisplayName(guildId, typingUsersArray[1]), c: getDisplayName(guildId, typingUsersArray[2]) }); + tooltipText = getIntlMessage("THREE_USERS_TYPING", { a: getDisplayName(guildId, typingUsersArray[0]), b: getDisplayName(guildId, typingUsersArray[1]), c: getDisplayName(guildId, typingUsersArray[2]) }); break; } default: { tooltipText = Settings.plugins.TypingTweaks.enabled ? buildSeveralUsers({ a: getDisplayName(guildId, typingUsersArray[0]), b: getDisplayName(guildId, typingUsersArray[1]), count: typingUsersArray.length - 2 }) - : i18n.Messages.SEVERAL_USERS_TYPING; + : getIntlMessage("SEVERAL_USERS_TYPING"); break; } } diff --git a/src/plugins/typingTweaks/index.tsx b/src/plugins/typingTweaks/index.tsx index d3f4a1409..4fb3c7757 100644 --- a/src/plugins/typingTweaks/index.tsx +++ b/src/plugins/typingTweaks/index.tsx @@ -112,8 +112,8 @@ export default definePlugin({ { find: "getCooldownTextStyle", replacement: { - match: /(?<=(\i)\.length\?\i.\i\.Messages.THREE_USERS_TYPING\.format\({\i:(\i),(?:\i:)?(\i),\i:\i}\):)\i\.\i\.Messages\.SEVERAL_USERS_TYPING/, - replace: (_, users, a, b) => `$self.buildSeveralUsers({ a: ${a}, b: ${b}, count: ${users}.length - 2 })` + match: /(,{a:(\i),b:(\i),c:\i}\):)\i\.\i\.string\(\i\.\i#{intl::SEVERAL_USERS_TYPING}\)(?<=(\i)\.length.+?)/, + replace: (_, rest, a, b, users) => `${rest}$self.buildSeveralUsers({ a: ${a}, b: ${b}, count: ${users}.length - 2 })` }, predicate: () => settings.store.alternativeFormatting } diff --git a/src/plugins/unlockedAvatarZoom/index.ts b/src/plugins/unlockedAvatarZoom/index.ts index 08503eb8b..79c204745 100644 --- a/src/plugins/unlockedAvatarZoom/index.ts +++ b/src/plugins/unlockedAvatarZoom/index.ts @@ -25,7 +25,7 @@ export default definePlugin({ settings, patches: [ { - find: ".Messages.AVATAR_UPLOAD_EDIT_MEDIA", + find: "#{intl::AVATAR_UPLOAD_EDIT_MEDIA}", replacement: { match: /maxValue:\d/, replace: "maxValue:$self.settings.store.zoomMultiplier", diff --git a/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx b/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx index c2d7be2e8..c2a54f14c 100644 --- a/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx +++ b/src/plugins/userMessagesPronouns/PronounsChatComponent.tsx @@ -18,9 +18,10 @@ import { getUserSettingLazy } from "@api/UserSettings"; import ErrorBoundary from "@components/ErrorBoundary"; +import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import { findByPropsLazy } from "@webpack"; -import { i18n, Tooltip, UserStore } from "@webpack/common"; +import { Tooltip, UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; import { settings } from "./settings"; @@ -44,7 +45,7 @@ function PronounsChatComponent({ message }: { message: Message; }) { const pronouns = useFormattedPronouns(message.author.id); return pronouns && ( - + {tooltipProps => ( null==") }); const getDMChannelIcon = findByCodeLazy(".getChannelIconURL({"); diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 07b18c27d..e0d5d8abd 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -57,7 +57,7 @@ export default definePlugin({ patches: [ // User Popout, Full Size Profile, Direct Messages Side Profile { - find: ".Messages.USER_PROFILE_LOAD_ERROR", + find: "#{intl::USER_PROFILE_LOAD_ERROR}", replacement: { match: /(\.fetchError.+?\?)null/, replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId,isProfile:true})` @@ -78,7 +78,7 @@ export default definePlugin({ { find: "PrivateChannel.renderAvatar", replacement: { - match: /\.Messages\.CLOSE_DM.+?}\)(?=])/, + match: /#{intl::CLOSE_DM}.+?}\)(?=])/, replace: "$&,$self.VoiceChannelIndicator({userId:arguments[0]?.user?.id})" }, predicate: () => settings.store.showVoiceChannelIndicator diff --git a/src/plugins/validReply/index.ts b/src/plugins/validReply/index.ts index b65496f44..989513d01 100644 --- a/src/plugins/validReply/index.ts +++ b/src/plugins/validReply/index.ts @@ -37,9 +37,9 @@ export default definePlugin({ authors: [Devs.newwares], patches: [ { - find: "Messages.REPLY_QUOTE_MESSAGE_NOT_LOADED", + find: "#{intl::REPLY_QUOTE_MESSAGE_NOT_LOADED}", replacement: { - match: /Messages\.REPLY_QUOTE_MESSAGE_NOT_LOADED/, + match: /#{intl::REPLY_QUOTE_MESSAGE_NOT_LOADED}\)/, replace: "$&,onMouseEnter:()=>$self.fetchReply(arguments[0])" } }, diff --git a/src/plugins/viewRaw/index.tsx b/src/plugins/viewRaw/index.tsx index 83c560df2..0134ea3e3 100644 --- a/src/plugins/viewRaw/index.tsx +++ b/src/plugins/viewRaw/index.tsx @@ -23,11 +23,12 @@ import { CodeBlock } from "@components/CodeBlock"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; +import { getIntlMessage } from "@utils/discord"; import { Margins } from "@utils/margins"; import { copyWithToast } from "@utils/misc"; import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; -import { Button, ChannelStore, Forms, i18n, Menu, Text } from "@webpack/common"; +import { Button, ChannelStore, Forms, Menu, Text } from "@webpack/common"; import { Message } from "discord-types/general"; @@ -122,7 +123,7 @@ function MakeContextCallback(name: "Guild" | "User" | "Channel"): NavContextMenu return (children, props) => { const value = props[name.toLowerCase()]; if (!value) return; - if (props.label === i18n.Messages.CHANNEL_ACTIONS_MENU_LABEL) return; // random shit like notification settings + if (props.label === getIntlMessage("CHANNEL_ACTIONS_MENU_LABEL")) return; // random shit like notification settings const lastChild = children.at(-1); if (lastChild?.key === "developer-actions") { diff --git a/src/plugins/volumeBooster/index.ts b/src/plugins/volumeBooster/index.ts index c38b2d1a5..241111d41 100644 --- a/src/plugins/volumeBooster/index.ts +++ b/src/plugins/volumeBooster/index.ts @@ -57,7 +57,7 @@ export default definePlugin({ patches: [ // Change the max volume for sliders to allow for values above 200 ...[ - ".Messages.USER_VOLUME", + "#{intl::USER_VOLUME}", "currentVolume:" ].map(find => ({ find, diff --git a/src/plugins/webContextMenus.web/index.ts b/src/plugins/webContextMenus.web/index.ts index bae780109..d3934bc26 100644 --- a/src/plugins/webContextMenus.web/index.ts +++ b/src/plugins/webContextMenus.web/index.ts @@ -127,11 +127,11 @@ export default definePlugin({ replace: "return [true" }, { - match: /(?<=COPY_IMAGE_MENU_ITEM,)action:/, + match: /(?<=#{intl::COPY_IMAGE_MENU_ITEM}\),)action:/, replace: "action:()=>$self.copyImage(arguments[0]),oldAction:" }, { - match: /(?<=SAVE_IMAGE_MENU_ITEM,)action:/, + match: /(?<=#{intl::SAVE_IMAGE_MENU_ITEM}\),)action:/, replace: "action:()=>$self.saveImage(arguments[0]),oldAction:" }, ] @@ -202,14 +202,14 @@ export default definePlugin({ } }, { - find: ".Messages.SEARCH_WITH_GOOGLE", + find: "#{intl::SEARCH_WITH_GOOGLE}", replacement: { match: /\i\.isPlatformEmbedded/, replace: "true" } }, { - find: ".Messages.COPY,hint:", + find: "#{intl::COPY}),hint:", replacement: [ { match: /\i\.isPlatformEmbedded/, @@ -224,10 +224,10 @@ export default definePlugin({ { find: '("interactionUsernameProfile', replacement: - { - match: /\i\.isPlatformEmbedded(?=.{0,50}\.tagName)/, - replace: "true" - }, + { + match: /\i\.isPlatformEmbedded(?=.{0,50}\.tagName)/, + replace: "true" + }, } ], diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index fed5a5d86..91fd791b2 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -19,12 +19,39 @@ import "./discord.css"; import { MessageObject } from "@api/MessageEvents"; -import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Channel, Guild, Message, User } from "discord-types/general"; import { Except } from "type-fest"; +import { runtimeHashMessageKey } from "./intlHash"; +import { Logger } from "./Logger"; import { MediaModalItem, MediaModalProps, openMediaModal } from "./modal"; +const IntlManagerLogger = new Logger("IntlManager"); + +/** + * Get an internationalized message from a non hashed key + * @param key The plain message key + * @param values The values to interpolate, if it's a rich message + */ +export function getIntlMessage(key: string, values?: Record): any { + return getIntlMessageFromHash(runtimeHashMessageKey(key), values, key); +} + +/** + * Get an internationalized message from a hashed key + * @param hashedKey The hashed message key + * @param values The values to interpolate, if it's a rich message + */ +export function getIntlMessageFromHash(hashedKey: string, values?: Record, originalKey?: string): any { + try { + return values == null ? i18n.intl.string(i18n.t[hashedKey]) : i18n.intl.format(i18n.t[hashedKey], values); + } catch (e) { + IntlManagerLogger.error(`Failed to get intl message for key: ${originalKey ?? hashedKey}`, e); + return originalKey ?? ""; + } +} + /** * Open the invite modal * @param code The invite code diff --git a/src/utils/index.ts b/src/utils/index.ts index 62f3f6e96..ed347fdc5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -22,6 +22,7 @@ export * from "./ChangeList"; export * from "./constants"; export * from "./discord"; export * from "./guards"; +export * from "./intlHash"; export * from "./lazy"; export * from "./lazyReact"; export * from "./localStorage"; diff --git a/src/utils/intlHash.ts b/src/utils/intlHash.ts new file mode 100644 index 000000000..e6b77d095 --- /dev/null +++ b/src/utils/intlHash.ts @@ -0,0 +1,52 @@ +/* eslint-disable simple-header/header */ + +/** + * discord-intl + * + * @copyright 2024 Discord, Inc. + * @link https://github.com/discord/discord-intl + * @license MIT + */ + +import { hash as h64 } from "@intrnl/xxhash64"; + +const BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""); +const IS_BIG_ENDIAN = (() => { + const array = new Uint8Array(4); + const view = new Uint32Array(array.buffer); + return !((view[0] = 1) & array[0]); +})(); + +function numberToBytes(number: number | bigint) { + number = BigInt(number); + const array: number[] = []; + const byteCount = Math.ceil(Math.floor(Math.log2(Number(number)) + 1) / 8); + for (let i = 0; i < byteCount; i++) { + array.unshift(Number((number >> BigInt(8 * i)) & BigInt(255))); + } + + const bytes = new Uint8Array(array); + // The native `hashToMessageKey` always works in Big/Network Endian bytes, so this array + // needs to be converted to the same endianness to get the same base64 result. + return IS_BIG_ENDIAN ? bytes : bytes.reverse(); +} + +/** + * Returns a consistent, short hash of the given key by first processing it through a hash digest, + * then encoding the first few bytes to base64. + * + * This function is specifically written to mirror the native backend hashing function used by + * `@discord/intl-loader-core`, to be able to hash names at runtime. + */ +export function runtimeHashMessageKey(key: string): string { + const hash = h64(key, 0); + const bytes = numberToBytes(hash); + return [ + BASE64_TABLE[bytes[0] >> 2], + BASE64_TABLE[((bytes[0] & 0x03) << 4) | (bytes[1] >> 4)], + BASE64_TABLE[((bytes[1] & 0x0f) << 2) | (bytes[2] >> 6)], + BASE64_TABLE[bytes[2] & 0x3f], + BASE64_TABLE[bytes[3] >> 2], + BASE64_TABLE[((bytes[3] & 0x03) << 4) | (bytes[3] >> 4)], + ].join(""); +} diff --git a/src/utils/patches.ts b/src/utils/patches.ts index 87f3ce78c..3812acd91 100644 --- a/src/utils/patches.ts +++ b/src/utils/patches.ts @@ -16,12 +16,31 @@ * along with this program. If not, see . */ +import { runtimeHashMessageKey } from "./intlHash"; import { Patch, PatchReplacement, ReplaceFn } from "./types"; export function canonicalizeMatch(match: T): T { - if (typeof match === "string") return match; - const canonSource = match.source - .replaceAll("\\i", "[A-Za-z_$][\\w$]*"); + let partialCanon = typeof match === "string" ? match : match.source; + partialCanon = partialCanon.replaceAll(/#{intl::([A-Za-z_$][\w$]*)}/g, (_, key) => { + const hashed = runtimeHashMessageKey(key); + + const isString = typeof match === "string"; + const hasSpecialChars = !Number.isNaN(Number(hashed[0])) || hashed.includes("+") || hashed.includes("/"); + + if (hasSpecialChars) { + return isString + ? `["${hashed}"]` + : String.raw`(?:\["${hashed}"\])`.replaceAll("+", "\\+"); + } + + return isString ? `.${hashed}` : String.raw`(?:\.${hashed})`; + }); + + if (typeof match === "string") { + return partialCanon as T; + } + + const canonSource = partialCanon.replaceAll(String.raw`\i`, String.raw`(?:[A-Za-z_$][\w$]*)`); return new RegExp(canonSource, match.flags) as T; } diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 0bcb82d1b..11526c0f3 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -56,7 +56,7 @@ export let FocusLock: t.FocusLock; export let useToken: t.useToken; export const MaskedLink = waitForComponent("MaskedLink", filters.componentByCode("MASKED_LINK)")); -export const Timestamp = waitForComponent("Timestamp", filters.byCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format")); +export const Timestamp = waitForComponent("Timestamp", filters.byCode("#{intl::MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL}")); export const Flex = waitForComponent("Flex", ["Justify", "Align", "Wrap"]); export const { OAuth2AuthorizeModal } = findByPropsLazy("OAuth2AuthorizeModal"); diff --git a/src/webpack/common/types/i18nMessages.ts b/src/webpack/common/types/i18nMessages.ts deleted file mode 100644 index fdf677fc0..000000000 --- a/src/webpack/common/types/i18nMessages.ts +++ /dev/null @@ -1,24 +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 { LiteralUnion } from "type-fest"; - -export type i18nMessages = LiteralUnion< - "TITLE_BAR_CLOSE_WINDOW" | "TITLE_BAR_MAXIMIZE_WINDOW" | "TITLE_BAR_MINIMIZE_WINDOW" | "en-US" | "en-GB" | "zh-CN" | "zh-TW" | "cs" | "da" | "nl" | "fr" | "de" | "el" | "hu" | "it" | "ja" | "ko" | "pl" | "pt-BR" | "ru" | "es-ES" | "sv-SE" | "tr" | "bg" | "uk" | "fi" | "no" | "hr" | "ro" | "lt" | "th" | "vi" | "hi" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_SERVERS" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_CHANNELS" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_BACK_FORWARD" | "KEYBIND_DESCRIPTION_MODAL_UNREAD_CHANNELS" | "KEYBIND_DESCRIPTION_MODAL_UNREAD_MENTION_CHANNELS" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_TO_CALL" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_PREVIOUS_GUILD" | "KEYBIND_DESCRIPTION_MODAL_QUICKSWITCHER" | "KEYBIND_DESCRIPTION_MODAL_CREATE_GUILD" | "DND_OPERATION_LABEL_START" | "DND_OPERATION_LABEL_MOVE" | "DND_OPERATION_LABEL_DROP" | "DND_OPERATION_LABEL_CANCEL" | "KEYBIND_DESCRIPTION_MODAL_MARK_SERVER_READ" | "KEYBIND_DESCRIPTION_MODAL_MARK_CHANNEL_READ" | "KEYBIND_DESCRIPTION_MODAL_CREATE_DM_GROUP" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_PINS" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_INBOX" | "KEYBIND_DESCRIPTION_MODAL_MARK_TOP_INBOX_CHANNEL_READ" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_USERS" | "KEYBIND_DESCRIPTION_MODAL_SEARCH_EMOJIS" | "KEYBIND_DESCRIPTION_MODAL_SEARCH_GIFS" | "KEYBIND_DESCRIPTION_MODAL_SEARCH_STICKERS" | "KEYBIND_DESCRIPTION_MODAL_SCROLL_CHAT" | "KEYBIND_DESCRIPTION_MODAL_JUMP_TO_FIRST_UNREAD" | "KEYBIND_DESCRIPTION_MODAL_FOCUS_TEXT_AREA" | "KEYBIND_DESCRIPTION_MODAL_UPLOAD_FILE" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_MUTE" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_DEAFEN" | "KEYBIND_DESCRIPTION_MODAL_CALL_ACCEPT" | "KEYBIND_DESCRIPTION_MODAL_CALL_DECLINE" | "KEYBIND_DESCRIPTION_MODAL_CALL_START" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_HELP" | "KEYBIND_DESCRIPTION_MODAL_SEARCH" | "KEYBIND_DESCRIPTION_MODAL_EASTER_EGG" | "EDIT_MESSAGE" | "DELETE_MESSAGE" | "PIN_MESSAGE" | "ADD_REACTION" | "MESSAGE_ACTION_REPLY" | "COPY_TEXT" | "MARK_UNREAD" | "GUILDS_BAR_A11Y_LABEL" | "SERVERS" | "NEW" | "ADD_A_SERVER" | "GUILD_DISCOVERY_TOOLTIP" | "ACCOUNT_A11Y_LABEL" | "GUILD_SIDEBAR_A11Y_LABEL" | "UNKNOWN_USER" | "LOADING" | "LOADING_DID_YOU_KNOW" | "CONNECTING_PROBLEMS_CTA" | "TWEET_US" | "SERVER_STATUS" | "NOTIFICATION_CENTER_INCOMING_FRIEND_REQUEST" | "COMMAND_SHRUG_MESSAGE_DESCRIPTION" | "DIRECT_MESSAGES" | "GUILD_TOOLTIP_A11Y_LABEL" | "FAVORITES_GUILD_NAME" | "MEMBER_VERIFICATION_FOLDER_NAME" | "DND_DROP_ABOVE" | "DND_DROP_COMBINE" | "GUILD_FOLDER_TOOLTIP_A11Y_LABEL" | "DND_END_OF_LIST" | "GUILD_SIDEBAR_ACTIONS_BUTTON" | "PREMIUM_GUILD_TIER_3" | "PREMIUM_GUILD_SUBSCRIPTION_SUBSCRIBER_COUNT_TOOLTIP" | "CHANNELS" | "NEW_UNREADS" | "NEW_MENTIONS" | "UNMUTE" | "MUTE" | "DEAFEN" | "SET_STATUS" | "LABEL_WITH_ONLINE_STATUS" | "STATUS_ONLINE" | "USER_SETTINGS" | "CHANNEL_HEADER_BAR_A11Y_LABEL" | "TEXT_CHANNEL" | "UPLOAD_TO" | "UPLOAD_AREA_HELP" | "THREADS" | "NOTIFICATION_SETTINGS" | "PINNED_MESSAGES" | "MEMBER_LIST_SHOWN" | "SEARCH" | "SEARCH_CLEAR" | "INBOX" | "HELP" | "TEXTAREA_PLACEHOLDER" | "TEXTAREA_TEXT_CHANNEL_A11Y_LABEL" | "CHANNEL_A11Y_LABEL" | "CHANNEL_CHAT_HEADING" | "CHANNEL_MESSAGES_A11Y_LABEL" | "CHANNEL_MESSAGES_A11Y_DESCRIPTION" | "CHAT_ATTACH_UPLOAD_A_FILE" | "CHAT_ATTACH_UPLOAD_TEXT_AS_FILE" | "CREATE_THREAD" | "CHAT_ATTACH_USE_SLASH_COMMAND" | "CHAT_ATTACH_UPLOAD_OR_INVITE" | "PREMIUM_GIFT_BUTTON_TOOLTIP" | "PREMIUM_GIFT_BUTTON_LABEL" | "GIF_BUTTON_LABEL" | "STICKER_BUTTON_LABEL" | "SELECT_EMOJI" | "CHARACTER_COUNT_CLOSE_TO_LIMIT" | "MEMBERS_LIST_LANDMARK_LABEL" | "MEMBERS" | "PREMIUM_GUILD_SUBSCRIPTIONS_GOAL" | "PREMIUM_GUILD_TIER_3_SHORT" | "PREMIUM_GUILD_SUBSCRIPTIONS_PROGRESS_BAR_BLURB" | "PREMIUM_GUILD_SUBSCRIPTIONS_PROGRESS_BAR_COMPLETED_BLURB" | "PREMIUM_GUILD_SUBSCRIPTIONS_NUDGE_TOOLTIP_COMPLETE" | "PREMIUM_GUILD_SUBSCRIPTIONS_PROGRESS_BAR_TADA_ICON_ALT_TEXT" | "GUILD_EVENTS" | "GUILD_SIDEBAR_DEFAULT_CHANNEL_A11Y_LABEL" | "CHANNEL_TOOLTIP_TEXT_LIMITED" | "CREATE_INSTANT_INVITE" | "EDIT_CHANNEL" | "CHANNEL_TOOLTIP_TEXT" | "CATEGORY_A11Y_LABEL" | "CREATE_CHANNEL" | "CHANNEL_TOOLTIP_RULES" | "GUILD_SIDEBAR_ANNOUNCEMENT_CHANNEL_A11Y_LABEL" | "CHANNEL_TOOLTIP_ANNOUNCEMENTS" | "GUILD_SIDEBAR_STAGE_CHANNEL_A11Y_LABEL" | "OPEN_CHAT" | "CHANNEL_TOOLTIP_STAGE_LIMITED" | "CHANNEL_TOOLTIP_TEXT_ACTIVE_THREADS" | "THREAD_GROUP_A11Y_LABEL" | "GUILD_SIDEBAR_THREAD_A11Y_LABEL" | "GUILD_SIDEBAR_VOICE_CHANNEL_A11Y_LABEL" | "GUILD_SIDEBAR_CHANNEL_A11Y_LABEL_UNREAD" | "GUILD_SIDEBAR_VOICE_CHANNEL_A11Y_LABEL_USERS" | "CHANNEL_TOOLTIP_VOICE" | "STATUS_UNKNOWN" | "MESSAGE_A11Y_ROLE_DESCRIPTION" | "ROLE_ICON_ALT_TEXT" | "CHANNEL_MESSAGE_REPLY_A11Y_LABEL" | "IMAGE" | "MESSAGE_EDITED" | "MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL" | "EMOJI_TOOLTIP_CLICK_CTA" | "REMOVE_MESSAGE_ATTACHMENT" | "VERIFIED_BOT_TOOLTIP" | "SUPPRESS_ALL_EMBEDS" | "CHANNEL_MEMBERS_A11Y_LABEL" | "GUILD_OWNER" | "PREMIUM_GUILD_SUBSCRIPTION_TOOLTIP" | "STATUS_ONLINE_MOBILE" | "STATUS_IDLE" | "STREAMING" | "LISTENING_TO" | "WATCHING" | "COMPETING" | "PLAYING_GAME" | "STATUS_DND" | "CHAT_ATTACH_INVITE_TO_LISTEN" | "ACTIVITY_PANEL_GO_LIVE_STREAM_GAME" | "SEARCH_ANSWER_HAS_LINK" | "SEARCH_ANSWER_HAS_EMBED" | "SEARCH_ANSWER_HAS_ATTACHMENT" | "SEARCH_ANSWER_HAS_VIDEO" | "SEARCH_ANSWER_HAS_IMAGE" | "SEARCH_ANSWER_HAS_SOUND" | "SEARCH_ANSWER_HAS_STICKER" | "SEARCH_FILTER_FROM" | "SEARCH_FILTER_MENTIONS" | "SEARCH_FILTER_HAS" | "SEARCH_FILTER_FILE_TYPE" | "SEARCH_FILTER_FILE_NAME" | "SEARCH_FILTER_BEFORE" | "SEARCH_FILTER_ON" | "SEARCH_FILTER_DURING" | "SEARCH_FILTER_AFTER" | "SEARCH_FILTER_IN" | "SEARCH_FILTER_PINNED" | "MESSAGE_UTILITIES_A11Y_LABEL" | "EDIT" | "MORE" | "SEARCH_SHORTCUT_TODAY" | "SEARCH_SHORTCUT_YESTERDAY" | "SEARCH_SHORTCUT_WEEK" | "SEARCH_SHORTCUT_MONTH" | "SEARCH_SHORTCUT_YEAR" | "SEARCH_GROUP_HEADER_SEARCH_OPTIONS" | "SEARCH_GROUP_HEADER_HISTORY" | "LEARN_MORE" | "SEARCH_ANSWER_FROM" | "SEARCH_ANSWER_MENTIONS" | "SEARCH_ANSWER_HAS" | "SEARCH_ANSWER_DATE" | "SEARCH_ANSWER_IN" | "SEARCH_ANSWER_BOOLEAN" | "SEARCH_CLEAR_HISTORY" | "SEARCH_FROM_SUGGESTIONS" | "MEMBER_LIST_HIDDEN" | "SEARCH_RESULTS_SECTION_LABEL" | "SEARCH_NEWEST_SHORT" | "SEARCH_OLDEST_SHORT" | "SEARCH_MOST_RELEVANT_SHORT" | "SEARCHING" | "TOTAL_RESULTS" | "JUMP" | "REPLY_QUOTE_MESSAGE_NOT_LOADED" | "COPY_MESSAGE_LINK" | "COPY_ID" | "MESSAGE_ACTIONS_MENU_LABEL" | "ACTIVE_THREADS_POPOUT_HEADER" | "ACTIVE_THREADS_POPOUT_LINK" | "THREAD_BROWSER_TIMESTAMP_MINUTES" | "THREAD_BROWSER_TIMESTAMP_HOURS" | "THREAD_BROWSER_TIMESTAMP_DAYS" | "THREAD_BROWSER_TIMESTAMP_MORE_THAN_MONTH" | "OPEN_CHANNEL_TOPIC" | "VIDEO" | "REPLY_QUOTE_NO_TEXT_CONTENT" | "PLAY" | "NEW_MEMBER_BADGE_TOOLTIP_TEXT" | "USER_SETTINGS_MY_ACCOUNT" | "USER_SETTINGS_PROFILES" | "PRIVACY_AND_SAFETY" | "AUTHORIZED_APPS" | "AUTH_SESSIONS" | "CONNECTIONS" | "CLIPS" | "FRIEND_REQUESTS" | "BILLING_SETTINGS" | "PREMIUM" | "PREMIUM_GUILD_SUBSCRIPTION_TITLE" | "SUBSCRIPTIONS_TITLE" | "GIFT_INVENTORY" | "BILLING" | "APP_SETTINGS" | "APPEARANCE" | "ACCESSIBILITY" | "VOICE_AND_VIDEO" | "POGGERMODE" | "TEXT_AND_IMAGES" | "NOTIFICATIONS" | "KEYBINDS" | "LANGUAGE" | "USER_SETTINGS_WINDOWS_SETTINGS" | "USER_SETTINGS_LINUX_SETTINGS" | "STREAMER_MODE" | "SETTINGS_ADVANCED" | "ACTIVITY_SETTINGS" | "ACTIVITY_PRIVACY" | "REGISTERED_GAMES" | "OVERLAY" | "WHATS_NEW" | "USER_SETTINGS_HYPESQUAD" | "LOGOUT" | "BETA" | "USER_SETTINGS_ACCOUNT_PASSWORD_AND_AUTHENTICATION" | "CHANGE_PASSWORD" | "USER_SETTINGS_EDIT_USER_PROFILE" | "ACTIONS" | "HYPESQUAD_ONLINE_BADGE_TOOLTIP" | "HYPESQUAD_HOUSE_1" | "ACTIVE_DEVELOPER_BADGE_TOOLTIP" | "PROFILE_USER_BADGES" | "USER_SETTINGS_LABEL_USERNAME" | "USER_SETTINGS_ACCOUNT_EDIT_USERNAME_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_EDIT_EMAIL_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_REVEAL_EMAIL_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_HIDE_EMAIL_A11Y_LABEL" | "USER_SETTINGS_LABEL_EMAIL" | "REVEAL" | "USER_SETTINGS_ACCOUNT_REVEAL_PHONE_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_HIDE_PHONE_A11Y_LABEL" | "USER_SETTINGS_LABEL_PHONE_NUMBER" | "USER_SETTINGS_ACCOUNT_REMOVE_PHONE_A11Y_LABEL" | "REMOVE" | "USER_SETTINGS_ACCOUNT_EDIT_PHONE_A11Y_LABEL" | "TWO_FA_VIEW_BACKUP_CODES" | "TWO_FA_ENABLED" | "TWO_FA_DESCRIPTION" | "TWO_FA_DISABLED_FOR_SERVER_SUBSCRIPTION_MOD" | "MFA_SMS_AUTH_CURRENT_PHONE" | "MFA_SMS_PHONE_NUMBER_REVEAL" | "MFA_SMS_ENABLE" | "CHANGE_PHONE_NUMBER" | "MFA_SMS_AUTH" | "MFA_SMS_AUTH_SALES_PITCH" | "TWO_FA_REMOVE" | "USER_SETTINGS_ACCOUNT_REMOVAL_SECTION" | "USER_SETTINGS_ACCOUNT_REMOVAL_DESCRIPTION" | "DISABLE_ACCOUNT" | "DELETE_ACCOUNT" | "CLOSE" | "PREMIUM_BADGE_TOOLTIP" | "SELECT" | "REPLYING_TO" | "SUPER_REACTION_NITRO_TOOLTIP" | "YOURE_VIEWING_OLDER_MESSAGES" | "JUMP_TO_PRESENT" | "REACT_WITH_COUNT_A11Y_LABEL" | "SEARCH_NO_RESULTS" | "GUILD_SIDEBAR_CHANNEL_A11Y_LABEL_LIMIT" | "COPY_LINK" | "DELETE" | "GUILD_SIDEBAR_DEFAULT_CHANNEL_A11Y_LABEL_WITH_MENTIONS" | "NEW_MESSAGES" | "NEW_MESSAGES_PILL" | "JUMP_TO_LAST_UNREAD_MESSAGE" | "MARK_AS_READ", - string ->; diff --git a/src/webpack/common/types/index.d.ts b/src/webpack/common/types/index.d.ts index a536cdcf1..77148dd0b 100644 --- a/src/webpack/common/types/index.d.ts +++ b/src/webpack/common/types/index.d.ts @@ -19,7 +19,6 @@ export * from "./classes"; export * from "./components"; export * from "./fluxEvents"; -export * from "./i18nMessages"; export * from "./menu"; export * from "./stores"; export * from "./utils"; diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts index c0a930049..00e3f4a0b 100644 --- a/src/webpack/common/types/utils.d.ts +++ b/src/webpack/common/types/utils.d.ts @@ -21,7 +21,6 @@ import type { ReactNode } from "react"; import { LiteralUnion } from "type-fest"; import type { FluxEvents } from "./fluxEvents"; -import { i18nMessages } from "./i18nMessages"; export { FluxEvents }; @@ -148,19 +147,6 @@ export interface LocaleInfo { postgresLang: string; } -export interface i18n { - getAvailableLocales(): Locale[]; - getLanguages(): LocaleInfo[]; - getDefaultLocale(): string; - getLocale(): string; - getLocaleInfo(): LocaleInfo; - setLocale(locale: string): void; - - loadPromise: Promise; - - Messages: Record; -} - export interface Clipboard { copy(text: string): void; SUPPORTS_COPY: boolean; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 2d0026b58..3f44d106d 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { runtimeHashMessageKey } from "@utils/intlHash"; import type { Channel } from "discord-types/general"; // eslint-disable-next-line path-alias/no-relative @@ -56,7 +57,10 @@ export const { match, P }: Pick = ma export const lodash: typeof import("lodash") = findByPropsLazy("debounce", "cloneDeep"); -export const i18n: t.i18n = findLazy(m => m.Messages?.["en-US"]); +export const i18n = mapMangledModuleLazy('defaultLocale:"en-US"', { + intl: filters.byProps("string", "format"), + t: filters.byProps(runtimeHashMessageKey("DISCORD")) +}); export let SnowflakeUtils: t.SnowflakeUtils; waitFor(["fromTimestamp", "extractTimestamp"], m => SnowflakeUtils = m); @@ -131,7 +135,7 @@ export const UserUtils = { export const UploadManager = findByPropsLazy("clearAll", "addFile"); export const UploadHandler = { - promptToUpload: findByCodeLazy(".ATTACHMENT_TOO_MANY_ERROR_TITLE,") as (files: File[], channel: Channel, draftType: Number) => void + promptToUpload: findByCodeLazy("#{intl::ATTACHMENT_TOO_MANY_ERROR_TITLE}") as (files: File[], channel: Channel, draftType: Number) => void }; export const ApplicationAssetUtils = findByPropsLazy("fetchAssetIds", "getAssetImage") as { From 439a4f8eb6df6a8f886ea4680b313bd3b5d724db Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:51:18 -0300 Subject: [PATCH 09/82] Bump to 1.10.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63ff0678b..97da80cdb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.10.5", + "version": "1.10.6", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 9d4e859a0a2873d8afb7a6503261336628abbe77 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:01:52 -0500 Subject: [PATCH 10/82] NoBlockedMessages: Fix for new i18n lib (#2996) --- src/plugins/messageLogger/index.tsx | 33 ++++++++++++++++++++++---- src/plugins/noBlockedMessages/index.ts | 14 +++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index 3ee9f3fad..bc3c1ed90 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -25,7 +25,6 @@ import { disableStyle, enableStyle } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; -import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; @@ -313,9 +312,35 @@ export default definePlugin({ ); }, - Messages: proxyLazy(() => ({ - DELETED_MESSAGE_COUNT: getMessage("{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}") - })), + Messages: { + // DELETED_MESSAGE_COUNT: getMessage("{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}") + // TODO: find a better way to generate intl messages + DELETED_MESSAGE_COUNT: () => ({ + ast: [[ + 6, + "count", + { + "=0": ["No deleted messages"], + one: [ + [ + 1, + "count" + ], + " deleted message" + ], + other: [ + [ + 1, + "count" + ], + " deleted messages" + ] + }, + 0, + "cardinal" + ]] + }) + }, patches: [ { diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 7884aa29c..1a1700e40 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -18,17 +18,18 @@ import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; +import { runtimeHashMessageKey } from "@utils/intlHash"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; +import { i18n } from "@webpack/common"; import { Message } from "discord-types/general"; const RelationshipStore = findByPropsLazy("getRelationships", "isBlocked"); interface MessageDeleteProps { - collapsedReason: { - message: string; - }; + // i18n message i18n.t["+FcYMz"] if deleted, with args + collapsedReason: () => any } export default definePlugin({ @@ -77,6 +78,11 @@ export default definePlugin({ }, shouldHide(props: MessageDeleteProps) { - return !props?.collapsedReason?.message.includes("deleted"); + try { + return props.collapsedReason() === i18n.t[runtimeHashMessageKey("BLOCKED_MESSAGE_COUNT")](); + } catch (e) { + console.error(e); + } + return false; } }); From 2270b88a98baf31cdd6fb5db429304048bc15515 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:52:26 -0300 Subject: [PATCH 11/82] intl macro: Support raw hash --- src/utils/patches.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/patches.ts b/src/utils/patches.ts index 3812acd91..097c64560 100644 --- a/src/utils/patches.ts +++ b/src/utils/patches.ts @@ -21,8 +21,8 @@ import { Patch, PatchReplacement, ReplaceFn } from "./types"; export function canonicalizeMatch(match: T): T { let partialCanon = typeof match === "string" ? match : match.source; - partialCanon = partialCanon.replaceAll(/#{intl::([A-Za-z_$][\w$]*)}/g, (_, key) => { - const hashed = runtimeHashMessageKey(key); + partialCanon = partialCanon.replaceAll(/#{intl::([\w$+/]*)(?:::(\w+))?}/g, (_, key, modifier) => { + const hashed = modifier === "raw" ? key : runtimeHashMessageKey(key); const isString = typeof match === "string"; const hasSpecialChars = !Number.isNaN(Number(hashed[0])) || hashed.includes("+") || hashed.includes("/"); @@ -40,7 +40,7 @@ export function canonicalizeMatch(match: T): T { return partialCanon as T; } - const canonSource = partialCanon.replaceAll(String.raw`\i`, String.raw`(?:[A-Za-z_$][\w$]*)`); + const canonSource = partialCanon.replaceAll("\\i", String.raw`(?:[A-Za-z_$][\w$]*)`); return new RegExp(canonSource, match.flags) as T; } From cd3a998c4b1cd2d99463c0f5997db95ea487034b Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 7 Nov 2024 15:07:00 -0300 Subject: [PATCH 12/82] Decor: Fix crashing --- src/plugins/consoleJanitor/index.ts | 48 ++++++++++++++- .../decor/lib/stores/AuthorizationStore.tsx | 2 +- src/plugins/messageLogger/index.tsx | 59 +++++++++---------- src/plugins/noBlockedMessages/index.ts | 4 +- src/webpack/common/utils.ts | 10 +++- 5 files changed, 85 insertions(+), 38 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 2d5d60ecf..c0e00110c 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -130,6 +130,52 @@ export default definePlugin({ replace: "" } }, + // Zustand section + { + find: "[DEPRECATED] Default export is deprecated. Instead use `import { create } from 'zustand'", + replacement: [ + { + match: /console\.warn\("\[DEPRECATED\] Default export is deprecated\. Instead use `import { create } from 'zustand'`\."\),/, + replace: "" + }, + { + match: /&&console\.warn\("\[DEPRECATED\] Passing a vanilla store will be unsupported in a future version\. Instead use `import { useStore } from 'zustand'`\."\)/, + replace: "" + }, + { + match: /console\.warn\("\[DEPRECATED\] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`\. They can be imported from 'zustand\/traditional'\. https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1937"\),/, + replace: "" + } + ] + }, + { + find: "[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead.", + replacement: { + match: /console\.warn\("\[DEPRECATED\] `getStorage`, `serialize` and `deserialize` options are deprecated\. Use `storage` option instead\."\),/, + replace: "" + } + }, + { + find: "[DEPRECATED] Default export is deprecated. Instead use import { createStore } from 'zustand/vanilla'.", + replacement: { + match: /console\.warn\("\[DEPRECATED\] Default export is deprecated\. Instead use import { createStore } from 'zustand\/vanilla'\."\),/, + replace: "" + } + }, + { + find: "[DEPRECATED] `context` will be removed in a future version. Instead use `import { createStore, useStore } from 'zustand'`. See: https://github.com/pmndrs/zustand/discussions/1180.", + replacement: { + match: /console\.warn\("\[DEPRECATED\] `context` will be removed in a future version\. Instead use `import { createStore, useStore } from 'zustand'`\. See: https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1180\."\);/, + replace: "" + } + }, + { + find: "[DEPRECATED] Default export is deprecated. Instead use `import { shallow } from 'zustand/shallow'`.", + replacement: { + match: /console\.warn\("\[DEPRECATED\] Default export is deprecated\. Instead use `import { shallow } from 'zustand\/shallow'`\."\),/, + replace: "" + } + }, // Patches discords generic logger function { find: "Σ:", @@ -147,5 +193,5 @@ export default definePlugin({ replace: "$self.NoopLogger()" } } - ], + ] }); diff --git a/src/plugins/decor/lib/stores/AuthorizationStore.tsx b/src/plugins/decor/lib/stores/AuthorizationStore.tsx index ba71da99e..7f3468fd0 100644 --- a/src/plugins/decor/lib/stores/AuthorizationStore.tsx +++ b/src/plugins/decor/lib/stores/AuthorizationStore.tsx @@ -93,7 +93,7 @@ export const useAuthorizationStore = proxyLazy(() => zustandCreate( } as AuthorizationState), { name: "decor-auth", - getStorage: () => indexedDBStorage, + storage: indexedDBStorage, partialize: state => ({ tokens: state.tokens }), onRehydrateStorage: () => state => state?.init() } diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index bc3c1ed90..a79e3f31e 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -28,7 +28,7 @@ import { getIntlMessage } from "@utils/discord"; import { Logger } from "@utils/Logger"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCodeLazy, findByPropsLazy } from "@webpack"; +import { findByPropsLazy } from "@webpack"; import { ChannelStore, FluxDispatcher, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common"; import { Message } from "discord-types/general"; @@ -43,7 +43,6 @@ interface MLMessage extends Message { } const styles = findByPropsLazy("edited", "communicationDisabled", "isSystemMessage"); -const getMessage = findByCodeLazy('replace(/^\\n+|\\n+$/g,"")'); function addDeleteStyle() { if (Settings.plugins.MessageLogger.deleteStyle === "text") { @@ -312,35 +311,33 @@ export default definePlugin({ ); }, - Messages: { - // DELETED_MESSAGE_COUNT: getMessage("{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}") - // TODO: find a better way to generate intl messages - DELETED_MESSAGE_COUNT: () => ({ - ast: [[ - 6, - "count", - { - "=0": ["No deleted messages"], - one: [ - [ - 1, - "count" - ], - " deleted message" + // DELETED_MESSAGE_COUNT: getMessage("{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}") + // TODO: Find a better way to generate intl messages + DELETED_MESSAGE_COUNT: () => ({ + ast: [[ + 6, + "count", + { + "=0": ["No deleted messages"], + one: [ + [ + 1, + "count" ], - other: [ - [ - 1, - "count" - ], - " deleted messages" - ] - }, - 0, - "cardinal" - ]] - }) - }, + " deleted message" + ], + other: [ + [ + 1, + "count" + ], + " deleted messages" + ] + }, + 0, + "cardinal" + ]] + }), patches: [ { @@ -531,7 +528,7 @@ export default definePlugin({ }, { match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\?.*?:/, - replace: '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.Messages.DELETED_MESSAGE_COUNT:', + replace: '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.DELETED_MESSAGE_COUNT:', }, ], predicate: () => Settings.plugins.MessageLogger.collapseDeleted diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 1a1700e40..65ce6136f 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -28,8 +28,8 @@ import { Message } from "discord-types/general"; const RelationshipStore = findByPropsLazy("getRelationships", "isBlocked"); interface MessageDeleteProps { - // i18n message i18n.t["+FcYMz"] if deleted, with args - collapsedReason: () => any + // Internal intl message for BLOCKED_MESSAGE_COUNT + collapsedReason: () => any; } export default definePlugin({ diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 3f44d106d..72f8a4275 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -163,9 +163,13 @@ waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); export const PermissionsBits: t.PermissionsBits = findLazy(m => typeof m.ADMINISTRATOR === "bigint"); -export const zustandCreate = findByCodeLazy("will be removed in v4"); +export const { zustandCreate } = mapMangledModuleLazy(["useSyncExternalStoreWithSelector:", "Object.assign"], { + zustandCreate: m => typeof m === "function" +}); -export const zustandPersist = findByCodeLazy("[zustand persist middleware]"); +export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?", { + zustandPersist: m => typeof m === "function" +}); export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); export const MessageCache = findByPropsLazy("clearCache", "_channelMessages"); @@ -181,7 +185,7 @@ export const ExpressionPickerStore: t.ExpressionPickerStore = mapMangledModuleLa toggleExpressionPicker: filters.byCode(/getState\(\)\.activeView===\i\?\i\(\):\i\(/), setExpressionPickerView: filters.byCode(/setState\({activeView:\i,lastActiveView:/), setSearchQuery: filters.byCode("searchQuery:"), - useExpressionPickerStore: filters.byCode("Object.is") + useExpressionPickerStore: filters.byCode(".getInitialState") }); export const PopoutActions: t.PopoutActions = mapMangledModuleLazy('type:"POPOUT_WINDOW_OPEN"', { From 5f7a2c59c621c11969def2cf44323d5703ef88bf Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:16:32 -0500 Subject: [PATCH 13/82] BetterFolders: Fix try-catch with no effect (#3000) --- src/plugins/betterFolders/index.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 50dee4f56..5d4d52c42 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -275,16 +275,16 @@ export default definePlugin({ }, makeGuildsBarGuildListFilter(isBetterFolders: boolean) { - try { return child => { if (isBetterFolders) { - return child?.props?.["aria-label"] === getIntlMessage("SERVERS"); + try { + return child?.props?.["aria-label"] === getIntlMessage("SERVERS"); + } catch (e) { + console.error(e); + } } return true; }; - } catch { - return true; - } }, makeGuildsBarTreeFilter(isBetterFolders: boolean) { From 64c3dd1c16a14efcc95f33e5f7d98d32b609ca1f Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:23:03 -0500 Subject: [PATCH 14/82] PatchHelper: Prevent trailing comma error (#2913) --- src/components/VencordSettings/PatchHelperTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/VencordSettings/PatchHelperTab.tsx b/src/components/VencordSettings/PatchHelperTab.tsx index fd33c09df..c11551873 100644 --- a/src/components/VencordSettings/PatchHelperTab.tsx +++ b/src/components/VencordSettings/PatchHelperTab.tsx @@ -247,7 +247,7 @@ function FullPatchInput({ setFind, setParsedFind, setMatch, setReplacement }: Fu } try { - const parsed = (0, eval)(`(${fullPatch})`) as Patch; + const parsed = (0, eval)(`([${fullPatch}][0])`) as Patch; if (!parsed.find) throw new Error("No 'find' field"); if (!parsed.replacement) throw new Error("No 'replacement' field"); From ce0740b885fc8efeaa9498932c56b9b101ab9619 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:27:19 -0500 Subject: [PATCH 15/82] TypingTweaks: Fix crashing in some languages (#2998) --- src/plugins/typingTweaks/index.tsx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/plugins/typingTweaks/index.tsx b/src/plugins/typingTweaks/index.tsx index 4fb3c7757..e2bbb4bc9 100644 --- a/src/plugins/typingTweaks/index.tsx +++ b/src/plugins/typingTweaks/index.tsx @@ -129,14 +129,22 @@ export default definePlugin({ buildSeveralUsers, mutateChildren(props: any, users: User[], children: any) { - if (!Array.isArray(children)) return children; + try { + if (!Array.isArray(children)) { + return children; + } - let element = 0; + let element = 0; - return children.map(c => - c.type === "strong" - ? - : c - ); + return children.map(c => + c.type === "strong" || (typeof c !== "string" && !React.isValidElement(c)) + ? + : c + ); + } catch (e) { + console.error(e); + } + + return children; } }); From 152d4fdbb30e9075a1934d0b0d6788b5a6a53c42 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 7 Nov 2024 15:29:17 -0300 Subject: [PATCH 16/82] Fix misc plugins errors on account switch --- src/plugins/relationshipNotifier/utils.ts | 2 ++ src/plugins/typingIndicator/index.tsx | 13 ++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/plugins/relationshipNotifier/utils.ts b/src/plugins/relationshipNotifier/utils.ts index 053cff835..84e812a75 100644 --- a/src/plugins/relationshipNotifier/utils.ts +++ b/src/plugins/relationshipNotifier/utils.ts @@ -50,6 +50,8 @@ async function runMigrations() { export async function syncAndRunChecks() { await runMigrations(); + if (UserStore.getCurrentUser() == null) return; + const [oldGuilds, oldGroups, oldFriends] = await DataStore.getMany([ guildsKey(), groupsKey(), diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index e23cf49d2..e9e343311 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -24,7 +24,7 @@ import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { findComponentByCodeLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildMemberStore, RelationshipStore, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; +import { GuildMemberStore, RelationshipStore, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; import { buildSeveralUsers } from "../typingTweaks"; @@ -44,7 +44,7 @@ function getDisplayName(guildId: string, userId: string) { return GuildMemberStore.getNick(guildId, userId) ?? (user as any).globalName ?? user.username; } -function TypingIndicator({ channelId }: { channelId: string; }) { +function TypingIndicator({ channelId, guildId }: { channelId: string; guildId: string; }) { const typingUsers: Record = useStateFromStores( [TypingStore], () => ({ ...TypingStore.getTypingUsers(channelId) as Record }), @@ -57,7 +57,6 @@ function TypingIndicator({ channelId }: { channelId: string; }) { } ); const currentChannelId: string = useStateFromStores([SelectedChannelStore], () => SelectedChannelStore.getChannelId()); - const guildId = ChannelStore.getChannel(channelId).guild_id; if (!settings.store.includeMutedChannels) { const isChannelMuted = UserGuildSettingsStore.isChannelMuted(guildId, channelId); @@ -165,7 +164,7 @@ export default definePlugin({ find: "UNREAD_IMPORTANT:", replacement: { match: /\.name\),.{0,120}\.children.+?:null(?<=,channel:(\i).+?)/, - replace: "$&,$self.TypingIndicator($1.id)" + replace: "$&,$self.TypingIndicator($1.id,$1.getGuildId())" } }, // Theads @@ -174,14 +173,14 @@ export default definePlugin({ find: "M11 9H4C2.89543 9 2 8.10457 2 7V1C2 0.447715 1.55228 0 1 0C0.447715 0 0 0.447715 0 1V7C0 9.20914 1.79086 11 4 11H11C11.5523 11 12 10.5523 12 10C12 9.44771 11.5523 9 11 9Z", replacement: { match: /mentionsCount:\i.+?null(?<=channel:(\i).+?)/, - replace: "$&,$self.TypingIndicator($1.id)" + replace: "$&,$self.TypingIndicator($1.id,$1.getGuildId())" } } ], - TypingIndicator: (channelId: string) => ( + TypingIndicator: (channelId: string, guildId: string) => ( - + ), }); From 3b295e1f6f7321cf7510547fa4c95dd61ff539be Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 8 Nov 2024 06:21:38 -0300 Subject: [PATCH 17/82] Revert "Decor: Fix crashing" cd3a998c4b1cd2d99463c0f5997db95ea487034b. --- src/plugins/consoleJanitor/index.ts | 46 ------------------- .../decor/lib/stores/AuthorizationStore.tsx | 2 +- src/webpack/common/utils.ts | 10 ++-- 3 files changed, 4 insertions(+), 54 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index c0e00110c..2c29bf670 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -130,52 +130,6 @@ export default definePlugin({ replace: "" } }, - // Zustand section - { - find: "[DEPRECATED] Default export is deprecated. Instead use `import { create } from 'zustand'", - replacement: [ - { - match: /console\.warn\("\[DEPRECATED\] Default export is deprecated\. Instead use `import { create } from 'zustand'`\."\),/, - replace: "" - }, - { - match: /&&console\.warn\("\[DEPRECATED\] Passing a vanilla store will be unsupported in a future version\. Instead use `import { useStore } from 'zustand'`\."\)/, - replace: "" - }, - { - match: /console\.warn\("\[DEPRECATED\] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`\. They can be imported from 'zustand\/traditional'\. https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1937"\),/, - replace: "" - } - ] - }, - { - find: "[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead.", - replacement: { - match: /console\.warn\("\[DEPRECATED\] `getStorage`, `serialize` and `deserialize` options are deprecated\. Use `storage` option instead\."\),/, - replace: "" - } - }, - { - find: "[DEPRECATED] Default export is deprecated. Instead use import { createStore } from 'zustand/vanilla'.", - replacement: { - match: /console\.warn\("\[DEPRECATED\] Default export is deprecated\. Instead use import { createStore } from 'zustand\/vanilla'\."\),/, - replace: "" - } - }, - { - find: "[DEPRECATED] `context` will be removed in a future version. Instead use `import { createStore, useStore } from 'zustand'`. See: https://github.com/pmndrs/zustand/discussions/1180.", - replacement: { - match: /console\.warn\("\[DEPRECATED\] `context` will be removed in a future version\. Instead use `import { createStore, useStore } from 'zustand'`\. See: https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1180\."\);/, - replace: "" - } - }, - { - find: "[DEPRECATED] Default export is deprecated. Instead use `import { shallow } from 'zustand/shallow'`.", - replacement: { - match: /console\.warn\("\[DEPRECATED\] Default export is deprecated\. Instead use `import { shallow } from 'zustand\/shallow'`\."\),/, - replace: "" - } - }, // Patches discords generic logger function { find: "Σ:", diff --git a/src/plugins/decor/lib/stores/AuthorizationStore.tsx b/src/plugins/decor/lib/stores/AuthorizationStore.tsx index 7f3468fd0..ba71da99e 100644 --- a/src/plugins/decor/lib/stores/AuthorizationStore.tsx +++ b/src/plugins/decor/lib/stores/AuthorizationStore.tsx @@ -93,7 +93,7 @@ export const useAuthorizationStore = proxyLazy(() => zustandCreate( } as AuthorizationState), { name: "decor-auth", - storage: indexedDBStorage, + getStorage: () => indexedDBStorage, partialize: state => ({ tokens: state.tokens }), onRehydrateStorage: () => state => state?.init() } diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 72f8a4275..3f44d106d 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -163,13 +163,9 @@ waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); export const PermissionsBits: t.PermissionsBits = findLazy(m => typeof m.ADMINISTRATOR === "bigint"); -export const { zustandCreate } = mapMangledModuleLazy(["useSyncExternalStoreWithSelector:", "Object.assign"], { - zustandCreate: m => typeof m === "function" -}); +export const zustandCreate = findByCodeLazy("will be removed in v4"); -export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?", { - zustandPersist: m => typeof m === "function" -}); +export const zustandPersist = findByCodeLazy("[zustand persist middleware]"); export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); export const MessageCache = findByPropsLazy("clearCache", "_channelMessages"); @@ -185,7 +181,7 @@ export const ExpressionPickerStore: t.ExpressionPickerStore = mapMangledModuleLa toggleExpressionPicker: filters.byCode(/getState\(\)\.activeView===\i\?\i\(\):\i\(/), setExpressionPickerView: filters.byCode(/setState\({activeView:\i,lastActiveView:/), setSearchQuery: filters.byCode("searchQuery:"), - useExpressionPickerStore: filters.byCode(".getInitialState") + useExpressionPickerStore: filters.byCode("Object.is") }); export const PopoutActions: t.PopoutActions = mapMangledModuleLazy('type:"POPOUT_WINDOW_OPEN"', { From fd1aba7babafc88a82f1e81d84cea77c1bdc66e0 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 8 Nov 2024 06:54:09 -0300 Subject: [PATCH 18/82] NoTrack: Remove obsolete patch --- src/plugins/_core/noTrack.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts index 8d6a1e76d..802e1c95a 100644 --- a/src/plugins/_core/noTrack.ts +++ b/src/plugins/_core/noTrack.ts @@ -59,15 +59,7 @@ export default definePlugin({ replace: "$&return;" } ] - }, - { - find: ".installedLogHooks)", - replacement: { - // if getDebugLogging() returns false, the hooks don't get installed. - match: "getDebugLogging(){", - replace: "getDebugLogging(){return false;" - } - }, + } ], startAt: StartAt.Init, From 49c9fa1c8edc32a3973db1b7bc7bd85d9e4d0a2a Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:26:42 -0300 Subject: [PATCH 19/82] Settings: Fix fallback patch --- scripts/generateReport.ts | 2 +- src/plugins/_core/settings.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 2ec9fba7c..c18bc14a3 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -225,7 +225,7 @@ page.on("console", async e => { plugin, type, id, - match: regex.replace(/\[A-Za-z_\$\]\[\\w\$\]\*/g, "\\i"), + match: regex.replace(/\(\?:\[A-Za-z_\$\]\[\\w\$\]\*\)/g, "\\i"), error: await maybeGetError(e.args()[3]) }); diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index a94e8cfaf..d58c7a98c 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -65,7 +65,7 @@ export default definePlugin({ replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` }, { - match: /({(?=.+?function (\i).{0,120}(\i)=\i\.useMemo.{0,60}return \i\.useMemo\(\(\)=>\i\(\3).+?function\(\){return )\2(?=})/, + match: /({(?=.+?function (\i).{0,160}(\i)=\i\.useMemo.{0,140}return \i\.useMemo\(\(\)=>\i\(\3).+?function\(\){return )\2(?=})/, replace: (_, rest, settingsHook) => `${rest}$self.wrapSettingsHook(${settingsHook})` } ] From 0cb84cee83ea3e3406eae26665f9a4c0d08e7efc Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:19:32 -0300 Subject: [PATCH 20/82] Bump to 1.10.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97da80cdb..d5b23e57c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.10.6", + "version": "1.10.7", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 1fe7912ec14fd5873d41ea8114d4f23914c283f1 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:23:07 -0300 Subject: [PATCH 21/82] Decor: Prevent crashing from useUserDecorAvatarDecoration --- .../decor/lib/stores/UsersDecorationsStore.ts | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/plugins/decor/lib/stores/UsersDecorationsStore.ts b/src/plugins/decor/lib/stores/UsersDecorationsStore.ts index 53aa33e63..a75115a3f 100644 --- a/src/plugins/decor/lib/stores/UsersDecorationsStore.ts +++ b/src/plugins/decor/lib/stores/UsersDecorationsStore.ts @@ -95,24 +95,30 @@ export const useUsersDecorationsStore = proxyLazy(() => zustandCreate((set: any, } as UsersDecorationsState))); export function useUserDecorAvatarDecoration(user?: User): AvatarDecoration | null | undefined { - const [decorAvatarDecoration, setDecorAvatarDecoration] = useState(user ? useUsersDecorationsStore.getState().getAsset(user.id) ?? null : null); + try { + const [decorAvatarDecoration, setDecorAvatarDecoration] = useState(user ? useUsersDecorationsStore.getState().getAsset(user.id) ?? null : null); - useEffect(() => { - const destructor = useUsersDecorationsStore.subscribe( - state => { - if (!user) return; - const newDecorAvatarDecoration = state.getAsset(user.id); - if (!newDecorAvatarDecoration) return; - if (decorAvatarDecoration !== newDecorAvatarDecoration) setDecorAvatarDecoration(newDecorAvatarDecoration); + useEffect(() => { + const destructor = useUsersDecorationsStore.subscribe( + state => { + if (!user) return; + const newDecorAvatarDecoration = state.getAsset(user.id); + if (!newDecorAvatarDecoration) return; + if (decorAvatarDecoration !== newDecorAvatarDecoration) setDecorAvatarDecoration(newDecorAvatarDecoration); + } + ); + + if (user) { + const { fetch: fetchUserDecorAvatarDecoration } = useUsersDecorationsStore.getState(); + fetchUserDecorAvatarDecoration(user.id); } - ); + return destructor; + }, []); - if (user) { - const { fetch: fetchUserDecorAvatarDecoration } = useUsersDecorationsStore.getState(); - fetchUserDecorAvatarDecoration(user.id); - } - return destructor; - }, []); + return decorAvatarDecoration ? { asset: decorAvatarDecoration, skuId: SKU_ID } : null; + } catch (e) { + console.error(e); + } - return decorAvatarDecoration ? { asset: decorAvatarDecoration, skuId: SKU_ID } : null; + return null; } From 69dc4fd59494b1aa7de21e65f6f8d041ddd98bc0 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:53:11 -0300 Subject: [PATCH 22/82] Decor: Fix avatar decorations not showing This reverts & edits commit 3b295e1f6f7321cf7510547fa4c95dd61ff539be. --- src/plugins/consoleJanitor/index.ts | 28 +++++++++++++++++++ .../decor/lib/stores/AuthorizationStore.tsx | 2 +- src/webpack/common/utils.ts | 10 +++++-- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 2c29bf670..4c5499cf4 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -130,6 +130,34 @@ export default definePlugin({ replace: "" } }, + // Zustand section + { + find: "[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.", + replacement: [ + { + match: /&&console\.warn\("\[DEPRECATED\] Passing a vanilla store will be unsupported in a future version\. Instead use `import { useStore } from 'zustand'`\."\)/, + replace: "" + }, + { + match: /console\.warn\("\[DEPRECATED\] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`\. They can be imported from 'zustand\/traditional'\. https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1937"\),/, + replace: "" + } + ] + }, + { + find: "[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead.", + replacement: { + match: /console\.warn\("\[DEPRECATED\] `getStorage`, `serialize` and `deserialize` options are deprecated\. Use `storage` option instead\."\),/, + replace: "" + } + }, + { + find: "[DEPRECATED] `context` will be removed in a future version. Instead use `import { createStore, useStore } from 'zustand'`. See: https://github.com/pmndrs/zustand/discussions/1180.", + replacement: { + match: /console\.warn\("\[DEPRECATED\] `context` will be removed in a future version\. Instead use `import { createStore, useStore } from 'zustand'`\. See: https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1180\."\);/, + replace: "" + } + }, // Patches discords generic logger function { find: "Σ:", diff --git a/src/plugins/decor/lib/stores/AuthorizationStore.tsx b/src/plugins/decor/lib/stores/AuthorizationStore.tsx index ba71da99e..7f3468fd0 100644 --- a/src/plugins/decor/lib/stores/AuthorizationStore.tsx +++ b/src/plugins/decor/lib/stores/AuthorizationStore.tsx @@ -93,7 +93,7 @@ export const useAuthorizationStore = proxyLazy(() => zustandCreate( } as AuthorizationState), { name: "decor-auth", - getStorage: () => indexedDBStorage, + storage: indexedDBStorage, partialize: state => ({ tokens: state.tokens }), onRehydrateStorage: () => state => state?.init() } diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 3f44d106d..4b1959b5a 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -163,9 +163,13 @@ waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); export const PermissionsBits: t.PermissionsBits = findLazy(m => typeof m.ADMINISTRATOR === "bigint"); -export const zustandCreate = findByCodeLazy("will be removed in v4"); +export const { zustandCreate } = mapMangledModuleLazy(["useSyncExternalStoreWithSelector:", "Object.assign", /(\i)\?(\i)\(\1\):\2/], { + zustandCreate: filters.byCode(/(\i)\?(\i)\(\1\):\2/) +}); -export const zustandPersist = findByCodeLazy("[zustand persist middleware]"); +export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?", { + zustandPersist: filters.byCode(/(\(\i,\i\))=>.+?\i\1/) +}); export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); export const MessageCache = findByPropsLazy("clearCache", "_channelMessages"); @@ -181,7 +185,7 @@ export const ExpressionPickerStore: t.ExpressionPickerStore = mapMangledModuleLa toggleExpressionPicker: filters.byCode(/getState\(\)\.activeView===\i\?\i\(\):\i\(/), setExpressionPickerView: filters.byCode(/setState\({activeView:\i,lastActiveView:/), setSearchQuery: filters.byCode("searchQuery:"), - useExpressionPickerStore: filters.byCode("Object.is") + useExpressionPickerStore: filters.byCode(/\(\i,\i=\i\)=>/) }); export const PopoutActions: t.PopoutActions = mapMangledModuleLazy('type:"POPOUT_WINDOW_OPEN"', { From 7ef536c6c68f60ac94e89f37968ef83ef3d4b35a Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:02:56 -0300 Subject: [PATCH 23/82] Decor: Prevent more crashes --- .../decor/lib/stores/UsersDecorationsStore.ts | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/plugins/decor/lib/stores/UsersDecorationsStore.ts b/src/plugins/decor/lib/stores/UsersDecorationsStore.ts index a75115a3f..f47ccbc56 100644 --- a/src/plugins/decor/lib/stores/UsersDecorationsStore.ts +++ b/src/plugins/decor/lib/stores/UsersDecorationsStore.ts @@ -99,19 +99,28 @@ export function useUserDecorAvatarDecoration(user?: User): AvatarDecoration | nu const [decorAvatarDecoration, setDecorAvatarDecoration] = useState(user ? useUsersDecorationsStore.getState().getAsset(user.id) ?? null : null); useEffect(() => { - const destructor = useUsersDecorationsStore.subscribe( - state => { - if (!user) return; - const newDecorAvatarDecoration = state.getAsset(user.id); - if (!newDecorAvatarDecoration) return; - if (decorAvatarDecoration !== newDecorAvatarDecoration) setDecorAvatarDecoration(newDecorAvatarDecoration); + const destructor = (() => { + try { + return useUsersDecorationsStore.subscribe( + state => { + if (!user) return; + const newDecorAvatarDecoration = state.getAsset(user.id); + if (!newDecorAvatarDecoration) return; + if (decorAvatarDecoration !== newDecorAvatarDecoration) setDecorAvatarDecoration(newDecorAvatarDecoration); + } + ); + } catch { + return () => { }; } - ); + })(); + + try { + if (user) { + const { fetch: fetchUserDecorAvatarDecoration } = useUsersDecorationsStore.getState(); + fetchUserDecorAvatarDecoration(user.id); + } + } catch { } - if (user) { - const { fetch: fetchUserDecorAvatarDecoration } = useUsersDecorationsStore.getState(); - fetchUserDecorAvatarDecoration(user.id); - } return destructor; }, []); From af1edc88bf4be9a74b6cd32b9c8e0c17935b5f77 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:27:21 -0500 Subject: [PATCH 24/82] FakeNitro: Fix embedding animated emojis (#3012) --- src/plugins/fakeNitro/index.tsx | 8 ++++---- src/utils/discord.tsx | 13 ++++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 087bb5551..86c5ae4d6 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -20,11 +20,11 @@ import { addPreEditListener, addPreSendListener, removePreEditListener, removePr import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies"; -import { getCurrentGuild } from "@utils/discord"; +import { getCurrentGuild, getEmojiURL } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType, Patch } from "@utils/types"; import { findByCodeLazy, findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack"; -import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, GuildMemberStore, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; +import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, GuildMemberStore, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; import type { Emoji } from "@webpack/types"; import type { Message } from "discord-types/general"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; @@ -920,7 +920,7 @@ export default definePlugin({ const emojiString = `<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`; - const url = new URL(IconUtils.getEmojiURL({ id: emoji.id, animated: emoji.animated, size: s.emojiSize })); + const url = new URL(getEmojiURL(emoji.id, emoji.animated, s.emojiSize)); url.searchParams.set("size", s.emojiSize.toString()); url.searchParams.set("name", emoji.name); @@ -953,7 +953,7 @@ export default definePlugin({ hasBypass = true; - const url = new URL(IconUtils.getEmojiURL({ id: emoji.id, animated: emoji.animated, size: s.emojiSize })); + const url = new URL(getEmojiURL(emoji.id, emoji.animated, s.emojiSize)); url.searchParams.set("size", s.emojiSize.toString()); url.searchParams.set("name", emoji.name); diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 91fd791b2..ec96d0d41 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -19,7 +19,7 @@ import "./discord.css"; import { MessageObject } from "@api/MessageEvents"; -import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Channel, Guild, Message, User } from "discord-types/general"; import { Except } from "type-fest"; @@ -212,3 +212,14 @@ export async function fetchUserProfile(id: string, options?: FetchUserProfileOpt export function getUniqueUsername(user: User) { return user.discriminator === "0" ? user.username : user.tag; } + +/** + * Get the URL for an emoji. This function always returns a gif URL for animated emojis, instead of webp + * @param id The emoji id + * @param animated Whether the emoji is animated + * @param size The size for the emoji + */ +export function getEmojiURL(id: string, animated: boolean, size: number) { + const url = IconUtils.getEmojiURL({ id, animated, size }); + return animated ? url.replace(".webp", ".gif") : url; +} From 211569f7f5c4023f3ef5f4a3b52b6e495d025ff6 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:41:57 -0300 Subject: [PATCH 25/82] AlwaysExpandRoles: Fix collapse roles button not appearing --- src/plugins/alwaysExpandRoles/index.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/alwaysExpandRoles/index.ts b/src/plugins/alwaysExpandRoles/index.ts index 1c20b9777..c674f90c5 100644 --- a/src/plugins/alwaysExpandRoles/index.ts +++ b/src/plugins/alwaysExpandRoles/index.ts @@ -28,10 +28,18 @@ export default definePlugin({ patches: [ { find: 'action:"EXPAND_ROLES"', - replacement: { - match: /(roles:\i(?=.+?(\i)\(!0\)[,;]\i\({action:"EXPAND_ROLES"}\)).+?\[\i,\2\]=\i\.useState\()!1\)/, - replace: (_, rest, setExpandedRoles) => `${rest}!0)` - } + replacement: [ + { + match: /(roles:\i(?=.+?(\i)\(!0\)[,;]\i\({action:"EXPAND_ROLES"}\)).+?\[\i,\2\]=\i\.useState\()!1\)/, + replace: (_, rest, setExpandedRoles) => `${rest}!0)` + }, + { + // Fix not calculating non-expanded roles because the above patch makes the default "expanded", + // which makes the collapse button never show up and calculation never occur + match: /(?<=useLayoutEffect\(\(\)=>{if\()\i/, + replace: isExpanded => "false" + } + ] } ] }); From 66a75747f80ad89e4047b378a7552847c1f2fd8e Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:44:13 -0500 Subject: [PATCH 26/82] ViewIcons: Fix conflict with unread Group DMs (#3011) --- src/plugins/viewIcons/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/viewIcons/index.tsx b/src/plugins/viewIcons/index.tsx index 629708140..c53116b4b 100644 --- a/src/plugins/viewIcons/index.tsx +++ b/src/plugins/viewIcons/index.tsx @@ -209,10 +209,11 @@ export default definePlugin({ }, // Group DMs top small & large icon { - find: /\.recipients\.length>=2(?! `${m},onClick:()=>$self.openAvatar(${iconUrl})` + // We have to check that icon is not an unread GDM in the server bar + replace: (m, iconUrl) => `${m},onClick:()=>arguments[0]?.size!=="SIZE_48"&&$self.openAvatar(${iconUrl})` } }, // User DMs top small icon From e0d66ff0719ce9c51c685dbdd6000ffc06b06d25 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:02:18 -0300 Subject: [PATCH 27/82] NoMosaic: Fix plugin not working in Canary --- src/plugins/consoleJanitor/index.ts | 7 ------- src/plugins/noMosaic/index.ts | 6 +++--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 4c5499cf4..a02fcad1b 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -151,13 +151,6 @@ export default definePlugin({ replace: "" } }, - { - find: "[DEPRECATED] `context` will be removed in a future version. Instead use `import { createStore, useStore } from 'zustand'`. See: https://github.com/pmndrs/zustand/discussions/1180.", - replacement: { - match: /console\.warn\("\[DEPRECATED\] `context` will be removed in a future version\. Instead use `import { createStore, useStore } from 'zustand'`\. See: https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1180\."\);/, - replace: "" - } - }, // Patches discords generic logger function { find: "Σ:", diff --git a/src/plugins/noMosaic/index.ts b/src/plugins/noMosaic/index.ts index 962b90fe7..6ff34a350 100644 --- a/src/plugins/noMosaic/index.ts +++ b/src/plugins/noMosaic/index.ts @@ -20,7 +20,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "NoMosaic", authors: [Devs.AutumnVN], - description: "Removes Discord new image mosaic", + description: "Removes Discord image mosaic", tags: ["image", "mosaic", "media"], settings, @@ -29,8 +29,8 @@ export default definePlugin({ { find: '=>"IMAGE"===', replacement: { - match: /=>"IMAGE"===\i\|\|"VIDEO"===\i;/, - replace: "=>false;" + match: /=>"IMAGE"===\i\|\|"VIDEO"===\i(?:\|\|("VISUAL_PLACEHOLDER"===\i))?;/, + replace: (_, visualPlaceholderPred) => visualPlaceholderPred != null ? `=>${visualPlaceholderPred};` : "=>false;" } }, { From 25ceff5ec2ba708f3668bac7a4338549b09ad71c Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:44:21 -0300 Subject: [PATCH 28/82] ChunkLoader: Avoid CSS debugging chunk --- src/debug/loadLazyChunks.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts index b7a8fbc66..6923d3a23 100644 --- a/src/debug/loadLazyChunks.ts +++ b/src/debug/loadLazyChunks.ts @@ -27,7 +27,12 @@ export async function loadLazyChunks() { const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?)\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/g); + const foundCssDebuggingLoad = false; + async function searchAndLoadLazyChunks(factoryCode: string) { + // Workaround to avoid loading the CSS debugging chunk which turns the app pink + const hasCssDebuggingLoad = foundCssDebuggingLoad ? false : factoryCode.includes(".cssDebuggingEnabled&&"); + const lazyChunks = factoryCode.matchAll(LazyChunkRegex); const validChunkGroups = new Set<[chunkIds: number[], entryPoint: number]>(); @@ -43,6 +48,16 @@ export async function loadLazyChunks() { let invalidChunkGroup = false; for (const id of chunkIds) { + if (hasCssDebuggingLoad) { + if (chunkIds.length > 1) { + throw new Error("Found multiple chunks in factory that loads the CSS debugging chunk"); + } + + invalidChunks.add(id); + invalidChunkGroup = true; + break; + } + if (wreq.u(id) == null || wreq.u(id) === "undefined.js") continue; const isWorkerAsset = await fetch(wreq.p + wreq.u(id)) From 76df29fba29f6b34ab9e8b6f392d465775f7aa4f Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:51:58 -0300 Subject: [PATCH 29/82] Actually stop searching for CSS debugging chunk --- src/debug/loadLazyChunks.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts index 6923d3a23..c7f8047db 100644 --- a/src/debug/loadLazyChunks.ts +++ b/src/debug/loadLazyChunks.ts @@ -27,11 +27,11 @@ export async function loadLazyChunks() { const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?)\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/g); - const foundCssDebuggingLoad = false; + let foundCssDebuggingLoad = false; async function searchAndLoadLazyChunks(factoryCode: string) { // Workaround to avoid loading the CSS debugging chunk which turns the app pink - const hasCssDebuggingLoad = foundCssDebuggingLoad ? false : factoryCode.includes(".cssDebuggingEnabled&&"); + const hasCssDebuggingLoad = foundCssDebuggingLoad ? false : (foundCssDebuggingLoad = factoryCode.includes(".cssDebuggingEnabled&&")); const lazyChunks = factoryCode.matchAll(LazyChunkRegex); const validChunkGroups = new Set<[chunkIds: number[], entryPoint: number]>(); From 8558b1a58948625c2c1f29be439d2329c36dfc82 Mon Sep 17 00:00:00 2001 From: Frocat <65976911+ItsFrocat@users.noreply.github.com> Date: Thu, 14 Nov 2024 23:54:01 +0100 Subject: [PATCH 30/82] ShikiCodeblocks: Updated codeblocks themes (#3013) --- .../shikiCodeblocks.desktop/api/themes.ts | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/plugins/shikiCodeblocks.desktop/api/themes.ts b/src/plugins/shikiCodeblocks.desktop/api/themes.ts index f31ce60b3..bc1dd184d 100644 --- a/src/plugins/shikiCodeblocks.desktop/api/themes.ts +++ b/src/plugins/shikiCodeblocks.desktop/api/themes.ts @@ -1,6 +1,6 @@ /* * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors + * Copyright (c) 2024 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 @@ -18,9 +18,9 @@ import { IShikiTheme } from "@vap/shiki"; -export const SHIKI_REPO = "shikijs/shiki"; -export const SHIKI_REPO_COMMIT = "0b28ad8ccfbf2615f2d9d38ea8255416b8ac3043"; -export const shikiRepoTheme = (name: string) => `https://raw.githubusercontent.com/${SHIKI_REPO}/${SHIKI_REPO_COMMIT}/packages/shiki/themes/${name}.json`; +export const SHIKI_REPO = "shikijs/textmate-grammars-themes"; +export const SHIKI_REPO_COMMIT = "2d87559c7601a928b9f7e0f0dda243d2fb6d4499"; +export const shikiRepoTheme = (name: string) => `https://raw.githubusercontent.com/${SHIKI_REPO}/${SHIKI_REPO_COMMIT}/packages/tm-themes/themes/${name}.json`; export const themes = { // Default @@ -30,33 +30,59 @@ export const themes = { MaterialCandy: "https://raw.githubusercontent.com/millsp/material-candy/master/material-candy.json", // More from Shiki repo + Andromeeda: shikiRepoTheme("andromeeda"), + AuroraX: shikiRepoTheme("aurora-x"), + AyuDark: shikiRepoTheme("ayu-dark"), + CatppuccinLatte: shikiRepoTheme("catppuccin-latte"), + CatppuccinFrappe: shikiRepoTheme("catppuccin-frappe"), + CatppuccinMacchiato: shikiRepoTheme("catppuccin-macchiato"), + CatppuccinMocha: shikiRepoTheme("catppuccin-mocha"), DraculaSoft: shikiRepoTheme("dracula-soft"), Dracula: shikiRepoTheme("dracula"), + EverforestDark: shikiRepoTheme("everforest-dark"), + EverforestLight: shikiRepoTheme("everforest-light"), + GithubDarkDefault: shikiRepoTheme("github-dark-default"), GithubDarkDimmed: shikiRepoTheme("github-dark-dimmed"), + GithubDarkHighContrast: shikiRepoTheme("github-dark-high-contrast"), GithubDark: shikiRepoTheme("github-dark"), + GithubLightDefault: shikiRepoTheme("github-light-default"), + GithubLightHighContrast: shikiRepoTheme("github-light-high-contrast"), GithubLight: shikiRepoTheme("github-light"), + Houston: shikiRepoTheme("houston"), + KanagawaDragon: shikiRepoTheme("kanagawa-dragon"), + KanagawaLotus: shikiRepoTheme("kanagawa-lotus"), + KanagawaWave: shikiRepoTheme("kanagawa-wave"), + LaserWave: shikiRepoTheme("laserwave"), LightPlus: shikiRepoTheme("light-plus"), - MaterialDarker: shikiRepoTheme("material-darker"), - MaterialDefault: shikiRepoTheme("material-default"), - MaterialLighter: shikiRepoTheme("material-lighter"), - MaterialOcean: shikiRepoTheme("material-ocean"), - MaterialPalenight: shikiRepoTheme("material-palenight"), + MaterialDarker: shikiRepoTheme("material-theme-darker"), + MaterialDefault: shikiRepoTheme("material-theme"), + MaterialLighter: shikiRepoTheme("material-theme-lighter"), + MaterialOcean: shikiRepoTheme("material-theme-ocean"), + MaterialPalenight: shikiRepoTheme("material-theme-palenight"), MinDark: shikiRepoTheme("min-dark"), MinLight: shikiRepoTheme("min-light"), Monokai: shikiRepoTheme("monokai"), + NightOwl: shikiRepoTheme("night-owl"), Nord: shikiRepoTheme("nord"), OneDarkPro: shikiRepoTheme("one-dark-pro"), + OneLight: shikiRepoTheme("one-light"), + Plastic: shikiRepoTheme("plastic"), Poimandres: shikiRepoTheme("poimandres"), + Red: shikiRepoTheme("red"), RosePineDawn: shikiRepoTheme("rose-pine-dawn"), RosePineMoon: shikiRepoTheme("rose-pine-moon"), RosePine: shikiRepoTheme("rose-pine"), SlackDark: shikiRepoTheme("slack-dark"), SlackOchin: shikiRepoTheme("slack-ochin"), + SnazzyLight: shikiRepoTheme("snazzy-light"), SolarizedDark: shikiRepoTheme("solarized-dark"), SolarizedLight: shikiRepoTheme("solarized-light"), + Synthwave84: shikiRepoTheme("synthwave-84"), + TokyoNight: shikiRepoTheme("tokyo-night"), + Vesper: shikiRepoTheme("vesper"), + VitesseBlack: shikiRepoTheme("vitesse-black"), VitesseDark: shikiRepoTheme("vitesse-dark"), VitesseLight: shikiRepoTheme("vitesse-light"), - CssVariables: shikiRepoTheme("css-variables"), }; export const themeCache = new Map(); From c4f6f151e6692c2fb3dafd103f89f63d578bad8b Mon Sep 17 00:00:00 2001 From: Lumap Date: Thu, 14 Nov 2024 23:57:16 +0100 Subject: [PATCH 31/82] PictureInPicture: Fix button not showing up (#3014) --- src/plugins/pictureInPicture/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/pictureInPicture/index.tsx b/src/plugins/pictureInPicture/index.tsx index 20cedf45b..ef3d35ff1 100644 --- a/src/plugins/pictureInPicture/index.tsx +++ b/src/plugins/pictureInPicture/index.tsx @@ -30,10 +30,10 @@ export default definePlugin({ { find: ".removeMosaicItemHoverButton),", replacement: { - match: /\.nonMediaMosaicItem\]:!(\i).{0,50}?children:\[\S,(\S)/, - replace: "$&,$1&&$2&&$self.renderPiPButton()," - }, - }, + match: /\.nonMediaMosaicItem\]:.{0,40}children:\[(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/, + replace: "$&$1&&$2&&$self.renderPiPButton()," + } + } ], renderPiPButton: ErrorBoundary.wrap(() => { From 99458da3beb21dcba71abc64cb99c0f4f232cb81 Mon Sep 17 00:00:00 2001 From: nyx <60797172+verticalsync@users.noreply.github.com> Date: Fri, 15 Nov 2024 01:00:11 +0200 Subject: [PATCH 32/82] ViewRaw: Add support for Group DMs (#3010) --- src/plugins/viewRaw/index.tsx | 1 + src/utils/constants.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/viewRaw/index.tsx b/src/plugins/viewRaw/index.tsx index 0134ea3e3..8ee1ca8d7 100644 --- a/src/plugins/viewRaw/index.tsx +++ b/src/plugins/viewRaw/index.tsx @@ -155,6 +155,7 @@ export default definePlugin({ "guild-context": MakeContextCallback("Guild"), "channel-context": MakeContextCallback("Channel"), "thread-context": MakeContextCallback("Channel"), + "gdm-context": MakeContextCallback("Channel"), "user-context": MakeContextCallback("User") }, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 70eca56fd..11ce47388 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -520,8 +520,8 @@ export const Devs = /* #__PURE__*/ Object.freeze({ id: 721717126523781240n, }, nyx: { - name: "verticalsync", - id: 328165170536775680n + name: "verticalsync.", + id: 1207087393929171095n }, nekohaxx: { name: "nekohaxx", @@ -575,7 +575,7 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "RamziAH", id: 1279957227612147747n, }, - SomeAspy: { + SomeAspy: { name: "SomeAspy", id: 516750892372852754n, }, From ea2772476dc6d042b1e3769ad24727b01b02878d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:45:07 -0300 Subject: [PATCH 33/82] RoleColorEverywhere: Poll Results & Cleanup Co-authored-by: jamesbt365 --- src/plugins/roleColorEverywhere/index.tsx | 133 ++++++++++++++-------- src/utils/constants.ts | 4 + 2 files changed, 90 insertions(+), 47 deletions(-) diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 204bc0be3..055c39874 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -20,6 +20,7 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { makeRange } from "@components/PluginSettings/components"; import { Devs } from "@utils/constants"; +import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy } from "@webpack"; import { ChannelStore, GuildMemberStore, GuildStore } from "@webpack/common"; @@ -51,6 +52,12 @@ const settings = definePluginSettings({ description: "Show role colors in the reactors list", restartNeeded: true }, + pollResults: { + type: OptionType.BOOLEAN, + default: true, + description: "Show role colors in the poll results", + restartNeeded: true + }, colorChatMessages: { type: OptionType.BOOLEAN, default: false, @@ -62,14 +69,15 @@ const settings = definePluginSettings({ description: "Intensity of message coloring.", markers: makeRange(0, 100, 10), default: 30 - }, + } }); - export default definePlugin({ name: "RoleColorEverywhere", - authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi], + authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi, Devs.jamesbt365], description: "Adds the top role color anywhere possible", + settings, + patches: [ // Chat Mentions { @@ -77,100 +85,106 @@ export default definePlugin({ replacement: [ { match: /onContextMenu:\i,color:\i,\.\.\.\i(?=,children:)(?<=user:(\i),channel:(\i).{0,500}?)/, - replace: "$&,color:$self.getUserColor($1?.id,{channelId:$2?.id})" + replace: "$&,color:$self.getColorInt($1?.id,$2?.id)" } ], - predicate: () => settings.store.chatMentions, + predicate: () => settings.store.chatMentions }, // Slate { find: ".userTooltip,children", replacement: [ { - match: /let\{id:(\i),guildId:(\i)[^}]*\}.*?\.\i,{(?=children)/, - replace: "$&color:$self.getUserColor($1,{guildId:$2})," + match: /let\{id:(\i),guildId:\i,channelId:(\i)[^}]*\}.*?\.\i,{(?=children)/, + replace: "$&color:$self.getColorInt($1,$2)," } ], - predicate: () => settings.store.chatMentions, + predicate: () => settings.store.chatMentions }, + // Member List Role Headers { find: 'tutorialId:"whos-online', replacement: [ { match: /null,\i," — ",\i\]/, - replace: "null,$self.roleGroupColor(arguments[0])]" + replace: "null,$self.RoleGroupColor(arguments[0])]" }, ], - predicate: () => settings.store.memberList, + predicate: () => settings.store.memberList }, { find: "#{intl::THREAD_BROWSER_PRIVATE}", replacement: [ { match: /children:\[\i," — ",\i\]/, - replace: "children:[$self.roleGroupColor(arguments[0])]" + replace: "children:[$self.RoleGroupColor(arguments[0])]" }, ], - predicate: () => settings.store.memberList, + predicate: () => settings.store.memberList }, + // Voice Users { - find: "renderPrioritySpeaker", + find: "renderPrioritySpeaker(){", replacement: [ { match: /renderName\(\){.+?usernameSpeaking\]:.+?(?=children)/, - replace: "$&...$self.getVoiceProps(this.props)," + replace: "$&style:$self.getColorStyle(this?.props?.user?.id,this?.props?.guildId)," } ], - predicate: () => settings.store.voiceUsers, + predicate: () => settings.store.voiceUsers }, + // Reaction List { find: ".reactorDefault", replacement: { - match: /,onContextMenu:e=>.{0,15}\((\i),(\i),(\i)\).{0,250}tag:"strong"/, - replace: "$&,style:{color:$self.getColor($2?.id,$1)}" + match: /,onContextMenu:\i=>.{0,15}\((\i),(\i),(\i)\).{0,250}tag:"strong"/, + replace: "$&,style:$self.getColorStyle($2?.id,$1?.channel?.id)" }, predicate: () => settings.store.reactorsList, }, + // Poll Results + { + find: ",reactionVoteCounts", + replacement: { + match: /\.nickname,(?=children:)/, + replace: "$&style:$self.getColorStyle(arguments[0]?.user?.id,arguments[0]?.channel?.id)," + }, + predicate: () => settings.store.pollResults + }, + // Messages { find: "#{intl::MESSAGE_EDITED}", replacement: { match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/, - replace: "style:{color:$self.useMessageColor($1)}," + replace: "style:$self.useMessageColorStyle($1)," }, - predicate: () => settings.store.colorChatMessages, - }, + predicate: () => settings.store.colorChatMessages + } ], - settings, - getColor(userId: string, { channelId, guildId }: { channelId?: string; guildId?: string; }) { - if (!(guildId ??= ChannelStore.getChannel(channelId!)?.guild_id)) return null; - return GuildMemberStore.getMember(guildId, userId)?.colorString ?? null; + getColorString(userId: string, channelOrGuildId: string) { + try { + const guildId = ChannelStore.getChannel(channelOrGuildId)?.guild_id ?? GuildStore.getGuild(channelOrGuildId)?.id; + if (guildId == null) return null; + + return GuildMemberStore.getMember(guildId, userId)?.colorString ?? null; + } catch (e) { + new Logger("RoleColorEverywhere").error("Failed to get color string", e); + } + + return null; }, - getUserColor(userId: string, ids: { channelId?: string; guildId?: string; }) { - const colorString = this.getColor(userId, ids); + getColorInt(userId: string, channelOrGuildId: string) { + const colorString = this.getColorString(userId, channelOrGuildId); return colorString && parseInt(colorString.slice(1), 16); }, - roleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => { - const role = GuildStore.getRole(guildId, id); + getColorStyle(userId: string, channelOrGuildId: string) { + const colorString = this.getColorString(userId, channelOrGuildId); - return ( - - {title ?? label} — {count} - - ); - }, { noop: true }), - - getVoiceProps({ user: { id: userId }, guildId }: { user: { id: string; }; guildId: string; }) { - return { - style: { - color: this.getColor(userId, { guildId }) - } + return colorString && { + color: colorString }; }, @@ -178,11 +192,36 @@ export default definePlugin({ try { const { messageSaturation } = settings.use(["messageSaturation"]); const author = useMessageAuthor(message); - if (author.colorString !== undefined && messageSaturation !== 0) + + if (author.colorString != null && messageSaturation !== 0) { return `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var(--text-normal))`; + } } catch (e) { - console.error("[RCE] failed to get message color", e); + new Logger("RoleColorEverywhere").error("Failed to get message color", e); } - return undefined; + + return null; }, + + useMessageColorStyle(message: any) { + const color = this.useMessageColor(message); + + return color && { + color + }; + }, + + RoleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => { + const role = GuildStore.getRole(guildId, id); + + return role != null && ( + + {title ?? label} — {count} + + ); + }, { noop: true }) }); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 11ce47388..362a22dee 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -579,6 +579,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "SomeAspy", id: 516750892372852754n, }, + jamesbt365: { + name: "jamesbt365", + id: 158567567487795200n, + }, } satisfies Record); // iife so #__PURE__ works correctly From 5cf22113cff362ac7168cab9066c85236cd80b73 Mon Sep 17 00:00:00 2001 From: jenku <80538856+jenkuuuuuu@users.noreply.github.com> Date: Sun, 17 Nov 2024 21:55:33 +0000 Subject: [PATCH 34/82] Decor: Update notice about joining the server for clarity (#3021) --- src/plugins/decor/ui/modals/CreateDecorationModal.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index f5596f391..57a39540d 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -20,7 +20,7 @@ import { AvatarDecorationModalPreview } from "../components"; const FileUpload = findComponentByCodeLazy("fileUploadInput,"); const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE=3]="POSITIVE', { - HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"), + HelpMessageTypes: filters.byProps("POSITIVE", "WARNING", "INFO"), HelpMessage: filters.byCode(".iconDiv") }); @@ -119,8 +119,8 @@ function CreateDecorationModal(props: ModalProps) { />
- -
You can receive updates on your decoration's review by joining + To receive updates on your decoration's review, join { e.preventDefault(); @@ -138,8 +138,8 @@ function CreateDecorationModal(props: ModalProps) { }} > Decor's Discord server - . -
+ and allow direct messages. + From cd61f4e7449343acfcc7debf42ee20958fcebf20 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:42:15 -0300 Subject: [PATCH 35/82] RoleColorEverywhere: Fix Online/Offline --- src/plugins/roleColorEverywhere/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 055c39874..090c35d3a 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -214,9 +214,9 @@ export default definePlugin({ RoleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => { const role = GuildStore.getRole(guildId, id); - return role != null && ( + return ( From a0308e03affd9345fe8774e528113ca280725d0e Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:17:20 -0300 Subject: [PATCH 36/82] Fix OpenInApp & ShowHiddenThings --- .../decor/ui/modals/ChangeDecorationModal.tsx | 12 ++++++++---- .../decor/ui/modals/CreateDecorationModal.tsx | 2 +- src/plugins/openInApp/index.ts | 2 +- src/plugins/showHiddenThings/index.ts | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx index 6501e0feb..a3edc0978 100644 --- a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx @@ -10,6 +10,7 @@ import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; import { classes, copyWithToast } from "@utils/misc"; import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; +import { Queue } from "@utils/Queue"; import { findComponentByCodeLazy } from "@webpack"; import { Alerts, Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Parser, Text, Tooltip, useEffect, UserStore, UserUtils, useState } from "@webpack/common"; import { User } from "discord-types/general"; @@ -49,6 +50,8 @@ interface SectionHeaderProps { section: Section; } +const fetchAuthorsQueue = new Queue(); + function SectionHeader({ section }: SectionHeaderProps) { const hasSubtitle = typeof section.subtitle !== "undefined"; const hasAuthorIds = typeof section.authorIds !== "undefined"; @@ -56,17 +59,18 @@ function SectionHeader({ section }: SectionHeaderProps) { const [authors, setAuthors] = useState([]); useEffect(() => { - (async () => { + fetchAuthorsQueue.push(async () => { if (!section.authorIds) return; for (const authorId of section.authorIds) { - const author = UserStore.getUser(authorId) ?? await UserUtils.getUser(authorId); + const author = UserStore.getUser(authorId) ?? await UserUtils.getUser(authorId).catch(() => null); + if (author == null) continue; + setAuthors(authors => [...authors, author]); } - })(); + }); }, [section.authorIds]); - return
{section.title} diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index 57a39540d..eb39c16df 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -119,7 +119,7 @@ function CreateDecorationModal(props: ModalProps) { />
- + To receive updates on your decoration's review, join { diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 1e4f30412..2d27c2b20 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -87,7 +87,7 @@ export default definePlugin({ { find: "trackAnnouncementMessageLinkClicked({", replacement: { - match: /function (\i\(\i,\i\)\{)(?=.{0,100}trusted:)/, + match: /function (\i\(\i,\i\)\{)(?=.{0,150}trusted:)/, replace: "async function $1 if(await $self.handleLink(...arguments)) return;" } }, diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 8fd6ef82e..9f6fd2a90 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -107,7 +107,7 @@ export default definePlugin({ predicate: () => settings.store.disableDisallowedDiscoveryFilters, all: true, replacement: { - match: /\i\.\i\.get\(\{url:\i\.\i\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\)/g, + match: /\i\.\i\.get\(\{url:\i\.\i\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0,rejectWithError:!1\}\)/g, replace: "Promise.resolve({ body: { valid: true } })" } } From 13993f3f69d587c247900589a88e4264cc57b0c8 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Sat, 23 Nov 2024 21:01:58 -0500 Subject: [PATCH 37/82] Decor: Fix avatar decorations not showing (again) (#3025) --- src/plugins/consoleJanitor/index.ts | 21 --------------------- src/webpack/common/utils.ts | 4 ++-- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index a02fcad1b..2c29bf670 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -130,27 +130,6 @@ export default definePlugin({ replace: "" } }, - // Zustand section - { - find: "[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.", - replacement: [ - { - match: /&&console\.warn\("\[DEPRECATED\] Passing a vanilla store will be unsupported in a future version\. Instead use `import { useStore } from 'zustand'`\."\)/, - replace: "" - }, - { - match: /console\.warn\("\[DEPRECATED\] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`\. They can be imported from 'zustand\/traditional'\. https:\/\/github\.com\/pmndrs\/zustand\/discussions\/1937"\),/, - replace: "" - } - ] - }, - { - find: "[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead.", - replacement: { - match: /console\.warn\("\[DEPRECATED\] `getStorage`, `serialize` and `deserialize` options are deprecated\. Use `storage` option instead\."\),/, - replace: "" - } - }, // Patches discords generic logger function { find: "Σ:", diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 4b1959b5a..dc337a2ef 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -163,8 +163,8 @@ waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); export const PermissionsBits: t.PermissionsBits = findLazy(m => typeof m.ADMINISTRATOR === "bigint"); -export const { zustandCreate } = mapMangledModuleLazy(["useSyncExternalStoreWithSelector:", "Object.assign", /(\i)\?(\i)\(\1\):\2/], { - zustandCreate: filters.byCode(/(\i)\?(\i)\(\1\):\2/) +export const { zustandCreate } = mapMangledModuleLazy(["useSyncExternalStoreWithSelector:", "Object.assign"], { + zustandCreate: filters.byCode(/=>(\i)\?\i\(\1/) }); export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?", { From ac1b1d44f5d994cd8d3c44e58f28bd1d76842cef Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Sat, 23 Nov 2024 21:03:59 -0500 Subject: [PATCH 38/82] ShowHiddenChannels: Fix viewing voice channels (#3033) --- src/plugins/showHiddenChannels/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index ba3675428..6b67aee8b 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -103,7 +103,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: /(?<=getBlockedUsersForVoiceChannel\((\i)\.id\);return\()/, + match: /(?<=getIgnoredUsersForVoiceChannel\((\i)\.id\);return\()/, replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&` }, { From f22d0e14a42fc600a4768afd3855cd5959829b81 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Sat, 23 Nov 2024 21:07:46 -0500 Subject: [PATCH 39/82] EmoteCloner: Fix recognizing animated emojis (#3027) --- src/plugins/emoteCloner/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/emoteCloner/index.tsx b/src/plugins/emoteCloner/index.tsx index 6dd3eb300..1b26e2f05 100644 --- a/src/plugins/emoteCloner/index.tsx +++ b/src/plugins/emoteCloner/index.tsx @@ -310,7 +310,8 @@ function buildMenuItem(type: "Emoji" | "Sticker", fetchData: () => Promisable { From f8dfe217b11844c2a08c1d3890def4a82cb192b8 Mon Sep 17 00:00:00 2001 From: Cassie <37855219+CodeF53@users.noreply.github.com> Date: Sat, 23 Nov 2024 19:08:53 -0700 Subject: [PATCH 40/82] Remove no-longer desired collaborator (#3032) --- src/plugins/clientTheme/index.tsx | 2 +- src/utils/constants.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/plugins/clientTheme/index.tsx b/src/plugins/clientTheme/index.tsx index 7e6484276..4c1668aae 100644 --- a/src/plugins/clientTheme/index.tsx +++ b/src/plugins/clientTheme/index.tsx @@ -110,7 +110,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "ClientTheme", - authors: [Devs.F53, Devs.Nuckyz], + authors: [Devs.Nuckyz], description: "Recreation of the old client theme experiment. Add a color to your Discord client theme", settings, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 362a22dee..e75825912 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -267,10 +267,6 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "arHSM", id: 841509053422632990n }, - F53: { - name: "Cassie (Code)", - id: 280411966126948353n - }, AutumnVN: { name: "AutumnVN", id: 393694671383166998n From 7ca4ea3d136db420e29f82535b2c6f1d59e6aa28 Mon Sep 17 00:00:00 2001 From: Hen <68553709+henmalib@users.noreply.github.com> Date: Sun, 24 Nov 2024 03:16:41 +0100 Subject: [PATCH 41/82] RoleColorEverywhere: Fix message headers colors (#3036) --- src/plugins/roleColorEverywhere/index.tsx | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 090c35d3a..7b811943d 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -156,7 +156,7 @@ export default definePlugin({ find: "#{intl::MESSAGE_EDITED}", replacement: { match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/, - replace: "style:$self.useMessageColorStyle($1)," + replace: "style:$self.useMessageColorsStyle($1)," }, predicate: () => settings.store.colorChatMessages } @@ -188,13 +188,19 @@ export default definePlugin({ }; }, - useMessageColor(message: any) { + useMessageColorsStyle(message: any) { try { const { messageSaturation } = settings.use(["messageSaturation"]); const author = useMessageAuthor(message); if (author.colorString != null && messageSaturation !== 0) { - return `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var(--text-normal))`; + const value = `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var({DEFAULT}))`; + + return { + color: value.replace("{DEFAULT}", "--text-normal"), + "--header-primary": value.replace("{DEFAULT}", "--header-primary"), + "--text-muted": value.replace("{DEFAULT}", "--text-muted") + }; } } catch (e) { new Logger("RoleColorEverywhere").error("Failed to get message color", e); @@ -203,14 +209,6 @@ export default definePlugin({ return null; }, - useMessageColorStyle(message: any) { - const color = this.useMessageColor(message); - - return color && { - color - }; - }, - RoleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => { const role = GuildStore.getRole(guildId, id); From 2bfeef88caa95d8af170807666c8595818fb2c48 Mon Sep 17 00:00:00 2001 From: samara Date: Sat, 23 Nov 2024 18:23:03 -0800 Subject: [PATCH 42/82] Update to newer Discord icons in Vencord Settings (#3029) --- src/components/Icons.tsx | 52 +++++++++++-------- .../PluginSettings/LinkIconButton.tsx | 7 ++- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx index d0d2ecbe8..e48cfe5f1 100644 --- a/src/components/Icons.tsx +++ b/src/components/Icons.tsx @@ -18,7 +18,7 @@ import "./iconStyles.css"; -import { getIntlMessage, getTheme, Theme } from "@utils/discord"; +import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import type { PropsWithChildren } from "react"; @@ -122,8 +122,8 @@ export function InfoIcon(props: IconProps) { >
); @@ -211,9 +211,10 @@ export function CogWheel(props: IconProps) { viewBox="0 0 24 24" > ); @@ -406,23 +407,30 @@ export function PencilIcon(props: IconProps) { ); } -const WebsiteIconDark = "/assets/e1e96d89e192de1997f73730db26e94f.svg"; -const WebsiteIconLight = "/assets/730f58bcfd5a57a5e22460c445a0c6cf.svg"; -const GithubIconLight = "/assets/3ff98ad75ac94fa883af5ed62d17c459.svg"; -const GithubIconDark = "/assets/6a853b4c87fce386cbfef4a2efbacb09.svg"; - -export function GithubIcon(props: ImageProps) { - const src = getTheme() === Theme.Light - ? GithubIconLight - : GithubIconDark; - - return ; +export function GithubIcon(props: IconProps) { + return ( + + + + ); } -export function WebsiteIcon(props: ImageProps) { - const src = getTheme() === Theme.Light - ? WebsiteIconLight - : WebsiteIconDark; - - return ; +export function WebsiteIcon(props: IconProps) { + return ( + + + + ); } diff --git a/src/components/PluginSettings/LinkIconButton.tsx b/src/components/PluginSettings/LinkIconButton.tsx index dd840f52e..4dae0e1e9 100644 --- a/src/components/PluginSettings/LinkIconButton.tsx +++ b/src/components/PluginSettings/LinkIconButton.tsx @@ -6,16 +6,19 @@ import "./LinkIconButton.css"; +import { getTheme, Theme } from "@utils/discord"; import { MaskedLink, Tooltip } from "@webpack/common"; import { GithubIcon, WebsiteIcon } from ".."; export function GithubLinkIcon() { - return ; + const theme = getTheme() === Theme.Light ? "#000000" : "#FFFFFF"; + return ; } export function WebsiteLinkIcon() { - return ; + const theme = getTheme() === Theme.Light ? "#000000" : "#FFFFFF"; + return ; } interface Props { From 5fb63246cacf4152010267e33c8cc32c01bbaa7e Mon Sep 17 00:00:00 2001 From: Etorix <92535668+EtorixDev@users.noreply.github.com> Date: Sun, 24 Nov 2024 16:25:30 -0800 Subject: [PATCH 43/82] Add support for onAuxClick on ChatBarButton (#3043) --- src/api/ChatButtons.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api/ChatButtons.tsx b/src/api/ChatButtons.tsx index fcb76fffc..5f9ae9e73 100644 --- a/src/api/ChatButtons.tsx +++ b/src/api/ChatButtons.tsx @@ -99,7 +99,8 @@ export interface ChatBarButtonProps { tooltip: string; onClick: MouseEventHandler; onContextMenu?: MouseEventHandler; - buttonProps?: Omit, "size" | "onClick" | "onContextMenu">; + onAuxClick?: MouseEventHandler; + buttonProps?: Omit, "size" | "onClick" | "onContextMenu" | "onAuxClick">; } export const ChatBarButton = ErrorBoundary.wrap((props: ChatBarButtonProps) => { return ( @@ -115,6 +116,7 @@ export const ChatBarButton = ErrorBoundary.wrap((props: ChatBarButtonProps) => { innerClassName={`${ButtonWrapperClasses.button} ${ChannelTextAreaClasses?.button}`} onClick={props.onClick} onContextMenu={props.onContextMenu} + onAuxClick={props.onAuxClick} {...props.buttonProps} >
From 23c9e2ce2212a03641cb524c931309c3ab113da4 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:30:27 -0500 Subject: [PATCH 44/82] ShowHiddenThings: Allow opening mod view on yourself (#3045) --- src/plugins/showHiddenThings/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 9f6fd2a90..30edb2470 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -75,6 +75,15 @@ export default definePlugin({ replace: "$1$2arguments[0].member.highestRoleId]", } }, + // allows you to open mod view on yourself + { + find: ".MEMBER_SAFETY,{modViewPanel:", + predicate: () => settings.store.showModView, + replacement: { + match: /\i(?=\?null)/, + replace: "false" + } + }, { find: "prod_discoverable_guilds", predicate: () => settings.store.disableDiscoveryFilters, From e7a54b05872c24d63f64b258e73f807c1010d431 Mon Sep 17 00:00:00 2001 From: Mia Rodriguez <62818119+xNasuni@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:35:12 -0500 Subject: [PATCH 45/82] SilentTyping: Improve button visual look (#3026) --- src/plugins/silentTyping/index.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index ad28999aa..d06ae8373 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -54,9 +54,17 @@ const SilentTypingToggle: ChatBarButton = ({ isMainChat }) => { tooltip={isEnabled ? "Disable Silent Typing" : "Enable Silent Typing"} onClick={toggle} > - - - {isEnabled && } + + + {isEnabled && ( + <> + + + + + + + )} ); From a9d44e3341d909ee46e4e769c44e5d50e84a7227 Mon Sep 17 00:00:00 2001 From: Sqaaakoi Date: Mon, 25 Nov 2024 17:14:25 +1300 Subject: [PATCH 46/82] PermissionsViewer: Fix permission description tooltip & cleanup (#3040) --- src/components/ExpandableHeader.css | 11 -- src/components/ExpandableHeader.tsx | 121 ------------------ src/components/index.ts | 1 - .../components/RolesAndUsersPermissions.tsx | 21 ++- .../components/UserPermissions.tsx | 94 ++++++++------ src/plugins/permissionsViewer/index.tsx | 9 +- src/plugins/permissionsViewer/styles.css | 16 ++- src/plugins/permissionsViewer/utils.ts | 48 +------ 8 files changed, 87 insertions(+), 234 deletions(-) delete mode 100644 src/components/ExpandableHeader.css delete mode 100644 src/components/ExpandableHeader.tsx diff --git a/src/components/ExpandableHeader.css b/src/components/ExpandableHeader.css deleted file mode 100644 index a556e36be..000000000 --- a/src/components/ExpandableHeader.css +++ /dev/null @@ -1,11 +0,0 @@ -.vc-expandableheader-center-flex { - display: flex; - place-items: center; -} - -.vc-expandableheader-btn { - all: unset; - cursor: pointer; - width: 24px; - height: 24px; -} diff --git a/src/components/ExpandableHeader.tsx b/src/components/ExpandableHeader.tsx deleted file mode 100644 index 473dffaa0..000000000 --- a/src/components/ExpandableHeader.tsx +++ /dev/null @@ -1,121 +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 "./ExpandableHeader.css"; - -import { classNameFactory } from "@api/Styles"; -import { Text, Tooltip, useState } from "@webpack/common"; - -const cl = classNameFactory("vc-expandableheader-"); - -export interface ExpandableHeaderProps { - onMoreClick?: () => void; - moreTooltipText?: string; - onDropDownClick?: (state: boolean) => void; - defaultState?: boolean; - headerText: string; - children: React.ReactNode; - buttons?: React.ReactNode[]; - forceOpen?: boolean; -} - -export function ExpandableHeader({ - children, - onMoreClick, - buttons, - moreTooltipText, - onDropDownClick, - headerText, - defaultState = false, - forceOpen = false, -}: ExpandableHeaderProps) { - const [showContent, setShowContent] = useState(defaultState || forceOpen); - - return ( - <> -
- - {headerText} - - -
- { - buttons ?? null - } - - { - onMoreClick && // only show more button if callback is provided - - {tooltipProps => ( - - )} - - } - - - - {tooltipProps => ( - - )} - -
-
- {showContent && children} - - ); -} diff --git a/src/components/index.ts b/src/components/index.ts index 38e610fd8..2782cb54e 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -10,7 +10,6 @@ export * from "./CodeBlock"; export * from "./DonateButton"; export { default as ErrorBoundary } from "./ErrorBoundary"; export * from "./ErrorCard"; -export * from "./ExpandableHeader"; export * from "./Flex"; export * from "./Heart"; export * from "./Icons"; diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx index 32dcaf8d6..b15937792 100644 --- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx +++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx @@ -22,12 +22,12 @@ import { InfoIcon, OwnerCrownIcon } from "@components/Icons"; import { getIntlMessage, getUniqueUsername } from "@utils/discord"; import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { findByCodeLazy } from "@webpack"; -import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common"; +import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, useMemo, UserStore, useState, useStateFromStores } from "@webpack/common"; import { UnicodeEmoji } from "@webpack/types"; import type { Guild, Role, User } from "discord-types/general"; import { settings } from ".."; -import { cl, getPermissionDescription, getPermissionString } from "../utils"; +import { cl, getGuildPermissionSpecMap } from "../utils"; import { PermissionAllowedIcon, PermissionDefaultIcon, PermissionDeniedIcon } from "./icons"; export const enum PermissionType { @@ -56,7 +56,7 @@ function getRoleIconSrc(role: Role) { } function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, header }: { permissions: Array; guild: Guild; modalProps: ModalProps; header: string; }) { - permissions.sort((a, b) => a.type - b.type); + const guildPermissionSpecMap = useMemo(() => getGuildPermissionSpecMap(guild), [guild.id]); useStateFromStores( [GuildMemberStore], @@ -65,6 +65,10 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea (old, current) => old.length === current.length ); + useEffect(() => { + permissions.sort((a, b) => a.type - b.type); + }, [permissions]); + useEffect(() => { const usersToRequest = permissions .filter(p => p.type === PermissionType.User && !GuildMemberStore.isMember(guild.id, p.id!)) @@ -173,7 +177,7 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea
- {Object.entries(PermissionsBits).map(([permissionName, bit]) => ( + {Object.values(PermissionsBits).map(bit => (
{(() => { @@ -192,9 +196,14 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea return PermissionDefaultIcon(); })()}
- {getPermissionString(permissionName)} + {guildPermissionSpecMap[String(bit)].title} - + { + const { description } = guildPermissionSpecMap[String(bit)]; + return typeof description === "function" ? i18n.intl.format(description, {}) : description; + })() + }> {props => }
diff --git a/src/plugins/permissionsViewer/components/UserPermissions.tsx b/src/plugins/permissionsViewer/components/UserPermissions.tsx index 720445daa..6eaeef841 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -17,7 +17,6 @@ */ import ErrorBoundary from "@components/ErrorBoundary"; -import { ExpandableHeader } from "@components/ExpandableHeader"; import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import { filters, findBulk, proxyLazyWebpack } from "@webpack"; @@ -25,7 +24,7 @@ import { PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/com import type { Guild, GuildMember } from "discord-types/general"; import { PermissionsSortOrder, settings } from ".."; -import { cl, getPermissionString, getSortedRoles, sortUserRoles } from "../utils"; +import { cl, getGuildPermissionSpecMap, getSortedRoles, sortUserRoles } from "../utils"; import openRolesAndUsersPermissionsModal, { PermissionType, type RoleOrUserPermission } from "./RolesAndUsersPermissions"; interface UserPermission { @@ -87,9 +86,11 @@ function GrantedByTooltip({ roleName, roleColor }: GrantedByTooltipProps) { ); } -function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { guild: Guild; guildMember: GuildMember; forceOpen?: boolean; }) { +function UserPermissionsComponent({ guild, guildMember, closePopout }: { guild: Guild; guildMember: GuildMember; closePopout: () => void; }) { const { permissionsSortOrder } = settings.use(["permissionsSortOrder"]); + const guildPermissionSpecMap = useMemo(() => getGuildPermissionSpecMap(guild), [guild.id]); + const [rolePermissions, userPermissions] = useMemo(() => { const userPermissions: UserPermissions = []; @@ -106,7 +107,7 @@ function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { g permissions: Object.values(PermissionsBits).reduce((prev, curr) => prev | curr, 0n) }); - const OWNER = getIntlMessage("GUILD_OWNER") || "Server Owner"; + const OWNER = getIntlMessage("GUILD_OWNER") ?? "Server Owner"; userPermissions.push({ permission: OWNER, roleName: "Owner", @@ -117,11 +118,11 @@ function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { g sortUserRoles(userRoles); - for (const [permission, bit] of Object.entries(PermissionsBits)) { + for (const bit of Object.values(PermissionsBits)) { for (const { permissions, colorString, position, name } of userRoles) { if ((permissions & bit) === bit) { userPermissions.push({ - permission: getPermissionString(permission), + permission: guildPermissionSpecMap[String(bit)].title, roleName: name, roleColor: colorString || "var(--primary-300)", rolePosition: position @@ -137,26 +138,15 @@ function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { g return [rolePermissions, userPermissions]; }, [permissionsSortOrder]); - return ( - - openRolesAndUsersPermissionsModal( - rolePermissions, - guild, - guildMember.nick || UserStore.getUser(guildMember.userId).username - ) - } - onDropDownClick={state => settings.store.defaultPermissionsDropdownState = !state} - defaultState={settings.store.defaultPermissionsDropdownState} - buttons={[ + return
+
+ Permissions +
{tooltipProps => (
{ @@ -164,8 +154,8 @@ function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { g }} > @@ -174,24 +164,46 @@ function UserPermissionsComponent({ guild, guildMember, forceOpen = false }: { g
)}
- ]}> - {userPermissions.length > 0 && ( -
- {userPermissions.map(({ permission, roleColor, roleName }) => ( - } - tooltipClassName={cl("granted-by-container")} - tooltipContentClassName={cl("granted-by-content")} + + {tooltipProps => ( +
{ + closePopout(); + openRolesAndUsersPermissionsModal(rolePermissions, guild, guildMember.nick || UserStore.getUser(guildMember.userId).username); + }} > - {tooltipProps => ( - - )} - - ))} -
- )} - - ); + + + +
+ )} + +
+
+ {userPermissions.length > 0 && ( +
+ {userPermissions.map(({ permission, roleColor, roleName }) => ( + } + tooltipClassName={cl("granted-by-container")} + tooltipContentClassName={cl("granted-by-content")} + > + {tooltipProps => ( + + )} + + ))} +
+ )} +
; } export default ErrorBoundary.wrap(UserPermissionsComponent, { noop: true }); diff --git a/src/plugins/permissionsViewer/index.tsx b/src/plugins/permissionsViewer/index.tsx index 20b0b1910..8d0cd4b16 100644 --- a/src/plugins/permissionsViewer/index.tsx +++ b/src/plugins/permissionsViewer/index.tsx @@ -56,11 +56,6 @@ export const settings = definePluginSettings({ { label: "Lowest Role", value: PermissionsSortOrder.LowestRole } ] }, - defaultPermissionsDropdownState: { - description: "Whether the permissions dropdown on user popouts should be open by default", - type: OptionType.BOOLEAN, - default: false - } }); function MenuItem(guildId: string, id?: string, type?: MenuItemParentType) { @@ -182,9 +177,9 @@ export default definePlugin({ ( + renderPopout={({ closePopout }) => ( - + )} > diff --git a/src/plugins/permissionsViewer/styles.css b/src/plugins/permissionsViewer/styles.css index 0123f86e2..b7e420964 100644 --- a/src/plugins/permissionsViewer/styles.css +++ b/src/plugins/permissionsViewer/styles.css @@ -1,12 +1,22 @@ /* User Permissions Component */ -.vc-permviewer-user-sortorder-btn { +.vc-permviewer-user-header-container { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; +} + +.vc-permviewer-user-header-btns { + display: flex; + gap: 8px; +} + +.vc-permviewer-user-header-btn { cursor: pointer; display: flex; align-items: center; justify-content: center; - width: 24px; - height: 24px; } /* RolesAndUsersPermissions Component */ diff --git a/src/plugins/permissionsViewer/utils.ts b/src/plugins/permissionsViewer/utils.ts index b2015840e..dfa81e731 100644 --- a/src/plugins/permissionsViewer/utils.ts +++ b/src/plugins/permissionsViewer/utils.ts @@ -17,57 +17,17 @@ */ import { classNameFactory } from "@api/Styles"; -import { getIntlMessage } from "@utils/discord"; -import { wordsToTitle } from "@utils/text"; -import { GuildStore, Parser } from "@webpack/common"; +import { findByPropsLazy } from "@webpack"; +import { GuildStore } from "@webpack/common"; import { Guild, GuildMember, Role } from "discord-types/general"; -import type { ReactNode } from "react"; import { PermissionsSortOrder, settings } from "."; import { PermissionType } from "./components/RolesAndUsersPermissions"; +export const { getGuildPermissionSpecMap } = findByPropsLazy("getGuildPermissionSpecMap"); + export const cl = classNameFactory("vc-permviewer-"); -function formatPermissionWithoutMatchingString(permission: string) { - return wordsToTitle(permission.toLowerCase().split("_")); -} - -// because discord is unable to be consistent with their names -const PermissionKeyMap = { - MANAGE_GUILD: "MANAGE_SERVER", - MANAGE_GUILD_EXPRESSIONS: "MANAGE_EXPRESSIONS", - CREATE_GUILD_EXPRESSIONS: "CREATE_EXPRESSIONS", - MODERATE_MEMBERS: "MODERATE_MEMBER", // HELLOOOO ?????? - STREAM: "VIDEO", - SEND_VOICE_MESSAGES: "ROLE_PERMISSIONS_SEND_VOICE_MESSAGE", -} as const; - -export function getPermissionString(permission: string) { - permission = PermissionKeyMap[permission] || permission; - - return getIntlMessage(permission) || - // shouldn't get here but just in case - formatPermissionWithoutMatchingString(permission); -} - -export function getPermissionDescription(permission: string): ReactNode { - // DISCORD PLEEEEEEEEAAAAASE IM BEGGING YOU :( - if (permission === "USE_APPLICATION_COMMANDS") - permission = "USE_APPLICATION_COMMANDS_GUILD"; - else if (permission === "SEND_VOICE_MESSAGES") - permission = "SEND_VOICE_MESSAGE_GUILD"; - else if (permission !== "STREAM") - permission = PermissionKeyMap[permission] || permission; - - const msg = getIntlMessage(`ROLE_PERMISSIONS_${permission}_DESCRIPTION`) as any; - if (msg?.hasMarkdown) - return Parser.parse(msg.message); - - if (typeof msg === "string") return msg; - - return ""; -} - export function getSortedRoles({ id }: Guild, member: GuildMember) { const roles = GuildStore.getRoles(id); From d8df96d1e34cd1c67724a0dd2702c2465406d585 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:41:00 -0500 Subject: [PATCH 47/82] BetterFolders: Fix dedicated sidebar (#3037) --- src/plugins/betterFolders/index.tsx | 34 +++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 5d4d52c42..68746d361 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -123,7 +123,7 @@ export default definePlugin({ }, // If we are rendering the Better Folders sidebar, we filter out everything but the servers and folders from the GuildsBar Guild List children { - match: /lastTargetNode:\i\[\i\.length-1\].+?Fragment.+?\]}\)\]/, + match: /lastTargetNode:\i\[\i\.length-1\].+?}\)\](?=}\))/, replace: "$&.filter($self.makeGuildsBarGuildListFilter(!!arguments[0]?.isBetterFolders))" }, // If we are rendering the Better Folders sidebar, we filter out everything but the scroller for the guild list from the GuildsBar Tree children @@ -275,24 +275,30 @@ export default definePlugin({ }, makeGuildsBarGuildListFilter(isBetterFolders: boolean) { - return child => { - if (isBetterFolders) { - try { - return child?.props?.["aria-label"] === getIntlMessage("SERVERS"); - } catch (e) { - console.error(e); - } - } - return true; - }; + return child => { + if (!isBetterFolders) return true; + + try { + return child?.props?.["aria-label"] === getIntlMessage("SERVERS"); + } catch (e) { + console.error(e); + } + + return true; + }; }, makeGuildsBarTreeFilter(isBetterFolders: boolean) { return child => { - if (isBetterFolders) { - return child?.props?.onScroll != null; + if (!isBetterFolders) return true; + + if (child?.props?.className?.includes("itemsContainer") && child.props.children != null) { + // Filter out everything but the scroller for the guild list + child.props.children = child.props.children.filter(child => child?.props?.onScroll != null); + return true; } - return true; + + return false; }; }, From 60b776669bb2775e561b9a3a670d6e33eef72a48 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:03:34 -0300 Subject: [PATCH 48/82] WebContextMenus: Fix copy context menu --- src/plugins/webContextMenus.web/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/webContextMenus.web/index.ts b/src/plugins/webContextMenus.web/index.ts index d3934bc26..a11ef2431 100644 --- a/src/plugins/webContextMenus.web/index.ts +++ b/src/plugins/webContextMenus.web/index.ts @@ -216,9 +216,12 @@ export default definePlugin({ replace: "true" }, { - match: /\i\.\i\.copy/, + match: /\i\.\i\.copy(?=\(\i)/, replace: "Vencord.Webpack.Common.Clipboard.copy" - }] + } + ], + all: true, + noWarn: true }, // Automod add filter words { From 11321eb693858a88665b5801ce173e7ebd6c68c4 Mon Sep 17 00:00:00 2001 From: v Date: Fri, 29 Nov 2024 16:11:55 +0100 Subject: [PATCH 49/82] Update CONTRIBUTING.md Plugins interacting with specific Discord bots are not allowed. --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c133225c..0146065e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,6 +31,7 @@ Before starting your plugin: - No FakeDeafen or FakeMute - No StereoMic - No plugins that simply hide or redesign ui elements. This can be done with CSS +- No plugins that interact with specific Discord bots (official Discord apps like Youtube WatchTogether are okay) - No selfbots or API spam (animated status, message pruner, auto reply, nitro snipers, etc) - No untrusted third party APIs. Popular services like Google or GitHub are fine, but absolutely no self hosted ones - No plugins that require the user to enter their own API key From 1150a503554b1a366e602b4ae27cacf424369851 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 29 Nov 2024 22:46:28 +0100 Subject: [PATCH 50/82] Badges: fix overflow in Discord's css --- src/plugins/_api/badges/fixDiscordBadgePadding.css | 5 +++++ src/plugins/_api/badges/index.tsx | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 src/plugins/_api/badges/fixDiscordBadgePadding.css diff --git a/src/plugins/_api/badges/fixDiscordBadgePadding.css b/src/plugins/_api/badges/fixDiscordBadgePadding.css new file mode 100644 index 000000000..eb1d60d5c --- /dev/null +++ b/src/plugins/_api/badges/fixDiscordBadgePadding.css @@ -0,0 +1,5 @@ +/* the profile popout badge container(s) */ +[class*="biteSize_"] [class*="tags_"] [class*="container_"] { + /* Discord has padding set to 2px instead of 1px, which causes the 12th badge to wrap to a new line. */ + padding: 0 1px; +} diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index c44d98b90..d02b5e1d8 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import "./fixDiscordBadgePadding.css"; + import { _getBadges, BadgePosition, BadgeUserArgs, ProfileBadge } from "@api/Badges"; import DonateButton from "@components/DonateButton"; import ErrorBoundary from "@components/ErrorBoundary"; From 02f50b161b0fda1686bbba71e4ef53bfee9dd124 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Fri, 29 Nov 2024 17:26:10 -0500 Subject: [PATCH 51/82] ImageZoom: Fix zoom level not saving (#3054) --- src/plugins/imageZoom/components/Magnifier.tsx | 18 +++++++++++------- src/webpack/common/react.ts | 3 ++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/plugins/imageZoom/components/Magnifier.tsx b/src/plugins/imageZoom/components/Magnifier.tsx index 585026d60..31fa7a117 100644 --- a/src/plugins/imageZoom/components/Magnifier.tsx +++ b/src/plugins/imageZoom/components/Magnifier.tsx @@ -18,7 +18,7 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; -import { FluxDispatcher, React, useRef, useState } from "@webpack/common"; +import { FluxDispatcher, useLayoutEffect, useRef, useState } from "@webpack/common"; import { ELEMENT_ID } from "../constants"; import { settings } from "../index"; @@ -55,7 +55,7 @@ export const Magnifier = ErrorBoundary.wrap(({ instance, size: i const imageRef = useRef(null); // since we accessing document im gonna use useLayoutEffect - React.useLayoutEffect(() => { + useLayoutEffect(() => { const onKeyDown = (e: KeyboardEvent) => { if (e.key === "Shift") { isShiftDown.current = true; @@ -135,12 +135,14 @@ export const Magnifier = ErrorBoundary.wrap(({ instance, size: i setReady(true); }); + document.addEventListener("keydown", onKeyDown); document.addEventListener("keyup", onKeyUp); document.addEventListener("mousemove", updateMousePosition); document.addEventListener("mousedown", onMouseDown); document.addEventListener("mouseup", onMouseUp); document.addEventListener("wheel", onWheel); + return () => { document.removeEventListener("keydown", onKeyDown); document.removeEventListener("keyup", onKeyUp); @@ -148,14 +150,16 @@ export const Magnifier = ErrorBoundary.wrap(({ instance, size: i document.removeEventListener("mousedown", onMouseDown); document.removeEventListener("mouseup", onMouseUp); document.removeEventListener("wheel", onWheel); - - if (settings.store.saveZoomValues) { - settings.store.zoom = zoom.current; - settings.store.size = size.current; - } }; }, []); + useLayoutEffect(() => () => { + if (settings.store.saveZoomValues) { + settings.store.zoom = zoom.current; + settings.store.size = size.current; + } + }); + if (!ready) return null; const box = element.current?.getBoundingClientRect(); diff --git a/src/webpack/common/react.ts b/src/webpack/common/react.ts index 17196132d..99f3f9dd4 100644 --- a/src/webpack/common/react.ts +++ b/src/webpack/common/react.ts @@ -22,6 +22,7 @@ import { findByPropsLazy, waitFor } from "../webpack"; export let React: typeof import("react"); export let useState: typeof React.useState; export let useEffect: typeof React.useEffect; +export let useLayoutEffect: typeof React.useLayoutEffect; export let useMemo: typeof React.useMemo; export let useRef: typeof React.useRef; export let useReducer: typeof React.useReducer; @@ -31,5 +32,5 @@ export const ReactDOM: typeof import("react-dom") & typeof import("react-dom/cli waitFor("useState", m => { React = m; - ({ useEffect, useState, useMemo, useRef, useReducer, useCallback } = React); + ({ useEffect, useState, useLayoutEffect, useMemo, useRef, useReducer, useCallback } = React); }); From fcece6199511108f7f9eeec65a6d9120f720deb2 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 29 Nov 2024 19:26:55 -0300 Subject: [PATCH 52/82] Bump to 1.10.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d5b23e57c..967c0ccc6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.10.7", + "version": "1.10.8", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 0ac80ce9d180bbdaf4d3863f4a249f3b165072df Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:10:08 -0300 Subject: [PATCH 53/82] MessagePopoverAPI: Add buttons after quick reactions --- src/plugins/_api/messagePopover.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/plugins/_api/messagePopover.ts b/src/plugins/_api/messagePopover.ts index 21e5accde..0133d0c64 100644 --- a/src/plugins/_api/messagePopover.ts +++ b/src/plugins/_api/messagePopover.ts @@ -23,11 +23,14 @@ export default definePlugin({ name: "MessagePopoverAPI", description: "API to add buttons to message popovers.", authors: [Devs.KingFish, Devs.Ven, Devs.Nuckyz], - patches: [{ - find: "#{intl::MESSAGE_UTILITIES_A11Y_LABEL}", - replacement: { - match: /\.jsx\)\((\i\.\i),\{label:\i\.\i\.string\(\i\.\i#{intl::MESSAGE_ACTION_REPLY}.{0,200}?"reply-self".{0,50}?\}\):null(?=,.+?message:(\i))/, - replace: "$&,Vencord.Api.MessagePopover._buildPopoverElements($1,$2)" + patches: [ + { + find: "#{intl::MESSAGE_UTILITIES_A11Y_LABEL}", + replacement: { + match: /(?<=:null),(.{0,40}togglePopout:.+?}\))\]}\):null,(?<=\((\i\.\i),{label:.+?:null,(\i&&!\i)\?\(0,\i\.jsxs?\)\(\i\.Fragment.+?message:(\i).+?)/, + replace: (_, ReactButton, ButtonComponent, showReactButton, message) => "" + + `]}):null,Vencord.Api.MessagePopover._buildPopoverElements(${ButtonComponent},${message}),${showReactButton}?${ReactButton}:null,` + } } - }], + ] }); From d70e0f27dcdaca24443d57b319fee2c0a8997501 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 2 Dec 2024 20:39:54 -0300 Subject: [PATCH 54/82] ServerListIndicators: Account for pending clans count --- src/plugins/serverListIndicators/index.tsx | 63 +++++++++------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/plugins/serverListIndicators/index.tsx b/src/plugins/serverListIndicators/index.tsx index 96833d8f3..7648bc2d0 100644 --- a/src/plugins/serverListIndicators/index.tsx +++ b/src/plugins/serverListIndicators/index.tsx @@ -20,9 +20,9 @@ import { addServerListElement, removeServerListElement, ServerListRenderPosition import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; -import { useForceUpdater } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; -import { GuildStore, PresenceStore, RelationshipStore } from "@webpack/common"; +import { findStoreLazy } from "@webpack"; +import { GuildStore, PresenceStore, RelationshipStore, useStateFromStores } from "@webpack/common"; const enum IndicatorType { SERVER = 1 << 0, @@ -30,13 +30,24 @@ const enum IndicatorType { BOTH = SERVER | FRIEND, } -let onlineFriends = 0; -let guildCount = 0; -let forceUpdateFriendCount: () => void; -let forceUpdateGuildCount: () => void; +const UserGuildJoinRequestStore = findStoreLazy("UserGuildJoinRequestStore"); function FriendsIndicator() { - forceUpdateFriendCount = useForceUpdater(); + const onlineFriendsCount = useStateFromStores([RelationshipStore, PresenceStore], () => { + let count = 0; + + const friendIds = RelationshipStore.getFriendIDs(); + for (const id of friendIds) { + const status = PresenceStore.getStatus(id) ?? "offline"; + if (status === "offline") { + continue; + } + + count++; + } + + return count; + }); return ( - {onlineFriends} online + {onlineFriendsCount} online ); } function ServersIndicator() { - forceUpdateGuildCount = useForceUpdater(); + const guildCount = useStateFromStores([GuildStore, UserGuildJoinRequestStore], () => { + const guildJoinRequests: string[] = UserGuildJoinRequestStore.computeGuildIds(); + const guilds = GuildStore.getGuilds(); + + // Filter only pending guild join requests + return GuildStore.getGuildCount() + guildJoinRequests.filter(id => guilds[id] == null).length; + }); return ( ; }, - flux: { - PRESENCE_UPDATES: handlePresenceUpdate, - GUILD_CREATE: handleGuildUpdate, - GUILD_DELETE: handleGuildUpdate, - }, - - start() { addServerListElement(ServerListRenderPosition.Above, this.renderIndicator); - - handlePresenceUpdate(); - handleGuildUpdate(); }, stop() { From 3f61fe722dfa92b467c907b14237767877ef6ed1 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 2 Dec 2024 21:51:29 -0300 Subject: [PATCH 55/82] AlwaysTrust: Fix disabling suspicious file popup --- src/plugins/alwaysTrust/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/alwaysTrust/index.ts b/src/plugins/alwaysTrust/index.ts index 7484a619c..0c89ae116 100644 --- a/src/plugins/alwaysTrust/index.ts +++ b/src/plugins/alwaysTrust/index.ts @@ -51,7 +51,7 @@ export default definePlugin({ { find: "bitbucket.org", replacement: { - match: /function \i\(\i\){(?=.{0,60}\.parse\(\i\))/, + match: /function \i\(\i\){(?=.{0,30}pathname:\i)/, replace: "$&return null;" }, predicate: () => settings.store.file From dd87f360d74f61b4532b523dc47cd734b6ffeb05 Mon Sep 17 00:00:00 2001 From: Etorix <92535668+EtorixDev@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:13:27 -0800 Subject: [PATCH 56/82] CommandsAPI: Fix spread overwriting omitted subcommand options (#3057) --- src/api/Commands/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/Commands/index.ts b/src/api/Commands/index.ts index e5803ba02..2b7a4de6c 100644 --- a/src/api/Commands/index.ts +++ b/src/api/Commands/index.ts @@ -110,6 +110,7 @@ function registerSubCommands(cmd: Command, plugin: string) { const subCmd = { ...cmd, ...o, + options: o.options !== undefined ? o.options : undefined, type: ApplicationCommandType.CHAT_INPUT, name: `${cmd.name} ${o.name}`, id: `${o.name}-${cmd.id}`, From 66286240820c132a8aa98bcaa2e9c7c2535ca403 Mon Sep 17 00:00:00 2001 From: Etorix <92535668+EtorixDev@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:16:13 -0800 Subject: [PATCH 57/82] CommandHelpers: Make findOption use nullish coalescing (#3047) --- src/api/Commands/commandHelpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/Commands/commandHelpers.ts b/src/api/Commands/commandHelpers.ts index 4ae022c59..ac1dafc98 100644 --- a/src/api/Commands/commandHelpers.ts +++ b/src/api/Commands/commandHelpers.ts @@ -54,5 +54,5 @@ export function sendBotMessage(channelId: string, message: PartialDeep) export function findOption(args: Argument[], name: string): T & {} | undefined; export function findOption(args: Argument[], name: string, fallbackValue: T): T & {}; export function findOption(args: Argument[], name: string, fallbackValue?: any) { - return (args.find(a => a.name === name)?.value || fallbackValue) as any; + return (args.find(a => a.name === name)?.value ?? fallbackValue) as any; } From df454ca95218dc32ef1521e5836f38c76bb24a61 Mon Sep 17 00:00:00 2001 From: Sqaaakoi Date: Tue, 3 Dec 2024 13:30:56 +1100 Subject: [PATCH 58/82] MutualGroupDMs: Fix in DM sidebar when no mutual friends/servers (#2976) --- src/plugins/mutualGroupDMs/index.tsx | 52 +++++++++++++++++++--------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index a4f690af1..080a79891 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -19,6 +19,7 @@ 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 { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, useMemo, UserStore } from "@webpack/common"; @@ -87,7 +88,7 @@ export default definePlugin({ replacement: [ { match: /\i\.useEffect.{0,100}(\i)\[0\]\.section/, - replace: "$self.pushSection($1, arguments[0].user);$&" + replace: "$self.pushSection($1,arguments[0].user);$&" }, { match: /\(0,\i\.jsx\)\(\i,\{items:\i,section:(\i)/, @@ -97,26 +98,46 @@ export default definePlugin({ }, { find: 'section:"MUTUAL_FRIENDS"', - replacement: { - match: /\.openUserProfileModal.+?\)}\)}\)(?<=(\(0,\i\.jsxs?\)\(\i\.\i,{className:(\i)\.divider}\)).+?)/, - replace: "$&,$self.renderDMPageList({user: arguments[0].user, Divider: $1, listStyle: $2.list})" - } + replacement: [ + { + match: /\i\|\|\i(?=\?\(0,\i\.jsxs?\)\(\i\.\i\.Overlay,)/, + replace: "$&||$self.getMutualGroupDms(arguments[0].user.id).length>0" + }, + { + match: /\.openUserProfileModal.+?\)}\)}\)(?<=,(\i)&&(\i)&&(\(0,\i\.jsxs?\)\(\i\.\i,{className:(\i)\.divider}\)).+?)/, + replace: (m, hasMutualGuilds, hasMutualFriends, Divider, classes) => "" + + `${m},$self.renderDMPageList({user:arguments[0].user,hasDivider:${hasMutualGuilds}||${hasMutualFriends},Divider:${Divider},listStyle:${classes}.list})` + } + ] } ], - pushSection(sections: any[], user: User) { - if (isBotOrSelf(user) || sections[IS_PATCHED]) return; + getMutualGroupDms(userId: string) { + try { + return getMutualGroupDms(userId); + } catch (e) { + new Logger("MutualGroupDMs").error("Failed to get mutual group dms:", e); + } - sections[IS_PATCHED] = true; - sections.push({ - section: "MUTUAL_GDMS", - text: getMutualGDMCountText(user) - }); + return []; + }, + + pushSection(sections: any[], user: User) { + try { + if (isBotOrSelf(user) || sections[IS_PATCHED]) return; + + sections[IS_PATCHED] = true; + sections.push({ + section: "MUTUAL_GDMS", + text: getMutualGDMCountText(user) + }); + } catch (e) { + new Logger("MutualGroupDMs").error("Failed to push mutual group dms section:", e); + } }, renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => { const mutualGDms = useMemo(() => getMutualGroupDms(user.id), [user.id]); - const entries = renderClickableGDMs(mutualGDms, onClose); return ( @@ -138,14 +159,13 @@ export default definePlugin({ ); }), - renderDMPageList: ErrorBoundary.wrap(({ user, Divider, listStyle }: { user: User, Divider: JSX.Element, listStyle: string; }) => { + renderDMPageList: ErrorBoundary.wrap(({ user, hasDivider, Divider, listStyle }: { user: User, hasDivider: boolean, Divider: JSX.Element, listStyle: string; }) => { const mutualGDms = getMutualGroupDms(user.id); if (mutualGDms.length === 0) return null; - return ( <> - {Divider} + {hasDivider && Divider} Date: Tue, 3 Dec 2024 21:51:41 -0300 Subject: [PATCH 59/82] WebContextMenus: Fix input bar menu --- src/plugins/webContextMenus.web/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/webContextMenus.web/index.ts b/src/plugins/webContextMenus.web/index.ts index a11ef2431..661238052 100644 --- a/src/plugins/webContextMenus.web/index.ts +++ b/src/plugins/webContextMenus.web/index.ts @@ -164,8 +164,8 @@ export default definePlugin({ find: 'getElementById("slate-toolbar"', predicate: () => settings.store.addBack, replacement: { - match: /(?<=handleContextMenu\(\i\)\{.{0,200}isPlatformEmbedded)\?/, - replace: "||true?" + match: /(?<=handleContextMenu\(\i\)\{.{0,200}isPlatformEmbedded)\)/, + replace: "||true)" } }, { From cdfc89b8192144bc7b58225655c1d52562a84e28 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:39:36 -0300 Subject: [PATCH 60/82] NoScreensharePreview: Migrate to stock Discord feature --- src/plugins/noScreensharePreview/index.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/plugins/noScreensharePreview/index.ts b/src/plugins/noScreensharePreview/index.ts index ca50ad284..6ad39a90f 100644 --- a/src/plugins/noScreensharePreview/index.ts +++ b/src/plugins/noScreensharePreview/index.ts @@ -16,20 +16,23 @@ * along with this program. If not, see . */ +import { Settings } from "@api/Settings"; +import { getUserSettingLazy } from "@api/UserSettings"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; +const DisableStreamPreviews = getUserSettingLazy("voiceAndVideo", "disableStreamPreviews")!; + +// @TODO: Delete this plugin in the future export default definePlugin({ name: "NoScreensharePreview", description: "Disables screenshare previews from being sent.", authors: [Devs.Nuckyz], - patches: [ - { - find: '"ApplicationStreamPreviewUploadManager"', - replacement: { - match: /await \i\.\i\.(makeChunkedRequest\(|post\(\{url:)\i\.\i\.STREAM_PREVIEW.+?\}\)/g, - replace: "0" - } + start() { + if (!DisableStreamPreviews.getSetting()) { + DisableStreamPreviews.updateSetting(true); } - ] + + Settings.plugins.NoScreensharePreview.enabled = false; + } }); From df44edd41ba185ab2afb437cda16c4bafd87ac7e Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:07:30 -0500 Subject: [PATCH 61/82] BetterFolders: Fix including open folders in main sidebar (#3064) --- src/plugins/betterFolders/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 68746d361..6f9b796e8 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -159,7 +159,7 @@ export default definePlugin({ ] }, { - find: ".FOLDER_ITEM_GUILD_ICON_MARGIN);", + find: ".expandedFolderBackground,", predicate: () => settings.store.sidebar, replacement: [ // We use arguments[0] to access the isBetterFolders variable in this nested folder component (the parent exports all the props so we don't have to patch it) From a3f5dc39a09506ecbeaa3c496ba9a1a95189a2cc Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 7 Dec 2024 00:13:59 +0100 Subject: [PATCH 62/82] CallTimer: fix crashing on canary --- src/plugins/callTimer/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/callTimer/index.tsx b/src/plugins/callTimer/index.tsx index c018cc715..01b1cb987 100644 --- a/src/plugins/callTimer/index.tsx +++ b/src/plugins/callTimer/index.tsx @@ -75,10 +75,11 @@ export default definePlugin({ patches: [{ find: "renderConnectionStatus(){", replacement: { - match: /(?<=renderConnectionStatus\(\)\{.+\.channel,children:)\i/, + match: /(?<=renderConnectionStatus\(\)\{.+\.channel,children:)\i(?=\})/, replace: "[$&, $self.renderTimer(this.props.channel.id)]" } }], + renderTimer(channelId: string) { return From cea0a3c9d97bbec08241a7294c2d0c7d41225d72 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 7 Dec 2024 19:14:49 -0300 Subject: [PATCH 63/82] NoScreensharePreview: Allow plugin to be turned on/off --- src/plugins/noScreensharePreview/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/noScreensharePreview/index.ts b/src/plugins/noScreensharePreview/index.ts index 6ad39a90f..d4bb9c1eb 100644 --- a/src/plugins/noScreensharePreview/index.ts +++ b/src/plugins/noScreensharePreview/index.ts @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -import { Settings } from "@api/Settings"; import { getUserSettingLazy } from "@api/UserSettings"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; @@ -28,11 +27,16 @@ export default definePlugin({ name: "NoScreensharePreview", description: "Disables screenshare previews from being sent.", authors: [Devs.Nuckyz], + start() { if (!DisableStreamPreviews.getSetting()) { DisableStreamPreviews.updateSetting(true); } + }, - Settings.plugins.NoScreensharePreview.enabled = false; + stop() { + if (DisableStreamPreviews.getSetting()) { + DisableStreamPreviews.updateSetting(false); + } } }); From 3a339636d138da5745322f6e317331d7d9387dc2 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 7 Dec 2024 19:55:37 -0300 Subject: [PATCH 64/82] Remove old plugin migrations --- src/plugins/disableCallIdle/index.ts | 2 -- src/plugins/newGuildSettings/index.tsx | 4 +--- src/plugins/partyMode/index.ts | 3 +-- src/plugins/serverInfo/index.tsx | 2 -- src/plugins/showHiddenThings/index.ts | 3 +-- src/plugins/youtubeAdblock.desktop/index.ts | 2 -- 6 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/plugins/disableCallIdle/index.ts b/src/plugins/disableCallIdle/index.ts index 82ab56f2c..5a1ac84fe 100644 --- a/src/plugins/disableCallIdle/index.ts +++ b/src/plugins/disableCallIdle/index.ts @@ -16,11 +16,9 @@ * along with this program. If not, see . */ -import { migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -migratePluginSettings("DisableCallIdle", "DisableDMCallIdle"); export default definePlugin({ name: "DisableCallIdle", description: "Disables automatically getting kicked from a DM voice call after 3 minutes and being moved to an AFK voice channel.", diff --git a/src/plugins/newGuildSettings/index.tsx b/src/plugins/newGuildSettings/index.tsx index 7cfb073fa..e613f7a00 100644 --- a/src/plugins/newGuildSettings/index.tsx +++ b/src/plugins/newGuildSettings/index.tsx @@ -20,7 +20,7 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; -import { definePluginSettings, migratePluginSettings } from "@api/Settings"; +import { definePluginSettings } from "@api/Settings"; import { CogWheel } from "@components/Icons"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -115,8 +115,6 @@ function applyDefaultSettings(guildId: string | null) { } } - -migratePluginSettings("NewGuildSettings", "MuteNewGuild"); export default definePlugin({ name: "NewGuildSettings", description: "Automatically mute new servers and change various other settings upon joining", diff --git a/src/plugins/partyMode/index.ts b/src/plugins/partyMode/index.ts index c40f2e3c7..f7cddbf97 100644 --- a/src/plugins/partyMode/index.ts +++ b/src/plugins/partyMode/index.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings, migratePluginSettings } from "@api/Settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType, ReporterTestable } from "@utils/types"; import { FluxDispatcher } from "@webpack/common"; @@ -41,7 +41,6 @@ const settings = definePluginSettings({ }, }); -migratePluginSettings("PartyMode", "Party mode 🎉"); export default definePlugin({ name: "PartyMode", description: "Allows you to use party mode cause the party never ends ✨", diff --git a/src/plugins/serverInfo/index.tsx b/src/plugins/serverInfo/index.tsx index a6dd6edf9..2a3f3adf1 100644 --- a/src/plugins/serverInfo/index.tsx +++ b/src/plugins/serverInfo/index.tsx @@ -5,7 +5,6 @@ */ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; -import { migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Menu } from "@webpack/common"; @@ -25,7 +24,6 @@ const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; ); }; -migratePluginSettings("ServerInfo", "ServerProfile"); // what was I thinking with this name lmao export default definePlugin({ name: "ServerInfo", description: "Allows you to view info about a server", diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 30edb2470..a5cf81294 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings, migratePluginSettings } from "@api/Settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType, PluginSettingDef } from "@utils/types"; @@ -35,7 +35,6 @@ const settings = definePluginSettings({ disableDisallowedDiscoveryFilters: opt("Disable filters in Server Discovery search that hide NSFW & disallowed servers."), }); -migratePluginSettings("ShowHiddenThings", "ShowTimeouts"); export default definePlugin({ name: "ShowHiddenThings", tags: ["ShowTimeouts", "ShowInvitesPaused", "ShowModView", "DisableDiscoveryFilters"], diff --git a/src/plugins/youtubeAdblock.desktop/index.ts b/src/plugins/youtubeAdblock.desktop/index.ts index 708b908d9..48f911795 100644 --- a/src/plugins/youtubeAdblock.desktop/index.ts +++ b/src/plugins/youtubeAdblock.desktop/index.ts @@ -4,12 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; // The entire code of this plugin can be found in native.ts -migratePluginSettings("YoutubeAdblock", "WatchTogetherAdblock"); export default definePlugin({ name: "YoutubeAdblock", description: "Block ads in YouTube embeds and the WatchTogether activity via AdGuard", From 99dc65fe4e9c50d6eef2f62c4211e80bf0a20477 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 7 Dec 2024 20:31:08 -0300 Subject: [PATCH 65/82] Fix TypingIndicator & CallTimer --- src/plugins/callTimer/index.tsx | 2 +- src/plugins/showHiddenChannels/index.tsx | 2 +- src/plugins/typingIndicator/index.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/callTimer/index.tsx b/src/plugins/callTimer/index.tsx index 01b1cb987..e16abc4a1 100644 --- a/src/plugins/callTimer/index.tsx +++ b/src/plugins/callTimer/index.tsx @@ -75,7 +75,7 @@ export default definePlugin({ patches: [{ find: "renderConnectionStatus(){", replacement: { - match: /(?<=renderConnectionStatus\(\)\{.+\.channel,children:)\i(?=\})/, + match: /(?<=renderConnectionStatus\(\){.+\.channel,children:).+?}\):\i(?=}\))/, replace: "[$&, $self.renderTimer(this.props.channel.id)]" } }], diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 6b67aee8b..181a6bc99 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -168,7 +168,7 @@ export default definePlugin({ }, // Add the hidden eye icon if the channel is hidden { - match: /\.name\),.{0,120}\.children.+?:null(?<=,channel:(\i).+?)/, + match: /\.name,{.{0,140}\.children.+?:null(?<=,channel:(\i).+?)/, replace: (m, channel) => `${m},$self.isHiddenChannel(${channel})?$self.HiddenChannelIcon():null` }, // Make voice channels also appear as muted if they are muted diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index e9e343311..e6a1b3b4f 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -163,7 +163,7 @@ export default definePlugin({ { find: "UNREAD_IMPORTANT:", replacement: { - match: /\.name\),.{0,120}\.children.+?:null(?<=,channel:(\i).+?)/, + match: /\.name,{.{0,140}\.children.+?:null(?<=,channel:(\i).+?)/, replace: "$&,$self.TypingIndicator($1.id,$1.getGuildId())" } }, From 4a5f0838e217253174401bb5e523c234239fd748 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 7 Dec 2024 20:32:16 -0300 Subject: [PATCH 66/82] Remove workaround for Devtools theme --- src/main/patcher.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/main/patcher.ts b/src/main/patcher.ts index e858f3fcd..e5b87290d 100644 --- a/src/main/patcher.ts +++ b/src/main/patcher.ts @@ -17,7 +17,7 @@ */ import { onceDefined } from "@shared/onceDefined"; -import electron, { app, BrowserWindowConstructorOptions, Menu, nativeTheme } from "electron"; +import electron, { app, BrowserWindowConstructorOptions, Menu } from "electron"; import { dirname, join } from "path"; import { initIpc } from "./ipcMain"; @@ -100,19 +100,6 @@ if (!IS_VANILLA) { super(options); initIpc(this); - - // Workaround for https://github.com/electron/electron/issues/43367. Vesktop also has its own workaround - // @TODO: Remove this when the issue is fixed - if (IS_DISCORD_DESKTOP) { - this.webContents.on("devtools-opened", () => { - if (!nativeTheme.shouldUseDarkColors) return; - - nativeTheme.themeSource = "light"; - setTimeout(() => { - nativeTheme.themeSource = "dark"; - }, 100); - }); - } } else super(options); } } From 8d65bcf74319004b8dbafb2599a109879ace1b52 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:09:54 -0300 Subject: [PATCH 67/82] BetterFolders: Fix folder icon setting --- src/plugins/betterFolders/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 6f9b796e8..c43e17110 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -185,7 +185,7 @@ export default definePlugin({ { // Decide if we should render the expanded folder background if we are rendering the Better Folders sidebar predicate: () => settings.store.showFolderIcon !== FolderIconDisplay.Always, - match: /(?<=\.wrapper,children:\[)/, + match: /(?<=\.isExpanded\),children:\[)/, replace: "$self.shouldShowFolderIconAndBackground(!!arguments[0]?.isBetterFolders,arguments[0]?.betterFoldersExpandedIds)&&" }, { From 9d3c91e9df7f5168da2ce8b6d1f60e0fd792f935 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:29:15 -0300 Subject: [PATCH 68/82] TypingTweaks: Fix plugin --- src/plugins/typingTweaks/index.tsx | 45 ++++++++++++++---------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/plugins/typingTweaks/index.tsx b/src/plugins/typingTweaks/index.tsx index e2bbb4bc9..026cd527b 100644 --- a/src/plugins/typingTweaks/index.tsx +++ b/src/plugins/typingTweaks/index.tsx @@ -91,34 +91,31 @@ export default definePlugin({ name: "TypingTweaks", description: "Show avatars and role colours in the typing indicator", authors: [Devs.zt], + settings, + patches: [ - // Style the indicator and add function call to modify the children before rendering { - find: "getCooldownTextStyle", - replacement: { - match: /(?<=children:\[(\i)\.length>0.{0,200}?"aria-atomic":!0,children:)\i/, - replace: "$self.mutateChildren(this.props, $1, $&), style: $self.TYPING_TEXT_STYLE" - } - }, - // Changes the indicator to keep the user object when creating the list of typing users - { - find: "getCooldownTextStyle", - replacement: { - match: /(?<=map\(\i=>)\i\.\i\.getName\(\i,this\.props\.channel\.id,(\i)\)/, - replace: "$1" - } - }, - // Adds the alternative formatting for several users typing - { - find: "getCooldownTextStyle", - replacement: { - match: /(,{a:(\i),b:(\i),c:\i}\):)\i\.\i\.string\(\i\.\i#{intl::SEVERAL_USERS_TYPING}\)(?<=(\i)\.length.+?)/, - replace: (_, rest, a, b, users) => `${rest}$self.buildSeveralUsers({ a: ${a}, b: ${b}, count: ${users}.length - 2 })` - }, - predicate: () => settings.store.alternativeFormatting + find: "#{intl::THREE_USERS_TYPING}", + replacement: [ + { + // Style the indicator and add function call to modify the children before rendering + match: /(?<=children:\[(\i)\.length>0.{0,200}?"aria-atomic":!0,children:)\i(?<=guildId:(\i).+?)/, + replace: "$self.mutateChildren($2,$1,$&),style:$self.TYPING_TEXT_STYLE" + }, + { + // Changes the indicator to keep the user object when creating the list of typing users + match: /\.map\((\i)=>\i\.\i\.getName\(\i,\i\.id,\1\)\)/, + replace: "" + }, + { + // Adds the alternative formatting for several users typing + match: /(,{a:(\i),b:(\i),c:\i}\):\i\.length>3&&\(\i=)\i\.\i\.string\(\i\.\i#{intl::SEVERAL_USERS_TYPING}\)(?<=(\i)\.length.+?)/, + replace: (_, rest, a, b, users) => `${rest}$self.buildSeveralUsers({ a: ${a}, b: ${b}, count: ${users}.length - 2 })`, + predicate: () => settings.store.alternativeFormatting + } + ] } ], - settings, TYPING_TEXT_STYLE: { display: "grid", From dcfddcbc2150c07f2dab5b6c43d9919eec005352 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:37:21 -0500 Subject: [PATCH 69/82] ConsoleJanitor: Add HLJS deprecations (#3062) --- src/plugins/consoleJanitor/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 2c29bf670..03c30ede4 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -66,6 +66,13 @@ export default definePlugin({ }, patches: [ + { + find: "https://github.com/highlightjs/highlight.js/issues/2277", + replacement: { + match: /(?<=&&\()console.log\(`Deprecated.+?`\),/, + replace: "" + } + }, { find: 'react-spring: The "interpolate" function', replacement: { From 464c4a9b614a93443575acfd160388d3eb09cb2f Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Tue, 10 Dec 2024 23:06:34 -0500 Subject: [PATCH 70/82] TypingTweaks: Fix usernames not being colored (#3070) --- src/plugins/typingTweaks/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/typingTweaks/index.tsx b/src/plugins/typingTweaks/index.tsx index 026cd527b..9e6459aba 100644 --- a/src/plugins/typingTweaks/index.tsx +++ b/src/plugins/typingTweaks/index.tsx @@ -125,7 +125,7 @@ export default definePlugin({ buildSeveralUsers, - mutateChildren(props: any, users: User[], children: any) { + mutateChildren(guildId: any, users: User[], children: any) { try { if (!Array.isArray(children)) { return children; @@ -135,7 +135,7 @@ export default definePlugin({ return children.map(c => c.type === "strong" || (typeof c !== "string" && !React.isValidElement(c)) - ? + ? : c ); } catch (e) { From 2dc8c2bf764be5409460bf96e16ea0c273cd0bf7 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 12 Dec 2024 01:47:55 -0500 Subject: [PATCH 71/82] Fix multiple plugins for latest Discord update (#3072) --- src/plugins/consoleJanitor/index.ts | 6 ++-- src/plugins/fakeNitro/index.tsx | 8 ++--- src/plugins/favEmojiFirst/index.ts | 2 +- src/plugins/messageLogger/index.tsx | 44 +++++++++++++------------- src/plugins/moreUserTags/index.tsx | 8 ++--- src/plugins/noBlockedMessages/index.ts | 4 +-- src/plugins/noPendingCount/index.ts | 4 +-- src/plugins/volumeBooster/index.ts | 4 +-- src/plugins/whoReacted/index.tsx | 4 +-- 9 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index 03c30ede4..d251ff740 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -74,9 +74,9 @@ export default definePlugin({ } }, { - find: 'react-spring: The "interpolate" function', + find: 'The "interpolate" function is deprecated in v10 (use "to" instead)', replacement: { - match: /,console.warn\('react-spring: The "interpolate" function is deprecated in v10 \(use "to" instead\)'\)/, + match: /,console.warn\(\i\+'The "interpolate" function is deprecated in v10 \(use "to" instead\)'\)/, replace: "" } }, @@ -133,7 +133,7 @@ export default definePlugin({ { find: "Slow dispatch on", replacement: { - match: /\i\.totalTime>100&&\i\.verbose\("Slow dispatch on ".+?\)\);/, + match: /\i\.totalTime>\i&&\i\.verbose\("Slow dispatch on ".+?\)\);/, replace: "" } }, diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 86c5ae4d6..d1aa69c7c 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -207,8 +207,8 @@ function makeBypassPatches(): Omit { return { find: "canUseCustomStickersEverywhere:", replacement: mapping.map(({ func, predicate }) => ({ - match: new RegExp(String.raw`(?<=${func}:function\(\i(?:,\i)?\){)`), - replace: "return true;", + match: new RegExp(String.raw`(?<=${func}:)\i`), + replace: "() => true", predicate })) }; @@ -297,8 +297,8 @@ export default definePlugin({ replacement: [ { // Overwrite incoming connection settings proto with our local settings - match: /CONNECTION_OPEN:function\((\i)\){/, - replace: (m, props) => `${m}$self.handleProtoChange(${props}.userSettingsProto,${props}.user);` + match: /function (\i)\((\i)\){(?=.*CONNECTION_OPEN:\1)/, + replace: (m, funcName, props) => `${m}$self.handleProtoChange(${props}.userSettingsProto,${props}.user);` }, { // Overwrite non local proto changes with our local settings diff --git a/src/plugins/favEmojiFirst/index.ts b/src/plugins/favEmojiFirst/index.ts index d1a5458d3..aa43a528e 100644 --- a/src/plugins/favEmojiFirst/index.ts +++ b/src/plugins/favEmojiFirst/index.ts @@ -57,7 +57,7 @@ export default definePlugin({ { // https://regex101.com/r/x2mobQ/1 // searchEmojis(...,maxCount: stuff) ... endEmojis = emojis.slice(0, maxCount - gifResults.length) - match: /,maxCount:(\i)(.{1,500}\i)=(\i)\.slice\(0,(\i-\i\.length)\)/, + match: /,maxCount:(\i)(.{1,500}\i)=(\i)\.slice\(0,(Math\.max\(\i,\i(?:-\i\.length){2})\)/, // ,maxCount:Infinity ... endEmojis = (emojis.sliceTo = n, emojis) replace: ",maxCount:Infinity$2=($3.sliceTo = $4, $3)" } diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index a79e3f31e..3d32d625e 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -346,35 +346,35 @@ export default definePlugin({ replacement: [ { // Add deleted=true to all target messages in the MESSAGE_DELETE event - match: /MESSAGE_DELETE:function\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?},/, + match: /function (?=.+?MESSAGE_DELETE:(\i))\1\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?}(?=function)/, replace: - "MESSAGE_DELETE:function($1){" + - " var cache = $2getOrCreate($1.channelId);" + - " cache = $self.handleDelete(cache, $1, false);" + - " $2commit(cache);" + - "}," + "function $1($2){" + + " var cache = $3getOrCreate($2.channelId);" + + " cache = $self.handleDelete(cache, $2, false);" + + " $3commit(cache);" + + "}" }, { // Add deleted=true to all target messages in the MESSAGE_DELETE_BULK event - match: /MESSAGE_DELETE_BULK:function\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?},/, + match: /function (?=.+?MESSAGE_DELETE_BULK:(\i))\1\((\i)\){let.+?((?:\i\.){2})getOrCreate.+?}(?=function)/, replace: - "MESSAGE_DELETE_BULK:function($1){" + - " var cache = $2getOrCreate($1.channelId);" + - " cache = $self.handleDelete(cache, $1, true);" + - " $2commit(cache);" + - "}," + "function $1($2){" + + " var cache = $3getOrCreate($2.channelId);" + + " cache = $self.handleDelete(cache, $2, true);" + + " $3commit(cache);" + + "}" }, { // Add current cached content + new edit time to cached message's editHistory - match: /(MESSAGE_UPDATE:function\((\i)\).+?)\.update\((\i)/, + match: /(function (\i)\((\i)\).+?)\.update\((\i)(?=.*MESSAGE_UPDATE:\2)/, replace: "$1" + - ".update($3,m =>" + - " (($2.message.flags & 64) === 64 || $self.shouldIgnore($2.message, true)) ? m :" + - " $2.message.edited_timestamp && $2.message.content !== m.content ?" + - " m.set('editHistory',[...(m.editHistory || []), $self.makeEdit($2.message, m)]) :" + + ".update($4,m =>" + + " (($3.message.flags & 64) === 64 || $self.shouldIgnore($3.message, true)) ? m :" + + " $3.message.edited_timestamp && $3.message.content !== m.content ?" + + " m.set('editHistory',[...(m.editHistory || []), $self.makeEdit($3.message, m)]) :" + " m" + ")" + - ".update($3" + ".update($4" }, { // fix up key (edit last message) attempting to edit a deleted message @@ -488,12 +488,12 @@ export default definePlugin({ find: '"ReferencedMessageStore"', replacement: [ { - match: /MESSAGE_DELETE:function\((\i)\).+?},/, - replace: "MESSAGE_DELETE:function($1){}," + match: /MESSAGE_DELETE:\i,/, + replace: "MESSAGE_DELETE:()=>{}," }, { - match: /MESSAGE_DELETE_BULK:function\((\i)\).+?},/, - replace: "MESSAGE_DELETE_BULK:function($1){}," + match: /MESSAGE_DELETE_BULK:\i,/, + replace: "MESSAGE_DELETE_BULK:()=>{}," } ] }, diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 6c9102d81..6a438675b 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -183,8 +183,8 @@ export default definePlugin({ { find: ".ORIGINAL_POSTER=", replacement: { - match: /\((\i)=\{\}\)\)\[(\i)\.BOT/, - replace: "($1=$self.getTagTypes()))[$2.BOT" + match: /(?=(\i)\[\i\.BOT)/, + replace: "$self.genTagTypes($1);" } }, { @@ -280,8 +280,7 @@ export default definePlugin({ .filter(Boolean); }, - getTagTypes() { - const obj = {}; + genTagTypes(obj) { let i = 100; tags.forEach(({ name }) => { obj[name] = ++i; @@ -291,7 +290,6 @@ export default definePlugin({ obj[`${name}-OP`] = ++i; obj[i] = `${name}-OP`; }); - return obj; }, isOPTag: (tag: number) => tag === Tag.Types.ORIGINAL_POSTER || tags.some(t => tag === Tag.Types[`${t.name}-OP`]), diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 65ce6136f..48ca63d18 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -54,8 +54,8 @@ export default definePlugin({ predicate: () => Settings.plugins.NoBlockedMessages.ignoreBlockedMessages === true, replacement: [ { - match: /(?<=MESSAGE_CREATE:function\((\i)\){)/, - replace: (_, props) => `if($self.isBlocked(${props}.message))return;` + match: /(?<=function (\i)\((\i)\){)(?=.*MESSAGE_CREATE:\1)/, + replace: (_, _funcName, props) => `if($self.isBlocked(${props}.message))return;` } ] })) diff --git a/src/plugins/noPendingCount/index.ts b/src/plugins/noPendingCount/index.ts index 4b98e6664..914deaa0e 100644 --- a/src/plugins/noPendingCount/index.ts +++ b/src/plugins/noPendingCount/index.ts @@ -74,10 +74,10 @@ export default definePlugin({ // This prevents the Message Requests tab from always hiding due to the previous patch (and is compatible with spam requests) // In short, only the red badge is hidden. Button visibility behavior isn't changed. { - find: ".getSpamChannelsCount()", + find: ".getSpamChannelsCount();return", predicate: () => settings.store.hideMessageRequestsCount, replacement: { - match: /(?<=getSpamChannelsCount\(\),\i=)\i\.getMessageRequestsCount\(\)/, + match: /(?<=getSpamChannelsCount\(\);return )\i\.getMessageRequestsCount\(\)/, replace: "$self.getRealMessageRequestCount()" } }, diff --git a/src/plugins/volumeBooster/index.ts b/src/plugins/volumeBooster/index.ts index 241111d41..c9a08bbc6 100644 --- a/src/plugins/volumeBooster/index.ts +++ b/src/plugins/volumeBooster/index.ts @@ -94,7 +94,7 @@ export default definePlugin({ find: "AudioContextSettingsMigrated", replacement: [ { - match: /(?<=isLocalMute\(\i,\i\),volume:.+?volume:)\i(?=})/, + match: /(?<=isLocalMute\(\i,\i\),volume:(\i).+?\i\(\i,\i,)\1(?=\))/, replace: "$&>200?200:$&" }, { @@ -109,7 +109,7 @@ export default definePlugin({ }, // Prevent the MediaEngineStore from overwriting our LocalVolumes above 200 with the ones the Discord Audio Context Settings sync sends { - find: '"MediaEngineStore"', + find: '="MediaEngineStore",', replacement: [ { match: /(\.settings\.audioContextSettings.+?)(\i\[\i\])=(\i\.volume)(.+?setLocalVolume\(\i,).+?\)/, diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index 24be9bef5..bcd070792 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -113,8 +113,8 @@ export default definePlugin({ { find: '"MessageReactionsStore"', replacement: { - match: /(?<=CONNECTION_OPEN:function\(\){)(\i)={}/, - replace: "$&;$self.reactions=$1" + match: /function (\i)\(\){(\i)={}(?=.*CONNECTION_OPEN:\1)/, + replace: "$&;$self.reactions=$2;" } }, { From 00c968473e83e4ee83cdec1f134e67d24bbf4b5a Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:35:40 -0500 Subject: [PATCH 72/82] FavoriteEmojiFirst: Fix sorting emojis (#3074) --- src/plugins/favEmojiFirst/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/favEmojiFirst/index.ts b/src/plugins/favEmojiFirst/index.ts index aa43a528e..ebb89f7e1 100644 --- a/src/plugins/favEmojiFirst/index.ts +++ b/src/plugins/favEmojiFirst/index.ts @@ -57,7 +57,7 @@ export default definePlugin({ { // https://regex101.com/r/x2mobQ/1 // searchEmojis(...,maxCount: stuff) ... endEmojis = emojis.slice(0, maxCount - gifResults.length) - match: /,maxCount:(\i)(.{1,500}\i)=(\i)\.slice\(0,(Math\.max\(\i,\i(?:-\i\.length){2})\)/, + match: /,maxCount:(\i)(.{1,500}\i)=(\i)\.slice\(0,(Math\.max\(\i,\i(?:-\i\.length){2}\))\)/, // ,maxCount:Infinity ... endEmojis = (emojis.sliceTo = n, emojis) replace: ",maxCount:Infinity$2=($3.sliceTo = $4, $3)" } From 5f1c5fa370467b2f853df66a015ec904ad002397 Mon Sep 17 00:00:00 2001 From: Lumap Date: Thu, 12 Dec 2024 23:40:44 +0100 Subject: [PATCH 73/82] AppleMusicRichPresence: Fix token fetching Regex (#3071) --- src/plugins/appleMusic.desktop/native.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/appleMusic.desktop/native.ts b/src/plugins/appleMusic.desktop/native.ts index 7d69a85ae..5a5479976 100644 --- a/src/plugins/appleMusic.desktop/native.ts +++ b/src/plugins/appleMusic.desktop/native.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { canonicalizeMatch } from "@utils/patches"; import { execFile } from "child_process"; import { promisify } from "util"; @@ -26,7 +27,7 @@ interface RemoteData { let cachedRemoteData: { id: string, data: RemoteData; } | { id: string, failures: number; } | null = null; const APPLE_MUSIC_BUNDLE_REGEX = /