From 5a7b3df59c9ecc98ba385d26a6d97f97c21ec0c4 Mon Sep 17 00:00:00 2001
From: thororen1234 <78185467+thororen1234@users.noreply.github.com>
Date: Sun, 9 Nov 2025 11:48:57 -0500
Subject: [PATCH] User Plugin Badge + Separate Modals
---
.../tabs/plugins/ContributorModal.tsx | 46 +++++++++++++++----
.../settings/tabs/plugins/PluginCard.tsx | 10 ++--
.../settings/tabs/plugins/PluginModal.tsx | 2 +-
src/equicordplugins/betterInvites/index.tsx | 4 +-
src/plugins/_api/badges/index.tsx | 29 ++++++++++--
src/utils/misc.ts | 3 --
6 files changed, 70 insertions(+), 24 deletions(-)
diff --git a/src/components/settings/tabs/plugins/ContributorModal.tsx b/src/components/settings/tabs/plugins/ContributorModal.tsx
index bbbd1364f..f9475cb1c 100644
--- a/src/components/settings/tabs/plugins/ContributorModal.tsx
+++ b/src/components/settings/tabs/plugins/ContributorModal.tsx
@@ -19,26 +19,28 @@ import { ModalContent, ModalRoot, openModal } from "@utils/modal";
import { User } from "@vencord/discord-types";
import { showToast, useEffect, useMemo, UserProfileStore, useStateFromStores } from "@webpack/common";
-import Plugins from "~plugins";
+import Plugins, { PluginMeta } from "~plugins";
import { GithubButton, WebsiteButton } from "./LinkIconButton";
import { PluginCard } from "./PluginCard";
const cl = classNameFactory("vc-author-modal-");
-export function openContributorModal(user: User) {
+type PluginFilter = "all" | "equicord" | "vencord" | "modified" | "user";
+
+export function openContributorModal(user: User, filter: PluginFilter = "all") {
openModal(modalProps =>
-
+
);
}
-function ContributorModal({ user }: { user: User; }) {
+function ContributorModal({ user, filter }: { user: User; filter: PluginFilter; }) {
useSettings();
const profile = useStateFromStores([UserProfileStore], () => UserProfileStore.getUserProfile(user.id));
@@ -53,9 +55,14 @@ function ContributorModal({ user }: { user: User; }) {
const plugins = useMemo(() => {
const allPlugins = Object.values(Plugins);
- const pluginsByAuthor = VencordDevsById[user.id] || EquicordDevsById[user.id]
+ const pluginsByAuthor = (VencordDevsById[user.id] || EquicordDevsById[user.id]) && filter !== "user"
? allPlugins.filter(p => p.authors.includes(VencordDevsById[user.id] || EquicordDevsById[user.id]))
- : allPlugins.filter(p => p.authors.some(a => a.name === user.username));
+ : filter === "user"
+ ? allPlugins.filter(p => {
+ const pluginMeta = PluginMeta[p.name];
+ return pluginMeta?.userPlugin && p.authors.some(a => a.id.toString() === user.id);
+ })
+ : allPlugins.filter(p => p.authors.some(a => a.name === user.username));
return pluginsByAuthor
.filter(p => !p.name.endsWith("API"))
@@ -64,6 +71,25 @@ function ContributorModal({ user }: { user: User; }) {
const ContributedHyperLink = contributed;
+ const filteredPlugins = useMemo(() => {
+ return plugins.filter(p => {
+ const pluginMeta = PluginMeta[p.name];
+ switch (filter) {
+ case "vencord":
+ return pluginMeta.folderName.startsWith("src/plugins/") ?? false;
+ case "equicord":
+ return pluginMeta.folderName.startsWith("src/equicordplugins/") ?? false;
+ case "user":
+ return pluginMeta?.userPlugin ?? false;
+ case "modified":
+ return p.isModified ?? false;
+ case "all":
+ default:
+ return () => true;
+ }
+ });
+ }, [plugins]);
+
return (
<>
@@ -90,9 +116,9 @@ function ContributorModal({ user }: { user: User; }) {
- {plugins.length ? (
+ {filteredPlugins.length ? (
- {user.username} has {ContributedHyperLink} to {pluralise(plugins.length, "plugin")}!
+ {user.username} has {ContributedHyperLink} to {pluralise(filteredPlugins.length, "plugin")}!
) : (
@@ -100,9 +126,9 @@ function ContributorModal({ user }: { user: User; }) {
)}
- {!!plugins.length && (
+ {!!filteredPlugins.length && (
- {plugins.map(p =>
+ {filteredPlugins.map(p =>
{
export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLeave, isNew }: PluginCardProps) {
const settings = Settings.plugins[plugin.name];
- const pluginMeta = PluginMeta[plugin.name];
- const isEquicordPlugin = pluginMeta.folderName.startsWith("src/equicordplugins/") ?? false;
- const isVencordPlugin = pluginMeta.folderName.startsWith("src/plugins/") ?? false;
- const isUserPlugin = pluginMeta.userPlugin ?? false;
- const isModifiedPlugin = plugin?.isModified ?? false;
const isEnabled = () => isPluginEnabled(plugin.name);
@@ -94,6 +89,11 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
settings.enabled = !wasEnabled;
}
+ const pluginMeta = PluginMeta[plugin.name];
+ const isEquicordPlugin = pluginMeta.folderName.startsWith("src/equicordplugins/") ?? false;
+ const isVencordPlugin = pluginMeta.folderName.startsWith("src/plugins/") ?? false;
+ const isUserPlugin = pluginMeta?.userPlugin ?? false;
+ const isModifiedPlugin = plugin.isModified ?? false;
const pluginInfo = [
{
condition: isModifiedPlugin,
diff --git a/src/components/settings/tabs/plugins/PluginModal.tsx b/src/components/settings/tabs/plugins/PluginModal.tsx
index 9be7e07a6..acace5f4f 100644
--- a/src/components/settings/tabs/plugins/PluginModal.tsx
+++ b/src/components/settings/tabs/plugins/PluginModal.tsx
@@ -191,7 +191,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
renderUser={(user: User) => (
openContributorModal(user)}
+ onClick={() => isEquicordPlugin ? openContributorModal(user, "equicord") : openContributorModal(user, "vencord")}
>
shouldShowContributorBadge(userId),
- onClick: (_, { userId }) => openContributorModal(UserStore.getUser(userId))
+ onClick: (_, { userId }) => openContributorModal(UserStore.getUser(userId), "vencord")
};
const EquicordContributorBadge: ProfileBadge = {
@@ -46,7 +49,27 @@ const EquicordContributorBadge: ProfileBadge = {
image: EQUICORD_CONTRIBUTOR_BADGE,
position: BadgePosition.START,
shouldShow: ({ userId }) => shouldShowEquicordContributorBadge(userId),
- onClick: (_, { userId }) => openContributorModal(UserStore.getUser(userId)),
+ onClick: (_, { userId }) => openContributorModal(UserStore.getUser(userId), "equicord"),
+ props: {
+ style: {
+ borderRadius: "50%",
+ transform: "scale(0.9)"
+ }
+ },
+};
+
+const UserPluginContributorBadge: ProfileBadge = {
+ description: "User Plugin Contributor",
+ image: USERPLUGIN_CONTRIBUTOR_BADGE,
+ position: BadgePosition.START,
+ shouldShow: ({ userId }) => {
+ const allPlugins = Object.values(Plugins);
+ return allPlugins.some(p => {
+ const pluginMeta = PluginMeta[p.name];
+ return pluginMeta?.userPlugin && p.authors.some(a => a.id.toString() === userId) && IS_DEV;
+ });
+ },
+ onClick: (_, { userId }) => openContributorModal(UserStore.getUser(userId), "user"),
props: {
style: {
borderRadius: "50%",
@@ -160,7 +183,7 @@ export default definePlugin({
}
},
- userProfileBadges: [ContributorBadge, EquicordContributorBadge],
+ userProfileBadges: [ContributorBadge, EquicordContributorBadge, UserPluginContributorBadge],
async start() {
await loadAllBadges();
diff --git a/src/utils/misc.ts b/src/utils/misc.ts
index ea0c8bce3..b5bdbd352 100644
--- a/src/utils/misc.ts
+++ b/src/utils/misc.ts
@@ -121,16 +121,13 @@ export function tryOrElse(func: () => T, fallback: T): T {
export function isEquicordGuild(id: string | null | undefined, isGuildId: boolean = false): boolean {
if (!id) return false;
-
if (isGuildId) return id === GUILD_ID;
-
const channel = ChannelStore.getChannel(id);
return channel.guild_id === GUILD_ID;
}
export function isSupportChannel(channelId: string | null | undefined): boolean {
if (!channelId) return false;
-
return channelId === SUPPORT_CHANNEL_ID;
}