diff --git a/src/equicordplugins/_api/userArea.ts b/src/equicordplugins/_api/userArea.ts index 9ed35d0c8..4f0d731c6 100644 --- a/src/equicordplugins/_api/userArea.ts +++ b/src/equicordplugins/_api/userArea.ts @@ -5,7 +5,7 @@ */ import { isPluginEnabled } from "@api/PluginManager"; -import betterUserArea from "@equicordplugins/betterUserArea"; +import declutter from "@equicordplugins/declutter"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findCssClassesLazy } from "@webpack"; @@ -43,6 +43,6 @@ export default definePlugin({ }, shouldHideTooltips() { - return isPluginEnabled(betterUserArea.name) && betterUserArea.settings.store.removeButtonTooltips; + return isPluginEnabled(declutter.name) && declutter.settings.store.removeButtonTooltips; } }); diff --git a/src/equicordplugins/anammox/index.ts b/src/equicordplugins/anammox/index.ts deleted file mode 100644 index 1ec80516c..000000000 --- a/src/equicordplugins/anammox/index.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { definePluginSettings } from "@api/Settings"; -import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; - -export const settings = definePluginSettings({ - dms: { - type: OptionType.BOOLEAN, - default: true, - description: "Remove shops above DMs list", - restartNeeded: true, - }, - quests: { - type: OptionType.BOOLEAN, - default: false, - description: "Remove quests above DMs list", - restartNeeded: true, - }, - serverBoost: { - type: OptionType.BOOLEAN, - default: true, - description: "Remove server boost info above channel list", - restartNeeded: true, - }, - billing: { - type: OptionType.BOOLEAN, - default: true, - description: "Remove billing settings", - restartNeeded: true, - }, - gift: { - type: OptionType.BOOLEAN, - default: true, - description: "Remove gift button", - restartNeeded: true, - }, - emojiList: { - type: OptionType.BOOLEAN, - default: true, - description: "Remove unavailable categories from the emoji picker", - restartNeeded: true, - }, -}); - -export default definePlugin({ - name: "Anammox", - description: "Hides various features related to nitro and the store", - authors: [Devs.Kyuuhachi], - settings, - - patches: [ - { - // Above DMs, mouse nav - find: 'tutorialId:"direct-messages"', - replacement: [ - { - match: /"nitro-tab-group"\)/, - replace: "$&&&undefined", - predicate: () => settings.store.dms - }, - { - match: /"discord-shop"\)/, - replace: "$&&&undefined", - predicate: () => settings.store.dms - }, - { - match: /"quests"\)/, - replace: "$&&&undefined", - predicate: () => settings.store.quests - }, - ], - }, - { - // Above DMs, keyboard nav - find: ".hasLibraryApplication()&&!", - replacement: [ - { - match: /\i\.\i\.APPLICATION_STORE,/, - replace: "/*$&*/", - }, - { - match: /\i\.\i\.COLLECTIBLES_SHOP,/, - replace: "/*$&*/", - }, - ], - predicate: () => settings.store.dms, - }, - { - // Channel list server boost progress bar - find: "useGuildActionRow", - replacement: { - match: /(GUILD_NEW_MEMBER_ACTIONS_PROGRESS_BAR\)):(\i(?:\.premiumProgressBarEnabled)?)/, - replace: "$1:null" - }, - predicate: () => settings.store.serverBoost, - }, - { - // Settings, sidebar - find: ".BILLING_SECTION,", - replacement: { - match: /(?<=buildLayout:\(\)=>)\[.+?\]/, - replace: "[]", - }, - predicate: () => settings.store.billing, - }, - { - // Gift button - find: '"sticker")', - replacement: { - match: /&&\i\.push\(\([^&]*?,"gift"\)\)/, - replace: "", - }, - predicate: () => settings.store.gift, - }, - { - // Emoji list - find: "#{intl::EMOJI_PICKER_EXPAND_EMOJI_SECTION}),size:", - replacement: { - match: /(\i)=\i\|\|!\i&&\i.\i.isEmojiCategoryNitroLocked\(\{[^}]*\}\);/, - replace: "$&$1||" - }, - predicate: () => settings.store.emojiList, - }, - { - // Emoji category list - find: "#{intl::EMOJI_CATEGORY_TOP_GUILD_EMOJI},{guildName:", - replacement: { - match: /(?<=(\i)\.unshift\((\i)\):)(?=\1\.push\(\2\))/, - replace: "$2.isNitroLocked||" - }, - predicate: () => settings.store.emojiList, - } - ], -}); diff --git a/src/equicordplugins/betterUserArea/index.ts b/src/equicordplugins/betterUserArea/index.ts deleted file mode 100644 index 0d48d04f3..000000000 --- a/src/equicordplugins/betterUserArea/index.ts +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2025 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { definePluginSettings } from "@api/Settings"; -import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; - -const settings = definePluginSettings({ - removeNameplate: { - type: OptionType.BOOLEAN, - description: "Remove nameplate styling.", - default: true, - restartNeeded: true - }, - removeAudioMenus: { - type: OptionType.BOOLEAN, - description: "Remove menus next to mute and deafen buttons.", - default: true, - restartNeeded: true - }, - alwaysShowUsername: { - type: OptionType.BOOLEAN, - description: "Always show username instead of status.", - default: true, - restartNeeded: true - }, - removeButtonTooltips: { - type: OptionType.BOOLEAN, - description: "Remove button tooltips.", - default: false, - restartNeeded: true - }, - removeAvatarDecoration: { - type: OptionType.BOOLEAN, - description: "Remove avatar decoration.", - default: true, - restartNeeded: true - }, - removeUsernameStyles: { - type: OptionType.BOOLEAN, - description: "Remove username colors and effects.", - default: true, - restartNeeded: true - } -}); - -export default definePlugin({ - name: "BetterUserArea", - description: "Customize and make the user area more clean.", - authors: [Devs.prism], - settings, - patches: [ - { - find: ".NITRO_PRIVACY_PERK_BETA_COACHMARK));", - replacement: [ - { - match: /,nameplate:\i,selectedGuildId:(\i),avatarDecoration/, - replace: ",nameplate:null,selectedGuildId:$1,avatarDecoration", - predicate: () => settings.store.removeNameplate - }, - { - match: /hoverText:(\i),forceHover:\i,children:/g, - replace: "hoverText:$1,forceHover:!0,children:", - predicate: () => settings.store.alwaysShowUsername - }, - { - match: /avatarDecoration:(.{0,70}),size:/, - replace: "avatarDecoration:void 0,size:", - predicate: () => settings.store.removeAvatarDecoration - }, - { - match: /displayNameStyles:(\i),/, - replace: "displayNameStyles:void 0,", - predicate: () => settings.store.removeUsernameStyles - } - ], - }, - { - find: '"MicrophoneButton"', - replacement: [ - { - match: /:\{tooltipText:\i\};/, - replace: ":{tooltipText:void 0};", - predicate: () => settings.store.removeButtonTooltips - }, - { - match: /(?<=#{intl::MUTE}\),)className:\i\.\i,/, - replace: "", - predicate: () => settings.store.removeAudioMenus - }, - { - match: /,\(0,\i\.jsxs?\)\(\i\.\i,\{.{0,600}#{intl::ACCOUNT_INPUT_OPTIONS}\)\}\)(?=\])/, - replace: "", - predicate: () => settings.store.removeAudioMenus - }, - ], - }, - { - find: "#{intl::f+DDY/::raw},{outputDeviceName", - replacement: [ - { - match: /(?<=role:"switch",)tooltipText:\i\}/, - replace: "tooltipText:void 0}", - predicate: () => settings.store.removeButtonTooltips - }, - { - match: /(?<=#{intl::DEAFEN}\),)className:\i\.\i,/, - replace: "", - predicate: () => settings.store.removeAudioMenus - }, - { - match: /,\(0,\i\.jsxs?\)\(\i\.\i,\{.{0,650}#{intl::ACCOUNT_OUTPUT_OPTIONS}\)\}\)(?=\])/, - replace: "", - predicate: () => settings.store.removeAudioMenus - } - ], - }, - { - find: "#{intl::USER_SETTINGS_WITH_BUILD_OVERRIDE}", - replacement: { - match: /tooltipText:\i,tooltipPositionKey/, - replace: "tooltipText:void 0,tooltipPositionKey" - }, - predicate: () => settings.store.removeButtonTooltips - }, - ], -}); diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx new file mode 100644 index 000000000..2aef52a4e --- /dev/null +++ b/src/equicordplugins/declutter/index.tsx @@ -0,0 +1,334 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings, migratePluginSetting, migratePluginSettings } from "@api/Settings"; +import { HeadingSecondary } from "@components/Heading"; +import { Devs, EquicordDevs } from "@utils/index"; +import definePlugin, { OptionType } from "@utils/types"; + +migratePluginSettings("Declutter", "BetterUserArea", "Anammox"); + +const migrationsAnammox = [ + ["dms", "removeShopAboveDM"], + ["quests", "removeQuestsAboveDM"], + ["serverBoost", "removeServerBoostInfo"], + ["billing", "removeBillingSettings"], + ["gift", "removeGiftButton"], + ["emojiList", "removeUnavailableEmojiPicker"], +]; + +for (const [oldKey, newKey] of migrationsAnammox) { + migratePluginSetting("Anammox", newKey, oldKey); +} + +export const settings = definePluginSettings({ + userProfileHeader: { + type: OptionType.COMPONENT, + component: () => SectionSeparator("User Profile"), + }, + removeAvatarDecoration: { + type: OptionType.BOOLEAN, + description: "Remove avatar decorations.", + default: true, + restartNeeded: true, + }, + removeNameplate: { + type: OptionType.BOOLEAN, + description: "Remove nameplates.", + default: true, + restartNeeded: true, + }, + removeProfileEffect: { + type: OptionType.BOOLEAN, + description: "Remove profile animation effects on open.", + default: true, + restartNeeded: true, + }, + removeClanTag: { + type: OptionType.BOOLEAN, + description: "Remove clan tags.", + default: true, + restartNeeded: true, + }, + alwaysShowUsername: { + type: OptionType.BOOLEAN, + description: "Always show username instead of status.", + default: true, + restartNeeded: true + }, + removeUsernameStyles: { + type: OptionType.BOOLEAN, + description: "Remove username colors and effects.", + default: true, + restartNeeded: true + }, + friendsListHeader: { + type: OptionType.COMPONENT, + component: () => SectionSeparator("Above Friends/DMs List"), + }, + removeShopAboveDM: { + type: OptionType.BOOLEAN, + description: "Remove shops above DMs list.", + default: true, + restartNeeded: true, + }, + removeQuestsAboveDM: { + type: OptionType.BOOLEAN, + description: "Remove quests above DMs list.", + default: false, + restartNeeded: true, + }, + miscHeader: { + type: OptionType.COMPONENT, + component: () => SectionSeparator("Misc"), + }, + removeServerBoostInfo: { + type: OptionType.BOOLEAN, + description: "Remove server boost info above channel list.", + default: true, + restartNeeded: true, + }, + removeBillingSettings: { + type: OptionType.BOOLEAN, + description: "Remove billing settings.", + default: true, + restartNeeded: true, + }, + removeGiftButton: { + type: OptionType.BOOLEAN, + description: "Remove gift button.", + default: true, + restartNeeded: true, + }, + removeUnavailableEmojiPicker: { + type: OptionType.BOOLEAN, + description: "Remove unavailable categories from the emoji picker.", + default: true, + restartNeeded: true, + }, + removeAudioMenus: { + type: OptionType.BOOLEAN, + description: "Remove menus next to mute and deafen buttons.", + default: true, + restartNeeded: true + }, + removeButtonTooltips: { + type: OptionType.BOOLEAN, + description: "Remove button tooltips.", + default: false, + restartNeeded: true + }, +}); + +function SectionSeparator(title: string) { + return ( + <> +
+ {title} +
+ + ); +} + +export default definePlugin({ + name: "Declutter", + description: "Declutter discord ui by removing unwanted elements such as profile customizations, shops, quests and more.", + authors: [EquicordDevs.Leon135, Devs.prism, Devs.Kyuuhachi], + settings, + patches: [ + { + // Avatar decoration + find: "getAvatarDecorationURL:", + replacement: { + match: /function \i\(\i\)\{(?=.{0,10}avatarDecoration)/, + replace: "$&return null;" + }, + predicate: () => settings.store.removeAvatarDecoration, + }, + { + // Nameplate + find: "#{intl::AVATAR_MALLOW}", + replacement: { + match: /function \i\(\i\)\{(?=.{0,25}skuId:)/, + replace: "$&return null;" + }, + predicate: () => settings.store.removeNameplate, + }, + { + // Profile banner animation effect + find: "bannerAdjustment,noBorderRadius", + replacement: { + match: /\i=\i=>\{(?=.{0,50}\.useReducedMotion\))/, + replace: "$&return null;" + }, + predicate: () => settings.store.removeProfileEffect, + }, + { + // Clan tag + find: ".GuildFeatures.GUILD_TAGS)", + replacement: { + match: /(?<=\.profile\?\.badge.{0,50}\i\)\{)/, + replace: "return false;" + }, + predicate: () => settings.store.removeClanTag, + }, + { + // Username styles and allways show username + find: ".NITRO_PRIVACY_PERK_BETA_COACHMARK));", + replacement: [ + { + match: /displayNameStyles:(\i),/, + replace: "displayNameStyles:void 0,", + predicate: () => settings.store.removeUsernameStyles + }, + { + match: /hoverText:(\i),forceHover:\i,children:/g, + replace: "hoverText:$1,forceHover:!0,children:", + predicate: () => settings.store.alwaysShowUsername + }, + ], + }, + { + // Button tooltips in user area + find: '"MicrophoneButton"', + replacement: [ + { + // Button tooltips + match: /:\{tooltipText:\i\};/, + replace: ":{tooltipText:void 0};", + predicate: () => settings.store.removeButtonTooltips + }, + { + // Audio menus + match: /(?<=#{intl::MUTE}\),)className:\i\.\i,/, + replace: "", + predicate: () => settings.store.removeAudioMenus + }, + { + // Audio menus + match: /,\(0,\i\.jsxs?\)\(\i\.\i,\{.{0,600}#{intl::ACCOUNT_INPUT_OPTIONS}\)\}\)(?=\])/, + replace: "", + predicate: () => settings.store.removeAudioMenus + }, + ], + }, + { + // Button tooltips in right click audio settings + find: "#{intl::f+DDY/::raw},{outputDeviceName", + replacement: [ + { + // Button tooltips + match: /(?<=role:"switch",)tooltipText:\i\}/, + replace: "tooltipText:void 0}", + predicate: () => settings.store.removeButtonTooltips + }, + { + // Audio menus + match: /(?<=#{intl::DEAFEN}\),)className:\i\.\i,/, + replace: "", + predicate: () => settings.store.removeAudioMenus + }, + { + // Audio menus + match: /,\(0,\i\.jsxs?\)\(\i\.\i,\{.{0,650}#{intl::ACCOUNT_OUTPUT_OPTIONS}\)\}\)(?=\])/, + replace: "", + predicate: () => settings.store.removeAudioMenus + } + ], + }, + { + // ? Another button tooltips + find: "#{intl::USER_SETTINGS_WITH_BUILD_OVERRIDE}", + replacement: { + match: /tooltipText:\i,tooltipPositionKey/, + replace: "tooltipText:void 0,tooltipPositionKey" + }, + predicate: () => settings.store.removeButtonTooltips + }, + { + // Above DMs section, shops and quests + find: 'tutorialId:"direct-messages"', + replacement: [ + { + match: /"nitro-tab-group"\)/, + replace: "$&&&undefined", + predicate: () => settings.store.removeShopAboveDM, + }, + { + match: /"discord-shop"\)/, + replace: "$&&&undefined", + predicate: () => settings.store.removeShopAboveDM + + }, + { + match: /"quests"\)/, + replace: "$&&&undefined", + predicate: () => settings.store.removeQuestsAboveDM + }, + ], + }, + { + // Above DMs section, keyboard navigation + find: ".hasLibraryApplication()&&!", + replacement: [ + { + match: /\i\.\i\.APPLICATION_STORE,/, + replace: "/*$&*/", + }, + { + match: /\i\.\i\.COLLECTIBLES_SHOP,/, + replace: "/*$&*/", + }, + ], + predicate: () => settings.store.removeShopAboveDM, + }, + { + // Channel list server boost progress bar + find: "useGuildActionRow", + replacement: { + match: /(GUILD_NEW_MEMBER_ACTIONS_PROGRESS_BAR\)):(\i(?:\.premiumProgressBarEnabled)?)/, + replace: "$1:null" + }, + predicate: () => settings.store.removeServerBoostInfo, + }, + { + // Billing settings + find: ".BILLING_SECTION,", + replacement: { + match: /(?<=buildLayout:\(\)=>)\[.+?\]/, + replace: "[]", + }, + predicate: () => settings.store.removeBillingSettings, + }, + { + // Gift button + find: '"sticker")', + replacement: { + match: /&&\i\.push\(\([^&]*?,"gift"\)\)/, + replace: "", + }, + predicate: () => settings.store.removeGiftButton, + }, + { + // Emoji list + find: "#{intl::EMOJI_PICKER_EXPAND_EMOJI_SECTION}),size:", + replacement: { + match: /(\i)=\i\|\|!\i&&\i.\i.isEmojiCategoryNitroLocked\(\{[^}]*\}\);/, + replace: "$&$1||" + }, + predicate: () => settings.store.removeUnavailableEmojiPicker, + }, + { + // Emoji category list + find: "#{intl::EMOJI_CATEGORY_TOP_GUILD_EMOJI},{guildName:", + replacement: { + match: /(?<=(\i)\.unshift\((\i)\):)(?=\1\.push\(\2\))/, + replace: "$2.isNitroLocked||" + }, + predicate: () => settings.store.removeUnavailableEmojiPicker, + } + ], +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 495f320a9..e0fef9853 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1260,6 +1260,10 @@ export const EquicordDevs = Object.freeze({ name: "yash", id: 889150838658977874n, }, + Leon135: { + name: "Leon135", + id: 309275452231385088n, + } } satisfies Record); // iife so #__PURE__ works correctly