diff --git a/native/navigation/invite-link-modal.react.js b/native/navigation/invite-link-modal.react.js new file mode 100644 --- /dev/null +++ b/native/navigation/invite-link-modal.react.js @@ -0,0 +1,174 @@ +// @flow + +import * as React from 'react'; +import { View, Text } from 'react-native'; + +import type { InviteLinkVerificationResponse } from 'lib/types/link-types.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 { 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; + + 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 buttons = React.useMemo(() => { + if (invitationDetails.status === 'valid') { + return ( + <> + + + + ); + } + return ( + + ); + }, [ + invitationDetails.status, + 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; diff --git a/native/navigation/root-navigator.react.js b/native/navigation/root-navigator.react.js --- a/native/navigation/root-navigator.react.js +++ b/native/navigation/root-navigator.react.js @@ -18,6 +18,7 @@ import { enableScreens } from 'react-native-screens'; import AppNavigator from './app-navigator.react.js'; +import InviteLinkModal from './invite-link-modal.react.js'; import { defaultStackScreenOptions } from './options.js'; import { RootNavigatorContext } from './root-navigator-context.js'; import RootRouter, { @@ -39,6 +40,7 @@ type RootParamList, TermsAndPrivacyRouteName, RegistrationRouteName, + InviteLinkModalRouteName, } from './route-names.js'; import LoggedOutModal from '../account/logged-out-modal.react.js'; import RegistrationNavigator from '../account/registration/registration-navigator.react.js'; @@ -203,6 +205,11 @@ component={TermsAndPrivacyModal} options={termsAndPrivacyModalScreenOptions} /> + ; @@ -180,6 +182,8 @@ typeaheadTooltipBorder: '#404040', typeaheadTooltipText: 'white', messageLabel: '#CCCCCC', + modalSeparator: '#404040', + secondaryButtonBorder: '#FFFFFF', }); const colors = { light, dark };