Page MenuHomePhabricator

D7524.diff
No OneTemporary

D7524.diff

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 (
+ <>
+ <Text style={styles.invitation}>You have been invited to join</Text>
+ <Text style={styles.communityName}>
+ {invitationDetails.community.name}
+ </Text>
+ </>
+ );
+ }
+ return (
+ <>
+ <Text style={styles.invalidInviteTitle}>Invite invalid</Text>
+ <Text style={styles.invalidInviteExplanation}>
+ This invite link may be expired, please try again with another invite
+ link
+ </Text>
+ </>
+ );
+ }, [
+ invitationDetails,
+ styles.communityName,
+ styles.invalidInviteExplanation,
+ styles.invalidInviteTitle,
+ styles.invitation,
+ ]);
+
+ const buttons = React.useMemo(() => {
+ if (invitationDetails.status === 'valid') {
+ return (
+ <>
+ <Button
+ style={[styles.button, styles.buttonPrimary, styles.gap]}
+ onPress={() => {}}
+ >
+ <Text style={styles.buttonText}>Accept Invite</Text>
+ </Button>
+ <Button
+ style={[styles.button, styles.buttonSecondary]}
+ onPress={props.navigation.goBack}
+ >
+ <Text style={styles.buttonText}>Cancel</Text>
+ </Button>
+ </>
+ );
+ }
+ return (
+ <Button
+ style={[styles.button, styles.buttonPrimary]}
+ onPress={props.navigation.goBack}
+ >
+ <Text style={styles.buttonText}>Return to Comm</Text>
+ </Button>
+ );
+ }, [
+ invitationDetails.status,
+ props.navigation.goBack,
+ styles.button,
+ styles.buttonPrimary,
+ styles.buttonSecondary,
+ styles.buttonText,
+ styles.gap,
+ ]);
+
+ return (
+ <Modal modalStyle={styles.modal}>
+ <View>{header}</View>
+ <View style={styles.separator} />
+ <View>{buttons}</View>
+ </Modal>
+ );
+}
+
+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}
/>
+ <Root.Screen
+ name={InviteLinkModalRouteName}
+ component={InviteLinkModal}
+ options={modalOverlayScreenOptions}
+ />
<Root.Screen
name={ThreadPickerModalRouteName}
component={ThreadPickerModal}
diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js
--- a/native/navigation/route-names.js
+++ b/native/navigation/route-names.js
@@ -3,6 +3,7 @@
import type { RouteProp } from '@react-navigation/native';
import type { ActionResultModalParams } from './action-result-modal.react.js';
+import type { InviteLinkModalParams } from './invite-link-modal.react';
import type { TermsAndPrivacyModalParams } from '../account/terms-and-privacy-modal.react.js';
import type { ThreadPickerModalParams } from '../calendar/thread-picker-modal.react.js';
import type { ComposeSubchannelParams } from '../chat/compose-subchannel.react.js';
@@ -58,6 +59,7 @@
export const HomeChatThreadListRouteName = 'HomeChatThreadList';
export const ImageModalRouteName = 'ImageModal';
export const ImagePasteModalRouteName = 'ImagePasteModal';
+export const InviteLinkModalRouteName = 'InviteLinkModal';
export const LoggedOutModalRouteName = 'LoggedOutModal';
export const MessageListRouteName = 'MessageList';
export const MessageReactionsModalRouteName = 'MessageReactionsModal';
@@ -97,6 +99,7 @@
+SubchannelsListModal: SubchannelListModalParams,
+MessageReactionsModal: MessageReactionsModalParams,
+Registration: void,
+ +InviteLinkModal: InviteLinkModalParams,
};
export type MessageTooltipRouteNames =
diff --git a/native/themes/colors.js b/native/themes/colors.js
--- a/native/themes/colors.js
+++ b/native/themes/colors.js
@@ -92,6 +92,8 @@
subthreadsModalBackground: '#EBEBEB',
subthreadsModalSearch: '#00000008',
messageLabel: '#0A0A0A',
+ modalSeparator: '#CCCCCC',
+ secondaryButtonBorder: '#FFFFFF',
});
export type Colors = $Exact<typeof light>;
@@ -180,6 +182,8 @@
typeaheadTooltipBorder: '#404040',
typeaheadTooltipText: 'white',
messageLabel: '#CCCCCC',
+ modalSeparator: '#404040',
+ secondaryButtonBorder: '#FFFFFF',
});
const colors = { light, dark };

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 9, 7:42 AM (21 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2450229
Default Alt Text
D7524.diff (7 KB)

Event Timeline