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 01/38] 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 02/38] 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 03/38] 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 04/38] 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 05/38] 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 06/38] 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 07/38] 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 08/38] 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 09/38] 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 10/38] 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 11/38] 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 12/38] 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 13/38] 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 14/38] 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 15/38] 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 16/38] 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 17/38] 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 18/38] 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 19/38] 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 20/38] 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 21/38] 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 22/38] 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 23/38] 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 24/38] 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 25/38] 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 26/38] 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 27/38] 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 28/38] 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 29/38] 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 30/38] 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 31/38] 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 32/38] 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 33/38] 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 34/38] 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 35/38] 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 36/38] 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 37/38] 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 38/38] 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 {