diff --git a/native/navigation/invite-link-modal.react.js b/native/navigation/invite-link-modal.react.js index 7bb3decad..5d3c3866e 100644 --- a/native/navigation/invite-link-modal.react.js +++ b/native/navigation/invite-link-modal.react.js @@ -1,174 +1,222 @@ // @flow +import invariant from 'invariant'; import * as React from 'react'; import { View, Text } from 'react-native'; +import { + joinThread, + joinThreadActionTypes, +} from 'lib/actions/thread-actions.js'; import type { InviteLinkVerificationResponse } from 'lib/types/link-types.js'; +import { + useDispatchActionPromise, + useServerCall, +} from 'lib/utils/action-utils.js'; +import { nonThreadCalendarQuery } from './nav-selectors.js'; +import { NavContext } from './navigation-context.js'; import type { RootNavigationProp } from './root-navigator.react.js'; import type { NavigationRoute } from './route-names.js'; import Button from '../components/button.react.js'; import Modal from '../components/modal.react.js'; +import { useSelector } from '../redux/redux-utils.js'; import { useStyles } from '../themes/colors.js'; export type InviteLinkModalParams = { +invitationDetails: InviteLinkVerificationResponse, +secret: string, }; type Props = { +navigation: RootNavigationProp<'InviteLinkModal'>, +route: NavigationRoute<'InviteLinkModal'>, }; function InviteLinkModal(props: Props): React.Node { const styles = useStyles(unboundStyles); - const { invitationDetails } = props.route.params; + const { invitationDetails, secret } = props.route.params; React.useEffect(() => { if (invitationDetails.status === 'already_joined') { props.navigation.goBack(); } }, [invitationDetails.status, props.navigation]); const header = React.useMemo(() => { if (invitationDetails.status === 'valid') { return ( <> You have been invited to join {invitationDetails.community.name} ); } return ( <> Invite invalid This invite link may be expired, please try again with another invite link ); }, [ invitationDetails, styles.communityName, styles.invalidInviteExplanation, styles.invalidInviteTitle, styles.invitation, ]); + const callJoinThread = useServerCall(joinThread); + const navContext = React.useContext(NavContext); + const calendarQuery = useSelector(state => + nonThreadCalendarQuery({ + redux: state, + navContext, + }), + ); + const communityID = invitationDetails.community?.id; + const createJoinCommunityAction = React.useCallback(async () => { + invariant( + communityID, + 'CommunityID should be present while calling this function', + ); + const query = calendarQuery(); + const result = await callJoinThread({ + threadID: communityID, + calendarQuery: { + startDate: query.startDate, + endDate: query.endDate, + filters: [ + ...query.filters, + { type: 'threads', threadIDs: [communityID] }, + ], + }, + inviteLinkSecret: secret, + }); + props.navigation.goBack(); + return result; + }, [calendarQuery, callJoinThread, communityID, props.navigation, secret]); + const dispatchActionPromise = useDispatchActionPromise(); + const joinCommunity = React.useCallback(() => { + dispatchActionPromise(joinThreadActionTypes, createJoinCommunityAction()); + }, [createJoinCommunityAction, dispatchActionPromise]); + const buttons = React.useMemo(() => { if (invitationDetails.status === 'valid') { return ( <> ); } return ( ); }, [ invitationDetails.status, + joinCommunity, props.navigation.goBack, styles.button, styles.buttonPrimary, styles.buttonSecondary, styles.buttonText, styles.gap, ]); return ( {header} {buttons} ); } const unboundStyles = { modal: { backgroundColor: 'modalForeground', paddingVertical: 24, paddingHorizontal: 16, flex: 0, }, invitation: { color: 'whiteText', textAlign: 'center', fontSize: 14, fontWeight: '400', lineHeight: 22, marginBottom: 24, }, communityName: { color: 'whiteText', textAlign: 'center', fontSize: 18, fontWeight: '500', lineHeight: 24, }, invalidInviteTitle: { color: 'whiteText', textAlign: 'center', fontSize: 22, fontWeight: '500', lineHeight: 28, marginBottom: 24, }, invalidInviteExplanation: { color: 'whiteText', textAlign: 'center', fontSize: 14, fontWeight: '400', lineHeight: 22, }, separator: { height: 1, backgroundColor: 'modalSeparator', marginVertical: 24, }, gap: { marginBottom: 16, }, button: { borderRadius: 8, paddingVertical: 12, paddingHorizontal: 24, }, buttonPrimary: { backgroundColor: 'purpleButton', }, buttonSecondary: { borderColor: 'secondaryButtonBorder', borderWidth: 1, }, buttonText: { color: 'whiteText', textAlign: 'center', fontSize: 16, fontWeight: '500', lineHeight: 24, }, }; export default InviteLinkModal;