From 09d58d4747462482a4f3e4cf636c8f74b32b4c8b Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 26 Nov 2025 12:44:02 -0500 Subject: [PATCH 01/33] t --- crowdin.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 crowdin.yml diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..c791867bb --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /i18n/en/ + translation: /i18n/%locale_with_underscore%/%original_file_name% From 8da71948e2c5999f53d2bc3dc1feba9df0b757f3 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 26 Nov 2025 12:45:36 -0500 Subject: [PATCH 02/33] remove mistake --- crowdin.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 crowdin.yml diff --git a/crowdin.yml b/crowdin.yml deleted file mode 100644 index c791867bb..000000000 --- a/crowdin.yml +++ /dev/null @@ -1,3 +0,0 @@ -files: - - source: /i18n/en/ - translation: /i18n/%locale_with_underscore%/%original_file_name% From dd19430300daca223781cb4e8130e9a14ca2d79a Mon Sep 17 00:00:00 2001 From: Etorix <92535668+EtorixDev@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:29:52 -0800 Subject: [PATCH 03/33] Questify: Fix patch. (#525) --- src/equicordplugins/questify/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/questify/index.tsx b/src/equicordplugins/questify/index.tsx index 0d6216c61..d50925220 100644 --- a/src/equicordplugins/questify/index.tsx +++ b/src/equicordplugins/questify/index.tsx @@ -1251,7 +1251,7 @@ export default definePlugin({ }, { // Add the trigger to the memo for rerendering the progress label. - match: /(\i.intl.string\(\i.\i#{intl::QUESTS_SEE_CODE}\)}\)}},\[)/, + match: /(\)}}},\[)/, replace: "$1questRerenderTrigger," }, { From 38e89b9789f09f32d3969f0f73748b2e275588cc Mon Sep 17 00:00:00 2001 From: Etorix <92535668+EtorixDev@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:32:11 -0800 Subject: [PATCH 04/33] SMYN: Merge GlobalNicknames. (#524) * Merge plugins. * Lint. --- src/equicordplugins/globalNicknames/index.tsx | 204 ------------- src/plugins/showMeYourName/index.tsx | 269 ++++++++++++------ src/plugins/showMeYourName/style.css | 10 + 3 files changed, 193 insertions(+), 290 deletions(-) delete mode 100644 src/equicordplugins/globalNicknames/index.tsx diff --git a/src/equicordplugins/globalNicknames/index.tsx b/src/equicordplugins/globalNicknames/index.tsx deleted file mode 100644 index e0c71c174..000000000 --- a/src/equicordplugins/globalNicknames/index.tsx +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { NavContextMenuPatchCallback } from "@api/ContextMenu"; -import { DataStore } from "@api/index"; -import { definePluginSettings } from "@api/Settings"; -import { Button } from "@components/Button"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { Heading } from "@components/Heading"; -import { EquicordDevs } from "@utils/constants"; -import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; -import definePlugin, { OptionType } from "@utils/types"; -import { Message, User } from "@vencord/discord-types"; -import { findComponentByCodeLazy } from "@webpack"; -import { Menu, React, TextInput, UserStore } from "@webpack/common"; - -const UserBoxIcon = findComponentByCodeLazy("0-3-3H5Zm10 6a3"); - -type NicknamesData = Record; - -let nicknames: NicknamesData = {}; - -const settings = definePluginSettings({ - enableMessages: { - type: OptionType.BOOLEAN, - description: "Show global nicknames in chat messages.", - default: true, - restartNeeded: true - }, - enableMemberList: { - type: OptionType.BOOLEAN, - description: "Show global nicknames in the member list.", - default: true, - restartNeeded: true - }, - enableVoiceChannels: { - type: OptionType.BOOLEAN, - description: "Show global nicknames in voice channels.", - default: true, - restartNeeded: true - }, - enableTypingIndicator: { - type: OptionType.BOOLEAN, - description: "Show global nicknames in the typing indicator.", - default: true, - restartNeeded: true - } -}); - -function NicknameModal({ modalProps, user }: { modalProps: ModalProps; user: User; }) { - const [value, setValue] = React.useState(nicknames[user.id] ?? ""); - - return ( - - - - Change Nickname - - - - -
- - Nickname - - -
-
- - - - -
- ); -} - -const userContextPatch: NavContextMenuPatchCallback = (children, { user }) => { - if (!user) return; - - const currentUser = UserStore.getCurrentUser(); - if (!currentUser || user.id === currentUser.id) return; - - children.push( - , - nicknames[user.id] ? ( - { - delete nicknames[user.id]; - await DataStore.set("GlobalNicknames", nicknames); - }} - /> - ) : ( - openModal(props => ( - - - - ))} - /> - ) - ); -}; - -export default definePlugin({ - name: "GlobalNicknames", - description: "Set custom nicknames for any user globally.", - authors: [EquicordDevs.Prism], - dependencies: ["ContextMenuAPI"], - settings, - - patches: [ - { - find: '="SYSTEM_TAG"', - predicate: () => settings.store.enableMessages, - replacement: { - match: /children:(.+?),"data-text":/, - replace: 'children:$self.patchMessageName(arguments[0])??($1),"data-text":' - } - }, - { - find: "let{colorRoleName:", - predicate: () => settings.store.enableMemberList, - replacement: { - match: /,name:(null!=\i\?\i:\i),colorStrings/, - replace: ",name:$self.patchName($1,arguments[0].user)||($1),colorStrings" - } - }, - { - find: ",connectUserDragSource:", - predicate: () => settings.store.enableVoiceChannels, - replacement: { - match: /nick:(\i),collapsed/, - replace: "nick:$self.patchName($1,arguments[0].user)||$1,collapsed" - } - }, - { - find: "#{intl::THREE_USERS_TYPING}", - predicate: () => settings.store.enableTypingIndicator, - replacement: { - match: /(\i\.\i\.getName\(\i\.guild_id,\i\.id),(\i)\)\)/, - replace: "$1,$self.patchTypingName($2)))" - } - } - ], - - async start() { - const data = await DataStore.get("GlobalNicknames"); - nicknames = data ?? {}; - }, - - patchMessageName(props: { message: Message; }): string | null { - const userId = props?.message?.author?.id; - return userId ? nicknames[userId] ?? null : null; - }, - - patchName(_: string, user: User): string | null { - return nicknames[user.id] ?? null; - }, - - patchTypingName(user: User): User { - const nickname = nicknames[user.id]; - if (!nickname) return user; - return { ...user, globalName: nickname, username: nickname } as User; - }, - - contextMenus: { - "user-context": userContextPatch - } -}); diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index 6f6234525..30ce3c6e8 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { DataStore } from "@api/index"; import "./style.css"; import { definePluginSettings, Settings } from "@api/Settings"; @@ -11,15 +12,21 @@ import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { GuildMember, Message, User } from "@vencord/discord-types"; import { findByCodeLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildMemberStore, GuildStore, MessageStore, RelationshipStore, StreamerModeStore, useEffect, UserStore } from "@webpack/common"; +import { ChannelStore, GuildMemberStore, GuildStore, Menu, MessageStore, RelationshipStore, StreamerModeStore, TextInput, useEffect, UserStore, useState } from "@webpack/common"; import { JSX } from "react"; +import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; +import { Button, ErrorBoundary, Heading, TextButton } from "@components/index"; +import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/index"; const wrapEmojis = findByCodeLazy("lastIndex;return"); const AccessibilityStore = findStoreLazy("AccessibilityStore"); const colorPattern = /^#(?:[\da-f]{3}){1,2}$|^#(?:[\da-f]{4}){1,2}$|(rgb|hsl)a?\((\s*-?\d+%?\s*,){2}(\s*-?\d+%?\s*)\)|(rgb|hsl)a?\((\s*-?\d+%?\s*,){3}\s*(0|(0?\.\d+)|1)\)$/iu; const roleColorPattern = /^role((?:\+|-)\d{0,4})?$/iu; const symbolPattern = /^[\p{S}\p{P}]{1,3}$/iu; -const templatePattern = /(?:\{(?:friend|nick|display|user)(?:,\s*(?:friend|nick|display|user))*\})/iu; +const templatePattern = /(?:\{(?:custom|friend|nick|display|user)(?:,\s*(?:custom|friend|nick|display|user))*\})/iu; + +type CustomNicknameData = Record; +let customNicknames: CustomNicknameData = {}; function adjustHex(color: string, percent: number): string { let hex = color.replace("#", ""); @@ -208,8 +215,8 @@ function validTemplate(value: string) { suffix.length > 3 || (!!prefix && !symbolPattern.test(prefix)) || (!!suffix && !symbolPattern.test(suffix)) || - targetProcessedNames.length > 4 || - targetProcessedNames.some(name => !["friend", "nick", "display", "user"].includes(name.trim())) + targetProcessedNames.length > 5 || + targetProcessedNames.some(name => !["custom", "friend", "nick", "display", "user"].includes(name.trim())) ); }); @@ -218,7 +225,13 @@ function validTemplate(value: string) { } } -function getProcessedNames(author: any, truncateAllNamesWithStreamerMode: boolean, discriminators: boolean): [string | null, string | null, string | null, string | null] { +function getProcessedNames(author: any, truncateAllNamesWithStreamerMode: boolean, discriminators: boolean): { + username: string | null; + display: string | null; + nick: string | null; + friend: string | null; + custom: string | null; +} { let discriminator: string | null = null; if (discriminators) { @@ -254,7 +267,13 @@ function getProcessedNames(author: any, truncateAllNamesWithStreamerMode: boolea ? friendName[0] + "..." : friendName as string; - return [username, display, nick, friend]; + const customName: string | null = customNicknames[author.id] || null; + const custom: string | null = !customName ? null + : StreamerModeStore.enabled && (truncateAllNamesWithStreamerMode || customName.toLowerCase() === author.username.toLowerCase()) + ? customName[0] + "..." + : customName; + + return { username, display, nick, friend, custom }; } interface mentionProps { @@ -351,8 +370,8 @@ function renderUsername( const isReaction = isReactionsTooltip || isReactionsPopout; const isVoice = type === "voiceChannel"; - const config = hookless ? settings.store : settings.use(["messages", "replies", "mentions", "memberList", "profilePopout", "reactions", "discriminators", "hideDefaultAtSign", "truncateAllNamesWithStreamerMode", "removeDuplicates", "ignoreGradients", "ignoreFonts", "animateGradients", "includedNames", "friendNameColor", "nicknameColor", "displayNameColor", "usernameColor", "nameSeparator", "triggerNameRerender"]); - const { messages, replies, mentions, memberList, profilePopout, reactions, discriminators, hideDefaultAtSign, truncateAllNamesWithStreamerMode, removeDuplicates, ignoreGradients, ignoreFonts, animateGradients, includedNames, friendNameColor, nicknameColor, displayNameColor, usernameColor, nameSeparator, triggerNameRerender } = config; + const config = hookless ? settings.store : settings.use(["messages", "replies", "mentions", "memberList", "profilePopout", "reactions", "discriminators", "hideDefaultAtSign", "truncateAllNamesWithStreamerMode", "removeDuplicates", "ignoreGradients", "ignoreFonts", "animateGradients", "includedNames", "customNameColor", "friendNameColor", "nicknameColor", "displayNameColor", "usernameColor", "nameSeparator", "triggerNameRerender"]); + const { messages, replies, mentions, memberList, profilePopout, reactions, discriminators, hideDefaultAtSign, truncateAllNamesWithStreamerMode, removeDuplicates, ignoreGradients, ignoreFonts, animateGradients, includedNames, customNameColor, friendNameColor, nicknameColor, displayNameColor, usernameColor, nameSeparator, triggerNameRerender } = config; const canUseGradient = ((author as GuildMember)?.guildId ? (GuildStore.getGuild((author as GuildMember).guildId) ?? {}).premiumFeatures?.features.includes("ENHANCED_ROLE_COLORS") : false); const textMutedValue = getComputedStyle(document.documentElement)?.getPropertyValue("--text-muted")?.trim() || "#72767d"; @@ -361,14 +380,16 @@ function renderUsername( const resolvedDisplayNameColor = author ? resolveColor(author, displayNameColor.trim(), "", canUseGradient) : null; const resolvedNicknameColor = author ? resolveColor(author, nicknameColor.trim(), "", canUseGradient) : null; const resolvedFriendNameColor = author ? resolveColor(author, friendNameColor.trim(), "", canUseGradient) : null; + const resolvedCustomNameColor = author ? resolveColor(author, customNameColor.trim(), "", canUseGradient) : null; const affixColor = { color: textMutedValue, "-webkit-text-fill-color": textMutedValue, isolation: "isolate", "white-space": "pre", "font-family": "var(--font-primary)", "letter-spacing": "normal" }; - const [username, display, nick, friend] = getProcessedNames(author, truncateAllNamesWithStreamerMode, discriminators); + const { username, display, nick, friend, custom } = getProcessedNames(author, truncateAllNamesWithStreamerMode, discriminators); const names: Record = { user: [username, resolvedUsernameColor], display: [display, resolvedDisplayNameColor], nick: [nick, resolvedNicknameColor], friend: [friend, resolvedFriendNameColor], + custom: [custom, resolvedCustomNameColor] }; const outputs: any[] = []; @@ -421,6 +442,7 @@ function renderUsername( let second = outputs.shift(); let third = outputs.shift(); let fourth = outputs.shift(); + let fifth = outputs.shift(); const firstValueWrapped = hookless ? (first.name || "") @@ -438,10 +460,15 @@ function renderUsername( ((fourth ?? {}).name || "") : wrapEmojis((fourth ?? {}).name || ""); + const fifthValueWrapped = hookless ? + ((fifth ?? {}).name || "") + : wrapEmojis((fifth ?? {}).name || ""); + first.wrapped = firstValueWrapped; second && (second.wrapped = secondValueWrapped); third && (third.wrapped = thirdValueWrapped); fourth && (fourth.wrapped = fourthValueWrapped); + fifth && (fifth.wrapped = fifthValueWrapped); if (isMessage && !messages) { return [null, null, null]; @@ -462,10 +489,14 @@ function renderUsername( return [fallbackText, <>{fallbackText}, fallbackText]; } - const prioritizeUsername = (new Set([first, second, third, fourth].filter(Boolean).map(pos => pos.name.toLowerCase())).size > 1); + const prioritizeUsername = (new Set([first, second, third, fourth, fifth].filter(Boolean).map(pos => pos.name.toLowerCase())).size > 1); if (removeDuplicates) { // Remove duplicates from back to front. Prioritize the earlier name, unless it's the username and there's more than one unique option, then prioritize it. + fifth && fourth && fifth.name.toLowerCase() === fourth.name.toLowerCase() ? fifth.type === "user" && prioritizeUsername ? fourth = null : fifth = null : null; + fifth && third && fifth.name.toLowerCase() === third.name.toLowerCase() ? fifth.type === "user" && prioritizeUsername ? third = null : fifth = null : null; + fifth && second && fifth.name.toLowerCase() === second.name.toLowerCase() ? fifth.type === "user" && prioritizeUsername ? second = null : fifth = null : null; + fifth && first && fifth.name.toLowerCase() === first.name.toLowerCase() ? fifth.type === "user" && prioritizeUsername ? first = null : fifth = null : null; fourth && third && fourth.name.toLowerCase() === third.name.toLowerCase() ? fourth.type === "user" && prioritizeUsername ? third = null : fourth = null : null; fourth && second && fourth.name.toLowerCase() === second.name.toLowerCase() ? fourth.type === "user" && prioritizeUsername ? second = null : fourth = null : null; fourth && first && fourth.name.toLowerCase() === first.name.toLowerCase() ? fourth.type === "user" && prioritizeUsername ? first = null : fourth = null : null; @@ -474,11 +505,12 @@ function renderUsername( second && first && second.name.toLowerCase() === first.name.toLowerCase() ? second.type === "user" && prioritizeUsername ? first = null : second = null : null; } - const remainingNames = [first, second, third, fourth].filter(Boolean); + const remainingNames = [first, second, third, fourth, fifth].filter(Boolean); first = remainingNames.shift(); second = remainingNames.shift(); third = remainingNames.shift(); fourth = remainingNames.shift(); + fifth = remainingNames.shift(); const useTopRoleStyle = isMention || isReactionsPopout; const topRoleStyle = resolveColor(author, "Role", "", canUseGradient); @@ -500,7 +532,8 @@ function renderUsername( const secondDataText = second && shouldAnimateSecondaryNames ? (second.prefix + second.name + second.suffix) : ""; const thirdDataText = third && shouldAnimateSecondaryNames ? (third.prefix + third.name + third.suffix) : ""; const fourthDataText = fourth && shouldAnimateSecondaryNames ? (fourth.prefix + fourth.name + fourth.suffix) : ""; - const allDataText = [firstDataText, secondDataText, thirdDataText, fourthDataText].filter(Boolean).join(nameSeparator).trim(); + const fifthDataText = fifth && shouldAnimateSecondaryNames ? (fifth.prefix + fifth.name + fifth.suffix) : ""; + const allDataText = [firstDataText, secondDataText, thirdDataText, fourthDataText, fifthDataText].filter(Boolean).join(nameSeparator).trim(); // Only mentions and reactions popouts should patch in the gradient glow or else a double glow will appear on messages. const hoveringClass = (isHovering ? " show-me-your-name-gradient-hovered" : ""); @@ -512,10 +545,12 @@ function renderUsername( const secondGroupClasses = "show-me-your-name-name-group show-me-your-name-second-name-group"; const thirdGroupClasses = "show-me-your-name-name-group show-me-your-name-third-name-group"; const fourthGroupClasses = "show-me-your-name-name-group show-me-your-name-fourth-name-group"; + const fifthGroupClasses = "show-me-your-name-name-group show-me-your-name-fifth-name-group"; const firstNameClasses = "show-me-your-name-name show-me-your-name-first-name"; const secondNameClasses = "show-me-your-name-name show-me-your-name-second-name"; const thirdNameClasses = "show-me-your-name-name show-me-your-name-third-name"; const fourthNameClasses = "show-me-your-name-name show-me-your-name-fourth-name"; + const fifthNameClasses = "show-me-your-name-name show-me-your-name-fifth-name"; const prefixClasses = "show-me-your-name-affix show-me-your-name-prefix"; const suffixClasses = "show-me-your-name-affix show-me-your-name-suffix"; @@ -549,85 +584,39 @@ function renderUsername( {first.wrapped} )} - {second && ( + {[ + { name: second, dataText: secondDataText, groupClass: secondGroupClasses, nameClass: secondNameClasses, position: "second" }, + { name: third, dataText: thirdDataText, groupClass: thirdGroupClasses, nameClass: thirdNameClasses, position: "third" }, + { name: fourth, dataText: fourthDataText, groupClass: fourthGroupClasses, nameClass: fourthNameClasses, position: "fourth" }, + { name: fifth, dataText: fifthDataText, groupClass: fifthGroupClasses, nameClass: fifthNameClasses, position: "fifth" } + ].map(({ name, dataText, groupClass, nameClass, position }) => name && ( {nameSeparator} - {second.prefix} + {name.prefix} - {second.wrapped} + {name.wrapped} - {second.suffix} + {name.suffix} - )} - {third && ( - - - {nameSeparator} - {third.prefix} - - {third.wrapped} - - {third.suffix} - - )} - {fourth && ( - - - {nameSeparator} - {fourth.prefix} - - {fourth.wrapped} - - {fourth.suffix} - - )} + ))} ); @@ -688,6 +677,98 @@ function removeHoveringReactionPopout(id: string) { settings.store.triggerNameRerender = !settings.store.triggerNameRerender; } +function CustomNicknameModal({ modalProps, user }: { modalProps: ModalProps; user: User; }) { + const [value, setValue] = useState(customNicknames[user.id] ?? ""); + + return ( + + + + {customNicknames[user.id] ? "Change SMYN Nickname" : "Add SMYN Nickname"} + + + + + + {"Set a custom SMYN nickname for this user. Make use of it by specifying {custom} in the SMYN template settings."} + +
+ + SMYN Nickname + + + { + setValue(""); + delete customNicknames[user.id]; + await DataStore.set("SMYNCustomNicknames", customNicknames); + settings.store.triggerNameRerender = !settings.store.triggerNameRerender; + }} + > + Reset SMYN Nickname + +
+
+ + + + +
+ ); +} + +const userContextPatch: NavContextMenuPatchCallback = (children, { user }) => { + if (!user) return; + + const currentUser = UserStore.getCurrentUser(); + if (!currentUser || user.id === currentUser.id) return; + + const group = findGroupChildrenByChildId("user-profile", children); + + !group && children.push(); + (group || children).push( + openModal(props => ( + + + + ))} + /> + ); +}; + const settings = definePluginSettings({ messages: { type: OptionType.BOOLEAN, @@ -747,17 +828,17 @@ const settings = definePluginSettings({ ignoreFonts: { type: OptionType.BOOLEAN, default: false, - description: "For the second, third, and fourth names, use GG SANS regardless of the user's custom font.", + description: "For the non-primary names, use Discord's default fonts regardless of the user's custom nitro font.", }, ignoreGradients: { type: OptionType.BOOLEAN, default: true, - description: "For the second, third, and fourth names, if the role has a gradient, ignore it in favor of the value below.", + description: "For the non-primary names, if the role has a gradient, ignore it in favor of the color set below.", }, animateGradients: { type: OptionType.BOOLEAN, default: false, - description: "For the second, third, and fourth names, if the role has a gradient, animate it. This is disabled by \"Ignore Gradients\" and reduced motion.", + description: "For the non-primary names, if the role has a gradient, animate it. This is disabled by \"Ignore Gradients\" and reduced motion.", }, nameSeparator: { type: OptionType.STRING, @@ -766,10 +847,16 @@ const settings = definePluginSettings({ }, includedNames: { type: OptionType.STRING, - description: "The order to display usernames, display names, nicknames, and friend names. Use the following placeholders: {user}, {display}, {nick}, {friend}. You can provide multiple name options to use as fallbacks if one is unavailable by separating them with commas as such: {friend, nick, display}. You can have up to three prefixes and three suffixes per name.", - default: "{friend, nick} [{display}] (@{user})", + description: "The order to display usernames, display names, nicknames, friend names, and custom names. Use the following placeholders: {user}, {display}, {nick}, {friend}, {custom}. You can provide multiple name options to use as fallbacks if one is unavailable by separating them with commas as such: {custom, friend, nick}. You can have up to three prefixes and three suffixes per name.", + default: "{custom, friend, nick} [{display}] (@{user})", isValid: validTemplate, }, + customNameColor: { + type: OptionType.STRING, + description: "The color to use for the custom name you assigned a user if it's not the first displayed. Leave blank for default. Accepts hex(a), rgb(a), or hsl(a) input. Use \"Role\" to follow the user's top role color. Use \"Role+-#\" to adjust the brightness by that percentage (ex: \"Role+15\")", + default: "Role-25", + isValid: validColor, + }, friendNameColor: { type: OptionType.STRING, description: "The color to use for a friend's nickname if it's not the first displayed. Leave blank for default. Accepts hex(a), rgb(a), or hsl(a) input. Use \"Role\" to follow the user's top role color. Use \"Role+-#\" to adjust the brightness by that percentage (ex: \"Role+15\")", @@ -804,8 +891,9 @@ const settings = definePluginSettings({ export default definePlugin({ name: "ShowMeYourName", - description: "Display any permutation of nicknames, display names, and usernames in chat.", - authors: [Devs.Rini, Devs.TheKodeToad, EquicordDevs.Etorix, Devs.sadan], + description: "Display any permutation of custom nicknames, friend nicknames, server nicknames, display names, and usernames in chat.", + authors: [Devs.Rini, Devs.TheKodeToad, EquicordDevs.Etorix, Devs.sadan, EquicordDevs.Prism], + tags: ["SMYN", "Nicknames", "Custom Nicknames",], isModified: true, settings, @@ -943,6 +1031,15 @@ export default definePlugin({ } ], + async start() { + const data = await DataStore.get("SMYNCustomNicknames"); + customNicknames = data ?? {}; + }, + + contextMenus: { + "user-context": userContextPatch + }, + flux: { RELATIONSHIP_UPDATE(data) { // Allows rerendering when changing friend names. diff --git a/src/plugins/showMeYourName/style.css b/src/plugins/showMeYourName/style.css index 58bd29db7..45cfb18a0 100644 --- a/src/plugins/showMeYourName/style.css +++ b/src/plugins/showMeYourName/style.css @@ -37,4 +37,14 @@ .show-me-your-name-gradient-hovered::after { opacity: .7; transition: opacity .1s ease-in-out +} + +.show-me-your-name-modal-footer-container button { + width: 100%; +} + +.show-me-your-name-reset-button { + margin-top: 8px; + font-size: 14px; + font-weight: 500; } \ No newline at end of file From 526fbb791c9d510e11fb5ad241f5d649766b032b Mon Sep 17 00:00:00 2001 From: 9gvuwu <130901666+9gvuwu@users.noreply.github.com> Date: Wed, 26 Nov 2025 22:34:55 +0100 Subject: [PATCH 05/33] feat: add "Ignore Bots" setting in Boo plugin (#521) * feat: add "Ignore Bots" setting in Boo plugin * t --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com> --- src/equicordplugins/boo/Boo.tsx | 6 +++--- src/equicordplugins/boo/index.tsx | 6 ++++++ src/utils/constants.ts | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/equicordplugins/boo/Boo.tsx b/src/equicordplugins/boo/Boo.tsx index 8e96ae4c1..b195847f9 100644 --- a/src/equicordplugins/boo/Boo.tsx +++ b/src/equicordplugins/boo/Boo.tsx @@ -163,8 +163,8 @@ export function Boo({ channel }: { channel: Channel; }) { return; } - // if exempted, remove from ghost tracking - if (isExempted) { + // if exempted or bot (if setting enabled), remove from ghost tracking + if (isExempted || (settings.store.ignoreBots && lastMessage.author.bot)) { if (countedChannels.has(id)) { countedChannels.delete(id); setBooCount(getBooCount() - 1); @@ -186,7 +186,7 @@ export function Boo({ channel }: { channel: Channel; }) { } }, [state.isCurrentUser, state.isDataProcessed, id, lastMessage?.id]); - if (!state.isDataProcessed || !currentUserId || !lastMessage || state.isCurrentUser || isChannelExempted(id) || isCleared) + if (!state.isDataProcessed || !currentUserId || !lastMessage || state.isCurrentUser || isChannelExempted(id) || isCleared || (settings.store.ignoreBots && lastMessage.author.bot)) return null; if (!settings.store.showDmIcons) return null; diff --git a/src/equicordplugins/boo/index.tsx b/src/equicordplugins/boo/index.tsx index 2abdc1157..788af9592 100644 --- a/src/equicordplugins/boo/index.tsx +++ b/src/equicordplugins/boo/index.tsx @@ -84,6 +84,12 @@ export const settings = definePluginSettings({ description: "Something might happen if you ignore someone for too long...", default: false, restartNeeded: false + }, + ignoreBots: { + type: OptionType.BOOLEAN, + description: "Ignore DMs from bots", + default: true, + restartNeeded: false } }); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index b5ab319d6..78010ea6c 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -632,7 +632,7 @@ export const Devs = /* #__PURE__*/ Object.freeze({ alfred: { name: "alfred", id: 1038466644353232967n - } + }, } satisfies Record); export const EquicordDevs = Object.freeze({ @@ -1205,7 +1205,7 @@ export const EquicordDevs = Object.freeze({ name: "neoarz", id: 1015372540937502851n }, - KamiRu:{ + KamiRu: { name: "KamiRu", id: 819191621676695563n }, From 61f6f4c270ab1ef5f5bd62ac84b361b3defad66f Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:00:01 -0500 Subject: [PATCH 06/33] EquicordHelper: Remove old patch --- src/equicordplugins/equicordHelper/index.tsx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/equicordplugins/equicordHelper/index.tsx b/src/equicordplugins/equicordHelper/index.tsx index 08c367b7e..ab4f5d054 100644 --- a/src/equicordplugins/equicordHelper/index.tsx +++ b/src/equicordplugins/equicordHelper/index.tsx @@ -14,12 +14,6 @@ import { PluginButtons } from "./pluginButtons"; import { PluginCards } from "./pluginCards"; const settings = definePluginSettings({ - disableCreateDMButton: { - type: OptionType.BOOLEAN, - description: "Disables the create dm button", - restartNeeded: true, - default: false, - }, disableDMContextMenu: { type: OptionType.BOOLEAN, description: "Disables the DM list context menu in favor of the x button", @@ -59,15 +53,6 @@ export default definePlugin({ } ] }, - // Disable Giant Create DM Button - { - find: ".createDMButtonContainer,", - predicate: () => settings.store.disableCreateDMButton, - replacement: { - match: /"create-dm"\)/, - replace: "$&&&false" - }, - }, // Remove DM Context Menu { find: "#{intl::DM_OPTIONS}", From 722218c120efce29b6457f2d1fdf72c4e87fab4c Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:34:55 -0500 Subject: [PATCH 07/33] ShowResourceChannels: Fix Patch --- .../showResourceChannels/index.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/equicordplugins/showResourceChannels/index.ts b/src/equicordplugins/showResourceChannels/index.ts index fbba862ee..d3ca76589 100644 --- a/src/equicordplugins/showResourceChannels/index.ts +++ b/src/equicordplugins/showResourceChannels/index.ts @@ -11,11 +11,15 @@ export default definePlugin({ name: "ShowResourceChannels", description: "shows the channels hidden behind the server resources in the channel list", authors: [EquicordDevs.VillainsRule], - patches: [{ - find: '"should_show_in_recents"', - replacement: [{ - match: /\i\.hideResourceChannels&&/, - replace: "false&&" - }] - }] + patches: [ + { + find: ".GUILD_DIRECTORY:null", + replacement: [ + { + match: /\i\.hideResourceChannels&&/, + replace: "false&&" + } + ] + } + ] }); From 62569ef3bedbee38264c584991870712bcb55094 Mon Sep 17 00:00:00 2001 From: prism Date: Wed, 26 Nov 2025 17:58:42 -0800 Subject: [PATCH 08/33] feat(Alert): use native alert components (#527) --- src/components/Alert.tsx | 57 +++++++++++++++++++ src/components/index.ts | 1 + src/equicordplugins/_misc/styles.css | 11 ---- src/equicordplugins/equicordHelper/index.tsx | 2 - src/equicordplugins/followVoiceUser/index.tsx | 12 ++-- src/equicordplugins/guildTagSettings/index.ts | 2 - .../neverPausePreviews/index.tsx | 12 ++-- src/equicordplugins/platformSpoofer/index.tsx | 12 ++-- .../questCompleter.discordDesktop/index.tsx | 1 - src/equicordplugins/questFocused/index.tsx | 12 ++-- .../universalMention/index.tsx | 6 +- 11 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 src/components/Alert.tsx delete mode 100644 src/equicordplugins/_misc/styles.css diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx new file mode 100644 index 000000000..60c21f448 --- /dev/null +++ b/src/components/Alert.tsx @@ -0,0 +1,57 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { filters, mapMangledModuleLazy } from "@webpack"; +import type { ReactNode } from "react"; + +const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE="positive', { + HelpMessageTypes: filters.byProps("POSITIVE", "WARNING", "INFO", "ERROR"), + HelpMessage: filters.byCode(".iconDiv") +}); + +export interface AlertProps { + children: ReactNode; + className?: string; +} + +function Warning({ children, className }: AlertProps) { + return ( + + {children} + + ); +} + +function Info({ children, className }: AlertProps) { + return ( + + {children} + + ); +} + +function Error({ children, className }: AlertProps) { + return ( + + {children} + + ); +} + +function Positive({ children, className }: AlertProps) { + return ( + + {children} + + ); +} + +export const Alert = { + Warning, + Info, + Error, + Positive +}; diff --git a/src/components/index.ts b/src/components/index.ts index dd851be5d..a384f977e 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +export * from "./Alert"; export * from "./BaseText"; export * from "./Button"; export * from "./Card"; diff --git a/src/equicordplugins/_misc/styles.css b/src/equicordplugins/_misc/styles.css deleted file mode 100644 index 41ce53d89..000000000 --- a/src/equicordplugins/_misc/styles.css +++ /dev/null @@ -1,11 +0,0 @@ -.plugin-warning { - font-size: 16px !important; - background-color: var(--info-warning-background) !important; - color: var(--info-warning-foreground) !important; - border: 1px solid var(--info-warning-foreground) !important; - border-radius: 5px !important; - font-weight: bold; - padding: 6px 10px; - text-align: center; - margin-top: 10px; -} diff --git a/src/equicordplugins/equicordHelper/index.tsx b/src/equicordplugins/equicordHelper/index.tsx index ab4f5d054..e03215075 100644 --- a/src/equicordplugins/equicordHelper/index.tsx +++ b/src/equicordplugins/equicordHelper/index.tsx @@ -4,8 +4,6 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import "@equicordplugins/_misc/styles.css"; - import { definePluginSettings } from "@api/Settings"; import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; diff --git a/src/equicordplugins/followVoiceUser/index.tsx b/src/equicordplugins/followVoiceUser/index.tsx index 009009cac..13dabbdf4 100644 --- a/src/equicordplugins/followVoiceUser/index.tsx +++ b/src/equicordplugins/followVoiceUser/index.tsx @@ -4,11 +4,9 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import "@equicordplugins/_misc/styles.css"; - import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { definePluginSettings } from "@api/Settings"; -import { Paragraph } from "@components/Paragraph"; +import { Alert } from "@components/Alert"; import { EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { Channel, User, VoiceState } from "@vencord/discord-types"; @@ -79,11 +77,11 @@ export default definePlugin({ description: "Follow a friend in voice chat.", authors: [EquicordDevs.TheArmagan], settings, - settingsAboutComponent: () => <> - + settingsAboutComponent: () => ( + This Plugin is used to follow a Friend/Friends into voice chat(s). - - , + + ), flux: { async VOICE_STATE_UPDATES({ voiceStates }: { voiceStates: VoiceState[]; }) { if (!followedUserInfo) return; diff --git a/src/equicordplugins/guildTagSettings/index.ts b/src/equicordplugins/guildTagSettings/index.ts index 6a1345b83..65e171c06 100644 --- a/src/equicordplugins/guildTagSettings/index.ts +++ b/src/equicordplugins/guildTagSettings/index.ts @@ -16,8 +16,6 @@ * along with this program. If not, see . */ -import "@equicordplugins/_misc/styles.css"; - import { definePluginSettings } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; import { Devs } from "@utils/constants"; diff --git a/src/equicordplugins/neverPausePreviews/index.tsx b/src/equicordplugins/neverPausePreviews/index.tsx index b1bef3d4a..6758e933e 100644 --- a/src/equicordplugins/neverPausePreviews/index.tsx +++ b/src/equicordplugins/neverPausePreviews/index.tsx @@ -16,9 +16,7 @@ * along with this program. If not, see . */ -import "@equicordplugins/_misc/styles.css"; - -import { Paragraph } from "@components/Paragraph"; +import { Alert } from "@components/Alert"; import { EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; @@ -26,11 +24,11 @@ export default definePlugin({ name: "NeverPausePreviews", description: "Prevents in-call/PiP previews (screenshare, streams, etc) from pausing even if the client loses focus", authors: [EquicordDevs.vappstar], - settingsAboutComponent: () => <> - + settingsAboutComponent: () => ( + This plugin will cause discord to use more resources than normal - - , + + ), patches: [ { find: "streamerPaused()", diff --git a/src/equicordplugins/platformSpoofer/index.tsx b/src/equicordplugins/platformSpoofer/index.tsx index d94b12617..5726fac5b 100644 --- a/src/equicordplugins/platformSpoofer/index.tsx +++ b/src/equicordplugins/platformSpoofer/index.tsx @@ -4,10 +4,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import "@equicordplugins/_misc/styles.css"; - import { definePluginSettings } from "@api/Settings"; -import { Paragraph } from "@components/Paragraph"; +import { Alert } from "@components/Alert"; import { EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { UserStore } from "@webpack/common"; @@ -51,11 +49,11 @@ export default definePlugin({ name: "PlatformSpoofer", description: "Spoof what platform or device you're on", authors: [EquicordDevs.Drag], - settingsAboutComponent: () => <> - + settingsAboutComponent: () => ( + We can't guarantee this plugin won't get you warned or banned. - - , + + ), settings: settings, patches: [ { diff --git a/src/equicordplugins/questCompleter.discordDesktop/index.tsx b/src/equicordplugins/questCompleter.discordDesktop/index.tsx index f4183f41a..357ad71bf 100644 --- a/src/equicordplugins/questCompleter.discordDesktop/index.tsx +++ b/src/equicordplugins/questCompleter.discordDesktop/index.tsx @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -import "@equicordplugins/_misc/styles.css"; import "./style.css"; import { showNotification } from "@api/Notifications"; diff --git a/src/equicordplugins/questFocused/index.tsx b/src/equicordplugins/questFocused/index.tsx index c8469c9b9..695a4f023 100644 --- a/src/equicordplugins/questFocused/index.tsx +++ b/src/equicordplugins/questFocused/index.tsx @@ -4,20 +4,18 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import "@equicordplugins/_misc/styles.css"; - -import { Paragraph } from "@components/Paragraph"; +import { Alert } from "@components/Alert"; import { EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; export default definePlugin({ name: "QuestFocused", description: "Prevent the quests player from pausing and possibly skip it all together.", - settingsAboutComponent: () => <> - + settingsAboutComponent: () => ( + You might need to spam left mouse button on the video to skip it. - - , + + ), authors: [EquicordDevs.secp192k1], patches: [ // Block pausing diff --git a/src/equicordplugins/universalMention/index.tsx b/src/equicordplugins/universalMention/index.tsx index 9ee127883..4b3c75f20 100644 --- a/src/equicordplugins/universalMention/index.tsx +++ b/src/equicordplugins/universalMention/index.tsx @@ -5,7 +5,7 @@ */ import { definePluginSettings } from "@api/Settings"; -import { Paragraph } from "@components/Paragraph"; +import { Alert } from "@components/Alert"; import { EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { User } from "@vencord/discord-types"; @@ -41,9 +41,9 @@ export default definePlugin({ description: "Mention any user, regardless of channel access.", settings, settingsAboutComponent: () => ( - + Using Global Mention can cause performance issues and show an absurd amount of users in the autocomplete. - + ), patches: [ From b6d8728b64bfb48a8cc837af069a834d3b04f8f0 Mon Sep 17 00:00:00 2001 From: Etorix <92535668+EtorixDev@users.noreply.github.com> Date: Wed, 26 Nov 2025 18:10:49 -0800 Subject: [PATCH 09/33] SMYN: Fix author undefined. (#528) --- src/plugins/showMeYourName/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index 30ce3c6e8..9b747cb5b 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -267,7 +267,7 @@ function getProcessedNames(author: any, truncateAllNamesWithStreamerMode: boolea ? friendName[0] + "..." : friendName as string; - const customName: string | null = customNicknames[author.id] || null; + const customName: string | null = !author?.id ? null : customNicknames[author.id] || null; const custom: string | null = !customName ? null : StreamerModeStore.enabled && (truncateAllNamesWithStreamerMode || customName.toLowerCase() === author.username.toLowerCase()) ? customName[0] + "..." From b48ce272506f876cf0d6ed3e075f6a003b068415 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 02:36:33 -0500 Subject: [PATCH 10/33] GlobalBadges: rework --- src/api/Badges.ts | 15 ++++ .../globalBadges/badgeComponent.tsx | 79 ----------------- .../globalBadges/badgeModal.tsx | 81 ------------------ src/equicordplugins/globalBadges/index.tsx | 84 ++++++++++++++++--- src/equicordplugins/globalBadges/settings.ts | 6 -- src/equicordplugins/globalBadges/styles.css | 58 ------------- src/equicordplugins/globalBadges/types.ts | 16 ---- src/equicordplugins/globalBadges/utils.ts | 47 ----------- .../iRememberYou/components/ui.tsx | 49 +++++------ src/equicordplugins/iRememberYou/styles.css | 54 ++++++------ src/plugins/_api/badges/index.tsx | 2 +- 11 files changed, 136 insertions(+), 355 deletions(-) delete mode 100644 src/equicordplugins/globalBadges/badgeComponent.tsx delete mode 100644 src/equicordplugins/globalBadges/badgeModal.tsx delete mode 100644 src/equicordplugins/globalBadges/types.ts delete mode 100644 src/equicordplugins/globalBadges/utils.ts diff --git a/src/api/Badges.ts b/src/api/Badges.ts index 82b6a63d4..9ab0f5cb2 100644 --- a/src/api/Badges.ts +++ b/src/api/Badges.ts @@ -17,9 +17,12 @@ */ import ErrorBoundary from "@components/ErrorBoundary"; +import globalBadges from "@equicordplugins/globalBadges"; import BadgeAPIPlugin from "@plugins/_api/badges"; import { ComponentType, HTMLProps } from "react"; +import { isPluginEnabled } from "./PluginManager"; + export const enum BadgePosition { START, END @@ -99,6 +102,18 @@ export function _getBadges(args: BadgeUserArgs) { const donorBadges = BadgeAPIPlugin.getDonorBadges(args.userId); const equicordDonorBadges = BadgeAPIPlugin.getEquicordDonorBadges(args.userId); + const GlobalBadges = isPluginEnabled(globalBadges.name) ? globalBadges.getGlobalBadges(args.userId) : false; + + // do globalbadges first so it shows before the contrib badges but after donor badges + if (GlobalBadges) { + badges.unshift( + ...GlobalBadges.map(badge => ({ + ...args, + ...badge, + })) + ); + } + if (donorBadges) { badges.unshift( ...donorBadges.map(badge => ({ diff --git a/src/equicordplugins/globalBadges/badgeComponent.tsx b/src/equicordplugins/globalBadges/badgeComponent.tsx deleted file mode 100644 index 19c8e8e1f..000000000 --- a/src/equicordplugins/globalBadges/badgeComponent.tsx +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { React, Tooltip, UserStore } from "@webpack/common"; -import { JSX } from "react"; - -import { openBadgeModal } from "./badgeModal"; -import { settings } from "./settings"; -import { BadgeCache } from "./types"; -import { cl, fetchBadges } from "./utils"; - -interface BadgeModalItem { - name: string; - rawName: string; -} - -export let badgeData; - -export const BadgeComponent = ({ name, img }: { name: string, img: string; }) => { - return ( - - {(tooltipProps: any) => ( - - )} - - ); -}; - -export const GlobalBadges = ({ userId }: { userId: string; }) => { - const [badges, setBadges] = React.useState({}); - React.useEffect(() => setBadges(fetchBadges(userId) ?? {}), [userId]); - - if (!badges) return null; - const globalBadges: JSX.Element[] = []; - const badgeModal: BadgeModalItem[] = []; - - Object.keys(badges).forEach(mod => { - if (!badges[mod] || !Array.isArray(badges[mod]) || badges[mod].length === 0) return; - - badges[mod].forEach(badge => { - if (!badge || !badge.tooltip || !badge.badge) return; - - const prefix = settings.store.showPrefix ? `(${mod})` : ""; - const suffix = settings.store.showSuffix ? `(${mod})` : ""; - const displayName = `${prefix} ${badge.tooltip} ${suffix}`; - - if (mod === "BadgeVault") { - badge.custom = true; - } - - globalBadges.push(); - badgeModal.push({ - name: displayName, - rawName: badge.tooltip, - ...badge - }); - }); - }); - badgeData = badgeModal; - - return ( -
openBadgeModal(UserStore.getUser(userId))} - > - {globalBadges} -
- ); -}; diff --git a/src/equicordplugins/globalBadges/badgeModal.tsx b/src/equicordplugins/globalBadges/badgeModal.tsx deleted file mode 100644 index 45c94b96c..000000000 --- a/src/equicordplugins/globalBadges/badgeModal.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { Button } from "@components/Button"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { HeadingTertiary } from "@components/Heading"; -import { Paragraph } from "@components/Paragraph"; -import { openInviteModal } from "@utils/discord"; -import { ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal"; -import { User } from "@vencord/discord-types"; -import { React, Tooltip } from "@webpack/common"; - -import { badgeData } from "./badgeComponent"; -import { cl, INVITE_LINK } from "./utils"; - -export const BadgeModalComponent = ({ name, img }: { name: string, img: string; }) => { - return ( - <> - - {(tooltipProps: any) => ( - - )} - - - ); -}; - -export function openBadgeModal(user: User) { - const badgeDataElements = badgeData.map(badge => ( - - )); - - openModal(modalprops => ( - - - - - - {user.username} - - - - {badgeDataElements.length ? ( - <> - - {badgeDataElements.length} global badge - {badgeDataElements.length > 1 ? "s" : ""}. - -
- {badgeDataElements} -
- - ) : ( - - No global badges. - - )} -
- - - -
-
- )); -} diff --git a/src/equicordplugins/globalBadges/index.tsx b/src/equicordplugins/globalBadges/index.tsx index 9af75cd04..05c7cb7d5 100644 --- a/src/equicordplugins/globalBadges/index.tsx +++ b/src/equicordplugins/globalBadges/index.tsx @@ -6,23 +6,57 @@ import "./styles.css"; -import { addProfileBadge, BadgePosition, ProfileBadge, removeProfileBadge } from "@api/Badges"; +import { BadgePosition, ProfileBadge } from "@api/Badges"; +import { classNameFactory } from "@api/Styles"; import { Button } from "@components/Button"; +import { BadgeContextMenu } from "@plugins/_api/badges"; import { Devs, EquicordDevs } from "@utils/constants"; import { openInviteModal } from "@utils/discord"; import definePlugin from "@utils/types"; -import { React } from "@webpack/common"; +import { ContextMenuApi, React } from "@webpack/common"; -import { GlobalBadges } from "./badgeComponent"; import { settings } from "./settings"; -import { cl, fetchBadges, INVITE_LINK } from "./utils"; -const Badge: ProfileBadge = { - component: b => , - position: BadgePosition.START, - shouldShow: userInfo => !!Object.keys(fetchBadges(userInfo.userId) ?? {}).length, - key: "GlobalBadges" -}; +let GlobalBadges = {}; +let intervalId: any; +const INVITE_LINK = "kwHCJPxp8t"; +const cl = classNameFactory("vc-global-badges-"); + +async function loadBadges() { + const globalBadges = await fetch("https://badges.equicord.org/users", { cache: "no-cache" }) + .then(r => r.json()); + + const filteredUsers: Record = {}; + + for (const key in globalBadges.users) { + filteredUsers[key] = globalBadges.users[key].map(b => { + if (b.url) { + return { tooltip: b.label, badge: b.url }; + } + return b; + }).filter(b => { + const url = b.badge; + // fix this when creations updates it + return url && + url.startsWith("https://") && + !url.startsWith("https://cdn.discordapp.com") && + !url.startsWith("https://images.equicord.org") && + !(url.startsWith("https://badges.vencord.dev/badges") && !url.startsWith("https://badges.vencord.dev/badges/reviewdb")) && + // !(!settings.store.showAero && url.startsWith(":aero_icon:")) && + // !(!settings.store.showVelocity && url.startsWith("Velocity")) && + // !(!settings.store.showVelocity && url.startsWith("Official Velocity")) && + !(!settings.store.showCustom && url.startsWith("https://gb.obamabot.me")) && + !(!settings.store.showNekocord && url.startsWith("https://nekocord.dev")) && + !(!settings.store.showReviewDB && url.startsWith("https://badges.vencord.dev/badges/reviewdb")) && + !(!settings.store.showAliucord && url.startsWith("https://aliucord.com")) && + !(!settings.store.showRa1ncord && url.startsWith("https://codeberg.org/raincord/badges")) && + !(!settings.store.showEnmity && url.startsWith("https://raw.githubusercontent.com/enmity-mod/badges")); + + }); + } + + GlobalBadges = filteredUsers; +} export default definePlugin({ name: "GlobalBadges", @@ -40,6 +74,32 @@ export default definePlugin({ ), - start: () => addProfileBadge(Badge), - stop: () => removeProfileBadge(Badge), + async start() { + await loadBadges(); + clearInterval(intervalId); + intervalId = setInterval(loadBadges, 1000 * 60 * 30); + }, + async stop() { + clearInterval(intervalId); + }, + get GlobalBadges() { + return GlobalBadges; + }, + getGlobalBadges(userId: string) { + return GlobalBadges[userId]?.map(badge => ({ + iconSrc: badge.badge, + description: badge.tooltip, + position: BadgePosition.START, + props: { + style: { + borderRadius: "50%", + transform: "scale(0.9)" + } + }, + onContextMenu(event, badge) { + ContextMenuApi.openContextMenu(event, () => ); + }, + + } satisfies ProfileBadge)); + } }); diff --git a/src/equicordplugins/globalBadges/settings.ts b/src/equicordplugins/globalBadges/settings.ts index cfcbf3d1b..85e0db7f0 100644 --- a/src/equicordplugins/globalBadges/settings.ts +++ b/src/equicordplugins/globalBadges/settings.ts @@ -78,12 +78,6 @@ export const settings = definePluginSettings({ default: true, restartNeeded: false }, - showReplugged: { - type: OptionType.BOOLEAN, - description: "Show Replugged Badges", - default: true, - restartNeeded: false - }, apiUrl: { type: OptionType.STRING, description: "API to use", diff --git a/src/equicordplugins/globalBadges/styles.css b/src/equicordplugins/globalBadges/styles.css index 3b098133d..9e712cf11 100644 --- a/src/equicordplugins/globalBadges/styles.css +++ b/src/equicordplugins/globalBadges/styles.css @@ -1,61 +1,3 @@ -.vc-global-badges-badges { - align-items: center; - display: flex; - flex-wrap: nowrap; -} - -.vc-global-badges-badge { - width: 20px; - height: 20px; - gap: 1px; -} - -.vc-global-badges-modal-name { - text-transform: none; - flex-grow: 0; - background: var(--background-base-lowest); - border-radius: 0 9999px 9999px 0; - padding: 6px 0.8em 6px 0.5em; - font-size: 20px; - height: 20px; - position: relative; - text-wrap: nowrap; -} - -.vc-global-badges-modal-name::before { - content: ""; - display: block; - position: absolute; - height: 100%; - width: 32px; - background: var(--background-base-lowest); - z-index: -1; - left: -32px; - top: 0; - border-top-left-radius: 9999px; - border-bottom-left-radius: 9999px; -} - -.vc-global-badges-modal-avatar { - height: 48px; - width: 48px; - border-radius: 50%; -} - -.vc-global-badges-modal-description { - font-size: 16px; -} - -.vc-global-badges-modal-text { - margin-left: 8px; -} - -.vc-global-badges-modal-badge { - width: 50px; - height: 50px; - margin: 2px; -} - .vc-global-badges-settings-button { width: 100%; height: 50px; diff --git a/src/equicordplugins/globalBadges/types.ts b/src/equicordplugins/globalBadges/types.ts deleted file mode 100644 index fc06b9265..000000000 --- a/src/equicordplugins/globalBadges/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -export type CustomBadge = { - tooltip: string; - badge: string; - custom?: boolean; -}; - -export interface BadgeCache { - badges: { [mod: string]: CustomBadge[]; }; - expires: number; -} diff --git a/src/equicordplugins/globalBadges/utils.ts b/src/equicordplugins/globalBadges/utils.ts deleted file mode 100644 index 49e348146..000000000 --- a/src/equicordplugins/globalBadges/utils.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { classNameFactory } from "@api/Styles"; - -import { settings } from "./settings"; -import { BadgeCache } from "./types"; - -const cache = new Map(); -const EXPIRES = 1000 * 60 * 15; - -export const cl = classNameFactory("vc-global-badges-"); -export const INVITE_LINK = "kwHCJPxp8t"; - -export const fetchBadges = (id: string): BadgeCache["badges"] | undefined => { - const cachedValue = cache.get(id); - if (!cache.has(id) || (cachedValue && cachedValue.expires < Date.now())) { - const services: string[] = []; - if (settings.store.showNekocord) services.push("nekocord"); - if (settings.store.showReviewDB) services.push("reviewdb"); - if (settings.store.showAero) services.push("aero"); - if (settings.store.showAliucord) services.push("aliucord"); - if (settings.store.showRa1ncord) services.push("ra1ncord"); - if (settings.store.showVelocity) services.push("velocity"); - if (settings.store.showEnmity) services.push("enmity"); - if (settings.store.showReplugged) services.push("replugged"); - if (settings.store.showCustom) services.push("badgevault"); - - if (services.length === 0) { - cache.set(id, { badges: {}, expires: Date.now() + EXPIRES }); - return {}; - } - - fetch(`${settings.store.apiUrl}${id}?seperated=true&capitalize=true&services=${services.join(",")}`) - .then(res => res.json() as Promise<{ status: number; badges: BadgeCache["badges"]; }>) - .then(body => { - cache.set(id, { badges: body.badges, expires: Date.now() + EXPIRES }); - return body.badges; - }) - .catch(() => null); - } else if (cachedValue) { - return cachedValue.badges; - } -}; diff --git a/src/equicordplugins/iRememberYou/components/ui.tsx b/src/equicordplugins/iRememberYou/components/ui.tsx index 27d530b75..0e3cb03d4 100644 --- a/src/equicordplugins/iRememberYou/components/ui.tsx +++ b/src/equicordplugins/iRememberYou/components/ui.tsx @@ -6,7 +6,7 @@ import { classNameFactory } from "@api/Styles"; import { BaseText } from "@components/BaseText"; -import { Flex } from "@components/Flex"; +import { HeadingPrimary } from "@components/Heading"; import { Paragraph } from "@components/Paragraph"; import { openUserProfile } from "@utils/discord"; import { Avatar, Clickable, React, TextInput, Tooltip, } from "@webpack/common"; @@ -44,11 +44,9 @@ function UsersCollectionRows({ usersCollection }: { usersCollection: Data["users .map(({ name, users }) => ( @@ -59,14 +57,14 @@ function UsersCollectionRows({ usersCollection }: { usersCollection: Data["users function UserRow({ user, allowOwner = true }: { user: IStorageUser, allowOwner?: boolean; }) { return ( - - - - openUserProfile(user.id)}> - - - - +
+
+ openUserProfile(user.id)}> + + + + +
{props => @@ -74,15 +72,14 @@ function UserRow({ user, allowOwner = true }: { user: IStorageUser, allowOwner?: } - - - - - - {user.id} - - - + + + {user.id} + + +
+
+
); } @@ -94,10 +91,10 @@ function SearchElement({ usersCollection }: { usersCollection: Data["usersCollec
{current && ( - +
{list.filter(user => user.tag.includes(current) || user.username.includes(current)) .map(user => )} - +
)}
); @@ -112,9 +109,9 @@ export function DataUI({ plugin, usersCollection }: { plugin: any; usersCollecti - +
- +
); } diff --git a/src/equicordplugins/iRememberYou/styles.css b/src/equicordplugins/iRememberYou/styles.css index 188f4218a..9eb1a6297 100644 --- a/src/equicordplugins/iRememberYou/styles.css +++ b/src/equicordplugins/iRememberYou/styles.css @@ -5,8 +5,15 @@ flex-direction: column; } +.vc-i-remember-you-header-name { + margin-top: 16px; +} + .vc-i-remember-you-header-btns { - gap: 8px; + display: grid; + grid-template-columns: repeat(2, minmax(0, 350px)); + gap: 10px; + margin-top: 8px; } .vc-i-remember-you-header { @@ -29,49 +36,38 @@ .vc-i-remember-you-user-avatar { cursor: pointer; - margin-right: 30px; + margin-right: 0; } .vc-i-remember-you-user-row { - margin: 0; - width: 100%; - flex-wrap: wrap; - align-items: center; + display: flex; + flex-direction: column; + gap: 6px; + padding: 4px; + align-items: flex-start; } .vc-i-remember-you-user-id { - height: min-content; + align-self: flex-start; opacity: 0.75; + height: min-content; } .vc-i-remember-you-user { - width: 500px; - gap: 250px; + display: flex; + flex-direction: row; align-items: center; - overflow-wrap: break-word; - margin-top: 5px; + gap: 8px; + width: 100%; + margin-top: 0; } .vc-i-remember-you-user-username { margin-top: 2px; } -.vc-i-remember-you-buttons { - margin-top: 10px; -} - -.vc-i-remember-you-buttons-save, -.vc-i-remember-you-buttons-cancel { - margin-left: 490px; - margin-top: 5px; - margin-bottom: 10px; -} - -.vc-i-remember-you-buttons-cancel { - margin-left: 12px; -} - -.vc-i-remember-you-buttons-reset { - cursor: pointer; - margin-left: 12px; +.vc-i-remember-you-user-tooltip { + display: flex; + flex-direction: column; + align-items: flex-start; } \ No newline at end of file diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index 873bf6705..354eae6d1 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -100,7 +100,7 @@ async function loadAllBadges(noCache = false) { let intervalId: any; -function BadgeContextMenu({ badge }: { badge: ProfileBadge & BadgeUserArgs; }) { +export function BadgeContextMenu({ badge }: { badge: ProfileBadge & BadgeUserArgs; }) { return ( Date: Thu, 27 Nov 2025 03:50:14 -0500 Subject: [PATCH 11/33] GlobalBadges: Update Filters & Toolbox Action --- src/equicordplugins/globalBadges/index.tsx | 50 ++++------------- src/equicordplugins/globalBadges/utils.ts | 65 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 src/equicordplugins/globalBadges/utils.ts diff --git a/src/equicordplugins/globalBadges/index.tsx b/src/equicordplugins/globalBadges/index.tsx index 05c7cb7d5..e29794dca 100644 --- a/src/equicordplugins/globalBadges/index.tsx +++ b/src/equicordplugins/globalBadges/index.tsx @@ -13,51 +13,15 @@ import { BadgeContextMenu } from "@plugins/_api/badges"; import { Devs, EquicordDevs } from "@utils/constants"; import { openInviteModal } from "@utils/discord"; import definePlugin from "@utils/types"; -import { ContextMenuApi, React } from "@webpack/common"; +import { ContextMenuApi, React, Toasts } from "@webpack/common"; import { settings } from "./settings"; +import { GlobalBadges, loadBadges } from "./utils"; -let GlobalBadges = {}; let intervalId: any; const INVITE_LINK = "kwHCJPxp8t"; const cl = classNameFactory("vc-global-badges-"); -async function loadBadges() { - const globalBadges = await fetch("https://badges.equicord.org/users", { cache: "no-cache" }) - .then(r => r.json()); - - const filteredUsers: Record = {}; - - for (const key in globalBadges.users) { - filteredUsers[key] = globalBadges.users[key].map(b => { - if (b.url) { - return { tooltip: b.label, badge: b.url }; - } - return b; - }).filter(b => { - const url = b.badge; - // fix this when creations updates it - return url && - url.startsWith("https://") && - !url.startsWith("https://cdn.discordapp.com") && - !url.startsWith("https://images.equicord.org") && - !(url.startsWith("https://badges.vencord.dev/badges") && !url.startsWith("https://badges.vencord.dev/badges/reviewdb")) && - // !(!settings.store.showAero && url.startsWith(":aero_icon:")) && - // !(!settings.store.showVelocity && url.startsWith("Velocity")) && - // !(!settings.store.showVelocity && url.startsWith("Official Velocity")) && - !(!settings.store.showCustom && url.startsWith("https://gb.obamabot.me")) && - !(!settings.store.showNekocord && url.startsWith("https://nekocord.dev")) && - !(!settings.store.showReviewDB && url.startsWith("https://badges.vencord.dev/badges/reviewdb")) && - !(!settings.store.showAliucord && url.startsWith("https://aliucord.com")) && - !(!settings.store.showRa1ncord && url.startsWith("https://codeberg.org/raincord/badges")) && - !(!settings.store.showEnmity && url.startsWith("https://raw.githubusercontent.com/enmity-mod/badges")); - - }); - } - - GlobalBadges = filteredUsers; -} - export default definePlugin({ name: "GlobalBadges", description: "Adds global badges from other client mods", @@ -82,6 +46,16 @@ export default definePlugin({ async stop() { clearInterval(intervalId); }, + toolboxActions: { + async "Refetch Global Badges"() { + await loadBadges(); + Toasts.show({ + id: Toasts.genId(), + message: "Successfully refetched global badges!", + type: Toasts.Type.SUCCESS + }); + } + }, get GlobalBadges() { return GlobalBadges; }, diff --git a/src/equicordplugins/globalBadges/utils.ts b/src/equicordplugins/globalBadges/utils.ts new file mode 100644 index 000000000..cb2bef47b --- /dev/null +++ b/src/equicordplugins/globalBadges/utils.ts @@ -0,0 +1,65 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./styles.css"; + +import { settings } from "./settings"; + +export let GlobalBadges = {}; +const serviceMap: Record = { + nekocord: "Nekocord", + reviewdb: "ReviewDB", + aero: "Aero", + aliucord: "Aliucord", + ra1ncord: "Ra1ncord", + velocity: "Velocity", + enmity: "Enmity", + badgevault: "BadgeVault", + vencord: "Vencord", + equicord: "Equicord", +}; + +export async function loadBadges() { + const url = settings.store.apiUrl.endsWith("/") ? settings.store.apiUrl + "users" : settings.store.apiUrl + "/users"; + const globalBadges = await fetch(url, { cache: "no-cache" }).then(r => r.json()); + const filteredUsers: Record = {}; + + for (const key in globalBadges.users) { + filteredUsers[key] = globalBadges.users[key].filter(b => { + const { mod } = b; + if (!mod) return false; + + const blockedMods = ["vencord", "equicord"]; + if (blockedMods.includes(mod)) return false; + + const conditionalMods = { + aero: settings.store.showAero, + velocity: settings.store.showVelocity, + badgevault: settings.store.showCustom, + nekocord: settings.store.showNekocord, + reviewdb: settings.store.showReviewDB, + aliucord: settings.store.showAliucord, + ra1ncord: settings.store.showRa1ncord, + enmity: settings.store.showEnmity + }; + + if (mod in conditionalMods && !conditionalMods[mod]) return false; + + return true; + }).map(b => { + const modFormatted = serviceMap[b.mod]; + const prefix = settings.store.showPrefix ? `${modFormatted} - ` : ""; + const suffix = settings.store.showSuffix ? ` - ${modFormatted}` : ""; + const tooltip = prefix + b.tooltip + suffix; + return { + ...b, + tooltip + }; + }); + } + + GlobalBadges = filteredUsers; +} From 275a5a9edf23e0cfd12e062f944b52d3aa838598 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 04:00:57 -0500 Subject: [PATCH 12/33] GlobalBadges: Add Badge Modal Back --- .../globalBadges/badgeModal.tsx | 80 +++++++++++++++++++ src/equicordplugins/globalBadges/index.tsx | 12 +-- src/equicordplugins/globalBadges/styles.css | 58 ++++++++++++++ src/equicordplugins/globalBadges/utils.ts | 5 ++ 4 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 src/equicordplugins/globalBadges/badgeModal.tsx diff --git a/src/equicordplugins/globalBadges/badgeModal.tsx b/src/equicordplugins/globalBadges/badgeModal.tsx new file mode 100644 index 000000000..df69a751c --- /dev/null +++ b/src/equicordplugins/globalBadges/badgeModal.tsx @@ -0,0 +1,80 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Button } from "@components/Button"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { HeadingTertiary } from "@components/Heading"; +import { Paragraph } from "@components/Paragraph"; +import { openInviteModal } from "@utils/discord"; +import { ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal"; +import { User } from "@vencord/discord-types"; +import { React, Tooltip } from "@webpack/common"; + +import { cl, GlobalBadges, INVITE_LINK } from "./utils"; + +export const BadgeModalComponent = ({ name, img }: { name: string, img: string; }) => { + return ( + <> + + {(tooltipProps: any) => ( + + )} + + + ); +}; + +export function openBadgeModal(user: User) { + const badgeDataElements = GlobalBadges[user.id].map(badge => ( + + )); + + openModal(modalprops => ( + + + + + + {user.username} + + + + {badgeDataElements.length ? ( + <> + + {badgeDataElements.length} global badge + {badgeDataElements.length > 1 ? "s" : ""}. + +
+ {badgeDataElements} +
+ + ) : ( + + No global badges. + + )} +
+ + + +
+
+ )); +} diff --git a/src/equicordplugins/globalBadges/index.tsx b/src/equicordplugins/globalBadges/index.tsx index e29794dca..7509f151c 100644 --- a/src/equicordplugins/globalBadges/index.tsx +++ b/src/equicordplugins/globalBadges/index.tsx @@ -7,20 +7,18 @@ import "./styles.css"; import { BadgePosition, ProfileBadge } from "@api/Badges"; -import { classNameFactory } from "@api/Styles"; import { Button } from "@components/Button"; import { BadgeContextMenu } from "@plugins/_api/badges"; import { Devs, EquicordDevs } from "@utils/constants"; import { openInviteModal } from "@utils/discord"; import definePlugin from "@utils/types"; -import { ContextMenuApi, React, Toasts } from "@webpack/common"; +import { ContextMenuApi, React, Toasts, UserStore } from "@webpack/common"; +import { openBadgeModal } from "./badgeModal"; import { settings } from "./settings"; -import { GlobalBadges, loadBadges } from "./utils"; +import { cl, GlobalBadges, INVITE_LINK, loadBadges } from "./utils"; let intervalId: any; -const INVITE_LINK = "kwHCJPxp8t"; -const cl = classNameFactory("vc-global-badges-"); export default definePlugin({ name: "GlobalBadges", @@ -73,7 +71,9 @@ export default definePlugin({ onContextMenu(event, badge) { ContextMenuApi.openContextMenu(event, () => ); }, - + onClick() { + return openBadgeModal(UserStore.getUser(userId)); + }, } satisfies ProfileBadge)); } }); diff --git a/src/equicordplugins/globalBadges/styles.css b/src/equicordplugins/globalBadges/styles.css index 9e712cf11..3b098133d 100644 --- a/src/equicordplugins/globalBadges/styles.css +++ b/src/equicordplugins/globalBadges/styles.css @@ -1,3 +1,61 @@ +.vc-global-badges-badges { + align-items: center; + display: flex; + flex-wrap: nowrap; +} + +.vc-global-badges-badge { + width: 20px; + height: 20px; + gap: 1px; +} + +.vc-global-badges-modal-name { + text-transform: none; + flex-grow: 0; + background: var(--background-base-lowest); + border-radius: 0 9999px 9999px 0; + padding: 6px 0.8em 6px 0.5em; + font-size: 20px; + height: 20px; + position: relative; + text-wrap: nowrap; +} + +.vc-global-badges-modal-name::before { + content: ""; + display: block; + position: absolute; + height: 100%; + width: 32px; + background: var(--background-base-lowest); + z-index: -1; + left: -32px; + top: 0; + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; +} + +.vc-global-badges-modal-avatar { + height: 48px; + width: 48px; + border-radius: 50%; +} + +.vc-global-badges-modal-description { + font-size: 16px; +} + +.vc-global-badges-modal-text { + margin-left: 8px; +} + +.vc-global-badges-modal-badge { + width: 50px; + height: 50px; + margin: 2px; +} + .vc-global-badges-settings-button { width: 100%; height: 50px; diff --git a/src/equicordplugins/globalBadges/utils.ts b/src/equicordplugins/globalBadges/utils.ts index cb2bef47b..5351fd2fa 100644 --- a/src/equicordplugins/globalBadges/utils.ts +++ b/src/equicordplugins/globalBadges/utils.ts @@ -6,9 +6,13 @@ import "./styles.css"; +import { classNameFactory } from "@api/Styles"; + import { settings } from "./settings"; export let GlobalBadges = {}; +export const INVITE_LINK = "kwHCJPxp8t"; +export const cl = classNameFactory("vc-global-badges-"); const serviceMap: Record = { nekocord: "Nekocord", reviewdb: "ReviewDB", @@ -56,6 +60,7 @@ export async function loadBadges() { const tooltip = prefix + b.tooltip + suffix; return { ...b, + name: b.tooltip, tooltip }; }); From 57677f2701c30cdb48f9671ea9ca495fbb52353f Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 04:03:44 -0500 Subject: [PATCH 13/33] GlobalBadges: fix mistake --- src/equicordplugins/globalBadges/badgeModal.tsx | 9 +++++---- src/equicordplugins/globalBadges/styles.css | 12 ------------ src/equicordplugins/globalBadges/utils.ts | 4 ++-- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/equicordplugins/globalBadges/badgeModal.tsx b/src/equicordplugins/globalBadges/badgeModal.tsx index df69a751c..e2c501b41 100644 --- a/src/equicordplugins/globalBadges/badgeModal.tsx +++ b/src/equicordplugins/globalBadges/badgeModal.tsx @@ -15,15 +15,16 @@ import { React, Tooltip } from "@webpack/common"; import { cl, GlobalBadges, INVITE_LINK } from "./utils"; -export const BadgeModalComponent = ({ name, img }: { name: string, img: string; }) => { +export const BadgeModalComponent = ({ key, tooltip, badge }: { key: string, tooltip: string, badge: string; }) => { return ( <> - + {(tooltipProps: any) => ( )} @@ -33,7 +34,7 @@ export const BadgeModalComponent = ({ name, img }: { name: string, img: string; export function openBadgeModal(user: User) { const badgeDataElements = GlobalBadges[user.id].map(badge => ( - + )); openModal(modalprops => ( diff --git a/src/equicordplugins/globalBadges/styles.css b/src/equicordplugins/globalBadges/styles.css index 3b098133d..07e07532d 100644 --- a/src/equicordplugins/globalBadges/styles.css +++ b/src/equicordplugins/globalBadges/styles.css @@ -1,15 +1,3 @@ -.vc-global-badges-badges { - align-items: center; - display: flex; - flex-wrap: nowrap; -} - -.vc-global-badges-badge { - width: 20px; - height: 20px; - gap: 1px; -} - .vc-global-badges-modal-name { text-transform: none; flex-grow: 0; diff --git a/src/equicordplugins/globalBadges/utils.ts b/src/equicordplugins/globalBadges/utils.ts index 5351fd2fa..8271166ad 100644 --- a/src/equicordplugins/globalBadges/utils.ts +++ b/src/equicordplugins/globalBadges/utils.ts @@ -13,7 +13,7 @@ import { settings } from "./settings"; export let GlobalBadges = {}; export const INVITE_LINK = "kwHCJPxp8t"; export const cl = classNameFactory("vc-global-badges-"); -const serviceMap: Record = { +export const serviceMap: Record = { nekocord: "Nekocord", reviewdb: "ReviewDB", aero: "Aero", @@ -60,7 +60,7 @@ export async function loadBadges() { const tooltip = prefix + b.tooltip + suffix; return { ...b, - name: b.tooltip, + key: b.tooltip, tooltip }; }); From 45707411cf4eb3baacf06ce337a50c81b69b9795 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 04:46:34 -0500 Subject: [PATCH 14/33] Questify: Stable comp --- src/equicordplugins/questify/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/questify/index.tsx b/src/equicordplugins/questify/index.tsx index d50925220..85af75edb 100644 --- a/src/equicordplugins/questify/index.tsx +++ b/src/equicordplugins/questify/index.tsx @@ -1251,7 +1251,7 @@ export default definePlugin({ }, { // Add the trigger to the memo for rerendering the progress label. - match: /(\)}}},\[)/, + match: /(\i\.intl\.string\(\i\.\i#{intl::QUESTS_SEE_CODE}\)\}\)\}\},\[|\)\}\}\},\[)/, replace: "$1questRerenderTrigger," }, { From b0c74a59bb26826994dcb27149992d0a800cf9a8 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:59:00 -0500 Subject: [PATCH 15/33] ChatBarButtons: Fix Icons + Add AudioProcessor Def --- src/api/PluginManager.ts | 19 ++++++++--- src/equicordplugins/customSounds/index.tsx | 5 ++- src/equicordplugins/ingtoninator/index.tsx | 29 ++++++++++++---- .../invisibleChat.desktop/index.tsx | 34 ++++++++++++------- .../messageFetchTimer/index.tsx | 31 +++++++++++------ src/equicordplugins/sekaiStickers/index.tsx | 5 ++- src/equicordplugins/signature/index.tsx | 14 +++++++- src/equicordplugins/talkInReverse/index.tsx | 13 ++++++- src/plugins/silentTyping/index.tsx | 14 ++++++-- src/utils/types.ts | 4 +++ 10 files changed, 126 insertions(+), 42 deletions(-) diff --git a/src/api/PluginManager.ts b/src/api/PluginManager.ts index 2d57a4e59..9acfc94ee 100644 --- a/src/api/PluginManager.ts +++ b/src/api/PluginManager.ts @@ -40,6 +40,7 @@ import Plugins from "~plugins"; export { Plugins as plugins }; import { traceFunction } from "../debug/Tracer"; +import { addAudioProcessor, removeAudioProcessor } from "./AudioPlayer"; const logger = new Logger("PluginManager", "#a6d189"); @@ -187,7 +188,9 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: const { name, commands, contextMenus, managedStyle, userProfileBadges, onBeforeMessageEdit, onBeforeMessageSend, onMessageClick, - renderChatBarButton, chatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton, messagePopoverButton, renderNicknameIcon + renderChatBarButton, chatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton, messagePopoverButton, + // Custom + renderNicknameIcon, audioProcessor } = p; if (p.start) { @@ -241,13 +244,16 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: // @ts-expect-error: legacy code doesn't have icon else if (renderChatBarButton) addChatBarButton(name, renderChatBarButton); if (renderMemberListDecorator) addMemberListDecorator(name, renderMemberListDecorator); - if (renderNicknameIcon) addNicknameIcon(name, renderNicknameIcon); if (renderMessageDecoration) addMessageDecoration(name, renderMessageDecoration); if (renderMessageAccessory) addMessageAccessory(name, renderMessageAccessory); if (messagePopoverButton) addMessagePopoverButton(name, messagePopoverButton.render, messagePopoverButton.icon); // @ts-expect-error: legacy code doesn't have icon else if (renderMessagePopoverButton) addMessagePopoverButton(name, renderMessagePopoverButton); + // Custom + if (renderNicknameIcon) addNicknameIcon(name, renderNicknameIcon); + if (audioProcessor) addAudioProcessor(name, audioProcessor); + return true; }, p => `startPlugin ${p.name}`); @@ -255,7 +261,9 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu const { name, commands, contextMenus, managedStyle, userProfileBadges, onBeforeMessageEdit, onBeforeMessageSend, onMessageClick, - renderChatBarButton, chatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton, messagePopoverButton, renderNicknameIcon + renderChatBarButton, chatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton, messagePopoverButton, + // Custom + renderNicknameIcon, audioProcessor } = p; if (p.stop) { @@ -305,11 +313,14 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu if (chatBarButton || renderChatBarButton) removeChatBarButton(name); if (renderMemberListDecorator) removeMemberListDecorator(name); - if (renderNicknameIcon) removeNicknameIcon(name); if (renderMessageDecoration) removeMessageDecoration(name); if (renderMessageAccessory) removeMessageAccessory(name); if (messagePopoverButton || renderMessagePopoverButton) removeMessagePopoverButton(name); + // Custom + if (renderNicknameIcon) removeNicknameIcon(name); + if (audioProcessor) removeAudioProcessor(name); + return true; }, p => `stopPlugin ${p.name}`); diff --git a/src/equicordplugins/customSounds/index.tsx b/src/equicordplugins/customSounds/index.tsx index 0df8ae15c..ecdac9e7d 100644 --- a/src/equicordplugins/customSounds/index.tsx +++ b/src/equicordplugins/customSounds/index.tsx @@ -6,7 +6,7 @@ import "./styles.css"; -import { addAudioProcessor, AudioProcessor, PreprocessAudioData, removeAudioProcessor } from "@api/AudioPlayer"; +import { AudioProcessor, PreprocessAudioData } from "@api/AudioPlayer"; import { get as getFromDataStore } from "@api/DataStore"; import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; @@ -399,10 +399,10 @@ export default definePlugin({ settings, getCustomSoundURL, startAt: StartAt.Init, + audioProcessor: getCustomSoundURL, async start() { console.log("[CustomSounds] Plugin starting..."); - addAudioProcessor("CustomSounds", this.getCustomSoundURL); try { await preloadDataURIs(); @@ -413,7 +413,6 @@ export default definePlugin({ }, stop() { - removeAudioProcessor("CustomSounds"); console.log("[CustomSounds] Plugin stopped"); } }); diff --git a/src/equicordplugins/ingtoninator/index.tsx b/src/equicordplugins/ingtoninator/index.tsx index 0a777f340..83fc16875 100644 --- a/src/equicordplugins/ingtoninator/index.tsx +++ b/src/equicordplugins/ingtoninator/index.tsx @@ -79,24 +79,39 @@ const IngtoninatorButton: ChatBarButtonFactory = ({ isMainChat }) => { onClick={toggle} > {isEnabled ? ( - - - + enabledIcon() ) : ( - - - + disabledIcon() )} ); }; +function enabledIcon() { + return ( + + + + ); +} + +function disabledIcon() { + return ( + + + + ); +} + export default definePlugin({ name: "Ingtoninator", description: "Suffixes 'ington' to a random word in your message", authors: [EquicordDevs.zyqunix], settings, - renderChatBarButton: IngtoninatorButton, + chatBarButton: { + icon: disabledIcon, + render: IngtoninatorButton + }, start() { addMessagePreSendListener(handleMessage); }, diff --git a/src/equicordplugins/invisibleChat.desktop/index.tsx b/src/equicordplugins/invisibleChat.desktop/index.tsx index 37a14d4d2..4b3235534 100644 --- a/src/equicordplugins/invisibleChat.desktop/index.tsx +++ b/src/equicordplugins/invisibleChat.desktop/index.tsx @@ -65,7 +65,7 @@ function Indicator() { } -const ChatBarIcon: ChatBarButtonFactory = ({ isMainChat }) => { +const ChatBarRender: ChatBarButtonFactory = ({ isMainChat }) => { if (!isMainChat) return null; return ( @@ -76,20 +76,26 @@ const ChatBarIcon: ChatBarButtonFactory = ({ isMainChat }) => { "aria-haspopup": "dialog", }} > - - - + {ChatBarIcon()} ); }; +function ChatBarIcon() { + return ( + + + + ); +} + const settings = definePluginSettings({ savedPasswords: { type: OptionType.STRING, @@ -149,6 +155,11 @@ export default definePlugin({ reporterTestable: ReporterTestable.Patches, settings, + chatBarButton: { + icon: ChatBarIcon, + render: ChatBarRender + }, + patches: [ { // Indicator @@ -165,7 +176,6 @@ export default definePlugin({ const { default: StegCloak } = await getStegCloak(); steggo = new StegCloak(true, false); }, - renderChatBarButton: ChatBarIcon, messagePopoverButton: { icon: PopOverIcon, render(message) { diff --git a/src/equicordplugins/messageFetchTimer/index.tsx b/src/equicordplugins/messageFetchTimer/index.tsx index 40a6a7bff..93640440b 100644 --- a/src/equicordplugins/messageFetchTimer/index.tsx +++ b/src/equicordplugins/messageFetchTimer/index.tsx @@ -72,14 +72,7 @@ const FetchTimeButton: ChatBarButtonFactory = ({ isMainChat }) => { alignItems: "center", gap: "4px" }}> - - - + {FetchTimeIcon()} { ); }; +function FetchTimeIcon() { + return ( + + + + ); +} + function formatTimeAgo(timestamp: Date): string { const now = new Date(); const diff = now.getTime() - timestamp.getTime(); @@ -145,6 +151,11 @@ export default definePlugin({ authors: [EquicordDevs.GroupXyz], settings, + chatBarButton: { + icon: FetchTimeIcon, + render: FetchTimeButton + }, + start() { FluxDispatcher.subscribe("CHANNEL_SELECT", handleChannelSelect); FluxDispatcher.subscribe("LOAD_MESSAGES_SUCCESS", handleMessageLoad); @@ -164,7 +175,5 @@ export default definePlugin({ currentFetch = null; channelTimings.clear(); currentChannelId = null; - }, - - renderChatBarButton: FetchTimeButton, + } }); diff --git a/src/equicordplugins/sekaiStickers/index.tsx b/src/equicordplugins/sekaiStickers/index.tsx index bfbc07feb..08cc3058f 100644 --- a/src/equicordplugins/sekaiStickers/index.tsx +++ b/src/equicordplugins/sekaiStickers/index.tsx @@ -36,7 +36,10 @@ export default definePlugin({ authors: [Devs.MaiKokain], dependencies: ["ChatInputButtonAPI"], settings, - renderChatBarButton: SekaiStickerChatButton, + chatBarButton: { + icon: kanadeSvg, + render: SekaiStickerChatButton + }, async start() { const fonts = [{ name: "YurukaStd", url: "https://raw.githubusercontent.com/TheOriginalAyaka/sekai-stickers/47a2ca33b8cb35f59800e8faad48980e4ce5ea71/src/fonts/YurukaStd.woff2" }, { name: "SSFangTangTi", url: "https://raw.githubusercontent.com/TheOriginalAyaka/sekai-stickers/main/src/fonts/ShangShouFangTangTi.woff2" }]; if (!IS_FONTS_LOADED) { diff --git a/src/equicordplugins/signature/index.tsx b/src/equicordplugins/signature/index.tsx index 69d428d8f..5eb1d6b22 100644 --- a/src/equicordplugins/signature/index.tsx +++ b/src/equicordplugins/signature/index.tsx @@ -70,6 +70,14 @@ const SignatureToggle: ChatBarButtonFactory = ({ isMainChat }) => { ); }; +function SignatureIcon() { + return ( + + + + ); +} + const handleMessage = ((channelId, msg) => { if (!settings.store.isEnabled) { msg.content = msg.content; @@ -103,7 +111,6 @@ export default definePlugin({ description: "Automated fingerprint/end text", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana, EquicordDevs.KrystalSkull], dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"], - renderChatBarButton: SignatureToggle, start: () => { if (settings.store.isEnabled) true; @@ -115,6 +122,11 @@ export default definePlugin({ }, + chatBarButton: { + icon: SignatureIcon, + render: SignatureToggle + }, + settings, contextMenus: { diff --git a/src/equicordplugins/talkInReverse/index.tsx b/src/equicordplugins/talkInReverse/index.tsx index 7ecf97e5a..de5bc0477 100644 --- a/src/equicordplugins/talkInReverse/index.tsx +++ b/src/equicordplugins/talkInReverse/index.tsx @@ -54,10 +54,21 @@ const ReverseMessageToggle: ChatBarButtonFactory = ({ isMainChat }) => { ); }; +function ReverseMessageIcon() { + return ( + + + + ); +} + export default definePlugin({ name: "TalkInReverse", authors: [EquicordDevs.Tolgchu], description: "Reverses the message content before sending it.", dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"], - renderChatBarButton: ReverseMessageToggle, + chatBarButton: { + icon: ReverseMessageIcon, + render: ReverseMessageToggle + } }); diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index c4b973ed1..4b0c41a8d 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -201,6 +201,14 @@ const SilentTypingChatToggle: ChatBarButtonFactory = ({ channel, type }) => { ); }; +function SilentTypingChatIcon() { + return ( + + + + ); +} + function getEffectiveList(): string[] { if (settings.store.defaultHidden) { if (!settings.store.disabledLocations) { @@ -298,6 +306,10 @@ export default definePlugin({ contextMenus: { "textarea-context": ChatBarContextCheckbox }, + chatBarButton: { + icon: SilentTypingChatIcon, + render: SilentTypingChatToggle + }, patches: [ { @@ -425,6 +437,4 @@ export default definePlugin({ if (checkEnabled(channelId)) return; FluxDispatcher.dispatch({ type: "TYPING_START_LOCAL", channelId }); }, - - renderChatBarButton: SilentTypingChatToggle, }); diff --git a/src/utils/types.ts b/src/utils/types.ts index d882dd785..a03ab10b5 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { AudioProcessor } from "@api/AudioPlayer"; import type { ProfileBadge } from "@api/Badges"; import type { ChatBarButtonData, ChatBarButtonFactory } from "@api/ChatButtons"; import type { NavContextMenuPatchCallback } from "@api/ContextMenu"; @@ -195,7 +196,10 @@ export interface PluginDef { renderMessageDecoration?: MessageDecorationFactory; renderMemberListDecorator?: MemberListDecoratorFactory; + + // Custom renderNicknameIcon?: NicknameIconFactory; + audioProcessor?: AudioProcessor; // TODO: Remove eventually /** From 4850a6401ff92b0a261a3e54dab21541b5ca72d2 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:00:48 -0500 Subject: [PATCH 16/33] Fix Requires --- src/api/PluginManager.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/PluginManager.ts b/src/api/PluginManager.ts index 9acfc94ee..d5b01f39d 100644 --- a/src/api/PluginManager.ts +++ b/src/api/PluginManager.ts @@ -365,9 +365,12 @@ export const initPluginManager = onlyOnce(function init() { if (p.renderMessageAccessory) neededApiPlugins.add("MessageAccessoriesAPI"); if (p.renderMessageDecoration) neededApiPlugins.add("MessageDecorationsAPI"); if (p.messagePopoverButton || p.renderMessagePopoverButton) neededApiPlugins.add("MessagePopoverAPI"); - if (p.renderNicknameIcon) neededApiPlugins.add("NicknameIconsAPI"); if (p.userProfileBadge) neededApiPlugins.add("BadgeAPI"); + // Custom + if (p.renderNicknameIcon) neededApiPlugins.add("NicknameIconsAPI"); + if (p.audioProcessor) neededApiPlugins.add("AudioPlayerAPI"); + for (const key of pluginKeysToBind) { p[key] &&= p[key].bind(p) as any; } From 0c0498e531f75b16ddb8c5ec9af608fb9633d566 Mon Sep 17 00:00:00 2001 From: prism Date: Thu, 27 Nov 2025 13:47:59 -0800 Subject: [PATCH 17/33] feat(HeaderBarAPI): Add API to register header bar buttons (#530) * feat(HeaderBarAPI): Add API to register header bar buttons * bleh * t * t * a * t --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com> --- src/api/HeaderBar.tsx | 62 +++++++++++++++ src/api/PluginManager.ts | 18 +++-- src/api/index.ts | 6 ++ src/equicordplugins/baseDecoder/index.tsx | 1 - src/equicordplugins/customSounds/index.tsx | 5 +- src/equicordplugins/dontFilterMe/index.tsx | 46 +++++------- src/equicordplugins/equicordToolbox/index.tsx | 35 +++------ src/equicordplugins/findReply/index.tsx | 2 - src/equicordplugins/holyNotes/index.tsx | 48 ++---------- src/equicordplugins/husk/index.tsx | 1 - .../components/LogsButton.tsx | 25 +------ .../messageLoggerEnhanced/index.tsx | 30 +------- src/equicordplugins/moreUserTags/index.tsx | 1 - src/equicordplugins/noBulletPoints/index.tsx | 13 +--- src/equicordplugins/polishWording/index.ts | 6 +- .../questCompleter.discordDesktop/index.tsx | 75 +++---------------- src/equicordplugins/sekaiStickers/index.tsx | 1 - .../showBadgesInChat/index.tsx | 9 +-- src/equicordplugins/signature/index.tsx | 21 ++---- src/equicordplugins/soggy/index.tsx | 28 +------ .../soundBoardLogger/index.tsx | 33 +------- .../soundBoardLogger/settings.tsx | 9 --- .../splitLargeMessages/index.ts | 9 +-- src/equicordplugins/talkInReverse/index.tsx | 2 +- src/equicordplugins/translatePlus/index.tsx | 1 - src/plugins/_api/headerBar.ts | 24 ++++++ src/plugins/platformIndicators/index.tsx | 52 +++---------- src/plugins/silentTyping/index.tsx | 1 - src/plugins/userVoiceShow/index.tsx | 36 ++++----- src/utils/types.ts | 4 +- 30 files changed, 204 insertions(+), 400 deletions(-) create mode 100644 src/api/HeaderBar.tsx create mode 100644 src/plugins/_api/headerBar.ts diff --git a/src/api/HeaderBar.tsx b/src/api/HeaderBar.tsx new file mode 100644 index 000000000..04d740f8c --- /dev/null +++ b/src/api/HeaderBar.tsx @@ -0,0 +1,62 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import ErrorBoundary from "@components/ErrorBoundary"; +import { useEffect, useState } from "@webpack/common"; +import type { JSX } from "react"; + +export type HeaderBarButtonFactory = () => JSX.Element | null; + +interface HeaderBarButton { + render: HeaderBarButtonFactory; + priority: number; +} + +export const buttons = new Map(); + +const listeners = new Set<() => void>(); + +/** + * Add a button to the header bar. + * @param id Unique identifier for the button. + * @param render Function that renders the button component. + * @param priority Higher priority = more to the right. Default is 0. + */ +export function addHeaderBarButton(id: string, render: HeaderBarButtonFactory, priority = 0) { + buttons.set(id, { render, priority }); + listeners.forEach(l => l()); +} + +/** + * Remove a button from the header bar. + * @param id The identifier of the button to remove. + */ +export function removeHeaderBarButton(id: string) { + buttons.delete(id); + listeners.forEach(l => l()); +} + +function HeaderBarButtons() { + const [, forceUpdate] = useState(0); + + useEffect(() => { + const listener = () => forceUpdate(n => n + 1); + listeners.add(listener); + return () => { listeners.delete(listener); }; + }, []); + + const sorted = Array.from(buttons).sort(([, a], [, b]) => a.priority - b.priority); + + return sorted.map(([id, { render: Button }]) => ( + + - )} - - - ); - }, - renderNavBar(e) { - if (Array.isArray(e.toolbar)) - return e.toolbar.unshift( - - - - ); - - e.toolbar = [ - - - , - e.toolbar, - ]; - } + renderHeaderBarButton: ToolBarHeader }); diff --git a/src/equicordplugins/sekaiStickers/index.tsx b/src/equicordplugins/sekaiStickers/index.tsx index 08cc3058f..af1d6c1af 100644 --- a/src/equicordplugins/sekaiStickers/index.tsx +++ b/src/equicordplugins/sekaiStickers/index.tsx @@ -34,7 +34,6 @@ export default definePlugin({ name: "SekaiStickers", description: "Sekai Stickers built in discord originally from github.com/TheOriginalAyaka", authors: [Devs.MaiKokain], - dependencies: ["ChatInputButtonAPI"], settings, chatBarButton: { icon: kanadeSvg, diff --git a/src/equicordplugins/showBadgesInChat/index.tsx b/src/equicordplugins/showBadgesInChat/index.tsx index ec23fde67..4d672e144 100644 --- a/src/equicordplugins/showBadgesInChat/index.tsx +++ b/src/equicordplugins/showBadgesInChat/index.tsx @@ -4,7 +4,6 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecorations"; import { Devs, EquicordDevs } from "@utils/constants"; import { isEquicordPluginDev, isPluginDev } from "@utils/misc"; import definePlugin from "@utils/types"; @@ -142,12 +141,8 @@ export default definePlugin({ name: "ShowBadgesInChat", authors: [Devs.Inbestigator, EquicordDevs.KrystalSkull], description: "Shows the message author's badges beside their name in chat.", - dependencies: ["MessageDecorationsAPI"], settings, - start: () => { - addMessageDecoration("vc-show-badges-in-chat", props => props.message?.author ? : null); - }, - stop: () => { - removeMessageDecoration("vc-show-badges-in-chat"); + renderMessageDecoration(props) { + return props.message?.author ? : null; } }); diff --git a/src/equicordplugins/signature/index.tsx b/src/equicordplugins/signature/index.tsx index 5eb1d6b22..7c5630650 100644 --- a/src/equicordplugins/signature/index.tsx +++ b/src/equicordplugins/signature/index.tsx @@ -7,7 +7,6 @@ import { ChatBarButton, ChatBarButtonFactory } from "@api/ChatButtons"; import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; -import { addMessagePreSendListener, removeMessagePreSendListener } from "@api/MessageEvents"; import { definePluginSettings } from "@api/Settings"; import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -78,14 +77,6 @@ function SignatureIcon() { ); } -const handleMessage = ((channelId, msg) => { - if (!settings.store.isEnabled) { - msg.content = msg.content; - } else { - msg.content = textProcessing(msg.content); - } -}); - const ChatBarContextCheckbox: NavContextMenuPatchCallback = children => { const { isEnabled, contextMenu } = settings.use(["isEnabled", "contextMenu"]); if (!contextMenu) return; @@ -110,16 +101,18 @@ export default definePlugin({ name: "Signature", description: "Automated fingerprint/end text", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana, EquicordDevs.KrystalSkull], - dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"], - + onBeforeMessageSend(channelId, msg) { + if (!settings.store.isEnabled) { + msg.content = msg.content; + } else { + msg.content = textProcessing(msg.content); + } + }, start: () => { if (settings.store.isEnabled) true; - addMessagePreSendListener(handleMessage); }, stop: () => { if (settings.store.isEnabled) false; - removeMessagePreSendListener(handleMessage); - }, chatBarButton: { diff --git a/src/equicordplugins/soggy/index.tsx b/src/equicordplugins/soggy/index.tsx index edd0361e2..caf1b4659 100644 --- a/src/equicordplugins/soggy/index.tsx +++ b/src/equicordplugins/soggy/index.tsx @@ -6,7 +6,6 @@ import { AudioPlayerInterface, createAudioPlayer } from "@api/AudioPlayer"; import { definePluginSettings } from "@api/Settings"; -import ErrorBoundary from "@components/ErrorBoundary"; import { EquicordDevs } from "@utils/constants"; import { ModalProps, ModalRoot, openModal } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; @@ -143,15 +142,7 @@ export default definePlugin({ authors: [EquicordDevs.sliwka], settings, dependencies: ["AudioPlayerAPI"], - patches: [ - { - find: ".controlButtonWrapper,", - replacement: { - match: /(function \i\(\i\){)(.{1,200}toolbar.{1,450}mobileToolbar)/, - replace: "$1$self.addIconToToolBar(arguments[0]);$2" - } - } - ], + renderHeaderBarButton: SoggyButton, start() { assignBoop(settings.store.boopLink, settings.store.boopVolume * 100); @@ -162,21 +153,4 @@ export default definePlugin({ boopSound?.delete(); song?.delete(); }, - - // taken from message logger lol - addIconToToolBar(e: { toolbar: React.ReactNode[] | React.ReactNode; }) { - if (Array.isArray(e.toolbar)) - return e.toolbar.unshift( - - - - ); - - e.toolbar = [ - - - , - e.toolbar, - ]; - }, }); diff --git a/src/equicordplugins/soundBoardLogger/index.tsx b/src/equicordplugins/soundBoardLogger/index.tsx index 41aa76180..5d95a2f2d 100644 --- a/src/equicordplugins/soundBoardLogger/index.tsx +++ b/src/equicordplugins/soundBoardLogger/index.tsx @@ -4,14 +4,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { addChatBarButton, removeChatBarButton } from "@api/ChatButtons"; import { disableStyle, enableStyle } from "@api/Styles"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; import { FluxDispatcher } from "@webpack/common"; -import { CharBarButton, ChatBarIcon } from "./components/Icons"; import { OpenSBLogsButton } from "./components/SoundBoardLog"; import settings from "./settings"; import { updateLoggedSounds } from "./store"; @@ -22,33 +19,9 @@ export default definePlugin({ name: "SoundBoardLogger", authors: [Devs.Moxxie, EquicordDevs.Fres, Devs.amy, Devs.thororen], description: "Logs all soundboards that are played in a voice chat and allows you to download them", - dependencies: ["AudioPlayerAPI", "ChatInputButtonAPI"], - patches: [ - { - predicate: () => settings.store.IconLocation === "toolbar", - find: ".controlButtonWrapper,", - replacement: { - match: /(function \i\(\i\){)(.{1,500}toolbar.{1,500}mobileToolbar)/, - replace: "$1$self.addSBIconToToolBar(arguments[0]);$2" - } - } - ], + dependencies: ["AudioPlayerAPI"], settings, - addSBIconToToolBar(e: { toolbar: React.ReactNode[] | React.ReactNode; }) { - if (Array.isArray(e.toolbar)) - return e.toolbar.unshift( - - - - ); - - e.toolbar = [ - - - , - e.toolbar, - ]; - }, + renderHeaderBarButton: OpenSBLogsButton, start() { enableStyle(styles); FluxDispatcher.subscribe("VOICE_CHANNEL_EFFECT_SEND", async sound => { @@ -56,10 +29,8 @@ export default definePlugin({ await updateLoggedSounds(sound); getListeners().forEach(cb => cb()); }); - if (settings.store.IconLocation === "chat") addChatBarButton("vc-soundlog-button", CharBarButton, ChatBarIcon); }, stop() { disableStyle(styles); - if (settings.store.IconLocation === "chat") removeChatBarButton("vc-soundlog-button"); } }); diff --git a/src/equicordplugins/soundBoardLogger/settings.tsx b/src/equicordplugins/soundBoardLogger/settings.tsx index 6c9453077..75d211c5d 100644 --- a/src/equicordplugins/soundBoardLogger/settings.tsx +++ b/src/equicordplugins/soundBoardLogger/settings.tsx @@ -85,15 +85,6 @@ const settings = definePluginSettings({ default: 0.5, markers: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] }, - IconLocation: { - description: "choose where to show the SoundBoard Log icon (requires restart)", - type: OptionType.SELECT, - options: [ - { label: "Toolbar", value: "toolbar", default: true }, - { label: "Chat input", value: "chat" } - ], - restartNeeded: true - }, }); export default settings; diff --git a/src/equicordplugins/splitLargeMessages/index.ts b/src/equicordplugins/splitLargeMessages/index.ts index 50dadff56..0e52af7f4 100644 --- a/src/equicordplugins/splitLargeMessages/index.ts +++ b/src/equicordplugins/splitLargeMessages/index.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { addMessagePreSendListener, MessageSendListener, removeMessagePreSendListener } from "@api/MessageEvents"; +import { MessageSendListener } from "@api/MessageEvents"; import { definePluginSettings } from "@api/Settings"; import { EquicordDevs } from "@utils/constants"; import { getCurrentChannel, sendMessage } from "@utils/discord"; @@ -117,16 +117,11 @@ export default definePlugin({ name: "SplitLargeMessages", description: "Splits large messages into multiple to fit Discord's message limit.", authors: [EquicordDevs.Reycko], - dependencies: ["MessageEventsAPI"], settings, + onBeforeMessageSend: listener, start() { if (settings.store.maxLength === 0) maxLength = autoMaxLength(); - addMessagePreSendListener(listener); - }, - - stop() { - removeMessagePreSendListener(listener); }, patches: [ diff --git a/src/equicordplugins/talkInReverse/index.tsx b/src/equicordplugins/talkInReverse/index.tsx index de5bc0477..c469c9b31 100644 --- a/src/equicordplugins/talkInReverse/index.tsx +++ b/src/equicordplugins/talkInReverse/index.tsx @@ -66,7 +66,7 @@ export default definePlugin({ name: "TalkInReverse", authors: [EquicordDevs.Tolgchu], description: "Reverses the message content before sending it.", - dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"], + dependencies: ["MessageEventsAPI"], chatBarButton: { icon: ReverseMessageIcon, render: ReverseMessageToggle diff --git a/src/equicordplugins/translatePlus/index.tsx b/src/equicordplugins/translatePlus/index.tsx index 2457d0877..78e48b120 100644 --- a/src/equicordplugins/translatePlus/index.tsx +++ b/src/equicordplugins/translatePlus/index.tsx @@ -46,7 +46,6 @@ const messageCtxPatch: NavContextMenuPatchCallback = (children, { message }) => export default definePlugin({ name: "Translate+", description: "Vencord's translate plugin but with support for artistic languages!", - dependencies: ["MessageAccessoriesAPI"], authors: [Devs.Ven, EquicordDevs.Prince527], settings, contextMenus: { diff --git a/src/plugins/_api/headerBar.ts b/src/plugins/_api/headerBar.ts new file mode 100644 index 000000000..20af4ecb4 --- /dev/null +++ b/src/plugins/_api/headerBar.ts @@ -0,0 +1,24 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { EquicordDevs } from "@utils/constants"; +import definePlugin from "@utils/types"; + +export default definePlugin({ + name: "HeaderBarAPI", + description: "API to add buttons to the header bar.", + authors: [EquicordDevs.Prism], + + patches: [ + { + find: '?"BACK_FORWARD_NAVIGATION":', + replacement: { + match: /(?<=\i\.Fragment,\{children:\[.{1,500}className:\i\}\))(?=\])/, + replace: ",...Vencord.Api.HeaderBar._addButtons()" + } + } + ] +}); diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index 9d1541dbc..17d44cd45 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -18,9 +18,6 @@ import "./style.css"; -import { addMemberListDecorator, removeMemberListDecorator } from "@api/MemberListDecorators"; -import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecorations"; -import { addNicknameIcon, removeNicknameIcon } from "@api/NicknameIcons"; import { definePluginSettings, migratePluginSetting, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { classes } from "@utils/misc"; @@ -192,49 +189,22 @@ const PlatformIndicator = ({ user, isProfile, isMessage, isMemberList }: Platfor ); }; -function toggleMemberListDecorators(enabled: boolean) { - if (enabled) { - addMemberListDecorator("PlatformIndicators", props => ); - } else { - removeMemberListDecorator("PlatformIndicators"); - } -} - -function toggleNicknameIcons(enabled: boolean) { - if (enabled) { - addNicknameIcon("PlatformIndicators", props => , 1); - } else { - removeNicknameIcon("PlatformIndicators"); - } -} - -function toggleMessageDecorators(enabled: boolean) { - if (enabled) { - addMessageDecoration("PlatformIndicators", props => ); - } else { - removeMessageDecoration("PlatformIndicators"); - } -} - migratePluginSetting("PlatformIndicators", "profiles", "badges"); const settings = definePluginSettings({ list: { type: OptionType.BOOLEAN, description: "Show indicators in the member list", default: true, - onChange: toggleMemberListDecorators }, profiles: { type: OptionType.BOOLEAN, description: "Show indicators in user profiles", default: true, - onChange: toggleNicknameIcons }, messages: { type: OptionType.BOOLEAN, description: "Show indicators inside messages", default: true, - onChange: toggleMessageDecorators }, colorMobileIndicator: { type: OptionType.BOOLEAN, @@ -278,19 +248,21 @@ export default definePlugin({ name: "PlatformIndicators", description: "Adds platform indicators (Desktop, Mobile, Web...) to users", authors: [Devs.kemo, Devs.TheSun, Devs.Nuckyz, Devs.Ven], - dependencies: ["MemberListDecoratorsAPI", "NicknameIconsAPI", "MessageDecorationsAPI"], settings, - - start() { - if (settings.store.list) toggleMemberListDecorators(true); - if (settings.store.profiles) toggleNicknameIcons(true); - if (settings.store.messages) toggleMessageDecorators(true); + renderNicknameIcon(props) { + if (!settings.store.profiles) return null; + return ( + + ); }, + renderMemberListDecorator(props) { + if (!settings.store.list) return null; + return ; - stop() { - if (settings.store.list) toggleMemberListDecorators(false); - if (settings.store.profiles) toggleNicknameIcons; - if (settings.store.messages) toggleMessageDecorators(false); + }, + renderMessageDecoration(props) { + if (!settings.store.messages) return null; + return ; }, patches: [ diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index 4b0c41a8d..8637889ac 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -296,7 +296,6 @@ export default definePlugin({ name: "SilentTyping", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana, EquicordDevs.Etorix], description: "Hide your typing indicator from chat.", - dependencies: ["ChatInputButtonAPI"], isModified: true, settings, diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 5f1a05e54..70c22cf59 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -18,9 +18,6 @@ import "./style.css"; -import { addMemberListDecorator, removeMemberListDecorator } from "@api/MemberListDecorators"; -import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecorations"; -import { addNicknameIcon, removeNicknameIcon } from "@api/NicknameIcons"; import { definePluginSettings } from "@api/Settings"; import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -52,9 +49,22 @@ export default definePlugin({ name: "UserVoiceShow", description: "Shows an indicator when a user is in a Voice Channel", authors: [Devs.Nuckyz, Devs.LordElias, EquicordDevs.omaw], - dependencies: ["NicknameIconsAPI", "MemberListDecoratorsAPI", "MessageDecorationsAPI"], settings, + renderNicknameIcon({ userId }) { + if (!settings.store.showInUserProfileModal) return null; + return ( + + ); + }, + renderMemberListDecorator({ user }) { + if (!settings.store.showInMemberList) return null; + return user == null ? null : ; + }, + renderMessageDecoration({ message }) { + if (!settings.store.showInMessages) return null; + return message?.author == null ? null : ; + }, patches: [ // Friends List { @@ -67,23 +77,5 @@ export default definePlugin({ } ], - start() { - if (settings.store.showInUserProfileModal) { - addNicknameIcon("UserVoiceShow", ({ userId }) => ); - } - if (settings.store.showInMemberList) { - addMemberListDecorator("UserVoiceShow", ({ user }) => user == null ? null : ); - } - if (settings.store.showInMessages) { - addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : ); - } - }, - - stop() { - removeNicknameIcon("UserVoiceShow"); - removeMemberListDecorator("UserVoiceShow"); - removeMessageDecoration("UserVoiceShow"); - }, - VoiceChannelIndicator }); diff --git a/src/utils/types.ts b/src/utils/types.ts index a03ab10b5..14b6f8327 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -20,6 +20,7 @@ import { AudioProcessor } from "@api/AudioPlayer"; import type { ProfileBadge } from "@api/Badges"; import type { ChatBarButtonData, ChatBarButtonFactory } from "@api/ChatButtons"; import type { NavContextMenuPatchCallback } from "@api/ContextMenu"; +import { HeaderBarButtonFactory } from "@api/HeaderBar"; import type { MemberListDecoratorFactory } from "@api/MemberListDecorators"; import type { MessageAccessoryFactory } from "@api/MessageAccessories"; import type { MessageDecorationFactory } from "@api/MessageDecorations"; @@ -199,7 +200,8 @@ export interface PluginDef { // Custom renderNicknameIcon?: NicknameIconFactory; - audioProcessor?: AudioProcessor; + renderHeaderBarButton?: HeaderBarButtonFactory; + onAudioProcessor?: AudioProcessor; // TODO: Remove eventually /** From d8b8e365cfae1a240fd2c1a4126986387e842293 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:52:33 -0500 Subject: [PATCH 18/33] onAudioProcessor -> audioProcessor --- src/api/PluginManager.ts | 12 ++++++------ src/equicordplugins/customSounds/index.tsx | 2 +- src/utils/types.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/api/PluginManager.ts b/src/api/PluginManager.ts index 0c9e00911..c1e4cdb2a 100644 --- a/src/api/PluginManager.ts +++ b/src/api/PluginManager.ts @@ -191,7 +191,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: onBeforeMessageEdit, onBeforeMessageSend, onMessageClick, renderChatBarButton, chatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton, messagePopoverButton, // Custom - renderNicknameIcon, renderHeaderBarButton, onAudioProcessor + renderNicknameIcon, renderHeaderBarButton, audioProcessor } = p; if (p.start) { @@ -254,7 +254,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: // Custom if (renderNicknameIcon) addNicknameIcon(name, renderNicknameIcon); if (renderHeaderBarButton) addHeaderBarButton(name, renderHeaderBarButton); - if (onAudioProcessor) addAudioProcessor(name, onAudioProcessor); + if (audioProcessor) addAudioProcessor(name, audioProcessor); return true; }, p => `startPlugin ${p.name}`); @@ -265,7 +265,7 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu onBeforeMessageEdit, onBeforeMessageSend, onMessageClick, renderChatBarButton, chatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton, messagePopoverButton, // Custom - renderNicknameIcon, renderHeaderBarButton, onAudioProcessor + renderNicknameIcon, renderHeaderBarButton, audioProcessor } = p; if (p.stop) { @@ -322,7 +322,7 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu // Custom if (renderNicknameIcon) removeNicknameIcon(name); if (renderHeaderBarButton) removeHeaderBarButton(name); - if (onAudioProcessor) removeAudioProcessor(name); + if (audioProcessor) removeAudioProcessor(name); return true; }, p => `stopPlugin ${p.name}`); @@ -335,7 +335,7 @@ export const initPluginManager = onlyOnce(function init() { "onBeforeMessageEdit", "onBeforeMessageSend", "onMessageClick", "renderChatBarButton", "renderMemberListDecorator", "renderMessageAccessory", "renderMessageDecoration", "renderMessagePopoverButton", // Custom - "renderNicknameIcon", "renderHeaderBarButton", "onAudioProcessor" + "renderNicknameIcon", "renderHeaderBarButton" ]; const neededApiPlugins = new Set(); @@ -375,7 +375,7 @@ export const initPluginManager = onlyOnce(function init() { // Custom if (p.renderNicknameIcon) neededApiPlugins.add("NicknameIconsAPI"); if (p.renderHeaderBarButton) neededApiPlugins.add("HeaderBarAPI"); - if (p.onAudioProcessor) neededApiPlugins.add("AudioPlayerAPI"); + if (p.audioProcessor) neededApiPlugins.add("AudioPlayerAPI"); for (const key of pluginKeysToBind) { p[key] &&= p[key].bind(p) as any; diff --git a/src/equicordplugins/customSounds/index.tsx b/src/equicordplugins/customSounds/index.tsx index ee66cb6be..38e593432 100644 --- a/src/equicordplugins/customSounds/index.tsx +++ b/src/equicordplugins/customSounds/index.tsx @@ -396,7 +396,7 @@ export default definePlugin({ authors: [Devs.ScattrdBlade, Devs.TheKodeToad], settings, startAt: StartAt.Init, - onAudioProcessor: getCustomSoundURL, + audioProcessor: getCustomSoundURL, async start() { console.log("[CustomSounds] Plugin starting..."); diff --git a/src/utils/types.ts b/src/utils/types.ts index 14b6f8327..f70902291 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -201,7 +201,7 @@ export interface PluginDef { // Custom renderNicknameIcon?: NicknameIconFactory; renderHeaderBarButton?: HeaderBarButtonFactory; - onAudioProcessor?: AudioProcessor; + audioProcessor?: AudioProcessor; // TODO: Remove eventually /** From 34c724e3ed6092175fca8f7a918efbcbb28d4211 Mon Sep 17 00:00:00 2001 From: creations Date: Fri, 28 Nov 2025 23:22:53 -0500 Subject: [PATCH 19/33] add firefox to publish (#531) * add firefox to publish * add sources * rename sources --- .github/workflows/publish.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index add75c8a8..a69c9bccc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -77,13 +77,18 @@ jobs: if: steps.check.outputs.release == 'true' run: pnpm buildWebStandalone + - name: Create sources zip + if: steps.check.outputs.release == 'true' + run: zip -r dist/extension-sources.zip . -x "node_modules/*" -x "dist/*" -x ".git/*" + - name: Publish extension if: steps.check.outputs.release == 'true' - run: | - cd dist/browser/chromium-unpacked - pnpx chrome-webstore-upload-cli@2.1.0 upload --auto-publish + run: pnpx publish-browser-extension@latest --chrome-zip dist/extension-chrome.zip --firefox-zip dist/extension-firefox.zip --firefox-sources-zip dist/extension-sources.zip env: - EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }} - CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }} - CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }} - REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }} + CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }} + CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }} + CHROME_CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }} + CHROME_REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }} + FIREFOX_EXTENSION_ID: ${{ secrets.FIREFOX_EXTENSION_ID }} + FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }} + FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }} From 9d11a50e6603251295d404c0d998dc701cf395d7 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Fri, 28 Nov 2025 23:24:49 -0500 Subject: [PATCH 20/33] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df95c1c8b..5d123d02e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.13.6.2", + "version": "1.13.6.3", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { From 475f8af89d8613c6f737ef2164045d420cfad71a Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sun, 30 Nov 2025 13:06:47 -0500 Subject: [PATCH 21/33] AccountPanelServerProfile: Fix AlwaysExpandProfiles Conflict --- .../alwaysExpandProfiles/index.ts | 6 +- src/equicordplugins/videoSpeed/index.tsx | 96 ------------------- .../accountPanelServerProfile/index.tsx | 6 +- 3 files changed, 8 insertions(+), 100 deletions(-) delete mode 100644 src/equicordplugins/videoSpeed/index.tsx diff --git a/src/equicordplugins/alwaysExpandProfiles/index.ts b/src/equicordplugins/alwaysExpandProfiles/index.ts index 785fefb0d..e7fa58419 100644 --- a/src/equicordplugins/alwaysExpandProfiles/index.ts +++ b/src/equicordplugins/alwaysExpandProfiles/index.ts @@ -17,13 +17,13 @@ export default definePlugin({ { find: '"view-profile"', replacement: { - match: /(user:(\i).*?"PRESS_VIEW_PROFILE".{0,200})return/, - replace: "$1return $self.openUserProfile($2);" + match: /(user:(\i).*?"PRESS_VIEW_PROFILE".{0,200}return)/, + replace: "$1 $self.openUserModal($2);" }, all: true }, ], - openUserProfile(user: User) { + openUserModal(user: User) { openUserProfile(user.id); } }); diff --git a/src/equicordplugins/videoSpeed/index.tsx b/src/equicordplugins/videoSpeed/index.tsx deleted file mode 100644 index 448d9ae71..000000000 --- a/src/equicordplugins/videoSpeed/index.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { definePluginSettings } from "@api/Settings"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; -import { Tooltip, useRef, useState } from "@webpack/common"; - -const settings = definePluginSettings( - { - preservePitch: { - type: OptionType.BOOLEAN, - description: "Should pitch be preserved when changing speed?", - default: false, - restartNeeded: true - }, - }); - -export default definePlugin({ - name: "VideoSpeed", - description: "Allows you to change the speed of videos", - authors: [Devs.Samwich], - settings, - patches: [ - { - find: /\.VIDEO\?\i\.videoControls:/, - replacement: { - match: /children:\[this\.renderPlayIcon\(\),.{0,200}\.setDurationRef}\),/, - replace: "$&$self.SpeedButton()," - }, - }, - ], - SpeedButton: ErrorBoundary.wrap(() => { - const elementRef = useRef(null); - - const [speed, setSpeed] = useState(1); - - const speedPaths = - { - 1.5: "M320 48a48 48 0 1 1 96 0a48 48 0 1 1-96 0m-115.5 73.3c-5.4-2.5-11.7-1.9-16.4 1.7l-40.9 30.7c-14.1 10.6-34.2 7.7-44.8-6.4s-7.7-34.2 6.4-44.8l40.9-30.7c23.7-17.8 55.3-21 82.1-8.4l90.4 42.5c29.1 13.7 36.8 51.6 15.2 75.5L299.1 224h97.4c30.3 0 53 27.7 47.1 57.4l-28.2 140.9c-3.5 17.3-20.3 28.6-37.7 25.1s-28.6-20.3-25.1-37.7L377 288h-70.3c8.6 19.6 13.3 41.2 13.3 64c0 88.4-71.6 160-160 160S0 440.4 0 352s71.6-160 160-160c11.1 0 22 1.1 32.4 3.3l54.2-54.2zM160 448a96 96 0 1 0 0-192a96 96 0 1 0 0 192", - 1.25: "M320 48a48 48 0 1 0-96 0a48 48 0 1 0 96 0M125.7 175.5c9.9-9.9 23.4-15.5 37.5-15.5c1.9 0 3.8.1 5.6.3L137.6 254c-9.3 28 1.7 58.8 26.8 74.5l86.2 53.9l-25.4 88.8c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l28.7-100.4c5.9-20.6-2.6-42.6-20.7-53.9L238 299l30.9-82.4l5.1 12.3c15 35.8 49.9 59.1 88.7 59.1H384c17.7 0 32-14.3 32-32s-14.3-32-32-32h-21.3c-12.9 0-24.6-7.8-29.5-19.7l-6.3-15c-14.6-35.1-44.1-61.9-80.5-73.1l-48.7-15C186.6 97.8 175 96 163.3 96c-31 0-60.8 12.3-82.7 34.3l-23.2 23.1c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l23.1-23.1zM91.2 352H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h69.6c19 0 36.2-11.2 43.9-28.5l11.5-25.9l-9.5-6a95.394 95.394 0 0 1-37.9-44.9z", - 1: "M112 48a48 48 0 1 1 96 0a48 48 0 1 1-96 0m40 304v128c0 17.7-14.3 32-32 32s-32-14.3-32-32V256.9l-28.6 47.6c-9.1 15.1-28.8 20-43.9 10.9s-20-28.8-10.9-43.9l58.3-97c17.4-28.9 48.6-46.6 82.3-46.6h29.7c33.7 0 64.9 17.7 82.3 46.6l58.3 97c9.1 15.1 4.2 34.8-10.9 43.9s-34.8 4.2-43.9-10.9L232 256.9V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V352z", - 0.5: "M368 32c41.7 0 75.9 31.8 79.7 72.5l85.6 26.3c25.4 7.8 42.8 31.3 42.8 57.9c0 21.8-11.7 41.9-30.7 52.7l-144.6 82.1l92.5 92.5H544c17.7 0 32 14.3 32 32s-14.3 32-32 32h-64c-8.5 0-16.6-3.4-22.6-9.4L346.9 360.2c11.7-36 3.2-77.1-25.4-105.7c-40.6-40.6-106.3-40.6-146.9-.1l-73.6 70c-6.4 6.1-6.7 16.2-.6 22.6s16.2 6.6 22.6.6l73.8-70.2l.1-.1l.1-.1c3.5-3.5 7.3-6.6 11.3-9.2c27.9-18.5 65.9-15.4 90.5 9.2c24.7 24.7 27.7 62.9 9 90.9c-2.6 3.8-5.6 7.5-9 10.9l-37 37H352c17.7 0 32 14.3 32 32s-14.3 32-32 32H64c-35.3 0-64-28.7-64-64C0 249.6 127 112.9 289.3 97.5C296.2 60.2 328.8 32 368 32m0 104a24 24 0 1 0 0-48a24 24 0 1 0 0 48" - }; - - return
- - {tooltipProps => ( -
{ - console.log(e); - let newSpeed; - switch (speed) { - case 1: - newSpeed = 1.25; - break; - case 1.25: - newSpeed = 1.5; - break; - case 1.5: - newSpeed = 0.5; - break; - case 0.5: - newSpeed = 1; - break; - } - const parent = e.currentTarget.parentNode!.parentNode!.parentNode!; - - // this works with audio too as it is but it doesnt always select the right audio tag - const media = parent.querySelector("video")! /* ?? document.querySelector("source")?.parentElement*/; - console.log(media); - media.playbackRate = newSpeed; - media.preservesPitch = settings.store.preservePitch; - setSpeed(newSpeed); - }} - > - -
- ) - } -
-
; - }, { noop: true }) -}); diff --git a/src/plugins/accountPanelServerProfile/index.tsx b/src/plugins/accountPanelServerProfile/index.tsx index 57144ec08..df3205967 100644 --- a/src/plugins/accountPanelServerProfile/index.tsx +++ b/src/plugins/accountPanelServerProfile/index.tsx @@ -4,14 +4,16 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; +import alwaysExpandProfiles from "@equicordplugins/alwaysExpandProfiles"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { User } from "@vencord/discord-types"; import { findComponentByCodeLazy } from "@webpack"; -import { ContextMenuApi, Menu } from "@webpack/common"; +import { ContextMenuApi, Menu, UserStore } from "@webpack/common"; interface UserProfileProps { popoutProps: Record; @@ -37,6 +39,8 @@ const AccountPanelContextMenu = ErrorBoundary.wrap(() => { label={prioritizeServerProfile ? "View Account Profile" : "View Server Profile"} disabled={getCurrentChannel()?.getGuildId() == null} action={e => { + const user = UserStore.getCurrentUser(); + if (isPluginEnabled(alwaysExpandProfiles.name)) return alwaysExpandProfiles.openUserModal(user); openAlternatePopout = true; accountPanelRef.current?.click(); }} From 97950239065e5a9bcf350a1d19abcf2d363217f3 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Sun, 30 Nov 2025 13:10:49 -0500 Subject: [PATCH 22/33] AccountPanelServerProfile: Format --- src/plugins/accountPanelServerProfile/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/accountPanelServerProfile/index.tsx b/src/plugins/accountPanelServerProfile/index.tsx index df3205967..cbf23bbab 100644 --- a/src/plugins/accountPanelServerProfile/index.tsx +++ b/src/plugins/accountPanelServerProfile/index.tsx @@ -39,8 +39,10 @@ const AccountPanelContextMenu = ErrorBoundary.wrap(() => { label={prioritizeServerProfile ? "View Account Profile" : "View Server Profile"} disabled={getCurrentChannel()?.getGuildId() == null} action={e => { - const user = UserStore.getCurrentUser(); - if (isPluginEnabled(alwaysExpandProfiles.name)) return alwaysExpandProfiles.openUserModal(user); + if (isPluginEnabled(alwaysExpandProfiles.name)) { + const user = UserStore.getCurrentUser(); + return alwaysExpandProfiles.openUserModal(user); + } openAlternatePopout = true; accountPanelRef.current?.click(); }} From ea5e7224bcc666c790855ae5d7f199844999ca25 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:33:12 -0500 Subject: [PATCH 23/33] Fix All Patches --- src/equicordplugins/questify/index.tsx | 2 +- src/equicordplugins/questify/utils/components.tsx | 4 ++-- src/equicordplugins/unreadBadgeCount/index.tsx | 2 +- src/plugins/decor/ui/index.ts | 2 +- src/plugins/noUnblockToJump/index.ts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/equicordplugins/questify/index.tsx b/src/equicordplugins/questify/index.tsx index 85af75edb..bf6af35d4 100644 --- a/src/equicordplugins/questify/index.tsx +++ b/src/equicordplugins/questify/index.tsx @@ -1073,7 +1073,7 @@ export default definePlugin({ }, { // Adds a maxDigits prop to the LowerBadge component which allows for not truncating, or for truncating at a specific threshold. - find: "STATUS_DANGER,disableColor", + find: '"renderBadgeCount"])', group: true, replacement: [ { diff --git a/src/equicordplugins/questify/utils/components.tsx b/src/equicordplugins/questify/utils/components.tsx index 9b14f999a..ff61c28ef 100644 --- a/src/equicordplugins/questify/utils/components.tsx +++ b/src/equicordplugins/questify/utils/components.tsx @@ -14,8 +14,8 @@ import { formatLowerBadge } from "./misc"; // GuildlessServerListItem's built-in pill does not support unread state. export const GuildlessServerListItemComponent = findComponentByCodeLazy("tooltip:", "lowerBadgeSize:"); export const GuildedServerListItemPillComponent = findComponentByCodeLazy('"pill":"empty"'); -export const ServerListItemLowerBadgeComponent = findComponentByCodeLazy("STATUS_DANGER,disableColor:"); -export const ServerListItemUpperBadgeComponent = findComponentByCodeLazy("STATUS_DANGER,shape:", "iconBadge,"); +export const ServerListItemLowerBadgeComponent = findComponentByCodeLazy("numberBadge", '"renderBadgeCount"'); +export const ServerListItemUpperBadgeComponent = findComponentByCodeLazy("iconBadge", ".ROUND,disableColor"); export const RadioGroup = findComponentByCodeLazy(',["label","description"'); export const QuestTile = findComponentByCodeLazy(".rowIndex,trackGuildAndChannelMetadata"); diff --git a/src/equicordplugins/unreadBadgeCount/index.tsx b/src/equicordplugins/unreadBadgeCount/index.tsx index c28dd7139..e1ee1d4e9 100644 --- a/src/equicordplugins/unreadBadgeCount/index.tsx +++ b/src/equicordplugins/unreadBadgeCount/index.tsx @@ -14,7 +14,7 @@ import { ReadStateStore, useStateFromStores } from "@webpack/common"; const UserGuildSettingsStore = findStoreLazy("UserGuildSettingsStore"); const JoinedThreadsStore = findStoreLazy("JoinedThreadsStore"); -const NumberBadge = findComponentByCodeLazy("numberBadge", ".STATUS_DANGER,"); +const NumberBadge = findComponentByCodeLazy("numberBadge", '"renderBadgeCount"'); const settings = definePluginSettings({ showOnMutedChannels: { diff --git a/src/plugins/decor/ui/index.ts b/src/plugins/decor/ui/index.ts index ec9a9e74f..52f6df2cb 100644 --- a/src/plugins/decor/ui/index.ts +++ b/src/plugins/decor/ui/index.ts @@ -10,5 +10,5 @@ import { extractAndLoadChunksLazy, findByPropsLazy } from "@webpack"; export const cl = classNameFactory("vc-decor-"); export const DecorationModalStyles = findByPropsLazy("modalPreview", "modalCloseButton", "spinner", "modal"); -export const requireAvatarDecorationModal = extractAndLoadChunksLazy(["initialSelectedDecoration:", /initialSelectedDecoration:\i,.{0,300}Promise\.all/]); +export const requireAvatarDecorationModal = extractAndLoadChunksLazy(["initialSelectedDecoration:", /initialSelectedDecoration:\i,.{0,200}onCloseModal:\i/]); export const requireCreateStickerModal = extractAndLoadChunksLazy(["stickerInspected]:"]); diff --git a/src/plugins/noUnblockToJump/index.ts b/src/plugins/noUnblockToJump/index.ts index b36a2e24d..5d876fc7b 100644 --- a/src/plugins/noUnblockToJump/index.ts +++ b/src/plugins/noUnblockToJump/index.ts @@ -27,7 +27,7 @@ export default definePlugin({ { find: "#{intl::UNIGNORE_TO_JUMP_BODY}", replacement: { - match: /return \i\.\i\.isBlockedForMessage\(/, + match: /if\(\i\.\i\.isBlockedForMessage\(/, replace: "return true;$&" } } From db6b92c226eb067e4380ac82864ee05fd20c7b33 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:35:50 -0500 Subject: [PATCH 24/33] NoUnblockToJump: Update Patch For Stable --- src/plugins/noUnblockToJump/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/noUnblockToJump/index.ts b/src/plugins/noUnblockToJump/index.ts index 5d876fc7b..d0921324c 100644 --- a/src/plugins/noUnblockToJump/index.ts +++ b/src/plugins/noUnblockToJump/index.ts @@ -27,7 +27,7 @@ export default definePlugin({ { find: "#{intl::UNIGNORE_TO_JUMP_BODY}", replacement: { - match: /if\(\i\.\i\.isBlockedForMessage\(/, + match: /(if\(|return )\i\.\i\.isBlockedForMessage\(/, replace: "return true;$&" } } From e3745f2ed1192a9268044e597c1ff49634291f94 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Tue, 2 Dec 2025 08:45:24 -0500 Subject: [PATCH 25/33] bump version + edge publishing --- .github/workflows/publish.yml | 6 +++++- package.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a69c9bccc..23499757e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -83,7 +83,8 @@ jobs: - name: Publish extension if: steps.check.outputs.release == 'true' - run: pnpx publish-browser-extension@latest --chrome-zip dist/extension-chrome.zip --firefox-zip dist/extension-firefox.zip --firefox-sources-zip dist/extension-sources.zip + run: pnpx publish-browser-extension@latest --chrome-zip dist/extension-chrome.zip --firefox-zip dist/extension-firefox.zip --firefox-sources-zip dist/extension-sources.zip --edge-zip dist/extension-chrome.zip + env: CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }} CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }} @@ -92,3 +93,6 @@ jobs: FIREFOX_EXTENSION_ID: ${{ secrets.FIREFOX_EXTENSION_ID }} FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }} FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }} + EDGE_PRODUCT_ID: ${{ secrets.EDGE_PRODUCT_ID }} + EDGE_CLIENT_ID: ${{ secrets.EDGE_CLIENT_ID }} + EDGE_API_KEY: ${{ secrets.EDGE_API_KEY }} diff --git a/package.json b/package.json index 5d123d02e..6a3f58794 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.13.6.3", + "version": "1.13.6.4", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { From 18513870a221d28dbe5d5ef6b0db91c9fe289ba2 Mon Sep 17 00:00:00 2001 From: prism Date: Tue, 2 Dec 2025 22:28:01 +0100 Subject: [PATCH 26/33] UI: cleanup and migration (#532) * cook * minor changes * h * t * b * revert * updates --------- Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com> --- src/components/Alert.tsx | 20 +++++---- src/components/ThemeSettings/ThemesTab.tsx | 5 ++- src/components/ThemeSettings/UserCSSModal.tsx | 4 +- src/components/settings/DonateButton.tsx | 42 ++++++------------- src/components/settings/SpecialCard.css | 1 + .../tabs/changelog/NewPluginsSection.tsx | 7 ++-- .../settings/tabs/changelog/index.tsx | 28 +++++-------- .../settings/tabs/plugins/PluginModal.tsx | 16 +++---- .../settings/tabs/plugins/styles.css | 2 +- .../tabs/sync/BackupAndRestoreTab.tsx | 29 +++++++------ .../settings/tabs/sync/CloudTab.tsx | 23 +++++----- .../settings/tabs/updater/Components.tsx | 7 ++-- .../settings/tabs/updater/index.tsx | 7 ++-- .../settings/tabs/vencord/DonateButton.tsx | 4 +- .../tabs/vencord/NotificationSettings.tsx | 3 +- .../settings/tabs/vencord/VencordTab.css | 5 +++ .../settings/tabs/vencord/index.tsx | 33 ++++++++------- src/plugins/_api/badges/modals.tsx | 6 +-- 18 files changed, 114 insertions(+), 128 deletions(-) diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx index 60c21f448..8e83f5738 100644 --- a/src/components/Alert.tsx +++ b/src/components/Alert.tsx @@ -5,7 +5,7 @@ */ import { filters, mapMangledModuleLazy } from "@webpack"; -import type { ReactNode } from "react"; +import type { ComponentType, CSSProperties, ReactNode } from "react"; const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE="positive', { HelpMessageTypes: filters.byProps("POSITIVE", "WARNING", "INFO", "ERROR"), @@ -15,35 +15,37 @@ const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE="positi export interface AlertProps { children: ReactNode; className?: string; + style?: CSSProperties; + icon?: ComponentType<{ className?: string; color?: string; }>; } -function Warning({ children, className }: AlertProps) { +function Warning({ children, className, style, icon }: AlertProps) { return ( - + {children} ); } -function Info({ children, className }: AlertProps) { +function Info({ children, className, style, icon }: AlertProps) { return ( - + {children} ); } -function Error({ children, className }: AlertProps) { +function Error({ children, className, style, icon }: AlertProps) { return ( - + {children} ); } -function Positive({ children, className }: AlertProps) { +function Positive({ children, className, style, icon }: AlertProps) { return ( - + {children} ); diff --git a/src/components/ThemeSettings/ThemesTab.tsx b/src/components/ThemeSettings/ThemesTab.tsx index 279b9d862..f283e48e3 100644 --- a/src/components/ThemeSettings/ThemesTab.tsx +++ b/src/components/ThemeSettings/ThemesTab.tsx @@ -21,6 +21,7 @@ import "./themesStyles.css"; import { isPluginEnabled } from "@api/PluginManager"; import { Settings, useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; +import { Button } from "@components/Button"; import { Card } from "@components/Card"; import { Divider } from "@components/Divider"; import { ErrorCard } from "@components/ErrorCard"; @@ -43,7 +44,7 @@ import { getThemeInfo, stripBOM, type UserThemeHeader } from "@utils/themes/bd"; import { usercssParse } from "@utils/themes/usercss"; import { getStylusWebStoreUrl } from "@utils/web"; import { findLazy } from "@webpack"; -import { Alerts, Button, React, showToast, TabBar, TextInput, Tooltip, useEffect, useMemo, useRef, useState } from "@webpack/common"; +import { Alerts, React, showToast, TabBar, TextInput, Tooltip, useEffect, useMemo, useRef, useState } from "@webpack/common"; import type { ComponentType, Ref, SyntheticEvent } from "react"; import type { UserstyleHeader } from "usercss-meta"; @@ -599,7 +600,7 @@ export function CspErrorCard() { {i !== 0 && }
{url} -
diff --git a/src/components/ThemeSettings/UserCSSModal.tsx b/src/components/ThemeSettings/UserCSSModal.tsx index c98c3deef..b4f3e4812 100644 --- a/src/components/ThemeSettings/UserCSSModal.tsx +++ b/src/components/ThemeSettings/UserCSSModal.tsx @@ -90,8 +90,8 @@ function ResetButton({ themeSettings, themeId, close, onReset }: ResetButtonProp onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} - onClick={async () => { - await close(); // close the modal first to stop rendering + onClick={() => { + close(); // close the modal first to stop rendering delete themeSettings[themeId]; onReset(); }}> diff --git a/src/components/settings/DonateButton.tsx b/src/components/settings/DonateButton.tsx index eb2a91e25..cc455305f 100644 --- a/src/components/settings/DonateButton.tsx +++ b/src/components/settings/DonateButton.tsx @@ -16,41 +16,24 @@ * along with this program. If not, see . */ +import { Button } from "@components/Button"; import { Heart } from "@components/Heart"; import { openInviteModal } from "@utils/discord"; import { ButtonProps } from "@vencord/discord-types"; -import { Button, showToast } from "@webpack/common"; - -export function VCDonateButton({ - look = Button.Looks.LINK, - color = Button.Colors.TRANSPARENT, - ...props -}: Partial) { - return ( - - ); -} +import { showToast } from "@webpack/common"; export function DonateButton({ - look = Button.Looks.LINK, - color = Button.Colors.TRANSPARENT, + equicord = false, ...props -}: Partial) { +}: Partial & { equicord?: boolean; }) { + const link = equicord ? "https://github.com/sponsors/thororen1234" : "https://github.com/sponsors/Vendicated"; return ( {!Settings.ignoreResetWarning && ( )} diff --git a/src/components/settings/tabs/sync/CloudTab.tsx b/src/components/settings/tabs/sync/CloudTab.tsx index a01cbee6a..ad77e4bdf 100644 --- a/src/components/settings/tabs/sync/CloudTab.tsx +++ b/src/components/settings/tabs/sync/CloudTab.tsx @@ -19,6 +19,7 @@ import { useSettings } from "@api/Settings"; import { authorizeCloud, deauthorizeCloud } from "@api/SettingsSync/cloudSetup"; import { deleteCloudSettings, eraseAllCloudData, getCloudSettings, putCloudSettings } from "@api/SettingsSync/cloudSync"; +import { Button } from "@components/Button"; import { CheckedTextInput } from "@components/CheckedTextInput"; import { Divider } from "@components/Divider"; import { FormSwitch } from "@components/FormSwitch"; @@ -28,7 +29,7 @@ import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab"; import { Margins } from "@utils/margins"; -import { Alerts, Button, Tooltip, useState } from "@webpack/common"; +import { Alerts, Tooltip, useState } from "@webpack/common"; function validateUrl(url: string) { try { @@ -60,7 +61,7 @@ function SettingsSyncSection() { />
- - diff --git a/src/components/settings/tabs/updater/Components.tsx b/src/components/settings/tabs/updater/Components.tsx index 8e3757c96..b56419dad 100644 --- a/src/components/settings/tabs/updater/Components.tsx +++ b/src/components/settings/tabs/updater/Components.tsx @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { Button } from "@components/Button"; import { Card } from "@components/Card"; import { ErrorCard } from "@components/ErrorCard"; import { Flex } from "@components/Flex"; @@ -13,7 +14,7 @@ import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { relaunch } from "@utils/native"; import { changes, checkForUpdates, update, updateError } from "@utils/updater"; -import { Alerts, Button, React, Toasts, useState } from "@webpack/common"; +import { Alerts, React, Toasts, useState } from "@webpack/common"; import { runWithDispatch } from "./runWithDispatch"; @@ -95,7 +96,7 @@ export function Updatable(props: CommonProps) { {isOutdated && ( )} }