From d5c6c4d92b9206b7b37d35e7970b9dbc04a960f5 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:19:07 -0500 Subject: [PATCH 01/10] Declutter: Fix Migration --- src/equicordplugins/declutter/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx index 468595bb2..cf4c44dc0 100644 --- a/src/equicordplugins/declutter/index.tsx +++ b/src/equicordplugins/declutter/index.tsx @@ -21,7 +21,7 @@ const migrationsAnammox = [ ]; for (const [oldKey, newKey] of migrationsAnammox) { - migratePluginSetting("Anammox", newKey, oldKey); + migratePluginSetting("Declutter", newKey, oldKey); } export const settings = definePluginSettings({ From e54678219e60f01382d9da0c9d8ec3222ac0cfb3 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:40:47 -0500 Subject: [PATCH 02/10] native define --- package.json | 2 +- src/equicordplugins/songSpotlight.desktop/index.tsx | 4 ++-- src/equicordplugins/songSpotlight.desktop/service.ts | 5 ++--- .../songSpotlight.desktop/ui/settings/AddSong.tsx | 4 ++-- .../songSpotlight.desktop/ui/settings/index.tsx | 4 ++-- src/equicordplugins/songSpotlight.desktop/ui/songs/index.tsx | 4 ++-- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 6e8ac3d1b..40f925406 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "typescript-transform-paths": "^3.5.5", "zip-local": "^0.3.5" }, - "packageManager": "pnpm@10.29.2", + "packageManager": "pnpm@10.30.3", "pnpm": { "patchedDependencies": { "@types/less@3.0.8": "patches/@types__less@3.0.8.patch" diff --git a/src/equicordplugins/songSpotlight.desktop/index.tsx b/src/equicordplugins/songSpotlight.desktop/index.tsx index 360dd6c7e..cf8ee449c 100644 --- a/src/equicordplugins/songSpotlight.desktop/index.tsx +++ b/src/equicordplugins/songSpotlight.desktop/index.tsx @@ -13,7 +13,7 @@ import definePlugin, { OptionType } from "@utils/types"; import { useAuthorizationStore } from "./lib/stores/AuthorizationStore"; import { useSongStore } from "./lib/stores/SongStore"; -import { clearCache } from "./service"; +import { Native } from "./service"; import Settings from "./ui/settings"; import ProfileSongs from "./ui/songs/ProfileSongs"; import WidgetSongs from "./ui/songs/WidgetSongs"; @@ -80,7 +80,7 @@ export default definePlugin({ // only gets cleared on full restart. we don't want that since // audio preview URLs expire very fast, so we just clear it on // plugin restart instead - clearCache(); + Native.clearCache(); useSongStore.getState().$refresh(); useAuthorizationStore.persist.rehydrate(); diff --git a/src/equicordplugins/songSpotlight.desktop/service.ts b/src/equicordplugins/songSpotlight.desktop/service.ts index e7334d52a..7dd16eab5 100644 --- a/src/equicordplugins/songSpotlight.desktop/service.ts +++ b/src/equicordplugins/songSpotlight.desktop/service.ts @@ -17,7 +17,7 @@ export function useRender(song: Song) { useEffect(() => { setFailed(false); setRender(null); - renderSong(song) + Native.renderSong(song) .catch(() => null) .then(info => info ? setRender(info) : setFailed(true)); }, [sid(song)]); @@ -25,5 +25,4 @@ export function useRender(song: Song) { return { failed, render }; } -export const { parseLink, renderSong, validateSong, clearCache } = VencordNative.pluginHelpers - .SongSpotlight as PluginNative; +export const Native = VencordNative.pluginHelpers.SongSpotlight as PluginNative; diff --git a/src/equicordplugins/songSpotlight.desktop/ui/settings/AddSong.tsx b/src/equicordplugins/songSpotlight.desktop/ui/settings/AddSong.tsx index 084ed2534..9b0767daa 100644 --- a/src/equicordplugins/songSpotlight.desktop/ui/settings/AddSong.tsx +++ b/src/equicordplugins/songSpotlight.desktop/ui/settings/AddSong.tsx @@ -10,7 +10,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { PlusIcon } from "@components/Icons"; import { cl, logger } from "@equicordplugins/songSpotlight.desktop/lib/utils"; -import { parseLink } from "@equicordplugins/songSpotlight.desktop/service"; +import { Native } from "@equicordplugins/songSpotlight.desktop/service"; import { parsers } from "@song-spotlight/api/handlers"; import { Song } from "@song-spotlight/api/structs"; import { closeModal, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; @@ -60,7 +60,7 @@ function AddSongModal({ modalProps, close, onAdd }: AddSongModalProps) { onClick={async () => { setPending(true); try { - const parsed = await parseLink(url); + const parsed = await Native.parseLink(url); if (!parsed) { setError("Invalid link"); return setPending(false); diff --git a/src/equicordplugins/songSpotlight.desktop/ui/settings/index.tsx b/src/equicordplugins/songSpotlight.desktop/ui/settings/index.tsx index 8dd5a166f..ef42841de 100644 --- a/src/equicordplugins/songSpotlight.desktop/ui/settings/index.tsx +++ b/src/equicordplugins/songSpotlight.desktop/ui/settings/index.tsx @@ -13,7 +13,7 @@ import { presentOAuth2Modal } from "@equicordplugins/songSpotlight.desktop/lib/o import { useAuthorizationStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/AuthorizationStore"; import { useSongStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/SongStore"; import { cl } from "@equicordplugins/songSpotlight.desktop/lib/utils"; -import { validateSong } from "@equicordplugins/songSpotlight.desktop/service"; +import { Native } from "@equicordplugins/songSpotlight.desktop/service"; import { Spinner } from "@equicordplugins/songSpotlight.desktop/ui/common"; import SongList from "@equicordplugins/songSpotlight.desktop/ui/settings/SongList"; import { UserData, UserDataSchema } from "@song-spotlight/api/structs"; @@ -48,7 +48,7 @@ function ImportButton({ overwrite, pending, setPending, onImport }: ImportButton return showToast("Invalid Song Spotlight data in clipboard!", Toasts.Type.FAILURE); } - const validated = await Promise.allSettled(data.map(song => validateSong(song))); + const validated = await Promise.allSettled(data.map(song => Native.validateSong(song))); if (!validated.every(x => x.status === "fulfilled" && x.value)) { setPending(false); return showToast("One or more imported songs were invalid.", Toasts.Type.FAILURE); diff --git a/src/equicordplugins/songSpotlight.desktop/ui/songs/index.tsx b/src/equicordplugins/songSpotlight.desktop/ui/songs/index.tsx index f78c71819..ee42b87d6 100644 --- a/src/equicordplugins/songSpotlight.desktop/ui/songs/index.tsx +++ b/src/equicordplugins/songSpotlight.desktop/ui/songs/index.tsx @@ -11,7 +11,7 @@ import { Link } from "@components/Link"; import { apiConstants } from "@equicordplugins/songSpotlight.desktop/lib/api"; import { useSongStore } from "@equicordplugins/songSpotlight.desktop/lib/stores/SongStore"; import { cl, formatCoverTooltip, formatDurationMs } from "@equicordplugins/songSpotlight.desktop/lib/utils"; -import { parseLink, useRender } from "@equicordplugins/songSpotlight.desktop/service"; +import { Native, useRender } from "@equicordplugins/songSpotlight.desktop/service"; import { CardClasses, ExplicitTag, @@ -84,7 +84,7 @@ function SongEntry({ entry, number, isLoaded, isPlaying, big, onClick }: SongEnt return showToast("You don't have enough space!"); } - const song = await parseLink(entry.link); + const song = await Native.parseLink(entry.link); if (!song) { return showToast("Uh oh, this song doesn't exist!", Toasts.Type.FAILURE); } From f512ea2bf278c183db8964da171afc3d17facb90 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:51:57 -0500 Subject: [PATCH 03/10] Fix Conflict --- src/equicordplugins/betterActivities/index.tsx | 2 +- src/equicordplugins/songSpotlight.desktop/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/equicordplugins/betterActivities/index.tsx b/src/equicordplugins/betterActivities/index.tsx index f5c35f122..bea8c1136 100644 --- a/src/equicordplugins/betterActivities/index.tsx +++ b/src/equicordplugins/betterActivities/index.tsx @@ -43,7 +43,7 @@ export default definePlugin({ }, { // Show all activities in the user popout/sidebar - find: /\.POPOUT,onClose:\i}\),nicknameIcons:.+?\.isProvisional/, + find: /onOpenUserProfileModal:\i,onClose:\i\}\),null/, replacement: { match: /((\i)=.{0,10}(\i)\.id\).*?,onInteraction:\i\}\),).{0,250}onClose:\i\}\)/, replace: "$1$self.showAllActivitiesComponent({ activity: $2, user: $3 })" diff --git a/src/equicordplugins/songSpotlight.desktop/index.tsx b/src/equicordplugins/songSpotlight.desktop/index.tsx index cf8ee449c..f69bab5f2 100644 --- a/src/equicordplugins/songSpotlight.desktop/index.tsx +++ b/src/equicordplugins/songSpotlight.desktop/index.tsx @@ -49,7 +49,7 @@ export default definePlugin({ { find: ".SIDEBAR}),nicknameIcons:", replacement: { - match: /{userId:(\i)\.id}\)}\)]}\)/, + match: /{userId:(\i)\.id}\)}\)]}\).{0,100}(?=\]\}\))/, replace: "$&,$self.renderProfileSongs({userId:$1.id})", }, }, From 37e7847ea2f3f7a5d3f76a8b78f398e9b403643e Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:56:24 -0500 Subject: [PATCH 04/10] oops --- src/equicordplugins/songSpotlight.desktop/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/songSpotlight.desktop/index.tsx b/src/equicordplugins/songSpotlight.desktop/index.tsx index f69bab5f2..83ecdf203 100644 --- a/src/equicordplugins/songSpotlight.desktop/index.tsx +++ b/src/equicordplugins/songSpotlight.desktop/index.tsx @@ -49,7 +49,7 @@ export default definePlugin({ { find: ".SIDEBAR}),nicknameIcons:", replacement: { - match: /{userId:(\i)\.id}\)}\)]}\).{0,100}(?=\]\}\))/, + match: /{userId:(\i)\.id}\)}\).{0,100}]}\)(?=\]\}\))/, replace: "$&,$self.renderProfileSongs({userId:$1.id})", }, }, From 9db2d746e8f921480928e126238cc233861e80b3 Mon Sep 17 00:00:00 2001 From: oma <57739965+Eazvy@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:59:17 -0500 Subject: [PATCH 05/10] fix PictureInPicture render on image files (#841) * fix(pictureInPicture): gate button for video media only * PictureInPicture: simplify media gating checks * PictureInPicture: guard mime check in shouldShowButton * fix replace & typeof * fix ugh * fix(pictureInPicture): handle array-shaped mimeType values * pictureInPicture: simplify mime type handling with join --- src/plugins/pictureInPicture/index.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/plugins/pictureInPicture/index.tsx b/src/plugins/pictureInPicture/index.tsx index ff8c00ebb..d1324dc82 100644 --- a/src/plugins/pictureInPicture/index.tsx +++ b/src/plugins/pictureInPicture/index.tsx @@ -30,12 +30,20 @@ export default definePlugin({ { find: '["VIDEO","CLIP","AUDIO"]', replacement: { - match: /(\[\i>0&&\i\.length>0.{0,150}?children:)(\i.slice\(\i\))(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/, - replace: (_, rest, origChildren, showDownload, isVisualMediaType) => `${rest}[${showDownload}&&${isVisualMediaType}&&$self.PictureInPictureButton(),...${origChildren}]` + match: /(\[\i>0&&\i\.length>0.{0,150}?children:)(\i.slice\(\i\))(?<=mimeType:(\i),downloadURL:(\i).+?showDownload:(\i).+?isVisualMediaType:(\i).+?)/, + replace: (_, rest, origChildren, mimeType, downloadURL, showDownload, isVisualMediaType) => + `${rest}[${showDownload}&&${isVisualMediaType}&&$self.shouldShowButton(${mimeType},${downloadURL})&&$self.PictureInPictureButton(),...${origChildren}]` } } ], + shouldShowButton(mimeType: string[] = [], downloadURL?: string) { + const normalizedMimeType = mimeType.join("/"); + if (normalizedMimeType.startsWith("video/")) return true; + if (!downloadURL) return false; + return /\.(mp4|webm|mov|m4v|ogv|avi)(?:$|[?#])/i.test(downloadURL); + }, + PictureInPictureButton: ErrorBoundary.wrap(() => { return ( From 19dc4ab68d60d18519e91936d8e8cfafe20b2e4e Mon Sep 17 00:00:00 2001 From: oma <57739965+Eazvy@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:59:57 -0500 Subject: [PATCH 06/10] fullVcPfp: add server profile avatar setting (#859) --- src/equicordplugins/fullVcPfp/index.tsx | 40 ++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/equicordplugins/fullVcPfp/index.tsx b/src/equicordplugins/fullVcPfp/index.tsx index 30fa24349..7c1300fda 100644 --- a/src/equicordplugins/fullVcPfp/index.tsx +++ b/src/equicordplugins/fullVcPfp/index.tsx @@ -4,17 +4,27 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { definePluginSettings } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; import { EquicordDevs } from "@utils/constants"; -import definePlugin from "@utils/types"; -import { ChannelRTCStore, IconUtils, UserStore, VoiceStateStore } from "@webpack/common"; +import definePlugin, { OptionType } from "@utils/types"; +import { ChannelRTCStore, ChannelStore, GuildMemberStore, IconUtils, UserStore, VoiceStateStore } from "@webpack/common"; import style from "./style.css?managed"; +const settings = definePluginSettings({ + useServerProfileAvatars: { + type: OptionType.BOOLEAN, + description: "Use server profile avatars in guild voice channels when available.", + default: false + } +}); + export default definePlugin({ name: "FullVCPFP", description: "Makes avatars take up the entire vc tile", authors: [EquicordDevs.mochienya], + settings, patches: [ { find: "\"data-selenium-video-tile\":", @@ -29,15 +39,37 @@ export default definePlugin({ if (!className.includes("tile") || !participantUserId) return; const user = UserStore.getUser(participantUserId); - const channelId = VoiceStateStore.getVoiceStateForUser(participantUserId)?.channelId!; + if (!user) return; + + const channelId = VoiceStateStore.getVoiceStateForUser(participantUserId)?.channelId; + if (!channelId) return; + const isSpeaking = ChannelRTCStore.getSpeakingParticipants(channelId).some(p => p.user.id === participantUserId && p.speaking); - const avatarUrl = IconUtils.getUserAvatarURL(user, isSpeaking, 1024); + const avatarUrl = settings.store.useServerProfileAvatars + ? this.getServerAvatarUrl(participantUserId, channelId, isSpeaking) ?? IconUtils.getUserAvatarURL(user, isSpeaking, 1024) + : IconUtils.getUserAvatarURL(user, isSpeaking, 1024); return { "--full-res-avatar": `url(${avatarUrl})` }; }, + getServerAvatarUrl(userId: string, channelId: string, canAnimate: boolean) { + const guildId = ChannelStore.getChannel(channelId)?.guild_id; + if (!guildId) return; + + const guildAvatar = GuildMemberStore.getMember(guildId, userId)?.avatar; + if (!guildAvatar) return; + + return IconUtils.getGuildMemberAvatarURLSimple({ + userId, + guildId, + avatar: guildAvatar, + canAnimate, + size: 1024 + }); + }, + start() { enableStyle(style); }, From e453ad296ff5fed75e5423e2b0b71cbc12fc815a Mon Sep 17 00:00:00 2001 From: Awizz Date: Mon, 2 Mar 2026 20:01:16 +0100 Subject: [PATCH 07/10] add DMKeeper plugin (#858) Co-Authored-By: thororen1234 <78185467+thororen1234@users.noreply.github.com> --- src/equicordplugins/dmKeeper/index.ts | 23 +++++++++++++++++++++++ src/utils/constants.ts | 6 +++++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/equicordplugins/dmKeeper/index.ts diff --git a/src/equicordplugins/dmKeeper/index.ts b/src/equicordplugins/dmKeeper/index.ts new file mode 100644 index 000000000..5ab843aa1 --- /dev/null +++ b/src/equicordplugins/dmKeeper/index.ts @@ -0,0 +1,23 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 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: "DMKeeper", + description: "Prevents Discord from automatically hiding old DM conversations from your sidebar.", + authors: [EquicordDevs.Awizz], + patches: [ + { + find: "getSortedPrivateChannels(){", + replacement: { + match: /(\i)\.length>(\i)&&(\i)\.shift\(\)/, + replace: "false" + } + } + ], +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e0fef9853..5ae897b51 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1263,7 +1263,11 @@ export const EquicordDevs = Object.freeze({ Leon135: { name: "Leon135", id: 309275452231385088n, - } + }, + Awizz: { + name: "Awizz", + id: 1267951485585461288n, + }, } satisfies Record); // iife so #__PURE__ works correctly From 8dd62834a21eedaa9698e629b1d2855c338a5c5d Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:31:31 -0500 Subject: [PATCH 08/10] Revert "add DMKeeper plugin (#858)" This reverts commit e453ad296ff5fed75e5423e2b0b71cbc12fc815a. --- src/equicordplugins/dmKeeper/index.ts | 23 ----------------------- src/utils/constants.ts | 6 +----- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 src/equicordplugins/dmKeeper/index.ts diff --git a/src/equicordplugins/dmKeeper/index.ts b/src/equicordplugins/dmKeeper/index.ts deleted file mode 100644 index 5ab843aa1..000000000 --- a/src/equicordplugins/dmKeeper/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2026 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: "DMKeeper", - description: "Prevents Discord from automatically hiding old DM conversations from your sidebar.", - authors: [EquicordDevs.Awizz], - patches: [ - { - find: "getSortedPrivateChannels(){", - replacement: { - match: /(\i)\.length>(\i)&&(\i)\.shift\(\)/, - replace: "false" - } - } - ], -}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 5ae897b51..e0fef9853 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1263,11 +1263,7 @@ export const EquicordDevs = Object.freeze({ Leon135: { name: "Leon135", id: 309275452231385088n, - }, - Awizz: { - name: "Awizz", - id: 1267951485585461288n, - }, + } } satisfies Record); // iife so #__PURE__ works correctly From 892bd12d24ef0b0192f3a0bbfb5522ad0ba3af7c Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 15:46:58 -0500 Subject: [PATCH 09/10] Fix Patch --- src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx b/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx index 8a410c26b..91320746e 100644 --- a/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx +++ b/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx @@ -98,7 +98,7 @@ export default definePlugin({ }, // enables clips { - find: "2022-11_clips_experiment", + find: "2026-03-clips-experiment", replacement: { match: /defaultConfig:\{enableClips:!\d,ignorePlatformRestriction:!\d,showClipsHeaderEntrypoint:!\d,enableScreenshotKeybind:!\d,enableVoiceOnlyClips:!\d,enableAdvancedSignals:!\d\}/, replace: "defaultConfig:{enableClips:!0,ignorePlatformRestriction:$self.settings.store.ignorePlatformRestriction,showClipsHeaderEntrypoint:!0,enableScreenshotKeybind:$self.settings.store.enableScreenshotKeybind,enableVoiceOnlyClips:$self.settings.store.enableVoiceOnlyClips,enableAdvancedSignals:$self.settings.store.enableAdvancedSignals}" From 6c0048f8279a507e66c85e8107915d0300679197 Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Mon, 2 Mar 2026 17:21:56 -0500 Subject: [PATCH 10/10] Fix Patch --- src/equicordplugins/richMagnetLinks/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equicordplugins/richMagnetLinks/index.tsx b/src/equicordplugins/richMagnetLinks/index.tsx index 39642334d..33a42efbb 100644 --- a/src/equicordplugins/richMagnetLinks/index.tsx +++ b/src/equicordplugins/richMagnetLinks/index.tsx @@ -22,7 +22,7 @@ export default definePlugin({ } }, { - find: '"flattenMarkdown"', + find: 'before:"@silent"', replacement: { match: /mention:{type:/, replace: "magnet:{type:\"inlineObject\"},$&",