add context menu options to vencord badges
This commit is contained in:
parent
8807564053
commit
17b90beee1
2 changed files with 75 additions and 18 deletions
|
|
@ -34,7 +34,9 @@ export interface ProfileBadge {
|
|||
image?: string;
|
||||
link?: string;
|
||||
/** Action to perform when you click the badge */
|
||||
onClick?(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, props: BadgeUserArgs): void;
|
||||
onClick?(event: React.MouseEvent, props: ProfileBadge & BadgeUserArgs): void;
|
||||
/** Action to perform when you right click the badge */
|
||||
onContextMenu?(event: React.MouseEvent, props: BadgeUserArgs & BadgeUserArgs): void;
|
||||
/** Should the user display this badge? */
|
||||
shouldShow?(userInfo: BadgeUserArgs): boolean;
|
||||
/** Optional props (e.g. style) for the badge, ignored for component badges */
|
||||
|
|
@ -76,21 +78,34 @@ export function removeProfileBadge(badge: ProfileBadge) {
|
|||
export function _getBadges(args: BadgeUserArgs) {
|
||||
const badges = [] as ProfileBadge[];
|
||||
for (const badge of Badges) {
|
||||
if (!badge.shouldShow || badge.shouldShow(args)) {
|
||||
const b = badge.getBadges
|
||||
? badge.getBadges(args).map(b => {
|
||||
b.component &&= ErrorBoundary.wrap(b.component, { noop: true });
|
||||
return b;
|
||||
})
|
||||
: [{ ...badge, ...args }];
|
||||
if (badge.shouldShow && !badge.shouldShow(args)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
badge.position === BadgePosition.START
|
||||
? badges.unshift(...b)
|
||||
: badges.push(...b);
|
||||
const b = badge.getBadges
|
||||
? badge.getBadges(args).map(badge => ({
|
||||
...args,
|
||||
...badge,
|
||||
component: badge.component && ErrorBoundary.wrap(badge.component, { noop: true })
|
||||
}))
|
||||
: [{ ...args, ...badge }];
|
||||
|
||||
if (badge.position === BadgePosition.START) {
|
||||
badges.unshift(...b);
|
||||
} else {
|
||||
badges.push(...b);
|
||||
}
|
||||
}
|
||||
|
||||
const donorBadges = BadgeAPIPlugin.getDonorBadges(args.userId);
|
||||
if (donorBadges) badges.unshift(...donorBadges);
|
||||
if (donorBadges) {
|
||||
badges.unshift(
|
||||
...donorBadges.map(badge => ({
|
||||
...args,
|
||||
...badge,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
return badges;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ import { openContributorModal } from "@components/settings/tabs";
|
|||
import { Devs } from "@utils/constants";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { shouldShowContributorBadge } from "@utils/misc";
|
||||
import { copyWithToast, shouldShowContributorBadge } from "@utils/misc";
|
||||
import { closeModal, ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||
import definePlugin from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { Forms, Toasts, UserStore } from "@webpack/common";
|
||||
import { ContextMenuApi, Forms, Menu, Toasts, UserStore } from "@webpack/common";
|
||||
|
||||
const CONTRIBUTOR_BADGE = "https://cdn.discordapp.com/emojis/1092089799109775453.png?size=64";
|
||||
|
||||
|
|
@ -56,9 +56,35 @@ async function loadBadges(noCache = false) {
|
|||
|
||||
let intervalId: any;
|
||||
|
||||
function BadgeContextMenu({ badge }: { badge: ProfileBadge & BadgeUserArgs; }) {
|
||||
console.log(badge);
|
||||
return (
|
||||
<Menu.Menu
|
||||
navId="vc-badge-context"
|
||||
onClose={ContextMenuApi.closeContextMenu}
|
||||
aria-label="Badge Options"
|
||||
>
|
||||
{badge.description && (
|
||||
<Menu.MenuItem
|
||||
id="vc-badge-copy-name"
|
||||
label="Copy Badge Name"
|
||||
action={() => copyWithToast(badge.description!)}
|
||||
/>
|
||||
)}
|
||||
{badge.image && (
|
||||
<Menu.MenuItem
|
||||
id="vc-badge-copy-link"
|
||||
label="Copy Badge Image Link"
|
||||
action={() => copyWithToast(badge.image!)}
|
||||
/>
|
||||
)}
|
||||
</Menu.Menu>
|
||||
);
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "BadgeAPI",
|
||||
description: "API to add badges to users.",
|
||||
description: "API to add badges to users",
|
||||
authors: [Devs.Megu, Devs.Ven, Devs.TheSun],
|
||||
required: true,
|
||||
patches: [
|
||||
|
|
@ -80,10 +106,10 @@ export default definePlugin({
|
|||
match: /(?<="aria-label":(\i)\.description,.{0,200})children:/,
|
||||
replace: "children:$1.component?$self.renderBadgeComponent({...$1}) :"
|
||||
},
|
||||
// conditionally override their onClick with badge.onClick if it exists
|
||||
// handle onClick and onContextMenu
|
||||
{
|
||||
match: /href:(\i)\.link/,
|
||||
replace: "...($1.onClick&&{onClick:vcE=>$1.onClick(vcE,$1)}),$&"
|
||||
replace: "...$self.getBadgeMouseEventHandlers($1),$&"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -137,6 +163,19 @@ export default definePlugin({
|
|||
}, { noop: true }),
|
||||
|
||||
|
||||
getBadgeMouseEventHandlers(badge: ProfileBadge & BadgeUserArgs) {
|
||||
const handlers = {} as Record<string, (e: React.MouseEvent) => void>;
|
||||
|
||||
if (!badge) return handlers; // sanity check
|
||||
|
||||
const { onClick, onContextMenu } = badge;
|
||||
|
||||
if (onClick) handlers.onClick = e => onClick(e, badge);
|
||||
if (onContextMenu) handlers.onContextMenu = e => onContextMenu(e, badge);
|
||||
|
||||
return handlers;
|
||||
},
|
||||
|
||||
getDonorBadges(userId: string) {
|
||||
return DonorBadges[userId]?.map(badge => ({
|
||||
image: badge.badge,
|
||||
|
|
@ -148,6 +187,9 @@ export default definePlugin({
|
|||
transform: "scale(0.9)" // The image is a bit too big compared to default badges
|
||||
}
|
||||
},
|
||||
onContextMenu(event, badge) {
|
||||
ContextMenuApi.openContextMenu(event, () => <BadgeContextMenu badge={badge} />);
|
||||
},
|
||||
onClick() {
|
||||
const modalKey = openModal(props => (
|
||||
<ErrorBoundary noop onError={() => {
|
||||
|
|
@ -203,6 +245,6 @@ export default definePlugin({
|
|||
</ErrorBoundary>
|
||||
));
|
||||
},
|
||||
}));
|
||||
} satisfies ProfileBadge));
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue