diff --git a/src/domain/Adventure/GroupModal/index.tsx b/src/domain/Adventure/GroupModal/index.tsx index a2bfbe24d..d1c710175 100644 --- a/src/domain/Adventure/GroupModal/index.tsx +++ b/src/domain/Adventure/GroupModal/index.tsx @@ -1,9 +1,13 @@ -import React, { useState } from 'react'; -import { useSafeArea } from 'react-native-safe-area-context'; +import React, { + ReactElement, + useEffect, + useLayoutEffect, + useState, +} from 'react'; import { RouteProp, useNavigation } from '@react-navigation/native'; import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'react-redux'; -import { ScrollView, View } from 'react-native'; +import { useSelector } from 'react-redux'; +import { ActivityIndicator, ScrollView, View } from 'react-native'; import { StackNavigationProp } from '@react-navigation/stack'; import Flex from 'components/Flex'; import Text from 'components/Text'; @@ -14,7 +18,13 @@ import Touchable from 'components/Touchable'; import VokeIcon from 'components/VokeIcon'; import theme from 'utils/theme'; import st from 'utils/st'; -import { AdventureStackParamList } from 'utils/types'; +import { + AdventureStackParamList, + TAdventureSingle, + TDataState, + TMessenger, +} from 'utils/types'; +import { RootState } from 'reducers'; import styles from './styles'; @@ -30,42 +40,68 @@ type Props = { route: RoutePropType; }; -function GroupModal(props: Props) { +function GroupModal(props: Props): ReactElement { + const smallCircle = st.fullWidth / 2 - 90; + const smallBox = st.fullWidth / 2 - 50; + const largeCircle = st.fullWidth / 2 - 80; + const largeBox = st.fullWidth / 2 - 30; + + const { adventureId } = props.route.params; const { t } = useTranslation(); - const insets = useSafeArea(); const navigation = useNavigation(); const me = useSelector(({ auth }) => auth.user); - const dispatch = useDispatch(); - const [isLoading, setIsLoading] = useState(false); - const { adventureId } = props.route.params; - // We update local adventures when accepting invite. + const [isLoading, setIsLoading] = useState(true); + const [messengers, setMessengers] = useState([]); + // We update local adventures in the background when accepting invite. // If no adventures in the local store at this point - we have a problem. - const myAdventures = useSelector(({ data }) => data.myAdventures.byId); - const adventure = myAdventures[adventureId]; - if (!adventure) { - // Backup plan: Redirect to My Adventures screen. - navigation.reset({ - index: 0, - routes: [{ name: 'LoggedInApp' }], - }); - return <>; - } - const allMessengers = adventure?.conversation?.messengers; - const messengers = allMessengers.filter( - i => i.first_name !== 'VokeBot' && (i || {}).id !== (me || {}).id, + const adventure: TAdventureSingle = useSelector( + ({ data }: RootState) => + data.myAdventures?.byId[ + adventureId as keyof TDataState['myAdventures']['byId'] + ] || {}, ); - const hasMoreMembers = messengers.length > 5; - if (messengers.length < 5) { - for (let m; messengers.length < 5; m++) { - messengers.push({ first_name: '' }); + useEffect(() => { + if (adventure?.id) { + const allMessengers = adventure?.conversation?.messengers; + if (allMessengers.length) { + // setAllMessengers(allMessengers.slice()); + const humanMessengers = allMessengers.filter( + i => i.first_name !== 'VokeBot' && (i || {}).id !== (me || {}).id, + ); + // Fake crowd. + if (humanMessengers.length < 5) { + for (let m = 0; humanMessengers.length < 5; m++) { + humanMessengers.push({ + id: 'fake', + first_name: '', + last_name: '', + avatar: { + small: '', + medium: '', + large: '', + }, + }); + } + } + setMessengers(humanMessengers.slice()); + setIsLoading(false); + } } - } + }, [adventure?.conversation?.messengers, adventure?.id, me]); - const smallCircle = st.fullWidth / 2 - 90; - const smallBox = st.fullWidth / 2 - 50; - const largeCircle = st.fullWidth / 2 - 80; - const largeBox = st.fullWidth / 2 - 30; + useLayoutEffect(() => { + const redirectTimer = setTimeout(() => { + // Backup plan: Redirect to My Adventures screen if nothing happen in 5sec. + navigation.reset({ + index: 0, + routes: [{ name: 'LoggedInApp' }], + }); + }, 5000); + return (): void => { + clearTimeout(redirectTimer); + }; + }); const handleJoinGroup = (): void => { // Go to the adventure steps screen. @@ -79,208 +115,218 @@ function GroupModal(props: Props) { contentContainerStyle={styles.container} scrollIndicatorInsets={{ right: 1 }} > - - - - - {t('modal:welcomeTo')} - {adventure.journey_invite?.name || adventure.name || ''}! - - - - - - - - - - {messengers.slice(0, 5).map((messenger, index) => ( - - {!messenger.avatar ? ( - - + <> + {isLoading ? ( + + + + ) : ( + <> + + + + + {t('modal:welcomeTo')} + {adventure.journey_invite?.name || adventure.name || ''}! + - ) : ( - - )} - - - {messenger.first_name} - - - ))} - - handleJoinGroup()} - style={{ - flex: 1, - width: '100%', - padding: theme.spacing.s, - }} - testID="ctaJoinGroup" - > - <> - + + + + + + {messengers.slice(0, 5).map((messenger, index) => ( + - + > + {!messenger.avatar ? ( + + + + ) : ( + + )} + + + {messenger.first_name} + + + ))} - handleJoinGroup()} style={{ flex: 1, + width: '100%', + padding: theme.spacing.s, }} + testID="ctaJoinGroup" > - + - {t('joinGroup')} - - - + }} + > + + + + + + {t('joinGroup')} + + + + + + - - - - - - {hasMoreMembers ? ( - - - navigation.navigate('AllMembersModal', { - adventureId: adventure.id, - isJoined: false, - }) - } - style={[ - st.bgOrange, - st.ph6, - st.pv5, - st.bw0, - st.br3, - st.mt5, - st.aic, - { width: st.fullWidth - 90 }, - ]} - > - - {t('allMembers')} + - - - ) : null} + {messengers.length > 5 ? ( + + + navigation.navigate('AllMembersModal', { + adventureId: adventure.id, + isJoined: false, + }) + } + style={[ + st.bgOrange, + st.ph6, + st.pv5, + st.bw0, + st.br3, + st.mt5, + st.aic, + { width: st.fullWidth - 90 }, + ]} + > + + {t('allMembers')} + + + + ) : null} + + )} + ); }