diff --git a/native/roles/change-roles-header-right-button.react.js b/native/roles/change-roles-header-right-button.react.js new file mode 100644 --- /dev/null +++ b/native/roles/change-roles-header-right-button.react.js @@ -0,0 +1,72 @@ +// @flow + +import { useNavigation } from '@react-navigation/native'; +import invariant from 'invariant'; +import * as React from 'react'; +import { Text } from 'react-native'; +import { TouchableOpacity } from 'react-native-gesture-handler'; + +import { + changeThreadMemberRoles, + changeThreadMemberRolesActionTypes, +} from 'lib/actions/thread-actions.js'; +import { + useDispatchActionPromise, + useServerCall, +} from 'lib/utils/action-utils.js'; + +import type { NavigationRoute } from '../navigation/route-names'; +import { useColors } from '../themes/colors.js'; + +type Props = { + +route: NavigationRoute<'ChangeRolesScreen'>, +}; + +function ChangeRolesHeaderRightButton(props: Props): React.Node { + const { threadInfo, memberInfo, role: selectedRole } = props.route.params; + const { role: initialRole } = memberInfo; + invariant(selectedRole, 'Expected selected role to be defined'); + const navigation = useNavigation(); + + const callChangeThreadMemberRoles = useServerCall(changeThreadMemberRoles); + const dispatchActionPromise = useDispatchActionPromise(); + + const { purpleLink } = useColors(); + const textStyle = React.useMemo( + () => ({ + color: purpleLink, + marginRight: 10, + }), + [purpleLink], + ); + + const handleSave = React.useCallback(() => { + if (selectedRole === initialRole) { + navigation.goBack(); + return; + } + + dispatchActionPromise( + changeThreadMemberRolesActionTypes, + callChangeThreadMemberRoles(threadInfo.id, [memberInfo.id], selectedRole), + ); + + navigation.goBack(); + }, [ + callChangeThreadMemberRoles, + dispatchActionPromise, + initialRole, + memberInfo.id, + navigation, + selectedRole, + threadInfo.id, + ]); + + return ( + + Save + + ); +} + +export default ChangeRolesHeaderRightButton; diff --git a/native/roles/change-roles-screen.react.js b/native/roles/change-roles-screen.react.js --- a/native/roles/change-roles-screen.react.js +++ b/native/roles/change-roles-screen.react.js @@ -3,13 +3,17 @@ import { useActionSheet } from '@expo/react-native-action-sheet'; import invariant from 'invariant'; import * as React from 'react'; -import { View, Text, Platform } from 'react-native'; +import { View, Text, Platform, ActivityIndicator } from 'react-native'; import { TouchableOpacity } from 'react-native-gesture-handler'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { changeThreadMemberRolesActionTypes } from 'lib/actions/thread-actions.js'; +import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; +import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types.js'; import { values } from 'lib/utils/objects.js'; +import ChangeRolesHeaderRightButton from './change-roles-header-right-button.react.js'; import UserAvatar from '../avatars/user-avatar.react.js'; import type { ChatNavigationProp } from '../chat/chat.react'; import SWMansionIcon from '../components/swmansion-icon.react.js'; @@ -28,11 +32,23 @@ +route: NavigationRoute<'ChangeRolesScreen'>, }; +const changeRolesLoadingStatusSelector = createLoadingStatusSelector( + changeThreadMemberRolesActionTypes, +); + function ChangeRolesScreen(props: Props): React.Node { - const { navigation } = props; + const { navigation, route } = props; const { threadInfo, memberInfo, role } = props.route.params; invariant(role, 'Role must be defined'); + const changeRolesLoadingStatus: LoadingStatus = useSelector( + changeRolesLoadingStatusSelector, + ); + const activityIndicatorStyle = React.useMemo( + () => ({ paddingRight: 15 }), + [], + ); + const styles = useStyles(unboundStyles); const [selectedRole, setSelectedRole] = React.useState(role); @@ -104,6 +120,24 @@ showActionSheetWithOptions, ]); + React.useEffect(() => { + navigation.setOptions({ + // eslint-disable-next-line react/display-name + headerRight: () => { + if (changeRolesLoadingStatus === 'loading') { + return ( + + ); + } + return ; + }, + }); + }, [changeRolesLoadingStatus, navigation, activityIndicatorStyle, route]); + return (