From 65c5897dc364d716fb48e7e0d1964ce3730e121e Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 18 Sep 2024 01:26:25 +0200 Subject: [PATCH 01/24] remove need to depend on CommandsAPI --- src/components/PluginSettings/index.tsx | 4 ++-- src/plugins/_core/supportHelper.tsx | 2 +- src/plugins/friendInvites/index.ts | 1 - src/plugins/index.ts | 5 +++++ src/plugins/messageTags/index.ts | 1 - src/plugins/moreCommands/index.ts | 1 - src/plugins/moreKaomoji/index.ts | 1 - src/plugins/petpet/index.ts | 1 - src/plugins/silentTyping/index.tsx | 2 +- src/plugins/spotifyShareCommands/index.ts | 1 - src/utils/types.ts | 4 ++-- src/webpack/common/types/components.d.ts | 2 +- 12 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 38ddc4a9..c3b6e908 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -292,10 +292,10 @@ export default function PluginSettings() { if (!pluginFilter(p)) continue; - const isRequired = p.required || depMap[p.name]?.some(d => settings.plugins[d].enabled); + const isRequired = p.required || p.isDependency || depMap[p.name]?.some(d => settings.plugins[d].enabled); if (isRequired) { - const tooltipText = p.required + const tooltipText = p.required || !depMap[p.name] ? "This plugin is required for Vencord to function." : makeDependencyList(depMap[p.name]?.filter(d => settings.plugins[d].enabled)); diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index de8e37c7..432896fc 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -142,7 +142,7 @@ export default definePlugin({ required: true, description: "Helps us provide support to you", authors: [Devs.Ven], - dependencies: ["CommandsAPI", "UserSettingsAPI", "MessageAccessoriesAPI"], + dependencies: ["UserSettingsAPI", "MessageAccessoriesAPI"], settings, diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index 20c615d6..3c5a324f 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -27,7 +27,6 @@ export default definePlugin({ name: "FriendInvites", description: "Create and manage friend invite links via slash commands (/create friend invite, /view friend invites, /revoke friend invites).", authors: [Devs.afn, Devs.Dziurwa], - dependencies: ["CommandsAPI"], commands: [ { name: "create friend invite", diff --git a/src/plugins/index.ts b/src/plugins/index.ts index ac6821a6..129e42a0 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -105,6 +105,11 @@ for (const p of pluginsValues) if (isPluginEnabled(p.name)) { settings[d].enabled = true; dep.isDependency = true; }); + + if (p.commands?.length) { + Plugins.CommandsAPI.isDependency = true; + settings.CommandsAPI.enabled = true; + } } for (const p of pluginsValues) { diff --git a/src/plugins/messageTags/index.ts b/src/plugins/messageTags/index.ts index 66de9d66..5ba4ab94 100644 --- a/src/plugins/messageTags/index.ts +++ b/src/plugins/messageTags/index.ts @@ -82,7 +82,6 @@ export default definePlugin({ default: true } }, - dependencies: ["CommandsAPI"], async start() { for (const tag of await getTags()) createTagCommand(tag); diff --git a/src/plugins/moreCommands/index.ts b/src/plugins/moreCommands/index.ts index 61312acc..02f3c373 100644 --- a/src/plugins/moreCommands/index.ts +++ b/src/plugins/moreCommands/index.ts @@ -33,7 +33,6 @@ export default definePlugin({ name: "MoreCommands", description: "echo, lenny, mock", authors: [Devs.Arjix, Devs.echo, Devs.Samu], - dependencies: ["CommandsAPI"], commands: [ { name: "echo", diff --git a/src/plugins/moreKaomoji/index.ts b/src/plugins/moreKaomoji/index.ts index b5e33d96..9a691fc4 100644 --- a/src/plugins/moreKaomoji/index.ts +++ b/src/plugins/moreKaomoji/index.ts @@ -24,7 +24,6 @@ export default definePlugin({ name: "MoreKaomoji", description: "Adds more Kaomoji to discord. ヽ(´▽`)/", authors: [Devs.JacobTm], - dependencies: ["CommandsAPI"], commands: [ { name: "dissatisfaction", description: " >﹏<" }, { name: "smug", description: "ಠ_ಠ" }, diff --git a/src/plugins/petpet/index.ts b/src/plugins/petpet/index.ts index 2e06d0b1..708c6f0c 100644 --- a/src/plugins/petpet/index.ts +++ b/src/plugins/petpet/index.ts @@ -88,7 +88,6 @@ export default definePlugin({ name: "petpet", description: "Adds a /petpet slash command to create headpet gifs from any image", authors: [Devs.Ven], - dependencies: ["CommandsAPI"], commands: [ { inputType: ApplicationCommandInputType.BUILT_IN, diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index 2a6a6428..ad28999a 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -88,7 +88,7 @@ export default definePlugin({ name: "SilentTyping", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana], description: "Hide that you are typing", - dependencies: ["CommandsAPI", "ChatInputButtonAPI"], + dependencies: ["ChatInputButtonAPI"], settings, contextMenus: { "textarea-context": ChatBarContextCheckbox diff --git a/src/plugins/spotifyShareCommands/index.ts b/src/plugins/spotifyShareCommands/index.ts index a3b82dc2..8c485666 100644 --- a/src/plugins/spotifyShareCommands/index.ts +++ b/src/plugins/spotifyShareCommands/index.ts @@ -76,7 +76,6 @@ export default definePlugin({ name: "SpotifyShareCommands", description: "Share your current Spotify track, album or artist via slash command (/track, /album, /artist)", authors: [Devs.katlyn], - dependencies: ["CommandsAPI"], commands: [ { name: "track", diff --git a/src/utils/types.ts b/src/utils/types.ts index e5486e9a..dd3c1157 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -72,13 +72,13 @@ export interface PluginDef { stop?(): void; patches?: Omit[]; /** - * List of commands. If you specify these, you must add CommandsAPI to dependencies + * List of commands that your plugin wants to register */ commands?: Command[]; /** * A list of other plugins that your plugin depends on. * These will automatically be enabled and loaded before your plugin - * Common examples are CommandsAPI, MessageEventsAPI... + * Generally these will be API plugins */ dependencies?: string[], /** diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index 6c762333..e493e295 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -69,7 +69,7 @@ export type FormText = ComponentType & TextProps> & { Types: FormTextTypes; }; export type Tooltip = ComponentType<{ - text: ReactNode; + text: ReactNode | ComponentType; children: FunctionComponent<{ onClick(): void; onMouseEnter(): void; From 8afd79dd50ab461279e884f994b9732f3344b808 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 18 Sep 2024 01:36:52 +0200 Subject: [PATCH 02/24] add Icons to webpack commons --- src/webpack/common/components.ts | 3 +++ src/webpack/common/types/components.d.ts | 9 +++++++++ src/webpack/common/types/iconNames.d.ts | 14 ++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/webpack/common/types/iconNames.d.ts diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 8a2807ff..0bcb82d1 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -28,6 +28,8 @@ export let Forms = {} as { FormText: t.FormText, }; +export let Icons = {} as t.Icons; + export let Card: t.Card; export let Button: t.Button; export let Switch: t.Switch; @@ -85,4 +87,5 @@ waitFor(["FormItem", "Button"], m => { Heading } = m); Forms = m; + Icons = m; }); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index e493e295..260a763a 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -18,6 +18,8 @@ import type { ComponentType, CSSProperties, FunctionComponent, HtmlHTMLAttributes, HTMLProps, KeyboardEvent, MouseEvent, PropsWithChildren, PropsWithRef, ReactNode, Ref } from "react"; +import { IconNames } from "./iconNames"; + export type TextVariant = "heading-sm/normal" | "heading-sm/medium" | "heading-sm/semibold" | "heading-sm/bold" | "heading-md/normal" | "heading-md/medium" | "heading-md/semibold" | "heading-md/bold" | "heading-lg/normal" | "heading-lg/medium" | "heading-lg/semibold" | "heading-lg/bold" | "heading-xl/normal" | "heading-xl/medium" | "heading-xl/bold" | "heading-xxl/normal" | "heading-xxl/medium" | "heading-xxl/bold" | "eyebrow" | "heading-deprecated-14/normal" | "heading-deprecated-14/medium" | "heading-deprecated-14/bold" | "text-xxs/normal" | "text-xxs/medium" | "text-xxs/semibold" | "text-xxs/bold" | "text-xs/normal" | "text-xs/medium" | "text-xs/semibold" | "text-xs/bold" | "text-sm/normal" | "text-sm/medium" | "text-sm/semibold" | "text-sm/bold" | "text-md/normal" | "text-md/medium" | "text-md/semibold" | "text-md/bold" | "text-lg/normal" | "text-lg/medium" | "text-lg/semibold" | "text-lg/bold" | "display-sm" | "display-md" | "display-lg" | "code"; export type FormTextTypes = Record<"DEFAULT" | "INPUT_PLACEHOLDER" | "DESCRIPTION" | "LABEL_BOLD" | "LABEL_SELECTED" | "LABEL_DESCRIPTOR" | "ERROR" | "SUCCESS", string>; export type HeadingTag = `h${1 | 2 | 3 | 4 | 5 | 6}`; @@ -502,3 +504,10 @@ export type Avatar = ComponentType; }>>; + +export type Icon = ComponentType>; + +export type Icons = Record; diff --git a/src/webpack/common/types/iconNames.d.ts b/src/webpack/common/types/iconNames.d.ts new file mode 100644 index 00000000..f09b666b --- /dev/null +++ b/src/webpack/common/types/iconNames.d.ts @@ -0,0 +1,14 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { LiteralUnion } from "type-fest"; + +// copy(Object.keys(findByProps("EyeIcon")).filter(k => k.endsWith("Icon")).map(JSON.stringify).join("|")) + +export type IconNames = LiteralUnion< + "AIcon" | "AccessibilityIcon" | "AchievementsIcon" | "ActivitiesIcon" | "ActivitiesPlusIcon" | "AirplayIcon" | "AnalyticsIcon" | "AngleBracketsIcon" | "AnnouncementsChatIcon" | "AnnouncementsIcon" | "AnnouncementsLockIcon" | "AnnouncementsWarningIcon" | "AppleBrandLightIcon" | "AppleNeutralIcon" | "AppsIcon" | "ArrowAngleDownLeftIcon" | "ArrowAngleLeftDownIcon" | "ArrowAngleLeftUpIcon" | "ArrowAngleRightDownIcon" | "ArrowAngleRightUpIcon" | "ArrowAngleUpLeftIcon" | "ArrowLargeDownIcon" | "ArrowLargeLeftIcon" | "ArrowLargeRightIcon" | "ArrowLargeUpIcon" | "ArrowSmallDownIcon" | "ArrowSmallLeftIcon" | "ArrowSmallRightIcon" | "ArrowSmallUpIcon" | "ArrowsLeftRightIcon" | "ArrowsUpDownIcon" | "AsteriskIcon" | "AtIcon" | "AttachmentIcon" | "BIcon" | "BackspaceIcon" | "BadgeIcon" | "BeakerIcon" | "BellIcon" | "BellSlashIcon" | "BellZIcon" | "BicycleIcon" | "BillIcon" | "BluetoothIcon" | "BlurBackgroundIcon" | "BoldIcon" | "BookCheckIcon" | "BookmarkIcon" | "BookmarkOutlineIcon" | "BoostTier1Icon" | "BoostTier1SimpleIcon" | "BoostTier2Icon" | "BoostTier2SimpleIcon" | "BoostTier3Icon" | "BoostTier3SimpleIcon" | "BrowserCheckeredIcon" | "BrowserIcon" | "BrowserLinkIcon" | "BrowserPlusIcon" | "BrowserQuestionMarkIcon" | "BugIcon" | "CalendarIcon" | "CalendarMinusIcon" | "CalendarPlusIcon" | "CalendarRetryIcon" | "CalendarXIcon" | "CameraIcon" | "CameraSwapIcon" | "CarIcon" | "ChannelListIcon" | "ChannelListMagnifyingGlassIcon" | "ChannelListMinusIcon" | "ChannelListPlusIcon" | "ChannelListRetryIcon" | "ChannelNotificationIcon" | "ChannelsFollowedIcon" | "ChatArrowRightIcon" | "ChatCheckIcon" | "ChatDotsIcon" | "ChatEyeIcon" | "ChatIcon" | "ChatMarkUnreadIcon" | "ChatMinusIcon" | "ChatPlusIcon" | "ChatRetryIcon" | "ChatSlowModeIcon" | "ChatSmileIcon" | "ChatSpeakIcon" | "ChatWarningIcon" | "ChatXIcon" | "CheckmarkLargeBoldIcon" | "CheckmarkLargeIcon" | "CheckmarkSmallBoldIcon" | "CheckmarkSmallIcon" | "ChevronLargeDownIcon" | "ChevronLargeLeftIcon" | "ChevronLargeRightIcon" | "ChevronLargeUpIcon" | "ChevronSmallDownIcon" | "ChevronSmallLeftIcon" | "ChevronSmallRightIcon" | "ChevronSmallUpIcon" | "CircleCheckIcon" | "CircleInformationIcon" | "CircleMinusIcon" | "CirclePlayIcon" | "CirclePlusIcon" | "CircleQuestionIcon" | "CircleWarningIcon" | "CircleXIcon" | "ClipboardCheckIcon" | "ClipboardListIcon" | "ClipsGalleryIcon" | "ClipsIcon" | "ClockIcon" | "ClockWarningIcon" | "ClockXIcon" | "CloudDownloadIcon" | "ClydeIcon" | "CollapseListIcon" | "CompassIcon" | "ConnectionAverageIcon" | "ConnectionBadIcon" | "ConnectionFineIcon" | "ConnectionUnknownIcon" | "ContactsIcon" | "CopyIcon" | "CreditCardIcon" | "CropIcon" | "CrownIcon" | "CrunchyrollBrandLightIcon" | "CrunchyrollNeutralIcon" | "DenyIcon" | "DoorEnterIcon" | "DoorExitIcon" | "DoubleCheckmarkIcon" | "DownloadIcon" | "DpadIcon" | "DragIcon" | "EducationIcon" | "EmbedIcon" | "EnvelopeIcon" | "ExpandGifIcon" | "ExperimentalLootboxIcon" | "ExperimentalPineappleSpongebobIcon" | "EyeDropperIcon" | "EyeIcon" | "EyePlusIcon" | "EyeSlashIcon" | "FacebookNeutralIcon" | "FileDenyIcon" | "FileIcon" | "FileUpIcon" | "FileWarningIcon" | "FiltersHorizontalIcon" | "FireIcon" | "FlagIcon" | "FlagMinusIcon" | "FlagPlusIcon" | "FlagRetryIcon" | "FlashIcon" | "FlipHorizontalIcon" | "FlipVerticalIcon" | "FolderIcon" | "FolderPlusIcon" | "FoodIcon" | "ForumIcon" | "ForumLockIcon" | "ForumWarningIcon" | "FriendsIcon" | "FullscreenEnterIcon" | "FullscreenExitIcon" | "GameControllerIcon" | "GifIcon" | "GiftIcon" | "GlobeEarthIcon" | "GridHorizontalIcon" | "GridSquareIcon" | "GridVerticalIcon" | "GroupArrowDownIcon" | "GroupArrowRightIcon" | "GroupIcon" | "GroupMinusIcon" | "GroupPlusIcon" | "GroupRetryIcon" | "HammerIcon" | "HammerMinusIcon" | "HammerPlusIcon" | "HammerRetryIcon" | "HammerXIcon" | "HandRequestSpeakIcon" | "HandRequestSpeakListIcon" | "HashmarkIcon" | "HdIcon" | "HeadphonesDenyIcon" | "HeadphonesIcon" | "HeadphonesSlashIcon" | "HeartIcon" | "HeartOutlineIcon" | "HomeIcon" | "HomeSlashIcon" | "HourglassIcon" | "HubIcon" | "IdIcon" | "ImageFileIcon" | "ImageFileUpIcon" | "ImageIcon" | "ImageLockIcon" | "ImagePlusIcon" | "ImageSparkleIcon" | "ImageTextIcon" | "ImageWarningIcon" | "ImagesIcon" | "InboxIcon" | "InstagramNeutralIcon" | "InventoryIcon" | "ItalicIcon" | "KeyIcon" | "KeyboardIcon" | "LanguageIcon" | "LaptopPhoneIcon" | "LettersIcon" | "LightbulbIcon" | "LinkExternalMediumIcon" | "LinkExternalSmallIcon" | "LinkIcon" | "LinkPlusIcon" | "ListBulletsIcon" | "ListNumberedIcon" | "LocationIcon" | "LockIcon" | "LockUnlockedIcon" | "MagicWandIcon" | "MagnifyingGlassIcon" | "ManaIcon" | "MaximizeIcon" | "MedalIcon" | "MenuIcon" | "MicrophoneArrowRightIcon" | "MicrophoneDenyIcon" | "MicrophoneIcon" | "MicrophoneSlashIcon" | "MinimizeIcon" | "MinusIcon" | "MobilePhoneControllerIcon" | "MobilePhoneIcon" | "MobilePhonePlusIcon" | "MobilePhoneSettingsIcon" | "MobilePhoneShareIcon" | "MobilePhoneSpeakerIcon" | "MobilePhoneVideoIcon" | "MobilePhoneXIcon" | "ModerationIcon" | "MoreHorizontalIcon" | "MoreVerticalIcon" | "MusicIcon" | "MusicSlashIcon" | "NatureIcon" | "NearbyScanIcon" | "NewUserIcon" | "NewUserSimpleIcon" | "NintendoSwitchNeutralIcon" | "NitroWheelIcon" | "ObjectIcon" | "PaintPaletteIcon" | "PaintbrushThickIcon" | "PaintbrushThickMinusIcon" | "PaintbrushThickPlusIcon" | "PaintbrushThickRetryIcon" | "PaintbrushThinIcon" | "PaintbrushThinMinusIcon" | "PaintbrushThinPlusIcon" | "PaintbrushThinRetryIcon" | "PaperIcon" | "PaperPlusIcon" | "PauseIcon" | "PencilIcon" | "PencilSparkleIcon" | "PhoneCallIcon" | "PhoneHangUpIcon" | "PhoneIcon" | "PiggyBankIcon" | "PinIcon" | "PinUprightIcon" | "PinUprightSlashIcon" | "PlayIcon" | "PlaystationNeutralIcon" | "PlusLargeIcon" | "PlusMediumIcon" | "PlusSmallIcon" | "PollsIcon" | "PrivacyAndSafetyIcon" | "PuzzlePieceIcon" | "PuzzlePieceMinusIcon" | "PuzzlePiecePlusIcon" | "PuzzlePieceRetryIcon" | "QrCodeIcon" | "QuestsIcon" | "QuoteIcon" | "ReactionIcon" | "ReceiptIcon" | "RecordPlayerIcon" | "RedoIcon" | "RefreshIcon" | "RemixIcon" | "RetryIcon" | "RibbonIcon" | "RobotIcon" | "RotateIcon" | "ScienceIcon" | "ScreenArrowIcon" | "ScreenIcon" | "ScreenSlashIcon" | "ScreenStreamIcon" | "ScreenSystemRequirementsIcon" | "ScreenXIcon" | "SendMessageIcon" | "ServerGridIcon" | "ServerIcon" | "SettingsArrowUpIcon" | "SettingsCircleIcon" | "SettingsIcon" | "SettingsInfoIcon" | "SettingsPlusIcon" | "ShareIcon" | "ShieldAtIcon" | "ShieldIcon" | "ShieldLockIcon" | "ShieldUserIcon" | "ShopIcon" | "ShopMinusIcon" | "ShopPlusIcon" | "ShopSparkleIcon" | "SignPostIcon" | "SlashBoxIcon" | "SlashIcon" | "SlashMinusIcon" | "SlashPlusIcon" | "SlashRetryIcon" | "SoundboardIcon" | "SoundboardSlashIcon" | "SparklesIcon" | "SpeedometerIcon" | "SpoilerIcon" | "StaffBadgeIcon" | "StageIcon" | "StageListIcon" | "StageLockIcon" | "StageMinusIcon" | "StageModeratorIcon" | "StagePlusIcon" | "StageRetryIcon" | "StageXIcon" | "StampIcon" | "StarIcon" | "StarOutlineIcon" | "StarShootingIcon" | "StickerDeadIcon" | "StickerIcon" | "StickerMinusIcon" | "StickerPlusIcon" | "StickerRetryIcon" | "StickerSadIcon" | "StickerSmallIcon" | "StickerWink1Icon" | "StickerWink2Icon" | "StopIcon" | "StrikethroughIcon" | "SuperReactionIcon" | "TagIcon" | "TagsIcon" | "TextIcon" | "TextLockIcon" | "TextWarningIcon" | "ThemeDarkIcon" | "ThemeLightIcon" | "ThemeMidnightIcon" | "ThreadIcon" | "ThreadLockIcon" | "ThreadMinusIcon" | "ThreadPlusIcon" | "ThreadRetryIcon" | "ThreadWarningIcon" | "ThumbsDownIcon" | "ThumbsUpIcon" | "TicketIcon" | "TiktokNeutralIcon" | "TimerIcon" | "TopicsIcon" | "TrainIcon" | "TrashIcon" | "TreehouseIcon" | "TrophyIcon" | "TvIcon" | "TwitterNeutralIcon" | "UnderlineIcon" | "UndoIcon" | "UnknownGameIcon" | "UnsendIcon" | "UploadIcon" | "UserArrowDiagonalBottomRightIcon" | "UserCheckIcon" | "UserCircleIcon" | "UserCircleStatusIcon" | "UserClockIcon" | "UserIcon" | "UserMinusIcon" | "UserPlayIcon" | "UserPlusIcon" | "UserRetryIcon" | "UserSquareIcon" | "UserStatusIcon" | "VideoIcon" | "VideoLockIcon" | "VideoSlashIcon" | "VoiceBluetoothIcon" | "VoiceLockIcon" | "VoiceLowIcon" | "VoiceNormalIcon" | "VoiceWarningIcon" | "VoiceXIcon" | "WalletIcon" | "WarningIcon" | "WaveformIcon" | "WaveformSlashIcon" | "WebhookIcon" | "WebhookPlusIcon" | "WidgetsIcon" | "WidgetsMinusIcon" | "WidgetsPlusIcon" | "WidgetsRetryIcon" | "WindowLaunchIcon" | "WindowReturnIcon" | "WindowTopIcon" | "WindowTopOutlineIcon" | "WrenchIcon" | "XLargeBoldIcon" | "XLargeIcon" | "XNeutralIcon" | "XSmallBoldIcon" | "XSmallIcon" | "XboxNeutralIcon" | "YoutubeNeutralIcon", + string +>; From c7e5295da0aa7ebea2c2632552abd14187a8d3ad Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 18 Sep 2024 21:33:46 +0200 Subject: [PATCH 03/24] SearchReply => FullSearchContext ~ now adds all options back --- src/plugins/fullSearchContext/README.md | 5 ++ src/plugins/fullSearchContext/index.tsx | 82 +++++++++++++++++++++++++ src/plugins/searchReply/README.md | 6 -- src/plugins/searchReply/index.tsx | 75 ---------------------- 4 files changed, 87 insertions(+), 81 deletions(-) create mode 100644 src/plugins/fullSearchContext/README.md create mode 100644 src/plugins/fullSearchContext/index.tsx delete mode 100644 src/plugins/searchReply/README.md delete mode 100644 src/plugins/searchReply/index.tsx diff --git a/src/plugins/fullSearchContext/README.md b/src/plugins/fullSearchContext/README.md new file mode 100644 index 00000000..4bc5feb5 --- /dev/null +++ b/src/plugins/fullSearchContext/README.md @@ -0,0 +1,5 @@ +# FullSearchContext + +Makes the message context menu in message search results have all options you'd expect. + +![](https://github.com/user-attachments/assets/472d1327-3935-44c7-b7c4-0978b5348550) diff --git a/src/plugins/fullSearchContext/index.tsx b/src/plugins/fullSearchContext/index.tsx new file mode 100644 index 00000000..158612c6 --- /dev/null +++ b/src/plugins/fullSearchContext/index.tsx @@ -0,0 +1,82 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import { migratePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { findByPropsLazy } from "@webpack"; +import { ChannelStore, ContextMenuApi, i18n, UserStore } from "@webpack/common"; +import { Message } from "discord-types/general"; +import type { MouseEvent } from "react"; + +const { useMessageMenu } = findByPropsLazy("useMessageMenu"); + +function MessageMenu({ message, channel, onHeightUpdate }) { + const canReport = message.author && + !(message.author.id === UserStore.getCurrentUser().id || message.author.system); + + return useMessageMenu({ + navId: "message-actions", + ariaLabel: i18n.Messages.MESSAGE_UTILITIES_A11Y_LABEL, + + message, + channel, + canReport, + onHeightUpdate, + onClose: () => ContextMenuApi.closeContextMenu(), + + textSelection: "", + favoriteableType: null, + favoriteableId: null, + favoriteableName: null, + itemHref: void 0, + itemSrc: void 0, + itemSafeSrc: void 0, + itemTextContent: void 0, + }); +} + +migratePluginSettings("FullSearchContext", "SearchReply"); +export default definePlugin({ + name: "FullSearchContext", + description: "Makes the message context menu in message search results have all options you'd expect", + authors: [Devs.Ven, Devs.Aria], + + patches: [{ + find: "onClick:this.handleMessageClick,", + replacement: { + match: /this(?=\.handleContextMenu\(\i,\i\))/, + replace: "$self" + } + }], + + handleContextMenu(event: MouseEvent, message: Message) { + const channel = ChannelStore.getChannel(message.channel_id); + if (!channel) return; + + event.stopPropagation(); + + ContextMenuApi.openContextMenu(event, contextMenuProps => + + ); + } +}); diff --git a/src/plugins/searchReply/README.md b/src/plugins/searchReply/README.md deleted file mode 100644 index b06798f7..00000000 --- a/src/plugins/searchReply/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# SearchReply - -Adds a reply button to search results. - -![the plugin in action](https://github.com/Vendicated/Vencord/assets/45497981/07e741d3-0f97-4e5c-82b0-80712ecf2cbb) - diff --git a/src/plugins/searchReply/index.tsx b/src/plugins/searchReply/index.tsx deleted file mode 100644 index 298e7421..00000000 --- a/src/plugins/searchReply/index.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; -import { ReplyIcon } from "@components/Icons"; -import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; -import { findByCodeLazy } from "@webpack"; -import { ChannelStore, i18n, Menu, PermissionsBits, PermissionStore, SelectedChannelStore } from "@webpack/common"; -import { Message } from "discord-types/general"; - - -const replyToMessage = findByCodeLazy(".TEXTAREA_FOCUS)", "showMentionToggle:"); - -const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => { - // make sure the message is in the selected channel - if (SelectedChannelStore.getChannelId() !== message.channel_id) return; - const channel = ChannelStore.getChannel(message?.channel_id); - if (!channel) return; - if (channel.guild_id && !PermissionStore.can(PermissionsBits.SEND_MESSAGES, channel)) return; - - // dms and group chats - const dmGroup = findGroupChildrenByChildId("pin", children); - if (dmGroup && !dmGroup.some(child => child?.props?.id === "reply")) { - const pinIndex = dmGroup.findIndex(c => c?.props.id === "pin"); - dmGroup.splice(pinIndex + 1, 0, ( - replyToMessage(channel, message, e)} - /> - )); - return; - } - - // servers - const serverGroup = findGroupChildrenByChildId("mark-unread", children); - if (serverGroup && !serverGroup.some(child => child?.props?.id === "reply")) { - serverGroup.unshift(( - replyToMessage(channel, message, e)} - /> - )); - return; - } -}; - - -export default definePlugin({ - name: "SearchReply", - description: "Adds a reply button to search results", - authors: [Devs.Aria], - contextMenus: { - "message": messageContextMenuPatch - } -}); From a015cf96f6413c718f1acfa5c4c27a2cd4b9f594 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 19 Sep 2024 05:25:31 -0300 Subject: [PATCH 04/24] UserVoiceShow: Fix setting name --- src/plugins/userVoiceShow/components.tsx | 41 +++++++++++------------- src/plugins/userVoiceShow/index.tsx | 6 ++-- src/plugins/userVoiceShow/style.css | 10 ++++-- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index fd7dbd29..095785dd 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -8,7 +8,7 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildStore, IconUtils, NavigationRouter, PermissionsBits, PermissionStore, showToast, Text, Toasts, Tooltip, useCallback, useMemo, UserStore, useStateFromStores } from "@webpack/common"; +import { ChannelStore, GuildStore, IconUtils, NavigationRouter, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; import { Channel } from "discord-types/general"; const cl = classNameFactory("vc-uvs-"); @@ -17,7 +17,7 @@ const { selectVoiceChannel } = findByPropsLazy("selectChannel", "selectVoiceChan const VoiceStateStore = findStoreLazy("VoiceStateStore"); const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -interface IconProps extends React.HTMLAttributes { +interface IconProps extends React.ComponentPropsWithoutRef<"div"> { size?: number; } @@ -71,23 +71,18 @@ interface VoiceChannelTooltipProps { function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { const voiceStates = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStatesForChannel(channel.id)); + const users = useMemo( () => Object.values(voiceStates).map(voiceState => UserStore.getUser(voiceState.userId)).filter(user => user != null), [voiceStates] ); - const guild = useMemo( - () => channel.getGuildId() == null ? undefined : GuildStore.getGuild(channel.getGuildId()), - [channel] - ); - - const guildIcon = useMemo(() => { - return guild?.icon == null ? undefined : IconUtils.getGuildIconURL({ - id: guild.id, - icon: guild.icon, - size: 30 - }); - }, [guild]); + const guild = channel.getGuildId() == null ? undefined : GuildStore.getGuild(channel.getGuildId()); + const guildIcon = guild?.icon == null ? undefined : IconUtils.getGuildIconURL({ + id: guild.id, + icon: guild.icon, + size: 30 + }); return ( <> @@ -103,7 +98,7 @@ function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { @@ -119,11 +114,14 @@ const clickTimers = {} as Record; export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); - const channel = useMemo(() => channelId == null ? undefined : ChannelStore.getChannel(channelId), [channelId]); - const onClick = useCallback((e: React.MouseEvent) => { + const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); + if (channel == null) return null; + + function onClick(e: React.MouseEvent) { e.preventDefault(); e.stopPropagation(); + if (channel == null || channelId == null) return; if (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) { @@ -147,18 +145,15 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChanne delete clickTimers[channelId]; }, 250); } - }, [channelId]); + } - const isLocked = useMemo(() => { - return !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel); - }, [channelId]); - - if (channel == null) return null; + const isLocked = !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel); return ( } tooltipClassName={cl("tooltip-container")} + tooltipContentClassName={cl("tooltip-content")} > {props => isLocked ? diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index dee713b5..5efd936c 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -32,7 +32,7 @@ const settings = definePluginSettings({ default: true, restartNeeded: true }, - showInVoiceMemberList: { + showInMemberList: { type: OptionType.BOOLEAN, description: "Show a user's Voice Channel indicator in the member and DMs list", default: true, @@ -82,12 +82,12 @@ export default definePlugin({ match: /\.subtext,children:.+?}\)\]}\)(?=])/, replace: "$&,$self.VoiceChannelIndicator({userId:arguments[0]?.user?.id})" }, - predicate: () => settings.store.showInVoiceMemberList + predicate: () => settings.store.showInMemberList } ], start() { - if (settings.store.showInVoiceMemberList) { + if (settings.store.showInMemberList) { addDecorator("UserVoiceShow", ({ user }) => user == null ? null : ); } }, diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index b4cc0063..3e36df21 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -15,7 +15,13 @@ } .vc-uvs-tooltip-container { - max-width: 200px; + max-width: 300px; +} + +.vc-uvs-tooltip-content { + display: flex; + flex-direction: column; + gap: 6px; } .vc-uvs-guild-name { @@ -31,7 +37,5 @@ .vc-uvs-vc-members { display: flex; - margin: 8px 0; - flex-direction: row; gap: 6px; } From 755e869db7d4615f51ff2d2de8d104b2024d7760 Mon Sep 17 00:00:00 2001 From: adryd Date: Thu, 19 Sep 2024 19:31:20 -0400 Subject: [PATCH 05/24] clearURLs: Add si@soundcloud.com to rule list (#2890) --- src/plugins/clearURLs/defaultRules.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/clearURLs/defaultRules.ts b/src/plugins/clearURLs/defaultRules.ts index b5aae5ff..e4e7d380 100644 --- a/src/plugins/clearURLs/defaultRules.ts +++ b/src/plugins/clearURLs/defaultRules.ts @@ -155,4 +155,5 @@ export const defaultRules = [ "igshid", "igsh", "share_id@reddit.com", + "si@soundcloud.com", ]; From f7587d9b2eb12ddb0e0a0020d69f26a105335cf6 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 20 Sep 2024 02:03:42 +0200 Subject: [PATCH 06/24] ShowHiddenThings: fix discovery keyword filter bypass --- src/plugins/showHiddenThings/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 9ffaa7e1..847dcd32 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -112,12 +112,12 @@ export default definePlugin({ }, // patch request that queries if term is allowed { - find: ".GUILD_DISCOVERY_VALID_TERM", + find: ".GUILD_DISCOVERY_VALID_TERM,query:", predicate: () => settings.store.disableDisallowedDiscoveryFilters, all: true, replacement: { - match: /\i\.\i\.get\(\{url:\i\.\i\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\);/g, - replace: "Promise.resolve({ body: { valid: true } });" + match: /\i\.\i\.get\(\{url:\i\.\i\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\)/g, + replace: "Promise.resolve({ body: { valid: true } })" } } ], From e8242f22c998ffdc50fa9e663c40c3da4d7fc4d8 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:06:26 -0300 Subject: [PATCH 07/24] UserVoiceShow: Better support for DM channels --- src/plugins/userVoiceShow/components.tsx | 63 +++++++++++++++++------- src/plugins/userVoiceShow/index.tsx | 6 +-- src/plugins/userVoiceShow/style.css | 15 +++++- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index 095785dd..fad860df 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -7,15 +7,22 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; -import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildStore, IconUtils, NavigationRouter, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; +import { filters, findByCodeLazy, findByPropsLazy, findComponentByCodeLazy, findStoreLazy, mapMangledModuleLazy } from "@webpack"; +import { ChannelStore, GuildStore, IconUtils, match, NavigationRouter, P, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; import { Channel } from "discord-types/general"; const cl = classNameFactory("vc-uvs-"); -const { selectVoiceChannel } = findByPropsLazy("selectChannel", "selectVoiceChannel"); +const { selectVoiceChannel } = findByPropsLazy("selectVoiceChannel", "selectChannel"); +const { useChannelName } = mapMangledModuleLazy(".Messages.GROUP_DM_ALONE", { + useChannelName: filters.byCode("()=>null==") +}); +const getDMChannelIcon = findByCodeLazy(".getChannelIconURL({"); const VoiceStateStore = findStoreLazy("VoiceStateStore"); + const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const Avatar = findComponentByCodeLazy(".AVATAR_STATUS_TYPING_16;"); +const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL"); interface IconProps extends React.ComponentPropsWithoutRef<"div"> { size?: number; @@ -28,7 +35,7 @@ function SpeakerIcon(props: IconProps) {
{ + return channel.recipients.length >= 2 && channel.icon == null + ? + : ; + }) + .otherwise(() => null); + const channelName = useChannelName(channel); + return ( <> {guild != null && ( -
+
{guildIcon != null && } {guild.name}
)} - {channel.name} +
+ {channelIcon} + {channelName} +
; -export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChannelIndicatorProps) => { +export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActionButton }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); if (channel == null) return null; + const isDM = channel.isDM() || channel.isMultiUserDM(); + const isLocked = !isDM && (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel)); + function onClick(e: React.MouseEvent) { e.preventDefault(); e.stopPropagation(); if (channel == null || channelId == null) return; - if (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) { + if (!isDM && !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) { showToast("You cannot view the user's Voice Channel", Toasts.Type.FAILURE); return; } @@ -133,7 +157,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChanne delete clickTimers[channelId]; if (e.detail > 1) { - if (!PermissionStore.can(PermissionsBits.CONNECT, channel)) { + if (!isDM && !PermissionStore.can(PermissionsBits.CONNECT, channel)) { showToast("You cannot join the user's Voice Channel", Toasts.Type.FAILURE); return; } @@ -147,19 +171,24 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChanne } } - const isLocked = !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel); - return ( } tooltipClassName={cl("tooltip-container")} tooltipContentClassName={cl("tooltip-content")} > - {props => - isLocked ? - - : - } + {props => { + const iconProps = { + ...props, + onClick, + size, + className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding") + }; + + return isLocked ? + + : ; + }} ); }, { noop: true }); diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 5efd936c..573fd0e3 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -77,10 +77,10 @@ export default definePlugin({ }, */ // Friends List { - find: ".avatar,animate:", + find: "null!=this.peopleListItemRef.current", replacement: { - match: /\.subtext,children:.+?}\)\]}\)(?=])/, - replace: "$&,$self.VoiceChannelIndicator({userId:arguments[0]?.user?.id})" + match: /\.actions,children:\[/, + replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,size:20,isActionButton:true})," }, predicate: () => settings.store.showInMemberList } diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index 3e36df21..67f4c495 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -1,6 +1,5 @@ .vc-uvs-speaker { color: var(--interactive-normal); - padding: 0 4px; display: flex; align-items: center; justify-content: center; @@ -14,6 +13,18 @@ color: var(--interactive-hover); } +.vc-uvs-speaker-padding { + padding: 0 4px; +} + +.vc-uvs-indicator-action-button { + background-color: var(--background-secondary); + border-radius: 100%; + height: 36px; + width: 36px; + margin-left: 10px; +} + .vc-uvs-tooltip-container { max-width: 300px; } @@ -24,7 +35,7 @@ gap: 6px; } -.vc-uvs-guild-name { +.vc-uvs-name { display: flex; align-items: center; gap: 8px; From 467157539c65d00b66bbd8d5cdc477d6951d6642 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:16:16 -0300 Subject: [PATCH 08/24] Bump to 1.10.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e65e1b0a..88633f65 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.10.1", + "version": "1.10.2", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 49b0a38c37c58856048958666c133e99035656a8 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:42:00 -0300 Subject: [PATCH 09/24] UserVoiceShow: Show in messages --- src/plugins/crashHandler/index.ts | 2 +- src/plugins/keepCurrentChannel/index.ts | 14 +++++------- src/plugins/userVoiceShow/components.tsx | 27 ++++++++++++++---------- src/plugins/userVoiceShow/index.tsx | 19 +++++++++++++---- src/plugins/userVoiceShow/style.css | 14 ++++++------ src/webpack/common/types/utils.d.ts | 7 +++++- src/webpack/common/utils.ts | 4 ++++ 7 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index ab881e60..221b115f 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -175,7 +175,7 @@ export default definePlugin({ } if (settings.store.attemptToNavigateToHome) { try { - NavigationRouter.transitionTo("/channels/@me"); + NavigationRouter.transitionToGuild("@me"); } catch (err) { CrashHandlerLogger.debug("Failed to navigate to home", err); } diff --git a/src/plugins/keepCurrentChannel/index.ts b/src/plugins/keepCurrentChannel/index.ts index b226c34e..1e0e742d 100644 --- a/src/plugins/keepCurrentChannel/index.ts +++ b/src/plugins/keepCurrentChannel/index.ts @@ -19,7 +19,7 @@ import * as DataStore from "@api/DataStore"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { ChannelStore, NavigationRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common"; +import { ChannelRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common"; export interface LogoutEvent { type: "LOGOUT"; @@ -40,11 +40,6 @@ interface PreviousChannel { let isSwitchingAccount = false; let previousCache: PreviousChannel | undefined; -function attemptToNavigateToChannel(guildId: string | null, channelId: string) { - if (!ChannelStore.hasChannel(channelId)) return; - NavigationRouter.transitionTo(`/channels/${guildId ?? "@me"}/${channelId}`); -} - export default definePlugin({ name: "KeepCurrentChannel", description: "Attempt to navigate to the channel you were in before switching accounts or loading Discord.", @@ -59,8 +54,9 @@ export default definePlugin({ if (!isSwitchingAccount) return; isSwitchingAccount = false; - if (previousCache?.channelId) - attemptToNavigateToChannel(previousCache.guildId, previousCache.channelId); + if (previousCache?.channelId) { + ChannelRouter.transitionToChannel(previousCache.channelId); + } }, async CHANNEL_SELECT({ guildId, channelId }: ChannelSelectEvent) { @@ -84,7 +80,7 @@ export default definePlugin({ await DataStore.set("KeepCurrentChannel_previousData", previousCache); } else if (previousCache.channelId) { - attemptToNavigateToChannel(previousCache.guildId, previousCache.channelId); + ChannelRouter.transitionToChannel(previousCache.channelId); } } }); diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index fad860df..f9a81c4b 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -8,7 +8,7 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; import { filters, findByCodeLazy, findByPropsLazy, findComponentByCodeLazy, findStoreLazy, mapMangledModuleLazy } from "@webpack"; -import { ChannelStore, GuildStore, IconUtils, match, NavigationRouter, P, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; +import { ChannelRouter, ChannelStore, GuildStore, IconUtils, match, P, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; import { Channel } from "discord-types/general"; const cl = classNameFactory("vc-uvs-"); @@ -24,6 +24,8 @@ const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaul const Avatar = findComponentByCodeLazy(".AVATAR_STATUS_TYPING_16;"); const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL"); +const ActionButtonClasses = findByPropsLazy("actionButton", "highlight"); + interface IconProps extends React.ComponentPropsWithoutRef<"div"> { size?: number; } @@ -74,9 +76,10 @@ function LockedSpeakerIcon(props: IconProps) { interface VoiceChannelTooltipProps { channel: Channel; + isLocked: boolean; } -function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { +function VoiceChannelTooltip({ channel, isLocked }: VoiceChannelTooltipProps) { const voiceStates = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStatesForChannel(channel.id)); const users = useMemo( @@ -113,7 +116,7 @@ function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { {channelName}
- + {isLocked ? : } ; -export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActionButton }: VoiceChannelIndicatorProps) => { +export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndicator, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); @@ -165,7 +170,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio selectVoiceChannel(channelId); } else { clickTimers[channelId] = setTimeout(() => { - NavigationRouter.transitionTo(`/channels/${channel.getGuildId() ?? "@me"}/${channelId}`); + ChannelRouter.transitionToChannel(channelId); delete clickTimers[channelId]; }, 250); } @@ -173,16 +178,16 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio return ( } + text={} tooltipClassName={cl("tooltip-container")} tooltipContentClassName={cl("tooltip-content")} > {props => { - const iconProps = { + const iconProps: IconProps = { ...props, - onClick, - size, - className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding") + className: classes(isMessageIndicator && cl("message-indicator"), (!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight), + size: isActionButton ? 20 : undefined, + onClick }; return isLocked ? diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 573fd0e3..98386a16 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -19,6 +19,7 @@ import "./style.css"; import { addDecorator, removeDecorator } from "@api/MemberListDecorators"; +import { addDecoration, removeDecoration } from "@api/MessageDecorations"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -37,13 +38,19 @@ const settings = definePluginSettings({ description: "Show a user's Voice Channel indicator in the member and DMs list", default: true, restartNeeded: true + }, + showInMessages: { + type: OptionType.BOOLEAN, + description: "Show a user's Voice Channel indicator in messages", + default: true, + restartNeeded: true } }); export default definePlugin({ name: "UserVoiceShow", description: "Shows an indicator when a user is in a Voice Channel", - authors: [Devs.LordElias, Devs.Nuckyz], + authors: [Devs.Nuckyz, Devs.LordElias], settings, patches: [ @@ -52,7 +59,7 @@ export default definePlugin({ find: ".Messages.USER_PROFILE_LOAD_ERROR", replacement: { match: /(\.fetchError.+?\?)null/, - replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId})` + replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId,isProfile:true})` }, predicate: () => settings.store.showInUserProfileModal }, @@ -79,8 +86,8 @@ export default definePlugin({ { find: "null!=this.peopleListItemRef.current", replacement: { - match: /\.actions,children:\[/, - replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,size:20,isActionButton:true})," + match: /\.actions,children:\[(?<=isFocused:(\i).+?)/, + replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true,shouldHighlight:$1})," }, predicate: () => settings.store.showInMemberList } @@ -90,10 +97,14 @@ export default definePlugin({ if (settings.store.showInMemberList) { addDecorator("UserVoiceShow", ({ user }) => user == null ? null : ); } + if (settings.store.showInMessages) { + addDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : ); + } }, stop() { removeDecorator("UserVoiceShow"); + removeDecoration("UserVoiceShow"); }, VoiceChannelIndicator diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index 67f4c495..d172975b 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -13,16 +13,14 @@ color: var(--interactive-hover); } -.vc-uvs-speaker-padding { - padding: 0 4px; +.vc-uvs-speaker-margin { + margin-left: 4px; } -.vc-uvs-indicator-action-button { - background-color: var(--background-secondary); - border-radius: 100%; - height: 36px; - width: 36px; - margin-left: 10px; +.vc-uvs-message-indicator { + display: inline-flex; + top: 2.5px; + position: relative; } .vc-uvs-tooltip-container { diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts index dd76d1ad..c0a93004 100644 --- a/src/webpack/common/types/utils.d.ts +++ b/src/webpack/common/types/utils.d.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Guild, GuildMember, User } from "discord-types/general"; +import { Channel, Guild, GuildMember, User } from "discord-types/general"; import type { ReactNode } from "react"; import { LiteralUnion } from "type-fest"; @@ -173,6 +173,11 @@ export interface NavigationRouter { transitionToGuild(guildId: string, ...args: unknown[]): void; } +export interface ChannelRouter { + transitionToChannel: (channelId: string) => void; + transitionToThread: (channel: Channel) => void; +} + export interface IconUtils { getUserAvatarURL(user: User, canAnimate?: boolean, size?: number, format?: string): string; getDefaultAvatarURL(id: string, discriminator?: string): string; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index b557f4da..2d0026b5 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -149,6 +149,10 @@ export const NavigationRouter: t.NavigationRouter = mapMangledModuleLazy("Transi back: filters.byCode("goBack()"), forward: filters.byCode("goForward()"), }); +export const ChannelRouter: t.ChannelRouter = mapMangledModuleLazy('"Thread must have a parent ID."', { + transitionToChannel: filters.byCode(".preload"), + transitionToThread: filters.byCode('"Thread must have a parent ID."') +}); export let SettingsRouter: any; waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); From 2d675b4b2e4c797315aff657298de96d07e4bbf1 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 21 Sep 2024 08:43:13 -0300 Subject: [PATCH 10/24] ReviewDB: Fix in panel profile (again) --- src/plugins/reviewDB/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index 9d93e53a..822ebde6 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -91,7 +91,7 @@ export default definePlugin({ } }, { - find: ".PANEL,interactionType:", + find: 'location:"UserProfilePanel"', replacement: { match: /{profileType:\i\.\i\.PANEL,children:\[/, replace: "$&$self.BiteSizeReviewsButton({user:arguments[0].user})," From 492b0cff0888452096d5c2ba45258e769f4f4ff1 Mon Sep 17 00:00:00 2001 From: Joona <69722179+Masterjoona@users.noreply.github.com> Date: Sat, 21 Sep 2024 18:22:19 +0300 Subject: [PATCH 11/24] OpenInApp: Fix opening in spotify activity cards for web (#2894) --- src/plugins/openInApp/index.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 7b62831f..576980cb 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -100,6 +100,20 @@ export default definePlugin({ replace: "true$1VencordNative.native.openExternal" } }, + { + find: "no artist ids in metadata", + predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify, + replacement: [ + { + match: /\i\.\i\.isProtocolRegistered\(\)/g, + replace: "true" + }, + { + match: /!\(0,\i\.isDesktop\)\(\)/, + replace: "false" + } + ] + }, { find: ".CONNECTED_ACCOUNT_VIEWED,", replacement: { From 1dc2d924932f29ccf7422ac51eb0fac90490634f Mon Sep 17 00:00:00 2001 From: Drew <84212701+MrDiamondDog@users.noreply.github.com> Date: Sat, 21 Sep 2024 13:10:46 -0600 Subject: [PATCH 12/24] ReplaceGoogleSearch: Fix DuckDuckGo URL (#2895) --- src/plugins/replaceGoogleSearch/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/replaceGoogleSearch/index.tsx b/src/plugins/replaceGoogleSearch/index.tsx index 43b0762a..593c9863 100644 --- a/src/plugins/replaceGoogleSearch/index.tsx +++ b/src/plugins/replaceGoogleSearch/index.tsx @@ -12,7 +12,7 @@ import { Flex, Menu } from "@webpack/common"; const DefaultEngines = { Google: "https://www.google.com/search?q=", - DuckDuckGo: "https://duckduckgo.com/", + DuckDuckGo: "https://duckduckgo.com/?q=", Brave: "https://search.brave.com/search?q=", Bing: "https://www.bing.com/search?q=", Yahoo: "https://search.yahoo.com/search?p=", From 22a5b18bfa0b736acc1a0393fe1ad3a82f828dc1 Mon Sep 17 00:00:00 2001 From: DokterKaj <54882101+DokterKaj@users.noreply.github.com> Date: Sun, 22 Sep 2024 03:12:20 +0800 Subject: [PATCH 13/24] CopyFileContents: Add padding to button (#2848) --- src/plugins/copyFileContents/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/copyFileContents/style.css b/src/plugins/copyFileContents/style.css index c643cf0f..91034bf2 100644 --- a/src/plugins/copyFileContents/style.css +++ b/src/plugins/copyFileContents/style.css @@ -1,6 +1,7 @@ .vc-cfc-button { color: var(--interactive-normal); cursor: pointer; + padding-left: 4px; } .vc-cfc-button:hover { From eaf62d8c1cd8ea7997e6efde04317e5b4700afbe Mon Sep 17 00:00:00 2001 From: Kyuuhachi <1547062+Kyuuhachi@users.noreply.github.com> Date: Sun, 22 Sep 2024 09:11:07 +0200 Subject: [PATCH 14/24] RoleColorEverywhere: Add coloring to message contents (#2893) --- src/plugins/roleColorEverywhere/index.tsx | 40 ++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index b5f66c09..e3b22fd6 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -18,10 +18,14 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; +import { makeRange } from "@components/PluginSettings/components"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; +import { findByCodeLazy } from "@webpack"; import { ChannelStore, GuildMemberStore, GuildStore } from "@webpack/common"; +const useMessageAuthor = findByCodeLazy('"Result cannot be null because the message is not null"'); + const settings = definePluginSettings({ chatMentions: { type: OptionType.BOOLEAN, @@ -46,13 +50,21 @@ const settings = definePluginSettings({ default: true, description: "Show role colors in the reactors list", restartNeeded: true - } + }, + messageSaturation: { + type: OptionType.SLIDER, + description: "Intensity of message coloring. 0 to disable.", + markers: makeRange(0, 100, 10), + default: 30, + // This is called only once at startup, but late enough that the store is initialized. + get restartNeeded() { return settings.store.messageSaturation === 0; } + }, }); export default definePlugin({ name: "RoleColorEverywhere", - authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN], + authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi], description: "Adds the top role color anywhere possible", patches: [ // Chat Mentions @@ -114,7 +126,15 @@ export default definePlugin({ replace: "$&,style:{color:$self.getColor($2?.id,$1)}" }, predicate: () => settings.store.reactorsList, - } + }, + { + find: '.Messages.MESSAGE_EDITED,")"', + replacement: { + match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/, + replace: "style:{color:$self.useMessageColor($1)}," + }, + predicate: () => settings.store.messageSaturation !== 0, + }, ], settings, @@ -148,5 +168,17 @@ export default definePlugin({ color: this.getColor(userId, { guildId }) } }; - } + }, + + useMessageColor(message: any) { + try { + const { messageSaturation } = settings.use(["messageSaturation"]); + const author = useMessageAuthor(message); + if (author.colorString !== undefined && messageSaturation !== 0) + return `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var(--text-normal))`; + } catch(e) { + console.error("[RCE] failed to get message color", e); + } + return undefined; + }, }); From e4318a887a70c9bf70888c55bec09e33efb2351d Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Sun, 22 Sep 2024 03:24:12 -0400 Subject: [PATCH 15/24] ConsoleJanitor: Ignore all loggers with whitelist (#2896) --- src/plugins/consoleJanitor/README.md | 4 +- src/plugins/consoleJanitor/index.ts | 61 ++++++++++++++-------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/plugins/consoleJanitor/README.md b/src/plugins/consoleJanitor/README.md index fbba766a..9737f53d 100644 --- a/src/plugins/consoleJanitor/README.md +++ b/src/plugins/consoleJanitor/README.md @@ -1,5 +1,5 @@ # ConsoleJanitor -Disables annoying console messages/errors. This plugin mainly removes errors/warnings that happen all the time and noisy/spammy logging messages. +Disables annoying console messages/errors. This plugin mainly removes errors/warnings that happen all the time and Discord logger messages. -Some of the disabled messages include the "notosans-400-normalitalic" error and MessageActionCreators, Routing/Utils loggers. +One of the disabled messages is the "Window state not initialized" warning, for example. diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts index f5f43c06..b0c8905f 100644 --- a/src/plugins/consoleJanitor/index.ts +++ b/src/plugins/consoleJanitor/index.ts @@ -6,7 +6,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; +import definePlugin, { OptionType, StartAt } from "@utils/types"; const Noop = () => { }; const NoopLogger = { @@ -22,10 +22,12 @@ const NoopLogger = { fileOnly: Noop }; +const logAllow = new Set(); + const settings = definePluginSettings({ - disableNoisyLoggers: { + disableLoggers: { type: OptionType.BOOLEAN, - description: "Disable noisy loggers like the MessageActionCreators", + description: "Disables Discords loggers", default: false, restartNeeded: true }, @@ -34,16 +36,34 @@ const settings = definePluginSettings({ description: "Disable the Spotify logger, which leaks account information and access token", default: true, restartNeeded: true + }, + whitelistedLoggers: { + type: OptionType.STRING, + description: "Semi colon separated list of loggers to allow even if others are hidden", + default: "GatewaySocket; Routing/Utils", + onChange(newVal: string) { + logAllow.clear(); + newVal.split(";").map(x => x.trim()).forEach(logAllow.add.bind(logAllow)); + } } }); export default definePlugin({ name: "ConsoleJanitor", description: "Disables annoying console messages/errors", - authors: [Devs.Nuckyz], + authors: [Devs.Nuckyz, Devs.sadan], settings, + startAt: StartAt.Init, + start() { + logAllow.clear(); + this.settings.store.whitelistedLoggers?.split(";").map(x => x.trim()).forEach(logAllow.add.bind(logAllow)); + }, + NoopLogger: () => NoopLogger, + shouldLog(logger: string) { + return logAllow.has(logger); + }, patches: [ { @@ -103,34 +123,13 @@ export default definePlugin({ replace: "" } }, - ...[ - '("MessageActionCreators")', '("ChannelMessages")', - '("Routing/Utils")', '("RTCControlSocket")', - '("ConnectionEventFramerateReducer")', '("RTCLatencyTestManager")', - '("OverlayBridgeStore")', '("RPCServer:WSS")', '("RPCServer:IPC")' - ].map(logger => ({ - find: logger, - predicate: () => settings.store.disableNoisyLoggers, - all: true, - replacement: { - match: new RegExp(String.raw`new \i\.\i${logger.replace(/([()])/g, "\\$1")}`), - replace: `$self.NoopLogger${logger}` - } - })), + // Patches discords generic logger function { - find: '"Experimental codecs: "', - predicate: () => settings.store.disableNoisyLoggers, + find: "Σ:", + predicate: () => settings.store.disableLoggers, replacement: { - match: /new \i\.\i\("Connection\("\.concat\(\i,"\)"\)\)/, - replace: "$self.NoopLogger()" - } - }, - { - find: '"_handleLocalVideoDisabled: ', - predicate: () => settings.store.disableNoisyLoggers, - replacement: { - match: /new \i\.\i\("RTCConnection\("\.concat.+?\)\)(?=,)/, - replace: "$self.NoopLogger()" + match: /(?<=&&)(?=console)/, + replace: "$self.shouldLog(arguments[0])&&" } }, { @@ -141,5 +140,5 @@ export default definePlugin({ replace: "$self.NoopLogger()" } } - ] + ], }); From db5fe2a39472275d2422035d3c55cb6f8cf15538 Mon Sep 17 00:00:00 2001 From: TheGreenPig <67547385+TheGreenPig@users.noreply.github.com> Date: Sun, 22 Sep 2024 09:38:32 +0200 Subject: [PATCH 16/24] Fix plugin settings inconsistency regarding setting names (#2884) --- .../PluginSettings/components/SettingNumericComponent.tsx | 5 ++++- .../PluginSettings/components/SettingSelectComponent.tsx | 5 ++++- .../PluginSettings/components/SettingSliderComponent.tsx | 5 ++++- .../PluginSettings/components/SettingTextComponent.tsx | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/PluginSettings/components/SettingNumericComponent.tsx b/src/components/PluginSettings/components/SettingNumericComponent.tsx index 446d2504..b724717d 100644 --- a/src/components/PluginSettings/components/SettingNumericComponent.tsx +++ b/src/components/PluginSettings/components/SettingNumericComponent.tsx @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import { Margins } from "@utils/margins"; +import { wordsFromCamel, wordsToTitle } from "@utils/text"; import { OptionType, PluginOptionNumber } from "@utils/types"; import { Forms, React, TextInput } from "@webpack/common"; @@ -54,7 +56,8 @@ export function SettingNumericComponent({ option, pluginSettings, definedSetting return ( - {option.description} + {wordsToTitle(wordsFromCamel(id))} + {option.description} . */ +import { Margins } from "@utils/margins"; +import { wordsFromCamel, wordsToTitle } from "@utils/text"; import { PluginOptionSelect } from "@utils/types"; import { Forms, React, Select } from "@webpack/common"; @@ -44,7 +46,8 @@ export function SettingSelectComponent({ option, pluginSettings, definedSettings return ( - {option.description} + {wordsToTitle(wordsFromCamel(id))} + {option.description}