Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
cc76bed
send code on navigation from contact method page
teneeto Aug 21, 2024
5a6f82b
fix lint
teneeto Aug 21, 2024
e526129
extract to function
teneeto Aug 21, 2024
9280c86
show link has been re-sent only when resend button is pressed
teneeto Aug 21, 2024
06d4979
fix lint
teneeto Aug 21, 2024
7f002bf
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Aug 21, 2024
a0212b3
fix lint
teneeto Aug 22, 2024
1d80914
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Aug 22, 2024
82f095d
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Aug 28, 2024
2cc1c20
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Aug 28, 2024
b1263d7
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Aug 29, 2024
bf2a654
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Sep 3, 2024
9503dba
update navigation for add new contact method
teneeto Sep 3, 2024
a84cbb5
fix conflict
teneeto Sep 3, 2024
fd9235b
remove add new contact method navigation
teneeto Sep 3, 2024
56d5937
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Sep 4, 2024
d137dc5
re: add new contact method navigation
teneeto Sep 10, 2024
4ed31ee
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Sep 11, 2024
52949cf
redirect user to contact list
teneeto Sep 13, 2024
aae2f6e
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Sep 17, 2024
8a7666e
navigate to contact method details
teneeto Sep 17, 2024
9ce5700
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Sep 26, 2024
14dab40
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 1, 2024
85a4e9c
use useOnyx
teneeto Oct 1, 2024
4cac86e
remove unused prop types
teneeto Oct 1, 2024
7922dbd
remove unused imports
teneeto Oct 1, 2024
910c01e
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 7, 2024
3b65496
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 9, 2024
6f1081d
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 15, 2024
0bed738
validation button should flex to end
teneeto Oct 16, 2024
57688fc
fix lint
teneeto Oct 16, 2024
2f9aaf0
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 16, 2024
59f2f2e
update button placement
teneeto Oct 17, 2024
7e92bfb
render component in ValidateCodeForm
teneeto Oct 17, 2024
14d4d0f
use normal text instead of dotindicator
teneeto Oct 17, 2024
2d0c1e2
add horizontal padding to other views except button
teneeto Oct 17, 2024
1c0f643
render only button in validateCodeForm
teneeto Oct 17, 2024
89d825d
add a bottom margin for magic code input
teneeto Oct 17, 2024
3195c6e
fix defaultContactDescription
teneeto Oct 17, 2024
466f8b2
update to contactMethodRemoveButton
teneeto Oct 17, 2024
19f8026
remove unused import
teneeto Oct 17, 2024
706124f
disable next line
teneeto Oct 17, 2024
5e4f1d9
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 21, 2024
2a7cc82
fix code validation form and menu items
teneeto Oct 21, 2024
c8848fe
navigate to contact method details
teneeto Oct 22, 2024
463f8d0
fix lint
teneeto Oct 22, 2024
cb11cd5
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 22, 2024
0aaea81
fix lint
teneeto Oct 22, 2024
3ef74ad
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 28, 2024
6b5b1e4
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Oct 30, 2024
84544fd
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 5, 2024
4afd0e4
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 6, 2024
c017c61
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 7, 2024
5fdb65a
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 8, 2024
94c341a
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 13, 2024
df28d0f
fix attachment modal double call
teneeto Nov 14, 2024
d254543
reverse unintended commit
teneeto Nov 14, 2024
67e0ed7
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 14, 2024
3415821
remove space
teneeto Nov 14, 2024
be159ea
fix lint
teneeto Nov 14, 2024
3dccd93
navigate back to contact methods
teneeto Nov 14, 2024
8a96df1
should not send secondary validation code twice
teneeto Nov 14, 2024
5d4aa5a
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 14, 2024
4f3937c
fix lint
teneeto Nov 14, 2024
443a34b
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 14, 2024
1d57a1a
Merge branch 'main' of github.com:teneeto/Expensify into fix/41330/se…
teneeto Nov 18, 2024
a40b7e6
check pending action verification before proceeding
teneeto Nov 18, 2024
8e091a2
include missing dep
teneeto Nov 18, 2024
a389c2d
Merge remote-tracking branch 'upstream/main' into fix/41330/send-code…
waterim Nov 29, 2024
cc8ede9
add clearUnvalidate
waterim Nov 29, 2024
d005947
Merge remote-tracking branch 'upstream/main' into fix/41330/send-code…
waterim Dec 10, 2024
a54a61c
fix lint
waterim Dec 10, 2024
00dc132
Merge remote-tracking branch 'upstream/main' into fix/41330/send-code…
waterim Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useFocusEffect} from '@react-navigation/native';
import type {ForwardedRef} from 'react';
import type {ForwardedRef, ReactNode} from 'react';
import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import {View} from 'react-native';
import type {StyleProp, ViewStyle} from 'react-native';
Expand Down Expand Up @@ -70,7 +70,9 @@ type ValidateCodeFormProps = {
/** Function is called when validate code modal is mounted and on magic code resend */
sendValidateCode: () => void;

/** Whether the form is loading or not */
/** A component to be rendered inside the validateCodeForm */
menuItems?: () => ReactNode;
/** Wheather the form is loading or not */
isLoading?: boolean;
};

Expand All @@ -85,6 +87,7 @@ function BaseValidateCodeForm({
clearError,
sendValidateCode,
buttonStyles,
menuItems,
hideSubmitButton,
isLoading,
}: ValidateCodeFormProps) {
Expand All @@ -93,6 +96,7 @@ function BaseValidateCodeForm({
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();

const [formError, setFormError] = useState<ValidateCodeFormError>({});
const [validateCode, setValidateCode] = useState('');
const inputValidateCodeRef = useRef<MagicCodeInputHandle>(null);
Expand Down Expand Up @@ -211,77 +215,84 @@ function BaseValidateCodeForm({

const shouldShowTimer = timeRemaining > 0 && !isOffline;
return (
<>
<MagicCodeInput
autoComplete={autoComplete}
ref={inputValidateCodeRef}
name="validateCode"
value={validateCode}
onChangeText={onTextInput}
errorText={formError?.validateCode ? translate(formError?.validateCode) : ErrorUtils.getLatestErrorMessage(account ?? {})}
hasError={!isEmptyObject(validateError)}
onFulfill={validateAndSubmitForm}
autoFocus={false}
/>
{shouldShowTimer && (
<Text style={[styles.mt5]}>
{translate('validateCodeForm.requestNewCode')}
<Text style={[styles.textBlue]}>00:{String(timeRemaining).padStart(2, '0')}</Text>
</Text>
)}
<OfflineWithFeedback
pendingAction={validateCodeAction?.pendingFields?.validateCodeSent}
errors={ErrorUtils.getLatestErrorField(validateCodeAction, 'actionVerified')}
errorRowStyles={[styles.mt2]}
onClose={() => User.clearValidateCodeActionError('actionVerified')}
>
{!shouldShowTimer && (
<View style={[styles.mt5, styles.dFlex, styles.flexColumn, styles.alignItemsStart]}>
<PressableWithFeedback
disabled={shouldDisableResendValidateCode}
style={[styles.mr1]}
onPress={resendValidateCode}
underlayColor={theme.componentBG}
hoverDimmingValue={1}
pressDimmingValue={0.2}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('validateCodeForm.magicCodeNotReceived')}
>
<Text style={[StyleUtils.getDisabledLinkStyles(shouldDisableResendValidateCode)]}>{translate('validateCodeForm.magicCodeNotReceived')}</Text>
</PressableWithFeedback>
</View>
)}
</OfflineWithFeedback>
{!!hasMagicCodeBeenSent && (
<DotIndicatorMessage
type="success"
style={[styles.mt6, styles.flex0]}
// eslint-disable-next-line @typescript-eslint/naming-convention
messages={{0: translate('validateCodeModal.successfulNewCodeRequest')}}
<View style={styles.flex1}>
<View style={[styles.ph5, styles.mb5]}>
<MagicCodeInput
autoComplete={autoComplete}
ref={inputValidateCodeRef}
name="validateCode"
value={validateCode}
onChangeText={onTextInput}
errorText={formError?.validateCode ? translate(formError?.validateCode) : ErrorUtils.getLatestErrorMessage(account ?? {})}
hasError={!isEmptyObject(validateError)}
onFulfill={validateAndSubmitForm}
autoFocus={false}
/>
)}
<OfflineWithFeedback
shouldDisplayErrorAbove
pendingAction={validatePendingAction}
errors={validateError}
errorRowStyles={[styles.mt2]}
onClose={() => clearError()}
style={buttonStyles}
>
{!hideSubmitButton && (
<Button
isDisabled={isOffline}
text={translate('common.verify')}
onPress={validateAndSubmitForm}
style={[styles.mt4]}
success
large
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
isLoading={account?.isLoading || isLoading}
{shouldShowTimer && (
<Text style={[styles.mt5]}>
{translate('validateCodeForm.requestNewCode')}
<Text style={[styles.textBlue]}>00:{String(timeRemaining).padStart(2, '0')}</Text>
</Text>
)}
<OfflineWithFeedback
pendingAction={validateCodeAction?.pendingFields?.validateCodeSent}
errors={ErrorUtils.getLatestErrorField(validateCodeAction, 'actionVerified')}
errorRowStyles={[styles.mt2]}
onClose={() => User.clearValidateCodeActionError('actionVerified')}
>
{!shouldShowTimer && (
<View style={[styles.mt5, styles.dFlex, styles.flexColumn, styles.alignItemsStart]}>
<PressableWithFeedback
disabled={shouldDisableResendValidateCode}
style={[styles.mr1]}
onPress={resendValidateCode}
underlayColor={theme.componentBG}
hoverDimmingValue={1}
pressDimmingValue={0.2}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('validateCodeForm.magicCodeNotReceived')}
>
<Text style={[StyleUtils.getDisabledLinkStyles(shouldDisableResendValidateCode)]}>{translate('validateCodeForm.magicCodeNotReceived')}</Text>
</PressableWithFeedback>
</View>
)}
</OfflineWithFeedback>
{!!hasMagicCodeBeenSent && (
<DotIndicatorMessage
type="success"
style={[styles.mt6, styles.flex0]}
// eslint-disable-next-line @typescript-eslint/naming-convention
messages={{0: translate('validateCodeModal.successfulNewCodeRequest')}}
/>
)}
</OfflineWithFeedback>
</>
</View>

{menuItems ? menuItems() : null}

<View style={[styles.flex1, styles.justifyContentEnd, styles.ph5]}>
<OfflineWithFeedback
shouldDisplayErrorAbove
pendingAction={validatePendingAction}
errors={validateError}
errorRowStyles={[styles.mt2]}
onClose={() => clearError()}
style={buttonStyles}
>
{!hideSubmitButton && (
<Button
isDisabled={isOffline}
text={translate('common.verify')}
onPress={validateAndSubmitForm}
style={[styles.mt4]}
success
large
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
isLoading={account?.isLoading || isLoading}
/>
)}
</OfflineWithFeedback>
</View>
</View>
);
}

Expand Down
14 changes: 8 additions & 6 deletions src/components/ValidateCodeActionModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function ValidateCodeActionModal({
sendValidateCode,
hasMagicCodeBeenSent,
isLoading,
isAddingNewContact,
shouldHandleNavigationBack,
}: ValidateCodeActionModalProps) {
const themeStyles = useThemeStyles();
Expand All @@ -43,13 +44,14 @@ function ValidateCodeActionModal({
}, [onClose, clearError]);

useEffect(() => {
if (!firstRenderRef.current || !isVisible || hasMagicCodeBeenSent) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if (!firstRenderRef.current || !isVisible || hasMagicCodeBeenSent || isAddingNewContact) {
return;
}
firstRenderRef.current = false;

sendValidateCode();
}, [isVisible, sendValidateCode, hasMagicCodeBeenSent]);
}, [isVisible, sendValidateCode, hasMagicCodeBeenSent, isAddingNewContact]);

return (
<Modal
Expand All @@ -75,9 +77,9 @@ function ValidateCodeActionModal({
onBackButtonPress={hide}
/>

<View style={[themeStyles.ph5, themeStyles.mt3, themeStyles.mb7, themeStyles.flex1]}>
<Text style={[themeStyles.mb3]}>{descriptionPrimary}</Text>
{!!descriptionSecondary && <Text style={[themeStyles.mb3]}>{descriptionSecondary}</Text>}
<View style={[themeStyles.flex1, themeStyles.mt3, themeStyles.pb5]}>
<Text style={[themeStyles.ph5, themeStyles.mb3]}>{descriptionPrimary}</Text>
{!!descriptionSecondary && <Text style={[themeStyles.ph5, themeStyles.mb3]}>{descriptionSecondary}</Text>}
<ValidateCodeForm
isLoading={isLoading}
validateCodeAction={validateCodeAction}
Expand All @@ -89,9 +91,9 @@ function ValidateCodeActionModal({
buttonStyles={[themeStyles.justifyContentEnd, themeStyles.flex1]}
ref={validateCodeFormRef}
hasMagicCodeBeenSent={hasMagicCodeBeenSent}
menuItems={footer}
/>
</View>
{footer?.()}
</ScreenWrapper>
</Modal>
);
Expand Down
3 changes: 3 additions & 0 deletions src/components/ValidateCodeActionModal/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ type ValidateCodeActionModalProps = {
/** Whether the form is loading or not */
isLoading?: boolean;

/** Whether adding new contact action is in progress */
isAddingNewContact?: boolean;

/** Whether handle navigation back when modal show. */
shouldHandleNavigationBack?: boolean;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) {
const [loginList, loginListResult] = useOnyx(ONYXKEYS.LOGIN_LIST);
const [session, sessionResult] = useOnyx(ONYXKEYS.SESSION);
const [myDomainSecurityGroups, myDomainSecurityGroupsResult] = useOnyx(ONYXKEYS.MY_DOMAIN_SECURITY_GROUPS);
const [pendingContactAction] = useOnyx(ONYXKEYS.PENDING_CONTACT_ACTION);
const [securityGroups, securityGroupsResult] = useOnyx(ONYXKEYS.COLLECTION.SECURITY_GROUP);
const [isLoadingReportData, isLoadingReportDataResult] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true});
const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(true);
Expand Down Expand Up @@ -78,6 +79,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) {
const loginData = useMemo(() => loginList?.[contactMethod], [loginList, contactMethod]);
const isDefaultContactMethod = useMemo(() => session?.email === loginData?.partnerUserID, [session?.email, loginData?.partnerUserID]);
const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin');
const isAddingNewContact = pendingContactAction?.contactMethod === contactMethod;

/**
* Attempt to set this contact method as user's "Default contact method"
Expand Down Expand Up @@ -143,10 +145,14 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) {
return;
}

if (pendingContactAction?.actionVerified) {
User.clearUnvalidatedNewContactMethodAction();
}

// Navigate to methods page on successful magic code verification
// validatedDate property is responsible to decide the status of the magic code verification
Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS.getRoute(backTo));
}, [prevValidatedDate, loginData?.validatedDate, isDefaultContactMethod, backTo, loginData]);
Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS.getRoute(backTo));
}, [prevValidatedDate, loginData?.validatedDate, isDefaultContactMethod, backTo, loginData, pendingContactAction?.actionVerified]);

useBeforeRemove(() => setIsValidateCodeActionModalVisible(false));

Expand Down Expand Up @@ -189,6 +195,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) {
title={translate('contacts.setAsDefault')}
icon={Expensicons.Star}
onPress={setAsDefault}
style={themeStyles.ph2}
/>
</OfflineWithFeedback>
) : null}
Expand All @@ -213,6 +220,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) {
icon={Expensicons.Trashcan}
iconFill={theme.danger}
onPress={() => toggleDeleteModal(true)}
style={themeStyles.ph2}
/>
</OfflineWithFeedback>
)}
Expand Down Expand Up @@ -271,6 +279,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) {
Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS.getRoute(backTo));
setIsValidateCodeActionModalVisible(false);
}}
isAddingNewContact={isAddingNewContact}
sendValidateCode={() => User.requestContactMethodValidateCode(contactMethod)}
descriptionPrimary={translate('contacts.enterMagicCode', {contactMethod: formattedContactMethod})}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
return;
}

Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS.route);
Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHOD_DETAILS.getRoute(pendingContactAction?.contactMethod ?? ''));
User.clearUnvalidatedNewContactMethodAction();
}, [pendingContactAction?.actionVerified]);
}, [pendingContactAction?.actionVerified, pendingContactAction?.contactMethod]);

const validate = React.useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.NEW_CONTACT_METHOD_FORM>): Errors => {
Expand Down
Loading