diff --git a/app/screens/invite/invite.tsx b/app/screens/invite/invite.tsx
index ea8e7423a..6adbd54ff 100644
--- a/app/screens/invite/invite.tsx
+++ b/app/screens/invite/invite.tsx
@@ -3,7 +3,7 @@
import React, {useCallback, useEffect, useState, useRef} from 'react';
import {IntlShape, useIntl} from 'react-intl';
-import {Keyboard, View, LayoutChangeEvent, Platform} from 'react-native';
+import {Keyboard, View, LayoutChangeEvent} from 'react-native';
import {OptionsTopBarButton} from 'react-native-navigation';
import {SafeAreaView} from 'react-native-safe-area-context';
@@ -28,33 +28,15 @@ import Summary from './summary';
import type {NavButtons} from '@typings/screens/navigation';
const CLOSE_BUTTON_ID = 'close-invite';
-const BACK_BUTTON_ID = 'back-invite';
const SEND_BUTTON_ID = 'send-invite';
-const SEARCH_TIMEOUT_MILLISECONDS = 200;
+const TIMEOUT_MILLISECONDS = 200;
const DEFAULT_RESULT = {sent: [], notSent: []};
-const makeLeftButton = (theme: Theme, type: LeftButtonType): OptionsTopBarButton => (
- (type === LeftButtonType.BACK) ? (
- {
- id: BACK_BUTTON_ID,
- icon: CompassIcon.getImageSourceSync(
- Platform.select({
- ios: 'arrow-back-ios',
- default: 'arrow-left',
- }),
- 24,
- theme.sidebarHeaderTextColor,
- ),
- testID: 'invite.back.button',
- }
- ) : (
- {
- id: CLOSE_BUTTON_ID,
- icon: CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor),
- testID: 'invite.close.button',
- }
- )
-);
+const makeLeftButton = (theme: Theme): OptionsTopBarButton => ({
+ id: CLOSE_BUTTON_ID,
+ icon: CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor),
+ testID: 'invite.close.button',
+});
const makeRightButton = (theme: Theme, formatMessage: IntlShape['formatMessage'], enabled: boolean): OptionsTopBarButton => ({
id: SEND_BUTTON_ID,
@@ -105,11 +87,6 @@ enum Stage {
LOADING = 'loading',
}
-enum LeftButtonType {
- CLOSE = 'close',
- BACK = 'back',
-}
-
type InviteProps = {
componentId: string;
teamId: string;
@@ -171,13 +148,12 @@ export default function Invite({
}, [serverUrl, teamId]);
const handleReset = () => {
+ setStage(Stage.LOADING);
+ setSendError('');
setTerm('');
setSearchResults([]);
- setSelectedIds({});
- setLoading(false);
setResult(DEFAULT_RESULT);
setStage(Stage.SELECTION);
- setSendError('');
};
const handleClearSearch = useCallback(() => {
@@ -196,7 +172,7 @@ export default function Invite({
searchTimeoutId.current = setTimeout(async () => {
await searchUsers(text);
setLoading(false);
- }, SEARCH_TIMEOUT_MILLISECONDS);
+ }, TIMEOUT_MILLISECONDS);
}, [searchUsers]);
const handleSelectItem = useCallback((item: SearchResult) => {
@@ -213,6 +189,15 @@ export default function Invite({
handleClearSearch();
}, [selectedIds, handleClearSearch]);
+ const handleRetry = () => {
+ setSendError('');
+ setStage(Stage.LOADING);
+
+ setTimeout(() => {
+ handleSend();
+ }, TIMEOUT_MILLISECONDS);
+ };
+
const handleSendError = () => {
setSendError(formatMessage({id: 'invite.send_error', defaultMessage: 'Something went wrong while trying to send invitations. Please check your network connection and try again.'}));
setResult(DEFAULT_RESULT);
@@ -327,12 +312,11 @@ export default function Invite({
};
useNavButtonPressed(CLOSE_BUTTON_ID, componentId, closeModal, [closeModal]);
- useNavButtonPressed(BACK_BUTTON_ID, componentId, handleReset, [handleReset]);
useNavButtonPressed(SEND_BUTTON_ID, componentId, handleSend, [handleSend]);
useEffect(() => {
const buttons: NavButtons = {
- leftButtons: [makeLeftButton(theme, stage === Stage.RESULT && sendError ? LeftButtonType.BACK : LeftButtonType.CLOSE)],
+ leftButtons: [makeLeftButton(theme)],
rightButtons: stage === Stage.SELECTION ? [makeRightButton(theme, formatMessage, selectedCount > 0)] : [],
};
@@ -379,7 +363,8 @@ export default function Invite({
selectedIds={selectedIds}
error={sendError}
onClose={closeModal}
- onRetry={handleReset}
+ onRetry={handleRetry}
+ onBack={handleReset}
testID='invite.screen.summary'
/>
);
diff --git a/app/screens/invite/summary.tsx b/app/screens/invite/summary.tsx
index 630704e14..8342c0579 100644
--- a/app/screens/invite/summary.tsx
+++ b/app/screens/invite/summary.tsx
@@ -12,6 +12,7 @@ import AlertSvg from '@components/illustrations/alert';
import ErrorSvg from '@components/illustrations/error';
import SuccessSvg from '@components/illustrations/success';
import {useTheme} from '@context/theme';
+import {t} from '@i18n';
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
import {makeStyleSheetFromTheme, changeOpacity} from '@utils/theme';
import {typography} from '@utils/typography';
@@ -67,6 +68,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
},
summaryButtonContainer: {
flexGrow: 1,
+ flexDirection: 'row',
+ justifyContent: 'center',
maxWidth: MAX_WIDTH_CONTENT,
},
summaryButtonTextContainer: {
@@ -83,6 +86,12 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
};
});
+enum SummaryButtonType {
+ DONE = 'done',
+ RETRY = 'retry',
+ BACK = 'back',
+}
+
type SummaryProps = {
result: Result;
selectedIds: {[id: string]: SearchResult};
@@ -90,6 +99,7 @@ type SummaryProps = {
testID: string;
onClose: () => void;
onRetry: () => void;
+ onBack: () => void;
}
export default function Summary({
@@ -99,8 +109,9 @@ export default function Summary({
testID,
onClose,
onRetry,
+ onBack,
}: SummaryProps) {
- const {formatMessage} = useIntl();
+ const {formatMessage, locale} = useIntl();
const theme = useTheme();
const styles = getStyleSheet(theme);
@@ -108,8 +119,6 @@ export default function Summary({
const sentCount = sent.length;
const notSentCount = notSent.length;
- const styleButtonText = buttonTextStyle(theme, 'lg', 'primary');
- const styleButtonBackground = buttonBackgroundStyle(theme, 'lg', 'primary');
const styleSummaryMessageText = useMemo(() => {
const style = [];
@@ -163,14 +172,67 @@ export default function Summary({
);
}
- const handleOnPressButton = useCallback(() => {
- if (error) {
- onRetry();
- return;
+ const renderButton = useCallback((type: SummaryButtonType) => {
+ let onPress;
+ let iconName = '';
+ let text;
+ let styleButtonText = buttonTextStyle(theme, 'lg', 'primary');
+ let styleButtonBackground = buttonBackgroundStyle(theme, 'lg', 'primary');
+ const styleButtonIcon = [];
+ styleButtonIcon.push(styles.summaryButtonIcon);
+
+ switch (type) {
+ case SummaryButtonType.BACK:
+ onPress = onBack;
+ iconName = 'chevron-left';
+ text = {
+ id: t('invite.summary.back'),
+ defaultMessage: 'Go back',
+ };
+ styleButtonText = buttonTextStyle(theme, 'lg', 'tertiary');
+ styleButtonBackground = [buttonBackgroundStyle(theme, 'lg', 'tertiary'), {marginRight: 8}];
+ styleButtonIcon.push({color: theme.buttonBg});
+ break;
+ case SummaryButtonType.RETRY:
+ onPress = onRetry;
+ iconName = 'refresh';
+ text = {
+ id: t('invite.summary.try_again'),
+ defaultMessage: 'Try again',
+ };
+ break;
+ case SummaryButtonType.DONE:
+ default:
+ onPress = onClose;
+ text = {
+ id: t('invite.summary.done'),
+ defaultMessage: 'Done',
+ };
+ break;
}
- onClose();
- }, [error, onRetry, onClose]);
+ return (
+
+ );
+ }, [theme, locale, onClose, onRetry, onBack]);
return (
-
+ {error ? (
+ <>
+ {renderButton(SummaryButtonType.BACK)}
+ {renderButton(SummaryButtonType.RETRY)}
+ >
+ ) : (
+ renderButton(SummaryButtonType.DONE)
+ )}