Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New contact method #15330

Merged
merged 47 commits into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
4298833
Add button for new contact in Contact methods page.
cristipaval Feb 21, 2023
d240884
Create NewContactMethodPage
cristipaval Feb 21, 2023
2d50115
Add description
cristipaval Feb 22, 2023
7fcecc5
Add input field for login.
cristipaval Feb 22, 2023
d46b4af
Add password input when no passwordless beta
cristipaval Feb 22, 2023
9d1f147
Add Button in new contact page.
cristipaval Feb 22, 2023
fc38d21
New contact methid button is not a fixed footer.
cristipaval Feb 22, 2023
d028688
Submit form when no passwordless beta.
cristipaval Feb 22, 2023
38a5de7
Merge remote-tracking branch 'origin/main' into cristi_new-contact-me…
cristipaval Feb 22, 2023
9c9c703
Add form validation.
cristipaval Feb 22, 2023
0dcbed8
For no, submit new contact method form only when no passwordless
cristipaval Feb 23, 2023
2a08b96
Merge remote-tracking branch 'origin/main' into cristi_new-contact-me…
cristipaval Mar 1, 2023
782b3b2
Integrate New Contact Method command
cristipaval Mar 7, 2023
b58614d
Merge remote-tracking branch 'origin/main' into cristi_new-contact-me…
cristipaval Mar 7, 2023
9723aa7
Fix conflicts after merge.
cristipaval Mar 7, 2023
01ed14a
Fix validateForm function
cristipaval Mar 8, 2023
64577c1
Improve the onyx data when calling AddNewContactMethod command
cristipaval Mar 9, 2023
636fc3c
Show magic code stuff in ContactMethodDetailsPage only if there are n…
cristipaval Mar 9, 2023
017af2f
Show errorFields.addedLogin in ContactMethodDetails
cristipaval Mar 9, 2023
b2df6c4
Delete contact method on server only if has been added successfully.
cristipaval Mar 9, 2023
047ee98
Show error description when a contact method failed to be added.
cristipaval Mar 9, 2023
85e59bd
Small typo in i18n
cristipaval Mar 9, 2023
335e47b
Merge remote-tracking branch 'origin/main' into cristi_new-contact-me…
cristipaval Mar 29, 2023
28ad9d0
Remove LoginField.
cristipaval Mar 29, 2023
cbfd568
Remove AddSecondaryLoginPage
cristipaval Mar 29, 2023
3a7f5a6
Do nothing if the new contact method is already claimed by the user.
cristipaval Mar 29, 2023
5f53d85
Disable autoCapitalize the input field on NewContactMethodPage
cristipaval Mar 29, 2023
3211e81
Remove deprecated set secondary login command
cristipaval Mar 29, 2023
836ed2e
Show pending state for the added contact method while offline.
cristipaval Mar 30, 2023
9bae9f8
Lint
cristipaval Mar 30, 2023
2959e90
Lint
cristipaval Mar 30, 2023
47a6c4d
Lint
cristipaval Mar 30, 2023
512fb39
Lint
cristipaval Mar 30, 2023
071b551
Give me the green checkmark Linter, or Imma quit!
cristipaval Mar 30, 2023
aba9ecf
Improve translations.
cristipaval Apr 5, 2023
ee5252f
Remove unnecessary optimistic data.
cristipaval Apr 5, 2023
12cfc2c
Remove unnecessary default to null.
cristipaval Apr 5, 2023
c37480e
Update src/pages/settings/Profile/Contacts/ContactMethodsPage.js
cristipaval Apr 5, 2023
f9f0fde
Update src/pages/settings/Profile/Contacts/ContactMethodsPage.js
cristipaval Apr 5, 2023
f7e874c
Update src/pages/settings/Profile/Contacts/NewContactMethodPage.js
cristipaval Apr 5, 2023
db660c7
Update src/ROUTES.js
cristipaval Apr 5, 2023
b7835f4
Update src/libs/actions/User.js
cristipaval Apr 5, 2023
e722fb6
Address feedback.
cristipaval Apr 5, 2023
73f6a78
Fix Linter errors.
cristipaval Apr 6, 2023
6b8383a
Improve the look of New Contact Method button
cristipaval Apr 10, 2023
7553807
Do not ask for confirmation when deleting a contact method which has …
cristipaval Apr 10, 2023
539fa78
Add function doc.
cristipaval Apr 10, 2023
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
2 changes: 1 addition & 1 deletion src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export default {
SETTINGS_ADD_DEBIT_CARD: 'settings/payments/add-debit-card',
SETTINGS_ADD_BANK_ACCOUNT: 'settings/payments/add-bank-account',
SETTINGS_ENABLE_PAYMENTS: 'settings/payments/enable-payments',
SETTINGS_ADD_LOGIN: 'settings/addlogin/:type',
getSettingsAddLoginRoute: type => `settings/addlogin/${type}`,
SETTINGS_PAYMENTS_TRANSFER_BALANCE: 'settings/payments/transfer-balance',
SETTINGS_PAYMENTS_CHOOSE_TRANSFER_ACCOUNT: 'settings/payments/choose-transfer-account',
Expand All @@ -53,6 +52,7 @@ export default {
SETTINGS_CONTACT_METHODS,
SETTINGS_CONTACT_METHOD_DETAILS: `${SETTINGS_CONTACT_METHODS}/:contactMethod/details`,
getEditContactMethodRoute: contactMethod => `${SETTINGS_CONTACT_METHODS}/${encodeURIComponent(contactMethod)}/details`,
SETTINGS_NEW_CONTACT_METHOD: `${SETTINGS_CONTACT_METHODS}/new`,
NEW_GROUP: 'new/group',
NEW_CHAT: 'new/chat',
REPORT,
Expand Down
10 changes: 3 additions & 7 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,14 @@ export default {
removeContactMethod: 'Remove contact method',
removeAreYouSure: 'Are you sure you want to remove this contact method? This action cannot be undone.',
resendMagicCode: 'Resend magic code',
failedNewContact: 'Failed to add this contact method.',
genericFailureMessages: {
requestContactMethodValidateCode: 'Failed to send a new magic code. Please wait a bit and try again.',
validateSecondaryLogin: 'Failed to validate contact method with given magic code. Please request a new code and try again.',
deleteContactMethod: 'Failed to delete contact method. Please reach out to Concierge for help.',
addContactMethod: 'Failed to add this contact method. Please reach out to Concierge for help.',
},
newContactMethod: 'New contact method',
},
pronouns: {
coCos: 'Co / Cos',
Expand Down Expand Up @@ -404,13 +407,6 @@ export default {
isShownOnProfile: 'Your timezone is shown on your profile.',
getLocationAutomatically: 'Automatically determine your location.',
},
addSecondaryLoginPage: {
addPhoneNumber: 'Add phone number',
addEmailAddress: 'Add email address',
enterPreferredPhoneNumberToSendValidationLink: 'Enter your preferred phone number to send a validation link.',
enterPreferredEmailToSendValidationLink: 'Enter your preferred email address to send a validation link.',
sendValidation: 'Send validation',
},
initialSettingsPage: {
about: 'About',
aboutPage: {
Expand Down
10 changes: 3 additions & 7 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,11 +365,14 @@ export default {
removeContactMethod: 'Eliminar método de contacto',
removeAreYouSure: '¿Estás seguro de que quieres eliminar este método de contacto? Esta acción no se puede deshacer.',
resendMagicCode: 'Reenviar código mágico',
failedNewContact: 'Hubo un error al añadir este método de contacto.',
genericFailureMessages: {
requestContactMethodValidateCode: 'No se ha podido enviar un nuevo código mágico. Espera un rato y vuelve a intentarlo.',
validateSecondaryLogin: 'No se ha podido validar el método de contacto con el código mágico provisto. Solicita un nuevo código y vuelve a intentarlo.',
deleteContactMethod: 'No se ha podido eliminar el método de contacto. Por favor contacta con Concierge para obtener ayuda.',
addContactMethod: 'Hubo un error al añadir este método de contacto. Por favor contacta con Concierge para obtener ayuda.',
},
newContactMethod: 'Nuevo método de contacto',
},
pronouns: {
coCos: 'Co / Cos',
Expand Down Expand Up @@ -403,13 +406,6 @@ export default {
isShownOnProfile: 'Tu zona horaria se muestra en tu perfil.',
getLocationAutomatically: 'Detecta tu ubicación automáticamente.',
},
addSecondaryLoginPage: {
addPhoneNumber: 'Agregar número de teléfono',
addEmailAddress: 'Agregar dirección de email',
enterPreferredPhoneNumberToSendValidationLink: 'Escribe tu número de teléfono para recibir el enlace de validación.',
enterPreferredEmailToSendValidationLink: 'Escribe tu email para recibir el enlace de validación.',
sendValidation: 'Enviar validación',
},
initialSettingsPage: {
about: 'Acerca de',
aboutPage: {
Expand Down
6 changes: 3 additions & 3 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,10 @@ const SettingsModalStackNavigator = createModalStackNavigator([
},
{
getComponent: () => {
const SettingsAddSecondaryLoginPage = require('../../../pages/settings/Profile/Contacts/AddSecondaryLoginPage').default;
return SettingsAddSecondaryLoginPage;
const SettingsNewContactMethodPage = require('../../../pages/settings/Profile/Contacts/NewContactMethodPage').default;
return SettingsNewContactMethodPage;
},
name: 'Settings_Add_Secondary_Login',
name: 'Settings_NewContactMethod',
},
{
getComponent: () => {
Expand Down
5 changes: 3 additions & 2 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,9 @@ export default {
Settings_ContactMethodDetails: {
path: ROUTES.SETTINGS_CONTACT_METHOD_DETAILS,
},
Settings_Add_Secondary_Login: {
path: ROUTES.SETTINGS_ADD_LOGIN,
Settings_NewContactMethod: {
path: ROUTES.SETTINGS_NEW_CONTACT_METHOD,
exact: true,
},
Settings_PersonalDetails_Initial: {
path: ROUTES.SETTINGS_PERSONAL_DETAILS,
Expand Down
100 changes: 62 additions & 38 deletions src/libs/actions/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import lodashGet from 'lodash/get';
import Onyx from 'react-native-onyx';
import moment from 'moment';
import ONYXKEYS from '../../ONYXKEYS';
import * as DeprecatedAPI from '../deprecatedAPI';
import * as API from '../API';
import CONFIG from '../../CONFIG';
import CONST from '../../CONST';
Expand Down Expand Up @@ -182,49 +181,19 @@ function updateNewsletterSubscription(isSubscribed) {
});
}

/**
* Adds a secondary login to a user's account
*
* @param {String} login
* @param {String} password
* @returns {Promise}
*/
function setSecondaryLoginAndNavigate(login, password) {
Onyx.merge(ONYXKEYS.ACCOUNT, {...CONST.DEFAULT_ACCOUNT_DATA, isLoading: true});

return DeprecatedAPI.User_SecondaryLogin_Send({
email: login,
password,
}).then((response) => {
if (response.jsonCode === 200) {
Onyx.set(ONYXKEYS.LOGIN_LIST, response.loginList);
Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS);
return;
}

let error = lodashGet(response, 'message', 'Unable to add secondary login. Please try again.');

// Replace error with a friendlier message
if (error.includes('already belongs to an existing Expensify account.')) {
error = 'This login already belongs to an existing Expensify account.';
}
if (error.includes('I couldn\'t validate the phone number')) {
error = Localize.translateLocal('common.error.phoneNumber');
}

Onyx.merge(ONYXKEYS.USER, {error});
}).finally(() => {
Onyx.merge(ONYXKEYS.ACCOUNT, {isLoading: false});
});
}
cristipaval marked this conversation as resolved.
Show resolved Hide resolved

/**
* Delete a specific contact method
*
* @param {String} contactMethod - the contact method being deleted
* @param {Object} oldLoginData
*/
function deleteContactMethod(contactMethod, oldLoginData) {
// If the contact method failed to be added to the account, then it should only be deleted locally.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it's for this method to worry about? Like maybe it is fine to call the API even if we know there is no point in it. It could just respond with success in this case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh interesting idea both ways - I think I would think it's safer to just call the API command no matter what, just in case it does exist in the server and needs to be deleted?

Copy link
Contributor Author

@cristipaval cristipaval Apr 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is that if the login is in Onyx only because failed to be added, the delete command fails.
I like the idea of changing Auth to return success when trying to delete a login that doesn't exist.
@Beamanator do you think we could add this to the list with follow-ups?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good instinct and I think it sounds like a valid Follow Up thing to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Added as a polish task!

if (lodashGet(oldLoginData, 'errorFields.addedLogin', null)) {
Onyx.merge(ONYXKEYS.LOGIN_LIST, {[contactMethod]: null});
return;
}

const optimisticData = [{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.LOGIN_LIST,
Expand Down Expand Up @@ -290,6 +259,61 @@ function clearContactMethodErrors(contactMethod, fieldName) {
});
}

/**
* Adds a secondary login to a user's account
*
* @param {String} contactMethod
* @param {String} password
*/
function addNewContactMethodAndNavigate(contactMethod, password) {
const optimisticData = [{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.LOGIN_LIST,
value: {
[contactMethod]: {
partnerUserID: contactMethod,
validatedDate: '',
errorFields: {
addedLogin: null,
},
pendingFields: {
addedLogin: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
},
}];
const successData = [{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.LOGIN_LIST,
value: {
[contactMethod]: {
pendingFields: {
addedLogin: null,
},
},
},
}];
const failureData = [{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.LOGIN_LIST,
value: {
[contactMethod]: {
errorFields: {
addedLogin: {
[DateUtils.getMicroseconds()]: Localize.translateLocal('contacts.genericFailureMessages.addContactMethod'),
},
},
pendingFields: {
addedLogin: null,
},
},
},
}];

API.write('AddNewContactMethod', {partnerUserID: contactMethod, password}, {optimisticData, successData, failureData});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not lowercasing the contactMethod caused issues when people started testing mixed-case contact methods - #19080

Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS);
}

/**
* Validates a login given an accountID and validation code
*
Expand Down Expand Up @@ -660,9 +684,9 @@ export {
resendValidateCode,
requestContactMethodValidateCode,
updateNewsletterSubscription,
setSecondaryLoginAndNavigate,
deleteContactMethod,
clearContactMethodErrors,
addNewContactMethodAndNavigate,
validateLogin,
validateSecondaryLogin,
isBlockedFromConcierge,
Expand Down
Loading