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

Clean up login list migration #12919

Merged
merged 3 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 3 additions & 27 deletions src/libs/LoginUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,6 @@ function getPhoneNumberWithoutUSCountryCodeAndSpecialChars(phone) {
return getPhoneNumberWithoutSpecialChars(phone.replace(/^\+1/, ''));
}

/**
* Converts a login list to an object, where the login partnerUserID is the key
*
* TODO: remove this once the server is always sending back the correct format!
* https://github.com/Expensify/App/issues/10960
*
* @param {Array|Object} loginList
* @return {Object}
*/
function convertLoginListToObject(loginList = {}) {
if (!_.isArray(loginList)) {
return loginList;
}

return _.reduce(loginList, (allLogins, login) => {
// eslint-disable-next-line no-param-reassign
allLogins[login.partnerUserID] = login;
return allLogins;
}, {});
}

/**
* Filter out all non-Expensify partners from login list
*
Expand All @@ -63,21 +42,18 @@ function keepExpensifyPartners(loginList = {}) {
}

/**
* Cleans login list that came from the server by doing two steps:
* 1. Converts login list to an object (in case it came as an array)
* 2. Only keeps logins with Expensify partner name
* Cleans login list that came from the server by only keeping logins with Expensify partner name
*
* @param {Array|Object} loginList
* @param {Object} loginList
* @returns {Object}
*/
function cleanLoginListServerResponse(loginList = {}) {
return keepExpensifyPartners(convertLoginListToObject(loginList));
return keepExpensifyPartners(loginList);
}

export {
getEmailWithoutMergedAccountPrefix,
getPhoneNumberWithoutSpecialChars,
getPhoneNumberWithoutUSCountryCodeAndSpecialChars,
convertLoginListToObject,
cleanLoginListServerResponse,
};
5 changes: 1 addition & 4 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import * as Localize from './Localize';
import Permissions from './Permissions';
import * as CollectionUtils from './CollectionUtils';
import Navigation from './Navigation/Navigation';
import * as LoginUtils from './LoginUtils';

/**
* OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can
Expand All @@ -27,9 +26,7 @@ Onyx.connect({
let loginList;
Onyx.connect({
key: ONYXKEYS.LOGIN_LIST,
callback: (val) => {
loginList = LoginUtils.convertLoginListToObject(val);
},
callback: val => loginList = _.isEmpty(val) ? {} : val,
});

let countryCodeByIP;
Expand Down
29 changes: 10 additions & 19 deletions src/pages/RequestCallPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,15 @@ import networkPropTypes from '../components/networkPropTypes';
import RequestCallConfirmationScreen from './RequestCallConfirmationScreen';
import Form from '../components/Form';

const loginPropTypes = PropTypes.shape({
/** Phone/Emails associated with user */
partnerUserID: PropTypes.string,
});

const propTypes = {
...withLocalizePropTypes,
...withCurrentUserPersonalDetailsPropTypes,

/** Login list for the user that is signed in */
loginList: PropTypes.oneOfType([
PropTypes.objectOf(loginPropTypes),

// TODO: remove this once this closes:
// https://github.com/Expensify/App/issues/10960
PropTypes.arrayOf(loginPropTypes),
]),
loginList: PropTypes.shape({
/** Phone/Emails associated with user */
partnerUserID: PropTypes.string,
}),

/** The policies which the user has access to */
policies: PropTypes.shape({
Expand Down Expand Up @@ -162,14 +154,13 @@ class RequestCallPage extends Component {
}

/**
* Gets the user's phone number from their secondary login.
* Returns null if it doesn't exist.
* Gets the user's phone number from their secondary logins.
* Returns empty string if it doesn't exist.
*
* @param {Array|Object} loginList
* @returns {String|null}
* @returns {String}
*/
getPhoneNumber(loginList) {
const secondaryLogin = _.find(_.values(LoginUtils.convertLoginListToObject(loginList)), login => Str.isSMSLogin(login.partnerUserID));
getPhoneNumber() {
const secondaryLogin = _.find(_.values(this.props.loginList), login => Str.isSMSLogin(login.partnerUserID));
return secondaryLogin ? Str.removeSMSDomain(secondaryLogin.partnerUserID) : '';
}

Expand Down Expand Up @@ -299,7 +290,7 @@ class RequestCallPage extends Component {
/>
<TextInput
inputID="phoneNumber"
defaultValue={this.getPhoneNumber(this.props.loginList)}
defaultValue={this.getPhoneNumber()}
label={this.props.translate('common.phoneNumber')}
name="phone"
keyboardType={CONST.KEYBOARD_TYPE.PHONE_PAD}
Expand Down
41 changes: 15 additions & 26 deletions src/pages/settings/Profile/ProfilePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,22 @@ import * as ValidationUtils from '../../../libs/ValidationUtils';
import * as ReportUtils from '../../../libs/ReportUtils';
import Form from '../../../components/Form';
import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
import * as LoginUtils from '../../../libs/LoginUtils';

const loginPropTypes = PropTypes.shape({
/** Value of partner name */
partnerName: PropTypes.string,

/** Phone/Email associated with user */
partnerUserID: PropTypes.string,

/** Date of when login was validated */
validatedDate: PropTypes.string,
});

const propTypes = {
/* Onyx Props */

/** Login list for the user that is signed in */
loginList: PropTypes.oneOfType([
PropTypes.objectOf(loginPropTypes),
loginList: PropTypes.shape({
/** Value of partner name */
partnerName: PropTypes.string,

/** Phone/Email associated with user */
partnerUserID: PropTypes.string,

/** Date of when login was validated */
validatedDate: PropTypes.string,
}),

// TODO: remove this once this closes:
// https://github.com/Expensify/App/issues/10960
PropTypes.arrayOf(loginPropTypes),
]),
...withLocalizePropTypes,
...withCurrentUserPersonalDetailsPropTypes,
};
Expand All @@ -77,7 +69,7 @@ class ProfilePage extends Component {
this.avatar = {uri: lodashGet(this.props.currentUserPersonalDetails, 'avatar') || this.defaultAvatar};
this.pronouns = props.currentUserPersonalDetails.pronouns;
this.state = {
logins: this.getLogins(LoginUtils.convertLoginListToObject(props.loginList)),
logins: this.getLogins(),
selectedTimezone: lodashGet(props.currentUserPersonalDetails.timezone, 'selected', CONST.DEFAULT_TIME_ZONE.selected),
isAutomaticTimezone: lodashGet(props.currentUserPersonalDetails.timezone, 'automatic', CONST.DEFAULT_TIME_ZONE.automatic),
hasSelfSelectedPronouns: !_.isEmpty(props.currentUserPersonalDetails.pronouns) && !props.currentUserPersonalDetails.pronouns.startsWith(CONST.PRONOUNS.PREFIX),
Expand All @@ -94,10 +86,8 @@ class ProfilePage extends Component {
let stateToUpdate = {};

// Recalculate logins if loginList has changed
const currentLoginList = LoginUtils.convertLoginListToObject(this.props.loginList);
const prevLoginList = LoginUtils.convertLoginListToObject(prevProps.loginList);
if (_.keys(currentLoginList).length !== _.keys(prevLoginList).length) {
stateToUpdate = {...stateToUpdate, logins: this.getLogins(currentLoginList)};
if (_.keys(this.props.loginList).length !== _.keys(prevProps.loginList).length) {
stateToUpdate = {...stateToUpdate, logins: this.getLogins()};
}

if (_.isEmpty(stateToUpdate)) {
Expand Down Expand Up @@ -141,11 +131,10 @@ class ProfilePage extends Component {
/**
* Get the most validated login of each type
*
* @param {Object} loginList
* @returns {Object}
*/
getLogins(loginList) {
return _.reduce(_.values(loginList), (logins, currentLogin) => {
getLogins() {
return _.reduce(_.values(this.props.loginList), (logins, currentLogin) => {
const type = Str.isSMSLogin(currentLogin.partnerUserID) ? CONST.LOGIN_TYPE.PHONE : CONST.LOGIN_TYPE.EMAIL;
const login = Str.removeSMSDomain(currentLogin.partnerUserID);

Expand Down