MM-42835_Invite People - add email+user invites

This commit is contained in:
Julian Mondragon
2023-01-23 12:59:57 -05:00
parent 3e4851e6fa
commit 557804ef45
5 changed files with 50 additions and 98 deletions

View File

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {Text, TouchableOpacity} from 'react-native';
import {Text, TouchableOpacity, View} from 'react-native';
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated';
import CompassIcon from '@components/compass_icon';
@@ -10,8 +10,10 @@ import {useTheme} from '@context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
type Props = {
email: string;
type SelectedChipProps = {
id: string;
text: string;
extra?: React.ReactNode;
onRemove: (id: string) => void;
testID?: string;
}
@@ -33,49 +35,59 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
marginRight: 8,
paddingHorizontal: 7,
},
remove: {
justifyContent: 'center',
marginLeft: 7,
extraContent: {
flexDirection: 'row',
alignItems: 'center',
color: theme.centerChannelColor,
},
text: {
marginLeft: 8,
color: theme.centerChannelColor,
...typography('Body', 100, 'SemiBold'),
},
remove: {
justifyContent: 'center',
marginLeft: 7,
},
};
});
export default function SelectedEmail({
email,
export default function SelectedChip({
id,
text,
extra,
onRemove,
testID,
}: Props) {
}: SelectedChipProps) {
const theme = useTheme();
const style = getStyleFromTheme(theme);
const onPress = useCallback(() => {
onRemove(email);
}, [onRemove, email]);
const selectedEmailTestID = `${testID}.${email}`;
onRemove(id);
}, [onRemove, id]);
return (
<Animated.View
entering={FadeIn.duration(FADE_DURATION)}
exiting={FadeOut.duration(FADE_DURATION)}
style={style.container}
testID={`${selectedEmailTestID}`}
testID={testID}
>
{extra && (
<View style={style.extraContent}>
{extra}
</View>
)}
<Text
style={style.text}
testID={`${selectedEmailTestID}.display_name`}
testID={`${testID}.display_name`}
>
{email}
{text}
</Text>
<TouchableOpacity
style={style.remove}
onPress={onPress}
testID={`${selectedEmailTestID}.remove.button`}
testID={`${testID}.remove.button`}
>
<CompassIcon
name='close-circle'

View File

@@ -6,6 +6,7 @@ import {LayoutChangeEvent, Platform, ScrollView, useWindowDimensions, View} from
import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {USER_CHIP_BOTTOM_MARGIN, USER_CHIP_HEIGHT} from '@components/selected_chip';
import Toast from '@components/toast';
import {General} from '@constants';
import {useTheme} from '@context/theme';
@@ -13,7 +14,7 @@ import {useIsTablet, useKeyboardHeightWithDuration} from '@hooks/device';
import Button from '@screens/bottom_sheet/button';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import SelectedUser, {USER_CHIP_BOTTOM_MARGIN, USER_CHIP_HEIGHT} from './selected_user';
import SelectedUser from './selected_user';
type Props = {

View File

@@ -3,18 +3,9 @@
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {
Text,
TouchableOpacity,
View,
} from 'react-native';
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated';
import CompassIcon from '@components/compass_icon';
import ProfilePicture from '@components/profile_picture';
import {useTheme} from '@context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import SelectedChip from '@components/selected_chip';
import {displayUsername} from '@utils/user';
type Props = {
@@ -40,87 +31,34 @@ type Props = {
testID?: string;
}
export const USER_CHIP_HEIGHT = 32;
export const USER_CHIP_BOTTOM_MARGIN = 8;
const FADE_DURATION = 100;
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
container: {
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
borderRadius: 16,
height: USER_CHIP_HEIGHT,
backgroundColor: changeOpacity(theme.centerChannelColor, 0.08),
marginBottom: USER_CHIP_BOTTOM_MARGIN,
marginRight: 8,
paddingHorizontal: 7,
},
remove: {
justifyContent: 'center',
marginLeft: 7,
},
profileContainer: {
flexDirection: 'row',
alignItems: 'center',
marginRight: 8,
color: theme.centerChannelColor,
},
text: {
color: theme.centerChannelColor,
...typography('Body', 100, 'SemiBold'),
},
};
});
export default function SelectedUser({
teammateNameDisplay,
user,
onRemove,
testID,
}: Props) {
const theme = useTheme();
const style = getStyleFromTheme(theme);
const intl = useIntl();
const onPress = useCallback(() => {
onRemove(user.id);
}, [onRemove, user.id]);
const onPress = useCallback((id: string) => {
onRemove(id);
}, [onRemove]);
const userItemTestID = `${testID}.${user.id}`;
return (
<Animated.View
entering={FadeIn.duration(FADE_DURATION)}
exiting={FadeOut.duration(FADE_DURATION)}
style={style.container}
testID={`${testID}.${user.id}`}
>
<View style={style.profileContainer}>
<SelectedChip
id={user.id}
text={displayUsername(user, intl.locale, teammateNameDisplay)}
extra={(
<ProfilePicture
author={user}
size={20}
iconSize={20}
testID={`${userItemTestID}.profile_picture`}
/>
</View>
<Text
style={style.text}
testID={`${testID}.${user.id}.display_name`}
>
{displayUsername(user, intl.locale, teammateNameDisplay)}
</Text>
<TouchableOpacity
style={style.remove}
onPress={onPress}
testID={`${testID}.${user.id}.remove.button`}
>
<CompassIcon
name='close-circle'
size={18}
color={changeOpacity(theme.centerChannelColor, 0.32)}
/>
</TouchableOpacity>
</Animated.View>
)}
onRemove={onPress}
testID={userItemTestID}
/>
);
}

View File

@@ -337,7 +337,7 @@ export default function Invite({
},
},
});
}, [componentId, locale, theme, stage]);
}, [componentId, locale, theme, stage === Stage.RESULT]);
useEffect(() => {
return () => {

View File

@@ -15,6 +15,7 @@ import {
import Animated, {useAnimatedStyle, useDerivedValue} from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import SelectedChip from '@components/selected_chip';
import SelectedUser from '@components/selected_users/selected_user';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import UserItem from '@components/user_item';
@@ -25,7 +26,6 @@ import {useIsTablet, useKeyboardHeight} from '@hooks/device';
import {makeStyleSheetFromTheme, changeOpacity} from '@utils/theme';
import {SearchResult} from './invite';
import SelectedEmail from './selected_email';
import SelectionSearchBar from './selection_search_bar';
import SelectionTeamBar from './selection_team_bar';
import TextItem, {TextItemType} from './text_item';
@@ -279,11 +279,12 @@ export default function Selection({
const selectedItem = selectedIds[id];
selectedItems.push(typeof selectedItem === 'string' ? (
<SelectedEmail
<SelectedChip
id={id}
key={id}
email={selectedItem}
text={selectedItem}
onRemove={handleOnRemoveItem}
testID='invite.selected_item'
testID={`invite.selected_item.${selectedItem}`}
/>
) : (
<SelectedUser