PermissionViewer: improve role context menu
This commit is contained in:
parent
b08fafb00b
commit
6a325e2c89
2 changed files with 112 additions and 81 deletions
|
|
@ -10,9 +10,10 @@ import { ImageIcon } from "@components/Icons";
|
|||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { getCurrentChannel, getCurrentGuild, openImageModal } from "@utils/discord";
|
||||
import { isTruthy } from "@utils/guards";
|
||||
import { classes } from "@utils/misc";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { PopoutProps } from "@vencord/discord-types";
|
||||
import { Guild, PopoutProps, Role } from "@vencord/discord-types";
|
||||
import { findByCodeLazy, findByPropsLazy, findCssClassesLazy } from "@webpack";
|
||||
import { GuildRoleStore, Menu, PermissionStore, Popout, useRef } from "@webpack/common";
|
||||
import { ComponentType } from "react";
|
||||
|
|
@ -85,6 +86,90 @@ type RoleMemberPopout = ComponentType<RoleMemberPopoutProps>;
|
|||
|
||||
let RoleMemberPopout: RoleMemberPopout = () => null;
|
||||
|
||||
export function buildExtraRoleContextMenuItems(role: Role, guild: Guild, popoutRef?: React.RefObject<any>) {
|
||||
if (!role) return { before: [], after: [] };
|
||||
|
||||
const before = [
|
||||
PermissionStore.getGuildPermissionProps(guild).canManageRoles && (
|
||||
<Menu.MenuItem
|
||||
key="vc-edit-role"
|
||||
id="vc-edit-role"
|
||||
label="Edit Role"
|
||||
action={async () => {
|
||||
await GuildSettingsActions.open(guild.id, "ROLES");
|
||||
GuildSettingsActions.selectRole(role.id);
|
||||
}}
|
||||
icon={PencilIcon}
|
||||
/>
|
||||
),
|
||||
role.colorString && (
|
||||
<Menu.MenuItem
|
||||
key="vc-copy-role-color"
|
||||
id="vc-copy-role-color"
|
||||
label="Copy Role Color"
|
||||
action={() => copyToClipboard(role.colorString!)}
|
||||
icon={AppearanceIcon}
|
||||
/>
|
||||
)
|
||||
].filter(isTruthy);
|
||||
|
||||
const after = [
|
||||
role.icon && (
|
||||
<Menu.MenuItem
|
||||
id="vc-view-role-icon"
|
||||
label="View Role Icon"
|
||||
action={() => {
|
||||
openImageModal({
|
||||
url: `${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${role.id}/${role.icon}.${settings.store.roleIconFileFormat}`,
|
||||
height: 128,
|
||||
width: 128
|
||||
});
|
||||
}}
|
||||
icon={ImageIcon}
|
||||
/>
|
||||
),
|
||||
popoutRef && (
|
||||
<Menu.MenuItem
|
||||
key="vc-view-role-members"
|
||||
id="vc-view-role-members"
|
||||
label="View Role Members"
|
||||
render={() => (
|
||||
<Popout
|
||||
position="right"
|
||||
align="center"
|
||||
targetElementRef={popoutRef}
|
||||
preload={() => loadRoleMembers(guild.id, role.id)}
|
||||
renderPopout={popoutProps => (
|
||||
<RoleMemberPopout
|
||||
popoutProps={popoutProps}
|
||||
guildId={guild.id}
|
||||
channelId={getCurrentChannel()!.id}
|
||||
roleId={role.id}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{popoutProps => (
|
||||
<div
|
||||
className={classes(MenuItemClasses.item, MenuItemClasses.labelContainer, MenuItemClasses.colorDefault)}
|
||||
ref={popoutRef}
|
||||
role="menuitem"
|
||||
{...popoutProps}
|
||||
>
|
||||
<div className={MenuItemClasses.label}>View Role Members</div>
|
||||
<div className={MenuItemClasses.iconContainer}>
|
||||
<RoleMembersIcon />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Popout>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
].filter(isTruthy);
|
||||
|
||||
return { before, after };
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterRoleContext",
|
||||
description: "Adds options to copy role color / edit role / view role icon when right clicking roles in the user profile",
|
||||
|
|
@ -121,81 +206,9 @@ export default definePlugin({
|
|||
const role = GuildRoleStore.getRole(guild.id, id);
|
||||
if (!role) return;
|
||||
|
||||
if (role.colorString) {
|
||||
children.unshift(
|
||||
<Menu.MenuItem
|
||||
id="vc-copy-role-color"
|
||||
label="Copy Role Color"
|
||||
action={() => copyToClipboard(role.colorString!)}
|
||||
icon={AppearanceIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (PermissionStore.getGuildPermissionProps(guild).canManageRoles) {
|
||||
children.unshift(
|
||||
<Menu.MenuItem
|
||||
id="vc-edit-role"
|
||||
label="Edit Role"
|
||||
action={async () => {
|
||||
await GuildSettingsActions.open(guild.id, "ROLES");
|
||||
GuildSettingsActions.selectRole(id);
|
||||
}}
|
||||
icon={PencilIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (role.icon) {
|
||||
children.push(
|
||||
<Menu.MenuItem
|
||||
id="vc-view-role-icon"
|
||||
label="View Role Icon"
|
||||
action={() => {
|
||||
openImageModal({
|
||||
url: `${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${role.id}/${role.icon}.${settings.store.roleIconFileFormat}`,
|
||||
height: 128,
|
||||
width: 128
|
||||
});
|
||||
}}
|
||||
icon={ImageIcon}
|
||||
/>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
children.push(
|
||||
<Menu.MenuItem id="vc-view-role-members" label="View Role Members" render={() => (
|
||||
<Popout
|
||||
position="right"
|
||||
align="center"
|
||||
targetElementRef={popoutRef}
|
||||
preload={() => loadRoleMembers(guild.id, id)}
|
||||
renderPopout={popoutProps => (
|
||||
<RoleMemberPopout
|
||||
popoutProps={popoutProps}
|
||||
guildId={guild.id}
|
||||
channelId={getCurrentChannel()!.id}
|
||||
roleId={id}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{popoutProps => (
|
||||
<div
|
||||
className={classes(MenuItemClasses.item, MenuItemClasses.labelContainer, MenuItemClasses.colorDefault)}
|
||||
ref={popoutRef}
|
||||
role="menuitem"
|
||||
{...popoutProps}
|
||||
>
|
||||
<div className={MenuItemClasses.label}>View Role Members</div>
|
||||
<div className={MenuItemClasses.iconContainer}>
|
||||
<RoleMembersIcon />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Popout>
|
||||
)} />
|
||||
);
|
||||
const { before, after } = buildExtraRoleContextMenuItems(role, guild, popoutRef);
|
||||
children.unshift(...before);
|
||||
children.push(...after);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Flex } from "@components/Flex";
|
||||
import { InfoIcon, OwnerCrownIcon } from "@components/Icons";
|
||||
import { InfoIcon, OwnerCrownIcon, RightArrow } from "@components/Icons";
|
||||
import { buildExtraRoleContextMenuItems } from "@plugins/betterRoleContext";
|
||||
import { cl, getGuildPermissionSpecMap, loadGetGuildPermissionSpecMap } from "@plugins/permissionsViewer/utils";
|
||||
import { copyToClipboard } from "@utils/clipboard";
|
||||
import { getIntlMessage, getUniqueUsername } from "@utils/discord";
|
||||
|
|
@ -26,7 +27,7 @@ import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, Mod
|
|||
import { Guild, Role, RoleOrUserPermission, UnicodeEmoji, User } from "@vencord/discord-types";
|
||||
import { PermissionOverwriteType } from "@vencord/discord-types/enums";
|
||||
import { findByCodeLazy } from "@webpack";
|
||||
import { ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildRoleStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, useMemo, UserStore, useState, useStateFromStores } from "@webpack/common";
|
||||
import { ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildRoleStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, useMemo, useRef, UserStore, useState, useStateFromStores } from "@webpack/common";
|
||||
|
||||
import { settings } from "..";
|
||||
import { PermissionAllowedIcon, PermissionDefaultIcon, PermissionDeniedIcon } from "./icons";
|
||||
|
|
@ -204,25 +205,42 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea
|
|||
);
|
||||
}
|
||||
|
||||
function IDIcon() {
|
||||
return (
|
||||
<svg width="18" height="18" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M15.3 14.48c-.46.45-1.08.67-1.86.67h-1.39V9.2h1.39c.78 0 1.4.22 1.86.67.46.45.68 1.22.68 2.31 0 1.1-.22 1.86-.68 2.31Z" />
|
||||
<path fill="currentColor" fillRule="evenodd" clipRule="evenodd" d="M5 2a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3H5Zm1 15h2.04V7.34H6V17Zm4-9.66V17h3.44c1.46 0 2.6-.42 3.38-1.25.8-.83 1.2-2.02 1.2-3.58s-.4-2.75-1.2-3.58c-.79-.83-1.92-1.25-3.38-1.25H10Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: string; onClose: () => void; }) {
|
||||
const popoutRef = useRef(null);
|
||||
const role = GuildRoleStore.getRole(guild.id, roleId);
|
||||
const { before, after } = buildExtraRoleContextMenuItems(role, guild, popoutRef);
|
||||
|
||||
return (
|
||||
<Menu.Menu
|
||||
navId={cl("role-context-menu")}
|
||||
onClose={ContextMenuApi.closeContextMenu}
|
||||
aria-label="Role Options"
|
||||
>
|
||||
{before}
|
||||
|
||||
<Menu.MenuItem
|
||||
id={cl("copy-role-id")}
|
||||
label={getIntlMessage("COPY_ID_ROLE")}
|
||||
action={() => {
|
||||
copyToClipboard(roleId);
|
||||
}}
|
||||
icon={IDIcon}
|
||||
action={() => copyToClipboard(roleId)}
|
||||
/>
|
||||
|
||||
{after}
|
||||
|
||||
{(settings.store as any).unsafeViewAsRole && (
|
||||
<Menu.MenuItem
|
||||
id={cl("view-as-role")}
|
||||
label={getIntlMessage("VIEW_AS_ROLE")}
|
||||
icon={() => <RightArrow height={18} width={18} />}
|
||||
action={() => {
|
||||
const role = GuildRoleStore.getRole(guild.id, roleId);
|
||||
if (!role) return;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue