User Plugin Badge + Separate Modals

This commit is contained in:
thororen1234 2025-11-09 11:48:57 -05:00
parent edb643fac2
commit 5a7b3df59c
No known key found for this signature in database
6 changed files with 70 additions and 24 deletions

View file

@ -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 =>
<ModalRoot {...modalProps}>
<ErrorBoundary>
<ModalContent className={cl("root")}>
<ContributorModal user={user} />
<ContributorModal user={user} filter={filter} />
</ModalContent>
</ErrorBoundary>
</ModalRoot>
);
}
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 = <Link href="https://github.com/Equicord/Equicord">contributed</Link>;
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 (
<>
<div className={cl("header")}>
@ -90,9 +116,9 @@ function ContributorModal({ user }: { user: User; }) {
</div>
</div>
{plugins.length ? (
{filteredPlugins.length ? (
<Paragraph>
{user.username} has {ContributedHyperLink} to {pluralise(plugins.length, "plugin")}!
{user.username} has {ContributedHyperLink} to {pluralise(filteredPlugins.length, "plugin")}!
</Paragraph>
) : (
<Paragraph>
@ -100,9 +126,9 @@ function ContributorModal({ user }: { user: User; }) {
</Paragraph>
)}
{!!plugins.length && (
{!!filteredPlugins.length && (
<div className={cl("plugins")}>
{plugins.map(p =>
{filteredPlugins.map(p =>
<PluginCard
key={p.name}
plugin={p}

View file

@ -36,11 +36,6 @@ interface PluginCardProps extends React.HTMLProps<HTMLDivElement> {
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,

View file

@ -191,7 +191,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
renderUser={(user: User) => (
<Clickable
className={AvatarStyles.clickableAvatar}
onClick={() => openContributorModal(user)}
onClick={() => isEquicordPlugin ? openContributorModal(user, "equicord") : openContributorModal(user, "vencord")}
>
<img
className={AvatarStyles.avatar}

View file

@ -7,7 +7,7 @@
import "./style.css";
import { InfoIcon } from "@components/Icons";
import { EquicordDevs } from "@utils/constants";
import { Devs, EquicordDevs } from "@utils/constants";
import { openUserProfile } from "@utils/discord";
import { classes } from "@utils/misc";
import definePlugin, { StartAt } from "@utils/types";
@ -33,7 +33,7 @@ function lurk(id: string) {
export default definePlugin({
name: "BetterInvites",
description: "See invites expiration date, view inviter profile and preview discoverable servers before joining by clicking their name",
authors: [EquicordDevs.iamme, EquicordDevs.thororen],
authors: [EquicordDevs.iamme, Devs.thororen],
patches: [
{
find: ".hideDetailsButtonContainer,",

View file

@ -28,17 +28,20 @@ import definePlugin from "@utils/types";
import { User } from "@vencord/discord-types";
import { ContextMenuApi, Menu, Toasts, UserStore } from "@webpack/common";
import Plugins, { PluginMeta } from "~plugins";
import { EquicordDonorModal, VencordDonorModal } from "./modals";
const CONTRIBUTOR_BADGE = "https://cdn.discordapp.com/emojis/1092089799109775453.png?size=64";
const EQUICORD_CONTRIBUTOR_BADGE = "https://equicord.org/assets/favicon.png";
const USERPLUGIN_CONTRIBUTOR_BADGE = "https://equicord.org/assets/icons/misc/userplugin.png";
const ContributorBadge: ProfileBadge = {
description: "Vencord Contributor",
image: CONTRIBUTOR_BADGE,
position: BadgePosition.START,
shouldShow: ({ userId }) => 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();

View file

@ -121,16 +121,13 @@ export function tryOrElse<T>(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;
}