diff --git a/app/soapbox/components/groups/group-avatar.tsx b/app/soapbox/components/groups/group-avatar.tsx index b862a92c0..91d6808d2 100644 --- a/app/soapbox/components/groups/group-avatar.tsx +++ b/app/soapbox/components/groups/group-avatar.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import React from 'react'; -import { useGroupRoles } from 'soapbox/hooks/useGroupRoles'; +import { GroupRoles } from 'soapbox/schemas/group-member'; import { Avatar } from '../ui'; @@ -16,17 +16,15 @@ interface IGroupAvatar { const GroupAvatar = (props: IGroupAvatar) => { const { group, size, withRing = false } = props; - const { normalizeRole } = useGroupRoles(); - - const isAdmin = normalizeRole(group.relationship?.role as any) === 'admin'; + const isOwner = group.relationship?.role === GroupRoles.OWNER; return ( { const features = useFeatures(); const intl = useIntl(); - const { roles, isAdminRole, normalizeRole } = useGroupRoles(); const blockGroupMember = useBlockGroupMember(group, member); const promoteGroupMember = usePromoteGroupMember(group, member); const demoteGroupMember = useDemoteGroupMember(group, member); @@ -57,13 +54,13 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { const account = useAccount(member.account.id) as AccountEntity; // Current user role - const isCurrentUserAdmin = normalizeRole(group.relationship?.role as any) === BaseGroupRoles.ADMIN; - const isCurrentUserModerator = normalizeRole(group.relationship?.role as any) === BaseGroupRoles.MODERATOR; + const isCurrentUserOwner = group.relationship?.role === GroupRoles.OWNER; + const isCurrentUserAdmin = group.relationship?.role === GroupRoles.ADMIN; // Member role - const isMemberAdmin = normalizeRole(member.role as any) === BaseGroupRoles.ADMIN; - const isMemberModerator = normalizeRole(member.role as any) === BaseGroupRoles.MODERATOR; - const isMemberUser = normalizeRole(member.role as any) === BaseGroupRoles.USER; + const isMemberOwner = member.role === GroupRoles.OWNER; + const isMemberAdmin = member.role === GroupRoles.ADMIN; + const isMemberUser = member.role === GroupRoles.USER; const handleKickFromGroup = () => { dispatch(openModal('CONFIRM', { @@ -91,44 +88,26 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { })); }; - const onPromote = (role: TruthSocialGroupRoles | BaseGroupRoles, warning?: boolean) => { - if (warning) { - return dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.promoteConfirmMessage, { name: account.username }), - confirm: intl.formatMessage(messages.promoteConfirm), - onConfirm: () => { - promoteGroupMember({ role: role, account_ids: [account.id] }, { - onSuccess() { - toast.success( - intl.formatMessage( - isAdminRole(role) ? messages.promotedToAdmin : messages.promotedToMod, { name: account.acct, role }, - ), - ); - }, - }); - }, - })); - } else { - promoteGroupMember({ role: role, account_ids: [account.id] }, { - onSuccess() { - toast.success( - intl.formatMessage( - isAdminRole(role) ? messages.promotedToAdmin : messages.promotedToMod, { name: account.acct, role }, - ), - ); - }, - }); - } + const handleAdminAssignment = () => { + dispatch(openModal('CONFIRM', { + heading: intl.formatMessage(messages.promoteConfirm), + message: intl.formatMessage(messages.promoteConfirmMessage, { name: account.username }), + confirm: intl.formatMessage(messages.promoteConfirm), + confirmationTheme: 'primary', + onConfirm: () => { + promoteGroupMember({ role: GroupRoles.ADMIN, account_ids: [account.id] }, { + onSuccess() { + toast.success( + intl.formatMessage(messages.promotedToAdmin, { name: account.acct }), + ); + }, + }); + }, + })); }; - const handlePromoteToGroupAdmin = () => onPromote(roles.admin, true); - - const handleAssignModerator = () => { - onPromote(roles.moderator, false); - }; - - const handleDemote = () => { - demoteGroupMember({ role: roles.user, account_ids: [account.id] }, { + const handleUserAssignment = () => { + demoteGroupMember({ role: GroupRoles.USER, account_ids: [account.id] }, { onSuccess() { toast.success(intl.formatMessage(messages.demotedToUser, { name: account.acct })); }, @@ -142,34 +121,26 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { return items; } - if (isCurrentUserAdmin && !isMemberAdmin && account.acct === account.username) { - if (isMemberModerator) { - if (features.groupsPromoteToAdmin) { - items.push({ - text: intl.formatMessage(messages.groupModPromoteAdmin, { name: account.username }), - icon: require('@tabler/icons/arrow-up-circle.svg'), - action: handlePromoteToGroupAdmin, - }); - } - + if (isCurrentUserOwner) { + if (isMemberUser) { items.push({ - text: intl.formatMessage(messages.groupModDemote, { role: roles.moderator, name: account.username }), + text: intl.formatMessage(messages.groupModPromoteMod, { role: GroupRoles.ADMIN }), icon: require('@tabler/icons/briefcase.svg'), - action: handleDemote, - destructive: true, + action: handleAdminAssignment, }); - } else if (isMemberUser) { + } else if (isMemberAdmin) { items.push({ - text: intl.formatMessage(messages.groupModPromoteMod, { role: roles.moderator }), + text: intl.formatMessage(messages.groupModDemote, { role: GroupRoles.ADMIN, name: account.username }), icon: require('@tabler/icons/briefcase.svg'), - action: handleAssignModerator, + action: handleUserAssignment, + destructive: true, }); } } if ( - (isCurrentUserAdmin || isCurrentUserModerator) && - (isMemberModerator || isMemberUser) && + (isCurrentUserOwner || isCurrentUserAdmin) && + (isMemberAdmin || isMemberUser) && member.role !== group.relationship.role ) { if (features.groupsKick) { @@ -198,12 +169,12 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { - {(isMemberAdmin || isMemberModerator) ? ( + {(isMemberOwner || isMemberAdmin) ? ( diff --git a/app/soapbox/features/group/group-members.tsx b/app/soapbox/features/group/group-members.tsx index 99ae8c28a..9fa1d135f 100644 --- a/app/soapbox/features/group/group-members.tsx +++ b/app/soapbox/features/group/group-members.tsx @@ -2,8 +2,8 @@ import React, { useMemo } from 'react'; import ScrollableList from 'soapbox/components/scrollable-list'; import { useGroupMembers } from 'soapbox/hooks/api/useGroupMembers'; -import { useGroupRoles } from 'soapbox/hooks/useGroupRoles'; import { useGroup } from 'soapbox/queries/groups'; +import { GroupRoles } from 'soapbox/schemas/group-member'; import PlaceholderAccount from '../placeholder/components/placeholder-account'; @@ -16,22 +16,20 @@ interface IGroupMembers { } const GroupMembers: React.FC = (props) => { - const { roles: { admin, moderator, user } } = useGroupRoles(); - const groupId = props.params.id; const { group, isFetching: isFetchingGroup } = useGroup(groupId); - const { groupMembers: admins, isFetching: isFetchingAdmins } = useGroupMembers(groupId, admin); - const { groupMembers: moderators, isFetching: isFetchingModerators } = useGroupMembers(groupId, moderator); - const { groupMembers: users, isFetching: isFetchingUsers, fetchNextPage, hasNextPage } = useGroupMembers(groupId, user); + const { groupMembers: owners, isFetching: isFetchingOwners } = useGroupMembers(groupId, GroupRoles.OWNER); + const { groupMembers: admins, isFetching: isFetchingAdmins } = useGroupMembers(groupId, GroupRoles.ADMIN); + const { groupMembers: users, isFetching: isFetchingUsers, fetchNextPage, hasNextPage } = useGroupMembers(groupId, GroupRoles.USER); - const isLoading = isFetchingGroup || isFetchingAdmins || isFetchingModerators || isFetchingUsers; + const isLoading = isFetchingGroup || isFetchingOwners || isFetchingAdmins || isFetchingUsers; const members = useMemo(() => [ + ...owners, ...admins, - ...moderators, ...users, - ], [admins, moderators, users]); + ], [owners, admins, users]); return ( <> diff --git a/app/soapbox/hooks/useGroupRoles.ts b/app/soapbox/hooks/useGroupRoles.ts deleted file mode 100644 index 138c8685e..000000000 --- a/app/soapbox/hooks/useGroupRoles.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { TRUTHSOCIAL } from 'soapbox/utils/features'; - -import { useBackend } from './useBackend'; - -enum TruthSocialGroupRoles { - ADMIN = 'owner', - MODERATOR = 'admin', - USER = 'user' -} - -enum BaseGroupRoles { - ADMIN = 'admin', - MODERATOR = 'moderator', - USER = 'user' -} - -const roleMap = { - [TruthSocialGroupRoles.ADMIN]: BaseGroupRoles.ADMIN, - [TruthSocialGroupRoles.MODERATOR]: BaseGroupRoles.MODERATOR, - [TruthSocialGroupRoles.USER]: BaseGroupRoles.USER, -}; - -/** - * Returns the correct role name depending on the used backend. - * - * @returns Object - */ -const useGroupRoles = () => { - const version = useBackend(); - const isTruthSocial = version.software === TRUTHSOCIAL; - const selectedRoles = isTruthSocial ? TruthSocialGroupRoles : BaseGroupRoles; - - const isAdminRole = (role: TruthSocialGroupRoles | BaseGroupRoles) => { - if (isTruthSocial) { - return role === TruthSocialGroupRoles.ADMIN; - } - - return role === BaseGroupRoles.ADMIN; - }; - - const normalizeRole = (role: TruthSocialGroupRoles) => { - if (isTruthSocial) { - return roleMap[role]; - } - - return role; - }; - - return { - isAdminRole, - normalizeRole, - roles: { - admin: selectedRoles.ADMIN, - moderator: selectedRoles.MODERATOR, - user: selectedRoles.USER, - }, - }; -}; - -export { useGroupRoles, TruthSocialGroupRoles, BaseGroupRoles }; \ No newline at end of file diff --git a/app/soapbox/locales/en.json b/app/soapbox/locales/en.json index ef79fb48a..5e3bcbae5 100644 --- a/app/soapbox/locales/en.json +++ b/app/soapbox/locales/en.json @@ -470,8 +470,8 @@ "confirmations.block.confirm": "Block", "confirmations.block.heading": "Block @{name}", "confirmations.block.message": "Are you sure you want to block {name}?", - "confirmations.block_from_group.confirm": "Block", - "confirmations.block_from_group.heading": "Block group member", + "confirmations.block_from_group.confirm": "Ban User", + "confirmations.block_from_group.heading": "Ban From Group", "confirmations.block_from_group.message": "Are you sure you want to ban @{name} from the group?", "confirmations.cancel.confirm": "Discard", "confirmations.cancel.heading": "Discard post", @@ -771,7 +771,7 @@ "group.group_mod_authorize": "Accept", "group.group_mod_authorize.success": "Accepted @{name} to group", "group.group_mod_block": "Ban from group", - "group.group_mod_block.success": "You have successfully blocked @{name} from the group", + "group.group_mod_block.success": "@{name} is banned", "group.group_mod_demote": "Remove {role} role", "group.group_mod_demote.success": "Demoted @{name} to group user", "group.group_mod_kick": "Kick @{name} from group", diff --git a/app/soapbox/main.tsx b/app/soapbox/main.tsx index f5cf9f0f5..bfc31649e 100644 --- a/app/soapbox/main.tsx +++ b/app/soapbox/main.tsx @@ -41,9 +41,9 @@ ready(() => { root.render(); - if (BuildConfig.NODE_ENV === 'production') { - // avoid offline in dev mode because it's harder to debug - // https://github.com/NekR/offline-plugin/pull/201#issuecomment-285133572 - OfflinePluginRuntime.install(); - } + // if (BuildConfig.NODE_ENV === 'production') { + // avoid offline in dev mode because it's harder to debug + // https://github.com/NekR/offline-plugin/pull/201#issuecomment-285133572 + OfflinePluginRuntime.install(); + // } }); \ No newline at end of file diff --git a/app/soapbox/queries/groups/members.ts b/app/soapbox/queries/groups/members.ts index d1707fb6c..4d0a0bb66 100644 --- a/app/soapbox/queries/groups/members.ts +++ b/app/soapbox/queries/groups/members.ts @@ -1,14 +1,14 @@ import { useQuery } from '@tanstack/react-query'; import { useApi } from 'soapbox/hooks'; -import { useGroupRoles } from 'soapbox/hooks/useGroupRoles'; import { normalizeAccount } from 'soapbox/normalizers'; +import { GroupRoles } from 'soapbox/schemas/group-member'; const GroupMemberKeys = { members: (id: string, role: string) => ['group', id, role] as const, }; -const useGroupMembers = (groupId: string, role: ReturnType['roles']['admin']) => { +const useGroupMembers = (groupId: string, role: GroupRoles) => { const api = useApi(); const getQuery = async () => { diff --git a/app/soapbox/schemas/group-member.ts b/app/soapbox/schemas/group-member.ts index 73e051588..4521450cb 100644 --- a/app/soapbox/schemas/group-member.ts +++ b/app/soapbox/schemas/group-member.ts @@ -2,27 +2,18 @@ import z from 'zod'; import { accountSchema } from './account'; -enum TruthSocialGroupRoles { - ADMIN = 'owner', - MODERATOR = 'admin', - USER = 'user' -} - -enum BaseGroupRoles { +enum GroupRoles { + OWNER = 'owner', ADMIN = 'admin', - MODERATOR = 'moderator', USER = 'user' } const groupMemberSchema = z.object({ id: z.string(), account: accountSchema, - role: z.union([ - z.nativeEnum(TruthSocialGroupRoles), - z.nativeEnum(BaseGroupRoles), - ]), + role: z.nativeEnum(GroupRoles), }); type GroupMember = z.infer; -export { groupMemberSchema, GroupMember }; \ No newline at end of file +export { groupMemberSchema, GroupMember, GroupRoles }; \ No newline at end of file