diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js new file mode 100644 --- /dev/null +++ b/lib/utils/role-utils.js @@ -0,0 +1,22 @@ +// @flow + +function constructRoleDeletionMessagePrompt( + defaultRoleName: string, + memberCount: number, +): string { + let message; + if (memberCount === 0) { + message = 'Are you sure you want to delete this role?'; + } else { + const messageNoun = memberCount === 1 ? 'member' : 'members'; + const messageVerb = memberCount === 1 ? 'is' : 'are'; + message = + `There ${messageVerb} currently ${memberCount} ${messageNoun} with ` + + `this role. Deleting the role will automatically assign the ` + + `${messageNoun} affected to the ${defaultRoleName} role.`; + } + + return message; +} + +export { constructRoleDeletionMessagePrompt }; diff --git a/native/roles/role-panel-entry.react.js b/native/roles/role-panel-entry.react.js --- a/native/roles/role-panel-entry.react.js +++ b/native/roles/role-panel-entry.react.js @@ -9,6 +9,7 @@ import type { UserSurfacedPermission } from 'lib/types/thread-permission-types.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; +import { useDisplayDeleteRoleAlert } from './role-utils.react.js'; import type { RolesNavigationProp } from './roles-navigator.react.js'; import CommIcon from '../components/comm-icon.react.js'; import SWMansionIcon from '../components/swmansion-icon.react.js'; @@ -38,15 +39,33 @@ ); invariant(existingRoleID, 'Role ID must exist for an existing role'); + const defaultRoleID = Object.keys(threadInfo.roles).find( + roleID => threadInfo.roles[roleID].isDefault, + ); + invariant(defaultRoleID, 'Default role ID must exist'); + + const displayDeleteRoleAlert = useDisplayDeleteRoleAlert( + threadInfo, + existingRoleID, + defaultRoleID, + memberCount, + ); + const options = React.useMemo(() => { const availableOptions = ['Edit role']; + // Since the `Members` role is able to be renamed, we need to check if the + // default role ID is the same as the existing role ID. + if (defaultRoleID !== existingRoleID) { + availableOptions.push('Delete role'); + } + if (Platform.OS === 'ios') { availableOptions.push('Cancel'); } return availableOptions; - }, []); + }, [defaultRoleID, existingRoleID]); const onOptionSelected = React.useCallback( (index: ?number) => { @@ -64,6 +83,8 @@ roleName, rolePermissions, }); + } else if (selectedOption === 'Delete role') { + displayDeleteRoleAlert(); } }, [ @@ -73,6 +94,7 @@ roleName, rolePermissions, threadInfo, + displayDeleteRoleAlert, ], ); diff --git a/native/roles/role-utils.react.js b/native/roles/role-utils.react.js new file mode 100644 --- /dev/null +++ b/native/roles/role-utils.react.js @@ -0,0 +1,64 @@ +// @flow + +import * as React from 'react'; +import { Alert } from 'react-native'; + +import { + deleteCommunityRole, + deleteCommunityRoleActionTypes, +} from 'lib/actions/thread-actions.js'; +import type { ThreadInfo } from 'lib/types/thread-types.js'; +import { + useDispatchActionPromise, + useServerCall, +} from 'lib/utils/action-utils.js'; +import { constructRoleDeletionMessagePrompt } from 'lib/utils/role-utils.js'; + +function useDisplayDeleteRoleAlert( + threadInfo: ThreadInfo, + existingRoleID: string, + defaultRoleID: string, + memberCount: number, +): () => void { + const defaultRoleName = threadInfo.roles[defaultRoleID].name; + const callDeleteCommunityRole = useServerCall(deleteCommunityRole); + const dispatchActionPromise = useDispatchActionPromise(); + + const onDeleteRole = React.useCallback(() => { + dispatchActionPromise( + deleteCommunityRoleActionTypes, + callDeleteCommunityRole({ + community: threadInfo.id, + roleID: existingRoleID, + }), + ); + }, [ + callDeleteCommunityRole, + dispatchActionPromise, + existingRoleID, + threadInfo.id, + ]); + + const message = constructRoleDeletionMessagePrompt( + defaultRoleName, + memberCount, + ); + + return React.useCallback( + () => + Alert.alert('Delete role', message, [ + { + text: 'Yes, delete role', + style: 'destructive', + onPress: onDeleteRole, + }, + { + text: 'Cancel', + style: 'cancel', + }, + ]), + [message, onDeleteRole], + ); +} + +export { useDisplayDeleteRoleAlert };