GlobalBadges: Use ManaSelect & Drop Badge Modal
This commit is contained in:
parent
02e854ea1b
commit
c148127818
6 changed files with 173 additions and 232 deletions
|
|
@ -19,7 +19,7 @@
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import globalBadges from "@equicordplugins/globalBadges";
|
import globalBadges from "@equicordplugins/globalBadges";
|
||||||
import BadgeAPIPlugin from "@plugins/_api/badges";
|
import BadgeAPIPlugin from "@plugins/_api/badges";
|
||||||
import { ComponentType, HTMLProps } from "react";
|
import { ComponentType, HTMLProps, ReactNode } from "react";
|
||||||
|
|
||||||
import { isPluginEnabled } from "./PluginManager";
|
import { isPluginEnabled } from "./PluginManager";
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ export interface ProfileBadge {
|
||||||
*/
|
*/
|
||||||
id: string,
|
id: string,
|
||||||
/** The tooltip to show on hover. Required for image badges */
|
/** The tooltip to show on hover. Required for image badges */
|
||||||
description?: string;
|
description?: string | ReactNode;
|
||||||
/** Custom component for the badge (tooltip not included) */
|
/** Custom component for the badge (tooltip not included) */
|
||||||
component?: ComponentType<ProfileBadge & BadgeUserArgs>;
|
component?: ComponentType<ProfileBadge & BadgeUserArgs>;
|
||||||
/** The custom image to use */
|
/** The custom image to use */
|
||||||
|
|
|
||||||
|
|
@ -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>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
@ -13,9 +13,8 @@ import { BadgeContextMenu } from "@plugins/_api/badges";
|
||||||
import { Devs, EquicordDevs } from "@utils/constants";
|
import { Devs, EquicordDevs } from "@utils/constants";
|
||||||
import { openInviteModal } from "@utils/discord";
|
import { openInviteModal } from "@utils/discord";
|
||||||
import definePlugin from "@utils/types";
|
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 { settings } from "./settings";
|
||||||
import { cl, GlobalBadges, INVITE_LINK, loadBadges } from "./utils";
|
import { cl, GlobalBadges, INVITE_LINK, loadBadges } from "./utils";
|
||||||
|
|
||||||
|
|
@ -75,9 +74,6 @@ export default definePlugin({
|
||||||
onContextMenu(event, badge) {
|
onContextMenu(event, badge) {
|
||||||
ContextMenuApi.openContextMenu(event, () => <BadgeContextMenu badge={badge} />);
|
ContextMenuApi.openContextMenu(event, () => <BadgeContextMenu badge={badge} />);
|
||||||
},
|
},
|
||||||
onClick() {
|
|
||||||
return openBadgeModal(UserStore.getUser(userId));
|
|
||||||
},
|
|
||||||
} satisfies ProfileBadge));
|
} satisfies ProfileBadge));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,58 @@
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { OptionType } from "@utils/types";
|
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({
|
export const settings = definePluginSettings({
|
||||||
showPrefix: {
|
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: {
|
apiUrl: {
|
||||||
type: OptionType.STRING,
|
type: OptionType.STRING,
|
||||||
description: "API to use",
|
description: "API to use",
|
||||||
|
|
@ -135,5 +91,121 @@ export const settings = definePluginSettings({
|
||||||
if (!value) return false;
|
if (!value) return false;
|
||||||
return true;
|
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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -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 {
|
.vc-global-badges-settings-button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ export const serviceMap: Record<string, string> = {
|
||||||
vendroidenhanced: "VendroidEnhanced",
|
vendroidenhanced: "VendroidEnhanced",
|
||||||
revenge: "Revenge",
|
revenge: "Revenge",
|
||||||
record: "ReCord",
|
record: "ReCord",
|
||||||
|
vencord: "Vencord",
|
||||||
|
equicord: "Equicord"
|
||||||
};
|
};
|
||||||
|
|
||||||
const blockedMods = ["vencord", "equicord"];
|
const blockedMods = ["vencord", "equicord"];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue