GlobalBadges: Use ManaSelect & Drop Badge Modal

This commit is contained in:
thororen1234 2026-07-04 14:09:39 -04:00
parent 02e854ea1b
commit c148127818
No known key found for this signature in database
6 changed files with 173 additions and 232 deletions

View file

@ -19,7 +19,7 @@
import ErrorBoundary from "@components/ErrorBoundary";
import globalBadges from "@equicordplugins/globalBadges";
import BadgeAPIPlugin from "@plugins/_api/badges";
import { ComponentType, HTMLProps } from "react";
import { ComponentType, HTMLProps, ReactNode } from "react";
import { isPluginEnabled } from "./PluginManager";
@ -34,7 +34,7 @@ export interface ProfileBadge {
*/
id: string,
/** The tooltip to show on hover. Required for image badges */
description?: string;
description?: string | ReactNode;
/** Custom component for the badge (tooltip not included) */
component?: ComponentType<ProfileBadge & BadgeUserArgs>;
/** The custom image to use */

View file

@ -1,83 +0,0 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import ErrorBoundary from "@components/ErrorBoundary";
import { HeadingTertiary } from "@components/Heading";
import { Paragraph } from "@components/Paragraph";
import { openInviteModal } from "@utils/discord";
import { RenderModalProps, User } from "@vencord/discord-types";
import { Modal, openModal, React, Tooltip } from "@webpack/common";
import { cl, GlobalBadges, INVITE_LINK } from "./utils";
export const BadgeModalComponent = ({ key, tooltip, badge }: { key: string, tooltip: string, badge: string; }) => {
return (
<>
<Tooltip text={tooltip} >
{(tooltipProps: any) => (
<img
className={cl("modal-badge")}
key={key}
{...tooltipProps}
src={badge}
/>
)}
</Tooltip>
</>
);
};
export function openBadgeModal(user: User) {
const badgeDataElements = GlobalBadges[user.id].map(badge => (
<BadgeModalComponent key={badge.key} tooltip={badge.tooltip} badge={badge.badge} />
));
openModal((modalprops: RenderModalProps) => (
<Modal
{...modalprops}
size="sm"
title={
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
<img
className={cl("modal-avatar")}
src={user.getAvatarURL(undefined, 512, true)}
alt=""
/>
<HeadingTertiary className={cl("modal-name")} style={{ color: "white" }}>
{user.username}
</HeadingTertiary>
</div>
}
actions={[
{
text: "Join GlobalBadges Server",
variant: "link",
onClick: () => openInviteModal(INVITE_LINK)
}
]}
>
<ErrorBoundary>
<div className={cl("modal-description")}>
{badgeDataElements.length ? (
<>
<Paragraph className={cl("modal-text")}>
{badgeDataElements.length} global badge
{badgeDataElements.length > 1 ? "s" : ""}.
</Paragraph>
<div className={cl("modal-badges")}>
{badgeDataElements}
</div>
</>
) : (
<Paragraph>
No global badges.
</Paragraph>
)}
</div>
</ErrorBoundary>
</Modal>
));
}

View file

@ -13,9 +13,8 @@ import { BadgeContextMenu } from "@plugins/_api/badges";
import { Devs, EquicordDevs } from "@utils/constants";
import { openInviteModal } from "@utils/discord";
import definePlugin from "@utils/types";
import { ContextMenuApi, React, Toasts, UserStore } from "@webpack/common";
import { ContextMenuApi, React, Toasts } from "@webpack/common";
import { openBadgeModal } from "./badgeModal";
import { settings } from "./settings";
import { cl, GlobalBadges, INVITE_LINK, loadBadges } from "./utils";
@ -75,9 +74,6 @@ export default definePlugin({
onContextMenu(event, badge) {
ContextMenuApi.openContextMenu(event, () => <BadgeContextMenu badge={badge} />);
},
onClick() {
return openBadgeModal(UserStore.getUser(userId));
},
} satisfies ProfileBadge));
}
});

View file

@ -6,6 +6,58 @@
import { definePluginSettings } from "@api/Settings";
import { OptionType } from "@utils/types";
import { findComponentByCodeLazy } from "@webpack";
import { loadBadges } from "./utils";
const ManaSelect = findComponentByCodeLazy('"data-mana-component":"select"');
const badgeOptions = [
{ label: "BadgeVault", value: "showCustom" },
{ label: "Nekocord", value: "showNekocord" },
{ label: "ReviewDB", value: "showReviewDB" },
{ label: "Aero", value: "showAero" },
{ label: "Aliucord", value: "showAliucord" },
{ label: "Raincord", value: "showRaincord" },
{ label: "Velocity", value: "showVelocity" },
{ label: "Enmity", value: "showEnmity" },
{ label: "Paicord", value: "showPaicord" },
{ label: "Bunny", value: "showBunny" },
{ label: "GooseMod", value: "showGooseMod" },
{ label: "Replugged", value: "showReplugged" },
{ label: "BetterDiscord", value: "showBetterDiscord" },
{ label: "Vendroid Enhanced", value: "showVendroidEnhanced" },
{ label: "Revenge", value: "showRevenge" },
{ label: "ReCord", value: "showReCord" }
] as const;
const badgeManaOptions = badgeOptions.map(opt => ({ ...opt, id: opt.value }));
function ShowXSettings() {
const currentSettings = settings.use(badgeOptions.map(o => o.value));
const selectedValues = badgeOptions.filter(o => currentSettings[o.value]).map(o => o.value);
async function updateSelection(value) {
const selectedKeys = new Set(Array.isArray(value) ? value : value ? [value] : []);
for (const o of badgeOptions) {
settings.store[o.value] = selectedKeys.has(o.value);
}
await loadBadges();
}
return (
<ManaSelect
label="Specific Client Mods"
options={badgeManaOptions}
value={selectedValues}
closeOnSelect={false}
maxOptionsVisible={7}
selectionMode="multiple"
wrapTags={true}
onSelectionChange={updateSelection}
/>
);
}
export const settings = definePluginSettings({
showPrefix: {
@ -30,102 +82,6 @@ export const settings = definePluginSettings({
}
})
},
showCustom: {
type: OptionType.BOOLEAN,
description: "Show Custom Badges",
default: true,
restartNeeded: false
},
showNekocord: {
type: OptionType.BOOLEAN,
description: "Show Nekocord Badges",
default: true,
restartNeeded: false
},
showReviewDB: {
type: OptionType.BOOLEAN,
description: "Show ReviewDB Badges",
default: true,
restartNeeded: false
},
showAero: {
type: OptionType.BOOLEAN,
description: "Show Aero Badges",
default: true,
restartNeeded: false
},
showAliucord: {
type: OptionType.BOOLEAN,
description: "Show Aliucord Badges",
default: true,
restartNeeded: false
},
showRaincord: {
type: OptionType.BOOLEAN,
description: "Show Raincord Badges",
default: true,
restartNeeded: false
},
showVelocity: {
type: OptionType.BOOLEAN,
description: "Show Velocity Badges",
default: true,
restartNeeded: false
},
showEnmity: {
type: OptionType.BOOLEAN,
description: "Show Enmity Badges",
default: true,
restartNeeded: false
},
showPaicord: {
type: OptionType.BOOLEAN,
description: "Show Paicord Badges",
default: true,
restartNeeded: false
},
showBunny: {
type: OptionType.BOOLEAN,
description: "Show Bunny Badges",
default: true,
restartNeeded: false
},
showGooseMod: {
type: OptionType.BOOLEAN,
description: "Show GooseMod Badges",
default: true,
restartNeeded: false
},
showReplugged: {
type: OptionType.BOOLEAN,
description: "Show Replugged Badges",
default: true,
restartNeeded: false
},
showBetterDiscord: {
type: OptionType.BOOLEAN,
description: "Show BetterDiscord Badges",
default: true,
restartNeeded: false
},
showVendroidEnhanced: {
type: OptionType.BOOLEAN,
description: "Show Vendroid Enhanced Badges",
default: true,
restartNeeded: false
},
showRevenge: {
type: OptionType.BOOLEAN,
description: "Show Revenge Badges",
default: true,
restartNeeded: false
},
showReCord: {
type: OptionType.BOOLEAN,
description: "Show ReCord Badges",
default: true,
restartNeeded: false
},
apiUrl: {
type: OptionType.STRING,
description: "API to use",
@ -135,5 +91,121 @@ export const settings = definePluginSettings({
if (!value) return false;
return true;
})
},
showClientMods: {
type: OptionType.COMPONENT,
component: ShowXSettings,
},
showCustom: {
type: OptionType.BOOLEAN,
description: "Show Custom Badges",
default: true,
restartNeeded: false,
hidden: true
},
showNekocord: {
type: OptionType.BOOLEAN,
description: "Show Nekocord Badges",
default: true,
restartNeeded: false,
hidden: true
},
showReviewDB: {
type: OptionType.BOOLEAN,
description: "Show ReviewDB Badges",
default: true,
restartNeeded: false,
hidden: true
},
showAero: {
type: OptionType.BOOLEAN,
description: "Show Aero Badges",
default: true,
restartNeeded: false,
hidden: true
},
showAliucord: {
type: OptionType.BOOLEAN,
description: "Show Aliucord Badges",
default: true,
restartNeeded: false,
hidden: true
},
showRaincord: {
type: OptionType.BOOLEAN,
description: "Show Raincord Badges",
default: true,
restartNeeded: false,
hidden: true
},
showVelocity: {
type: OptionType.BOOLEAN,
description: "Show Velocity Badges",
default: true,
restartNeeded: false,
hidden: true
},
showEnmity: {
type: OptionType.BOOLEAN,
description: "Show Enmity Badges",
default: true,
restartNeeded: false,
hidden: true
},
showPaicord: {
type: OptionType.BOOLEAN,
description: "Show Paicord Badges",
default: true,
restartNeeded: false,
hidden: true
},
showBunny: {
type: OptionType.BOOLEAN,
description: "Show Bunny Badges",
default: true,
restartNeeded: false,
hidden: true
},
showGooseMod: {
type: OptionType.BOOLEAN,
description: "Show GooseMod Badges",
default: true,
restartNeeded: false,
hidden: true
},
showReplugged: {
type: OptionType.BOOLEAN,
description: "Show Replugged Badges",
default: true,
restartNeeded: false,
hidden: true
},
showBetterDiscord: {
type: OptionType.BOOLEAN,
description: "Show BetterDiscord Badges",
default: true,
restartNeeded: false,
hidden: true
},
showVendroidEnhanced: {
type: OptionType.BOOLEAN,
description: "Show Vendroid Enhanced Badges",
default: true,
restartNeeded: false,
hidden: true
},
showRevenge: {
type: OptionType.BOOLEAN,
description: "Show Revenge Badges",
default: true,
restartNeeded: false,
hidden: true
},
showReCord: {
type: OptionType.BOOLEAN,
description: "Show ReCord Badges",
default: true,
restartNeeded: false,
hidden: true
}
});

View file

@ -1,49 +1,3 @@
.vc-global-badges-modal-name {
text-transform: none;
flex-grow: 0;
background: var(--background-base-lowest);
border-radius: 0 9999px 9999px 0;
padding: 6px 0.8em 6px 0.5em;
font-size: 20px;
height: 20px;
position: relative;
text-wrap: nowrap;
}
.vc-global-badges-modal-name::before {
content: "";
display: block;
position: absolute;
height: 100%;
width: 32px;
background: var(--background-base-lowest);
z-index: -1;
left: -32px;
top: 0;
border-top-left-radius: 9999px;
border-bottom-left-radius: 9999px;
}
.vc-global-badges-modal-avatar {
height: 48px;
width: 48px;
border-radius: 50%;
}
.vc-global-badges-modal-description {
font-size: 16px;
}
.vc-global-badges-modal-text {
margin-left: 8px;
}
.vc-global-badges-modal-badge {
width: 50px;
height: 50px;
margin: 2px;
}
.vc-global-badges-settings-button {
width: 100%;
height: 50px;

View file

@ -30,6 +30,8 @@ export const serviceMap: Record<string, string> = {
vendroidenhanced: "VendroidEnhanced",
revenge: "Revenge",
record: "ReCord",
vencord: "Vencord",
equicord: "Equicord"
};
const blockedMods = ["vencord", "equicord"];