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; }