Fix VencordToolbox & PermissionsViewer

Fixes components using popups as they now require you to pass a targetElementRef
This commit is contained in:
Nuckyz 2025-05-21 00:05:58 -03:00
parent e487529f06
commit bd4519a816
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
3 changed files with 39 additions and 29 deletions

View file

@ -26,7 +26,7 @@ import { Devs } from "@utils/constants";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
import { Button, ChannelStore, Dialog, GuildMemberStore, GuildStore, match, Menu, PermissionsBits, Popout, TooltipContainer, UserStore } from "@webpack/common"; import { Button, ChannelStore, Dialog, GuildMemberStore, GuildStore, match, Menu, PermissionsBits, Popout, TooltipContainer, useRef, UserStore } from "@webpack/common";
import type { Guild, GuildMember } from "discord-types/general"; import type { Guild, GuildMember } from "discord-types/general";
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions"; import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions";
@ -173,32 +173,38 @@ export default definePlugin({
} }
], ],
ViewPermissionsButton: ErrorBoundary.wrap(({ guild, guildMember }: { guild: Guild; guildMember: GuildMember; }) => ( ViewPermissionsButton: ErrorBoundary.wrap(({ guild, guildMember }: { guild: Guild; guildMember: GuildMember; }) => {
<Popout const buttonRef = useRef(null);
position="bottom"
align="center" return (
renderPopout={({ closePopout }) => ( <Popout
<Dialog className={PopoutClasses.container} style={{ width: "500px" }}> position="bottom"
<UserPermissions guild={guild} guildMember={guildMember} closePopout={closePopout} /> align="center"
</Dialog> targetElementRef={buttonRef}
)} renderPopout={({ closePopout }) => (
> <Dialog className={PopoutClasses.container} style={{ width: "500px" }}>
{popoutProps => ( <UserPermissions guild={guild} guildMember={guildMember} closePopout={closePopout} />
<TooltipContainer text="View Permissions"> </Dialog>
<Button )}
{...popoutProps} >
color={Button.Colors.CUSTOM} {popoutProps => (
look={Button.Looks.FILLED} <TooltipContainer text="View Permissions">
size={Button.Sizes.NONE} <Button
innerClassName={classes(RoleButtonClasses.buttonInner, RoleButtonClasses.icon)} {...popoutProps}
className={classes(RoleButtonClasses.button, RoleButtonClasses.icon, "vc-permviewer-role-button")} buttonRef={buttonRef}
> color={Button.Colors.CUSTOM}
<SafetyIcon height="16" width="16" /> look={Button.Looks.FILLED}
</Button> size={Button.Sizes.NONE}
</TooltipContainer> innerClassName={classes(RoleButtonClasses.buttonInner, RoleButtonClasses.icon)}
)} className={classes(RoleButtonClasses.button, RoleButtonClasses.icon, "vc-permviewer-role-button")}
</Popout> >
), { noop: true }), <SafetyIcon height="16" width="16" />
</Button>
</TooltipContainer>
)}
</Popout>
);
}, { noop: true }),
contextMenus: { contextMenus: {
"user-context": makeContextMenuPatch("roles", MenuItemParentType.User), "user-context": makeContextMenuPatch("roles", MenuItemParentType.User),

View file

@ -24,7 +24,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findComponentByCodeLazy } from "@webpack"; import { findComponentByCodeLazy } from "@webpack";
import { Menu, Popout, useState } from "@webpack/common"; import { Menu, Popout, useRef, useState } from "@webpack/common";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
const HeaderBarIcon = findComponentByCodeLazy(".HEADER_BAR_BADGE_TOP:", '.iconBadge,"top"'); const HeaderBarIcon = findComponentByCodeLazy(".HEADER_BAR_BADGE_TOP:", '.iconBadge,"top"');
@ -95,6 +95,7 @@ function VencordPopoutIcon(isShown: boolean) {
} }
function VencordPopoutButton() { function VencordPopoutButton() {
const buttonRef = useRef(null);
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
return ( return (
@ -104,10 +105,12 @@ function VencordPopoutButton() {
animation={Popout.Animation.NONE} animation={Popout.Animation.NONE}
shouldShow={show} shouldShow={show}
onRequestClose={() => setShow(false)} onRequestClose={() => setShow(false)}
targetElementRef={buttonRef}
renderPopout={() => VencordPopout(() => setShow(false))} renderPopout={() => VencordPopout(() => setShow(false))}
> >
{(_, { isShown }) => ( {(_, { isShown }) => (
<HeaderBarIcon <HeaderBarIcon
ref={buttonRef}
className="vc-toolbox-btn" className="vc-toolbox-btn"
onClick={() => setShow(v => !v)} onClick={() => setShow(v => !v)}
tooltip={isShown ? null : "Vencord Toolbox"} tooltip={isShown ? null : "Vencord Toolbox"}

View file

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import type { ComponentClass, ComponentPropsWithRef, ComponentType, CSSProperties, FunctionComponent, HtmlHTMLAttributes, HTMLProps, JSX, KeyboardEvent, MouseEvent, PointerEvent, PropsWithChildren, ReactNode, Ref } from "react"; import type { ComponentClass, ComponentPropsWithRef, ComponentType, CSSProperties, FunctionComponent, HtmlHTMLAttributes, HTMLProps, JSX, KeyboardEvent, MouseEvent, PointerEvent, PropsWithChildren, ReactNode, Ref, RefObject } from "react";
export type TextVariant = "heading-sm/normal" | "heading-sm/medium" | "heading-sm/semibold" | "heading-sm/bold" | "heading-md/normal" | "heading-md/medium" | "heading-md/semibold" | "heading-md/bold" | "heading-lg/normal" | "heading-lg/medium" | "heading-lg/semibold" | "heading-lg/bold" | "heading-xl/normal" | "heading-xl/medium" | "heading-xl/bold" | "heading-xxl/normal" | "heading-xxl/medium" | "heading-xxl/bold" | "eyebrow" | "heading-deprecated-14/normal" | "heading-deprecated-14/medium" | "heading-deprecated-14/bold" | "text-xxs/normal" | "text-xxs/medium" | "text-xxs/semibold" | "text-xxs/bold" | "text-xs/normal" | "text-xs/medium" | "text-xs/semibold" | "text-xs/bold" | "text-sm/normal" | "text-sm/medium" | "text-sm/semibold" | "text-sm/bold" | "text-md/normal" | "text-md/medium" | "text-md/semibold" | "text-md/bold" | "text-lg/normal" | "text-lg/medium" | "text-lg/semibold" | "text-lg/bold" | "display-sm" | "display-md" | "display-lg" | "code"; export type TextVariant = "heading-sm/normal" | "heading-sm/medium" | "heading-sm/semibold" | "heading-sm/bold" | "heading-md/normal" | "heading-md/medium" | "heading-md/semibold" | "heading-md/bold" | "heading-lg/normal" | "heading-lg/medium" | "heading-lg/semibold" | "heading-lg/bold" | "heading-xl/normal" | "heading-xl/medium" | "heading-xl/bold" | "heading-xxl/normal" | "heading-xxl/medium" | "heading-xxl/bold" | "eyebrow" | "heading-deprecated-14/normal" | "heading-deprecated-14/medium" | "heading-deprecated-14/bold" | "text-xxs/normal" | "text-xxs/medium" | "text-xxs/semibold" | "text-xxs/bold" | "text-xs/normal" | "text-xs/medium" | "text-xs/semibold" | "text-xs/bold" | "text-sm/normal" | "text-sm/medium" | "text-sm/semibold" | "text-sm/bold" | "text-md/normal" | "text-md/medium" | "text-md/semibold" | "text-md/bold" | "text-lg/normal" | "text-lg/medium" | "text-lg/semibold" | "text-lg/bold" | "display-sm" | "display-md" | "display-lg" | "code";
@ -426,6 +426,7 @@ export type Popout = ComponentType<{
} }
): ReactNode; ): ReactNode;
shouldShow?: boolean; shouldShow?: boolean;
targetElementRef: RefObject<any>;
renderPopout(args: { renderPopout(args: {
closePopout(): void; closePopout(): void;
isPositioned: boolean; isPositioned: boolean;