From ade5b06e1c294e46b42670593f842bf86731c49c Mon Sep 17 00:00:00 2001 From: Amy Date: Sat, 11 Apr 2026 14:39:08 -0400 Subject: [PATCH 1/7] chore: create RemoveMember modal Signed-off-by: Amy --- packages/client/components/modal/modals.tsx | 3 ++ .../components/modal/modals/RemoveMember.tsx | 50 +++++++++++++++++++ packages/client/components/modal/types.ts | 7 ++- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 packages/client/components/modal/modals/RemoveMember.tsx diff --git a/packages/client/components/modal/modals.tsx b/packages/client/components/modal/modals.tsx index 9da2b50ee..729cac803 100644 --- a/packages/client/components/modal/modals.tsx +++ b/packages/client/components/modal/modals.tsx @@ -57,6 +57,7 @@ import { UserProfileModal } from "./modals/UserProfile"; import { UserProfileMutualFriendsModal } from "./modals/UserProfileMutualFriends"; import { UserProfileMutualGroupsModal } from "./modals/UserProfileMutualGroups"; import { UserProfileRolesModal } from "./modals/UserProfileRoles"; +import { RemoveMemberModal } from "./modals/RemoveMember"; /** * Render the modal @@ -183,6 +184,8 @@ export function RenderModal(props: ActiveModal & { onClose: () => void }) { return ; case "edit_category": return ; + case "remove_member": + return ; default: console.error( diff --git a/packages/client/components/modal/modals/RemoveMember.tsx b/packages/client/components/modal/modals/RemoveMember.tsx new file mode 100644 index 000000000..207a13d76 --- /dev/null +++ b/packages/client/components/modal/modals/RemoveMember.tsx @@ -0,0 +1,50 @@ +import { Trans } from "@lingui-solid/solid/macro"; + +import { Avatar, Column, Dialog, DialogProps, Text } from "@revolt/ui"; + +import { useMutation } from "@tanstack/solid-query"; +import { useModals } from ".."; +import { Modals } from "../types"; + +/** + * Ban a server member with reason + */ +export function RemoveMemberModal( + props: DialogProps & Modals & { type: "remove_member" }, +) { + const { showError } = useModals(); + + const removeMember = useMutation(() => ({ + mutationFn: (user: string) => { + return props.group.removeMember(user); + }, + onError: showError, + })); + + return ( + Remove Member} + actions={[ + { text: Cancel }, + { + text: Remove, + onClick: () => removeMember.mutateAsync(props.user.id), + }, + ]} + isDisabled={removeMember.isPending} + > + + + + + Are you sure you want to remove{" "} + {props.user?.displayName ?? props.user.username} from{" "} + {props.group.name}? + + + + + ); +} diff --git a/packages/client/components/modal/types.ts b/packages/client/components/modal/types.ts index a6c6a020e..44da67f65 100644 --- a/packages/client/components/modal/types.ts +++ b/packages/client/components/modal/types.ts @@ -6,9 +6,9 @@ import { Emoji, File, ImageEmbed, + Message, MFA, MFATicket, - Message, PublicBot, PublicChannelInvite, Server, @@ -314,4 +314,9 @@ export type Modals = type: "edit_category"; server: Server; category: CategoryData; + } + | { + type: "remove_member"; + group: Channel; + user: User; }; From 0b93231ad3375721bcaf37b87298eb9689615af1 Mon Sep 17 00:00:00 2001 From: Amy Date: Sat, 11 Apr 2026 15:38:52 -0400 Subject: [PATCH 2/7] feat: remove group members closes #1026 Signed-off-by: Amy --- .../components/app/menus/UserContextMenu.tsx | 46 ++++++++++++++++--- .../interface/channels/text/MemberSidebar.tsx | 16 +++++-- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/packages/client/components/app/menus/UserContextMenu.tsx b/packages/client/components/app/menus/UserContextMenu.tsx index d67cdee22..8e795132d 100644 --- a/packages/client/components/app/menus/UserContextMenu.tsx +++ b/packages/client/components/app/menus/UserContextMenu.tsx @@ -1,4 +1,4 @@ -import { JSX, Match, Show, Switch } from "solid-js"; +import { createEffect, JSX, Match, Show, Switch } from "solid-js"; import { Trans } from "@lingui-solid/solid/macro"; import { useNavigate } from "@solidjs/router"; @@ -29,11 +29,7 @@ import MdReport from "@material-design-icons/svg/outlined/report.svg?component-s import MdChecked from "@material-symbols/svg-400/outlined/check_box.svg?component-solid"; import MdUnchecked from "@material-symbols/svg-400/outlined/check_box_outline_blank.svg?component-solid"; -import { - ContextMenu, - ContextMenuButton, - ContextMenuDivider, -} from "./ContextMenu"; +import { ContextMenu, ContextMenuButton, ContextMenuDivider } from "./ContextMenu"; import { NotificationContextMenu } from "./shared/NotificationContextMenu"; /** @@ -56,6 +52,10 @@ export function UserContextMenu(props: { // server context const params = useSmartParams(); + createEffect(() => { + console.log(props.channel?.type); + }); + /** * Open direct message channel */ @@ -189,6 +189,17 @@ export function UserContextMenu(props: { navigator.clipboard.writeText(props.user.id); } + /** + * Remove user from group + */ + function removeMember() { + openModal({ + type: "remove_member", + user: props.user, + group: props.channel!, + }); + } + return ( @@ -328,6 +339,22 @@ export function UserContextMenu(props: { + + + Remove Member + + + + + Report user @@ -414,11 +443,14 @@ export function UserContextMenu(props: { * Provide floating user menus on this element * @param user User * @param member Server Member + * @param contextMessage Message + * @param contextGroup Group */ export function floatingUserMenus( user: User, member?: ServerMember, contextMessage?: Message, + contextGroup?: Channel, ): JSX.Directives["floating"] & object { return { userCard: { @@ -435,7 +467,7 @@ export function floatingUserMenus( user={user} member={member} contextMessage={contextMessage} - channel={contextMessage?.channel} + channel={contextMessage?.channel ?? contextGroup} /> ); }, diff --git a/packages/client/src/interface/channels/text/MemberSidebar.tsx b/packages/client/src/interface/channels/text/MemberSidebar.tsx index 7c3835a5c..ee7dfe905 100644 --- a/packages/client/src/interface/channels/text/MemberSidebar.tsx +++ b/packages/client/src/interface/channels/text/MemberSidebar.tsx @@ -1,4 +1,4 @@ -import { Match, Show, Switch, createEffect, createMemo, on } from "solid-js"; +import { createEffect, createMemo, Match, on, Show, Switch } from "solid-js"; import { useLingui } from "@lingui-solid/solid/macro"; import { VirtualContainer } from "@minht11/solid-virtual-container"; @@ -16,9 +16,9 @@ import { OverflowingText, Row, Tooltip, - UserStatus, - Username, typography, + Username, + UserStatus, } from "@revolt/ui"; interface Props { @@ -311,7 +311,7 @@ export function GroupMemberSidebar(props: Props) { width: "100%", }} > - + )} @@ -378,7 +378,11 @@ const NameStatusStack = styled("div", { /** * Member */ -function Member(props: { user?: User; member?: ServerMember }) { +function Member(props: { + user?: User; + member?: ServerMember; + group?: Channel; +}) { const { t } = useLingui(); /** @@ -408,6 +412,8 @@ function Member(props: { user?: User; member?: ServerMember }) { use:floating={floatingUserMenus( (props.user ?? props.member?.user)!, props.member, + undefined, + props.group, )} > Date: Sat, 11 Apr 2026 15:52:57 -0400 Subject: [PATCH 3/7] chore: prevent non-owners from removing the group owner Signed-off-by: Amy --- packages/client/components/app/menus/UserContextMenu.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/components/app/menus/UserContextMenu.tsx b/packages/client/components/app/menus/UserContextMenu.tsx index 8e795132d..2e9dfaccd 100644 --- a/packages/client/components/app/menus/UserContextMenu.tsx +++ b/packages/client/components/app/menus/UserContextMenu.tsx @@ -343,7 +343,8 @@ export function UserContextMenu(props: { when={ props.channel?.type === "Group" && !props.user.self && - props.channel.havePermission("ManageChannel") + props.channel.havePermission("ManageChannel") && + !props.channel.owner?.self } > Date: Sat, 11 Apr 2026 15:56:41 -0400 Subject: [PATCH 4/7] chore: run formatter Signed-off-by: Amy --- packages/client/components/modal/modals.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/components/modal/modals.tsx b/packages/client/components/modal/modals.tsx index 729cac803..7c770a3e5 100644 --- a/packages/client/components/modal/modals.tsx +++ b/packages/client/components/modal/modals.tsx @@ -45,6 +45,7 @@ import { MFAFlowModal } from "./modals/MFAFlow"; import { MFARecoveryModal } from "./modals/MFARecovery"; import { OnboardingModal } from "./modals/Onboarding"; import { PolicyChangeModal } from "./modals/PolicyChange"; +import { RemoveMemberModal } from "./modals/RemoveMember"; import { RenameSessionModal } from "./modals/RenameSession"; import { ReportContentModal } from "./modals/ReportContent"; import { ResetBotTokenModal } from "./modals/ResetBotToken"; @@ -57,7 +58,6 @@ import { UserProfileModal } from "./modals/UserProfile"; import { UserProfileMutualFriendsModal } from "./modals/UserProfileMutualFriends"; import { UserProfileMutualGroupsModal } from "./modals/UserProfileMutualGroups"; import { UserProfileRolesModal } from "./modals/UserProfileRoles"; -import { RemoveMemberModal } from "./modals/RemoveMember"; /** * Render the modal From 1fa08ac23c34c618175ca0626526f3e3796d379f Mon Sep 17 00:00:00 2001 From: Amy Date: Sat, 11 Apr 2026 16:08:26 -0400 Subject: [PATCH 5/7] chore: make prettier shut the fuck up about eol im on windows, which prefers crlf but prettier expects lf by default this makes prettier shut the fuck up about those since they add visual noise (webstorm and prettier lint warn about those) and git converts those to crlf after committing anyway (see core.autocrlf) Signed-off-by: Amy --- .prettierrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index 77039d87f..15acb02b2 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,5 +2,6 @@ "tabWidth": 2, "useTabs": false, "plugins": ["prettier-plugin-organize-imports"], - "organizeImportsTypeOrder": "first" + "organizeImportsTypeOrder": "first", + "endOfLine": "auto" } From 524901c825c308d77e9699841ff586efdcd1cd68 Mon Sep 17 00:00:00 2001 From: Amy Date: Sat, 11 Apr 2026 16:11:40 -0400 Subject: [PATCH 6/7] chore: run formatter (for real) Signed-off-by: Amy --- packages/client/components/app/menus/UserContextMenu.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/client/components/app/menus/UserContextMenu.tsx b/packages/client/components/app/menus/UserContextMenu.tsx index 2e9dfaccd..3fd149efc 100644 --- a/packages/client/components/app/menus/UserContextMenu.tsx +++ b/packages/client/components/app/menus/UserContextMenu.tsx @@ -29,7 +29,11 @@ import MdReport from "@material-design-icons/svg/outlined/report.svg?component-s import MdChecked from "@material-symbols/svg-400/outlined/check_box.svg?component-solid"; import MdUnchecked from "@material-symbols/svg-400/outlined/check_box_outline_blank.svg?component-solid"; -import { ContextMenu, ContextMenuButton, ContextMenuDivider } from "./ContextMenu"; +import { + ContextMenu, + ContextMenuButton, + ContextMenuDivider, +} from "./ContextMenu"; import { NotificationContextMenu } from "./shared/NotificationContextMenu"; /** From 9718ef784827ee18d8bf4d02c9dd541c3378db6d Mon Sep 17 00:00:00 2001 From: Amy Date: Sun, 12 Apr 2026 09:47:37 -0400 Subject: [PATCH 7/7] chore: remove stray console log Signed-off-by: Amy --- packages/client/components/app/menus/UserContextMenu.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/client/components/app/menus/UserContextMenu.tsx b/packages/client/components/app/menus/UserContextMenu.tsx index 3fd149efc..a2a9beaaf 100644 --- a/packages/client/components/app/menus/UserContextMenu.tsx +++ b/packages/client/components/app/menus/UserContextMenu.tsx @@ -1,4 +1,4 @@ -import { createEffect, JSX, Match, Show, Switch } from "solid-js"; +import { JSX, Match, Show, Switch } from "solid-js"; import { Trans } from "@lingui-solid/solid/macro"; import { useNavigate } from "@solidjs/router"; @@ -56,10 +56,6 @@ export function UserContextMenu(props: { // server context const params = useSmartParams(); - createEffect(() => { - console.log(props.channel?.type); - }); - /** * Open direct message channel */