From 12376c622ee1568d7c4633272362534ca7aea2df Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 18:52:35 +0200 Subject: [PATCH 01/11] fix settings ui on canary --- src/plugins/_core/settings.tsx | 112 ++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 772ee9b64..0a6aea8b9 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -26,7 +26,7 @@ import UpdaterTab from "@components/VencordSettings/UpdaterTab"; import VencordTab from "@components/VencordSettings/VencordTab"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { React } from "@webpack/common"; +import { i18n, React } from "@webpack/common"; import gitHash from "~git-hash"; @@ -36,41 +36,55 @@ export default definePlugin({ authors: [Devs.Ven, Devs.Megu], required: true, - patches: [{ - find: ".versionHash", - replacement: [ - { - match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, - replace: (m, component, props) => { - props = props.replace(/children:\[.+\]/, ""); - return `${m},$self.makeInfoElements(${component}, ${props})`; + patches: [ + { + find: ".versionHash", + replacement: [ + { + match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, + replace: (m, component, props) => { + props = props.replace(/children:\[.+\]/, ""); + return `${m},$self.makeInfoElements(${component}, ${props})`; + } } + ] + }, + // Discord Stable + // FIXME: remove once change merged to stable + { + find: "Messages.ACTIVITY_SETTINGS", + replacement: { + get match() { + switch (Settings.plugins.Settings.settingsLocation) { + case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; + case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; + case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; + case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; + case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; + case "aboveActivity": + default: + return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; + } + }, + replace: "...$self.makeSettingsCategories($1),$&" + } + }, + // Discord Canary + { + find: "Messages.ACTIVITY_SETTINGS", + replacement: { + match: /(?<=section:(.{0,50})\.DIVIDER\}\))([,;])(?=.{0,200}(\i)\.push.{0,100}label:(\i)\.header)/, + replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` + } + }, + { + find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", + replacement: { + match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.UserSettingsSections\).*?(\i)\.default\.open\()/, + replace: "$2.default.open($1);return;" } - ] - }, { - find: "Messages.ACTIVITY_SETTINGS", - replacement: { - get match() { - switch (Settings.plugins.Settings.settingsLocation) { - case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; - case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; - case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; - case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; - case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; - case "aboveActivity": - default: - return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; - } - }, - replace: "...$self.makeSettingsCategories($1),$&" } - }, { - find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", - replacement: { - match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.UserSettingsSections\).*?(\i)\.default\.open\()/, - replace: "$2.default.open($1);return;" - } - }], + ], customSections: [] as ((SectionTypes: Record) => any)[], @@ -130,19 +144,43 @@ export default definePlugin({ ].filter(Boolean); }, + isRightSpot({ header, settings }: { header?: string; settings?: string[]; }) { + const firstChild = settings?.[0]; + // lowest two elements... sanity backup + if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS") return true; + + const { settingsLocation } = Settings.plugins.Settings; + + if (settingsLocation === "bottom") return firstChild === "LOGOUT"; + if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG"; + + const names = { + top: i18n.Messages.USER_SETTINGS, + aboveNitro: i18n.Messages.BILLING_SETTINGS, + belowNitro: i18n.Messages.APP_SETTINGS, + aboveActivity: i18n.Messages.ACTIVITY_SETTINGS + }; + return header === names[settingsLocation]; + }, + + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { + if (!this.isRightSpot(element)) return; + + elements.push(...this.makeSettingsCategories(sectionTypes)); + }, + options: { settingsLocation: { type: OptionType.SELECT, description: "Where to put the Vencord settings section", options: [ { label: "At the very top", value: "top" }, - { label: "Above the Nitro section", value: "aboveNitro" }, + { label: "Above the Nitro section", value: "aboveNitro", default: true }, { label: "Below the Nitro section", value: "belowNitro" }, - { label: "Above Activity Settings", value: "aboveActivity", default: true }, + { label: "Above Activity Settings", value: "aboveActivity" }, { label: "Below Activity Settings", value: "belowActivity" }, { label: "At the very bottom", value: "bottom" }, - ], - restartNeeded: true + ] }, }, From a54b55edad3e33c44ac1419d7d20c1724a528f7e Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 18:54:00 +0200 Subject: [PATCH 02/11] bump to v1.8.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e5845987..95f98a8ba 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.3", + "version": "1.8.4", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 719c6140f3fafb0ae04323268651f0b4f919af91 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 21:18:43 +0200 Subject: [PATCH 03/11] fix Vencord Settings section being added multiple times --- src/plugins/_core/settings.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 0a6aea8b9..b09af2c05 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -154,6 +154,8 @@ export default definePlugin({ if (settingsLocation === "bottom") return firstChild === "LOGOUT"; if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG"; + if (!header) return; + const names = { top: i18n.Messages.USER_SETTINGS, aboveNitro: i18n.Messages.BILLING_SETTINGS, @@ -163,8 +165,12 @@ export default definePlugin({ return header === names[settingsLocation]; }, + patchedSettings: new WeakSet(), + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { - if (!this.isRightSpot(element)) return; + if (this.patchedSettings.has(elements) || !this.isRightSpot(element)) return; + + this.patchedSettings.add(elements); elements.push(...this.makeSettingsCategories(sectionTypes)); }, From d8b3869b8113f304a352677907c6ee9975ee0cd1 Mon Sep 17 00:00:00 2001 From: Board <26598490+BoardTM@users.noreply.github.com> Date: Wed, 15 May 2024 01:07:33 +0200 Subject: [PATCH 04/11] ThemeAttributes: add larger avatar url variables to avatars (#2449) Co-authored-by: vee --- src/plugins/themeAttributes/README.md | 10 ++++++++- src/plugins/themeAttributes/index.ts | 30 ++++++++++++++++++++++++++- src/utils/constants.ts | 4 ++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/plugins/themeAttributes/README.md b/src/plugins/themeAttributes/README.md index 87cb803c5..89001aae4 100644 --- a/src/plugins/themeAttributes/README.md +++ b/src/plugins/themeAttributes/README.md @@ -1,6 +1,6 @@ # ThemeAttributes -This plugin adds data attributes to various elements inside Discord +This plugin adds data attributes and CSS variables to various elements inside Discord This allows themes to more easily theme those elements or even do things that otherwise wouldn't be possible @@ -19,3 +19,11 @@ This allows themes to more easily theme those elements or even do things that ot - `data-is-self` is a boolean indicating whether this is the current user's message ![image](https://github.com/Vendicated/Vencord/assets/45497981/34bd5053-3381-402f-82b2-9c812cc7e122) + +## CSS Variables + +### Avatars + +`--avatar-url-` contains a URL for the users avatar with the size attribute adjusted for the resolutions `128, 256, 512, 1024, 2048, 4096`. + +![image](https://github.com/Vendicated/Vencord/assets/26598490/192ddac0-c827-472f-9933-fa99ff36f723) diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index b8ceac621..b80844546 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -9,10 +9,11 @@ import definePlugin from "@utils/types"; import { UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; + export default definePlugin({ name: "ThemeAttributes", description: "Adds data attributes to various elements for theming purposes", - authors: [Devs.Ven], + authors: [Devs.Ven, Devs.Board], patches: [ // Add data-tab-id to all tab bar items @@ -32,9 +33,36 @@ export default definePlugin({ match: /\.messageListItem(?=,"aria)/, replace: "$&,...$self.getMessageProps(arguments[0])" } + }, + + // add --avatar-url- css variable to avatar img elements + // popout profiles + { + find: ".LABEL_WITH_ONLINE_STATUS", + replacement: { + match: /src:null!=\i\?(\i).{1,50}"aria-hidden":!0/, + replace: "$&,style:$self.getAvatarStyles($1)" + } + }, + // chat avatars + { + find: "showCommunicationDisabledStyles", + replacement: { + match: /src:(\i),"aria-hidden":!0/, + replace: "$&,style:$self.getAvatarStyles($1)" + } } ], + getAvatarStyles(src: string) { + return Object.fromEntries( + [128, 256, 512, 1024, 2048, 4096].map(size => [ + `--avatar-url-${size}`, + `url(${src.replace(/\d+$/, String(size))})` + ]) + ); + }, + getMessageProps(props: { message: Message; }) { const author = props.message?.author; const authorId = author?.id; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e446a27b6..69c18cd56 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -382,6 +382,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "ant0n", id: 145224646868860928n }, + Board: { + name: "BoardTM", + id: 285475344817848320n, + }, philipbry: { name: "philipbry", id: 554994003318276106n From 5232a85319d3db6fa30e6dd638f19582aae092c5 Mon Sep 17 00:00:00 2001 From: Ulysses Zhan Date: Tue, 14 May 2024 16:18:30 -0700 Subject: [PATCH 05/11] new plugin NoServerEmoji ~ hides server emojis from autocomplete (#1787) Co-authored-by: vee --- src/plugins/noServerEmojis/index.ts | 50 +++++++++++++++++++++++++++++ src/utils/constants.ts | 4 +++ 2 files changed, 54 insertions(+) create mode 100644 src/plugins/noServerEmojis/index.ts diff --git a/src/plugins/noServerEmojis/index.ts b/src/plugins/noServerEmojis/index.ts new file mode 100644 index 000000000..ed843769c --- /dev/null +++ b/src/plugins/noServerEmojis/index.ts @@ -0,0 +1,50 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +const settings = definePluginSettings({ + shownEmojis: { + description: "The types of emojis to show in the autocomplete menu.", + type: OptionType.SELECT, + default: "onlyUnicode", + options: [ + { label: "Only unicode emojis", value: "onlyUnicode" }, + { label: "Unicode emojis and server emojis from current server", value: "currentServer" }, + { label: "Unicode emojis and all server emojis (Discord default)", value: "all" } + ] + } +}); + +export default definePlugin({ + name: "NoServerEmojis", + authors: [Devs.UlyssesZhan], + description: "Do not show server emojis in the autocomplete menu.", + settings, + patches: [ + { + find: "}searchWithoutFetchingLatest(", + replacement: { + match: /searchWithoutFetchingLatest.{20,300}get\((\i).{10,40}?reduce\(\((\i),(\i)\)=>\{/, + replace: "$& if ($self.shouldSkip($1, $3)) return $2;" + } + } + ], + shouldSkip(guildId: string, emoji: any) { + if (emoji.type !== "GUILD_EMOJI") { + return false; + } + if (settings.store.shownEmojis === "onlyUnicode") { + return true; + } + if (settings.store.shownEmojis === "currentServer") { + return emoji.guildId !== guildId; + } + return false; + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 69c18cd56..21d891900 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -378,6 +378,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "ProffDea", id: 609329952180928513n }, + UlyssesZhan: { + name: "UlyssesZhan", + id: 586808226058862623n + }, ant0n: { name: "ant0n", id: 145224646868860928n From 81d3f5df1a5b0faee051a7b8cd74f4f45386e4c3 Mon Sep 17 00:00:00 2001 From: Ulysses Zhan Date: Tue, 14 May 2024 16:21:00 -0700 Subject: [PATCH 06/11] new plugin CtrlEnterSend (#1794) Co-authored-by: vee --- src/plugins/ctrlEnterSend/index.ts | 68 ++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/plugins/ctrlEnterSend/index.ts diff --git a/src/plugins/ctrlEnterSend/index.ts b/src/plugins/ctrlEnterSend/index.ts new file mode 100644 index 000000000..4b9dd8e06 --- /dev/null +++ b/src/plugins/ctrlEnterSend/index.ts @@ -0,0 +1,68 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +export default definePlugin({ + name: "CtrlEnterSend", + authors: [Devs.UlyssesZhan], + description: "Use Ctrl+Enter to send messages (customizable)", + settings: definePluginSettings({ + submitRule: { + description: "The way to send a message", + type: OptionType.SELECT, + options: [ + { + label: "Ctrl+Enter (Enter or Shift+Enter for new line)", + value: "ctrl+enter" + }, + { + label: "Shift+Enter (Enter for new line)", + value: "shift+enter" + }, + { + label: "Enter (Shift+Enter for new line; Discord default)", + value: "enter" + } + ], + default: "ctrl+enter" + }, + sendMessageInTheMiddleOfACodeBlock: { + description: "Whether to send a message in the middle of a code block", + type: OptionType.BOOLEAN, + default: true, + } + }), + patches: [ + { + find: "KeyboardKeys.ENTER&&(!", + replacement: { + match: /(?<=(\i)\.which===\i\.KeyboardKeys.ENTER&&).{0,100}(\(0,\i\.hasOpenPlainTextCodeBlock\)\(\i\)).{0,100}(?=&&\(\i\.preventDefault)/, + replace: "$self.shouldSubmit($1, $2)" + } + } + ], + shouldSubmit(event: KeyboardEvent, codeblock: boolean): boolean { + let result = false; + switch (this.settings.store.submitRule) { + case "shift+enter": + result = event.shiftKey; + break; + case "ctrl+enter": + result = event.ctrlKey; + break; + case "enter": + result = !event.shiftKey && !event.ctrlKey; + break; + } + if (!this.settings.store.sendMessageInTheMiddleOfACodeBlock) { + result &&= !codeblock; + } + return result; + } +}); From 97dd56ccdab091ba65b6e25efd172b0464b191d5 Mon Sep 17 00:00:00 2001 From: ! Sleepy <109904491+eepyfemboi@users.noreply.github.com> Date: Tue, 14 May 2024 17:17:19 -0700 Subject: [PATCH 07/11] MoreUserTags: Add chat moderator tag (#2424) Co-authored-by: Vendicated --- src/plugins/moreUserTags/index.tsx | 42 ++++++++++-------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index df47e5456..1257b4524 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -50,6 +50,7 @@ interface TagSettings { MODERATOR_STAFF: TagSetting, MODERATOR: TagSetting, VOICE_MODERATOR: TagSetting, + TRIAL_MODERATOR: TagSetting, [k: string]: TagSetting; } @@ -93,6 +94,11 @@ const tags: Tag[] = [ displayName: "VC Mod", description: "Can manage voice chats", permissions: ["MOVE_MEMBERS", "MUTE_MEMBERS", "DEAFEN_MEMBERS"] + }, { + name: "CHAT_MODERATOR", + displayName: "Chat Mod", + description: "Can timeout people", + permissions: ["MODERATE_MEMBERS"] } ]; const defaultSettings = Object.fromEntries( @@ -263,34 +269,14 @@ export default definePlugin({ ], start() { - if (settings.store.tagSettings) return; - // @ts-ignore - if (!settings.store.visibility_WEBHOOK) settings.store.tagSettings = defaultSettings; - else { - const newSettings = { ...defaultSettings }; - Object.entries(Vencord.PlainSettings.plugins.MoreUserTags).forEach(([name, value]) => { - const [setting, tag] = name.split("_"); - if (setting === "visibility") { - switch (value) { - case "always": - // its the default - break; - case "chat": - newSettings[tag].showInNotChat = false; - break; - case "not-chat": - newSettings[tag].showInChat = false; - break; - case "never": - newSettings[tag].showInChat = false; - newSettings[tag].showInNotChat = false; - break; - } - } - settings.store.tagSettings = newSettings; - delete Vencord.Settings.plugins.MoreUserTags[name]; - }); - } + settings.store.tagSettings ??= defaultSettings; + + // newly added field might be missing from old users + settings.store.tagSettings.CHAT_MODERATOR ??= { + text: "Chat Mod", + showInChat: true, + showInNotChat: true + }; }, getPermissions(user: User, channel: Channel): string[] { From 840d571ce2b756f2bde31296bec433930df14413 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 21:34:25 -0300 Subject: [PATCH 08/11] Fix BetterSettings & StartupTimings patch --- src/plugins/betterSettings/index.tsx | 2 +- src/plugins/startupTimings/index.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 5064bd538..e90e5c82a 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -119,7 +119,7 @@ export default definePlugin({ { // Settings cog context menu find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", replacement: { - match: /\(0,\i.default\)\(\)(?=\.filter\(\i=>\{let\{section:\i\}=)/, + match: /\(0,\i.useDefaultUserSettingsSections\)\(\)(?=\.filter\(\i=>\{let\{section:\i\}=)/, replace: "$self.wrapMenu($&)" } } diff --git a/src/plugins/startupTimings/index.tsx b/src/plugins/startupTimings/index.tsx index 742d822ae..cf366df38 100644 --- a/src/plugins/startupTimings/index.tsx +++ b/src/plugins/startupTimings/index.tsx @@ -26,10 +26,12 @@ export default definePlugin({ description: "Adds Startup Timings to the Settings menu", authors: [Devs.Megu], patches: [{ - find: "UserSettingsSections.PAYMENT_FLOW_MODAL_TEST_PAGE,", + find: "Messages.ACTIVITY_SETTINGS", replacement: { - match: /{section:\i\.UserSettingsSections\.PAYMENT_FLOW_MODAL_TEST_PAGE/, - replace: '{section:"StartupTimings",label:"Startup Timings",element:$self.StartupTimingPage},$&' + match: /(?<=}\)([,;])(\i\.settings)\.forEach.+?(\i)\.push.+}\))/, + replace: (_, commaOrSemi, settings, elements) => "" + + `${commaOrSemi}${settings}?.[0]==="CHANGELOG"` + + `&&${elements}.push({section:"StartupTimings",label:"Startup Timings",element:$self.StartupTimingPage})` } }], StartupTimingPage From 0e4724ec0d2ee3c9bd15f81d29dcbd8fec1211ce Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 15 May 2024 03:14:02 +0200 Subject: [PATCH 09/11] Settings: remove obsolete patch; add redundancy & more useful dbg copy --- src/plugins/_core/settings.tsx | 79 +++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index b09af2c05..81d1d1797 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -30,6 +30,9 @@ import { i18n, React } from "@webpack/common"; import gitHash from "~git-hash"; +type SectionType = "HEADER" | "DIVIDER" | "CUSTOM"; +type SectionTypes = Record; + export default definePlugin({ name: "Settings", description: "Adds Settings UI and debug info", @@ -41,34 +44,18 @@ export default definePlugin({ find: ".versionHash", replacement: [ { - match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, + match: /\[\(0,\i\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, replace: (m, component, props) => { props = props.replace(/children:\[.+\]/, ""); return `${m},$self.makeInfoElements(${component}, ${props})`; } + }, + { + match: /copyValue:\i\.join\(" "\)/, + replace: "$& + $self.getInfoString()" } ] }, - // Discord Stable - // FIXME: remove once change merged to stable - { - find: "Messages.ACTIVITY_SETTINGS", - replacement: { - get match() { - switch (Settings.plugins.Settings.settingsLocation) { - case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; - case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; - case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; - case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; - case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; - case "aboveActivity": - default: - return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; - } - }, - replace: "...$self.makeSettingsCategories($1),$&" - } - }, // Discord Canary { find: "Messages.ACTIVITY_SETTINGS", @@ -77,6 +64,13 @@ export default definePlugin({ replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` } }, + { + find: "useDefaultUserSettingsSections:function", + replacement: { + match: /(?<=useDefaultUserSettingsSections:function\(\){return )(\i)\}/, + replace: "$self.wrapSettingsHook($1)}" + } + }, { find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", replacement: { @@ -86,9 +80,9 @@ export default definePlugin({ } ], - customSections: [] as ((SectionTypes: Record) => any)[], + customSections: [] as ((SectionTypes: SectionTypes) => any)[], - makeSettingsCategories(SectionTypes: Record) { + makeSettingsCategories(SectionTypes: SectionTypes) { return [ { section: SectionTypes.HEADER, @@ -167,7 +161,7 @@ export default definePlugin({ patchedSettings: new WeakSet(), - addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: SectionTypes) { if (this.patchedSettings.has(elements) || !this.isRightSpot(element)) return; this.patchedSettings.add(elements); @@ -175,6 +169,20 @@ export default definePlugin({ elements.push(...this.makeSettingsCategories(sectionTypes)); }, + wrapSettingsHook(originalHook: (...args: any[]) => Record[]) { + return (...args: any[]) => { + const elements = originalHook(...args); + if (!this.patchedSettings.has(elements)) + elements.unshift(...this.makeSettingsCategories({ + HEADER: "HEADER", + DIVIDER: "DIVIDER", + CUSTOM: "CUSTOM" + })); + + return elements; + }; + }, + options: { settingsLocation: { type: OptionType.SELECT, @@ -213,15 +221,24 @@ export default definePlugin({ return ""; }, - makeInfoElements(Component: React.ComponentType, props: React.PropsWithChildren) { + getInfoRows() { const { electronVersion, chromiumVersion, additionalInfo } = this; - return ( - <> - Vencord {gitHash}{additionalInfo} - {electronVersion && Electron {electronVersion}} - {chromiumVersion && Chromium {chromiumVersion}} - + const rows = [`Vencord ${gitHash}${additionalInfo}`]; + + if (electronVersion) rows.push(`Electron ${electronVersion}`); + if (chromiumVersion) rows.push(`Chromium ${chromiumVersion}`); + + return rows; + }, + + getInfoString() { + return "\n" + this.getInfoRows().join("\n"); + }, + + makeInfoElements(Component: React.ComponentType, props: React.PropsWithChildren) { + return this.getInfoRows().map((text, i) => + {text} ); } }); From 46801de21fc587118710873bee7e78f517932cf0 Mon Sep 17 00:00:00 2001 From: mcpower Date: Wed, 15 May 2024 11:42:09 +1000 Subject: [PATCH 10/11] chore: tidy up suggested vscode extensions list (#2221) Co-authored-by: Vendicated --- .vscode/extensions.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f16f1e273..e86effb19 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,11 +1,9 @@ { "recommendations": [ "dbaeumer.vscode-eslint", - "eamodio.gitlens", "EditorConfig.EditorConfig", - "ExodiusStudios.comment-anchors", - "formulahendry.auto-rename-tag", "GregorBiswanger.json2ts", - "stylelint.vscode-stylelint" + "stylelint.vscode-stylelint", + "Vendicated.vencord-companion" ] } From 1fea8420938a4dfd519881132d5782a30604112a Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 22:47:19 -0300 Subject: [PATCH 11/11] BetterFolders: Fix scrolling --- src/plugins/betterFolders/index.tsx | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index d252682f8..795f19901 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { FluxDispatcher, i18n } from "@webpack/common"; +import { FluxDispatcher, i18n, useMemo } from "@webpack/common"; import FolderSideBar from "./FolderSideBar"; @@ -117,8 +117,8 @@ export default definePlugin({ }, // If we are rendering the Better Folders sidebar, we filter out guilds that are not in folders and unexpanded folders { - match: /(useStateFromStoresArray\).{0,25}let \i)=(\i\.\i.getGuildsTree\(\))/, - replace: (_, rest, guildsTree) => `${rest}=$self.getGuildTree(!!arguments[0].isBetterFolders,${guildsTree},arguments[0].betterFoldersExpandedIds)` + match: /\[(\i)\]=(\(0,\i\.useStateFromStoresArray\).{0,40}getGuildsTree\(\).+?}\))(?=,)/, + replace: (_, originalTreeVar, rest) => `[betterFoldersOriginalTree]=${rest},${originalTreeVar}=$self.getGuildTree(!!arguments[0].isBetterFolders,betterFoldersOriginalTree,arguments[0].betterFoldersExpandedIds)` }, // If we are rendering the Better Folders sidebar, we filter out everything but the servers and folders from the GuildsBar Guild List children { @@ -252,19 +252,21 @@ export default definePlugin({ } }, - getGuildTree(isBetterFolders: boolean, oldTree: any, expandedFolderIds?: Set) { - if (!isBetterFolders || expandedFolderIds == null) return oldTree; + getGuildTree(isBetterFolders: boolean, originalTree: any, expandedFolderIds?: Set) { + return useMemo(() => { + if (!isBetterFolders || expandedFolderIds == null) return originalTree; - const newTree = new GuildsTree(); - // Children is every folder and guild which is not in a folder, this filters out only the expanded folders - newTree.root.children = oldTree.root.children.filter(guildOrFolder => expandedFolderIds.has(guildOrFolder.id)); - // Nodes is every folder and guild, even if it's in a folder, this filters out only the expanded folders and guilds inside them - newTree.nodes = Object.fromEntries( - Object.entries(oldTree.nodes) - .filter(([_, guildOrFolder]: any[]) => expandedFolderIds.has(guildOrFolder.id) || expandedFolderIds.has(guildOrFolder.parentId)) - ); + const newTree = new GuildsTree(); + // Children is every folder and guild which is not in a folder, this filters out only the expanded folders + newTree.root.children = originalTree.root.children.filter(guildOrFolder => expandedFolderIds.has(guildOrFolder.id)); + // Nodes is every folder and guild, even if it's in a folder, this filters out only the expanded folders and guilds inside them + newTree.nodes = Object.fromEntries( + Object.entries(originalTree.nodes) + .filter(([_, guildOrFolder]: any[]) => expandedFolderIds.has(guildOrFolder.id) || expandedFolderIds.has(guildOrFolder.parentId)) + ); - return newTree; + return newTree; + }, [isBetterFolders, originalTree, expandedFolderIds]); }, makeGuildsBarGuildListFilter(isBetterFolders: boolean) {