From 1a05abf51fd938fa65e762175f8b1e86d3e16d21 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 24 Jun 2022 11:29:05 -0400 Subject: [PATCH 01/38] Refactor AuthScreens.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/libs/Navigation/AppNavigator/AuthScreens.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 8a0e5e53dcf..e667ce6eb81 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -40,14 +40,20 @@ import LogOutPreviousUserPage from '../../../pages/LogOutPreviousUserPage'; import networkPropTypes from '../../../components/networkPropTypes'; import {withNetwork} from '../../../components/OnyxProvider'; +let currentUserLogin; Onyx.connect({ - key: ONYXKEYS.MY_PERSONAL_DETAILS, + key: ONYXKEYS.SESSION, + callback: val => currentUserLogin = val && val.email, +}); + +Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS, callback: (val) => { if (!val) { return; } - const timezone = lodashGet(val, 'timezone', {}); + const timezone = lodashGet(val, [currentUserLogin, 'timezone'], {}); const currentTimezone = moment.tz.guess(true); // If the current timezone is different than the user's timezone, and their timezone is set to automatic From 8b67fd988a04e017bfdeeba07f1c59851f9ff2dc Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 24 Jun 2022 15:58:06 -0400 Subject: [PATCH 02/38] Flag wich details in the personalDetails object belong to the current user --- src/libs/actions/PersonalDetails.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index cc7add84320..2747b589d24 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -135,6 +135,9 @@ function fetchPersonalDetails() { } const allPersonalDetails = formatPersonalDetails(personalDetailsList); + + // Flag which details belong to the currently logged in user for easy access before storing + allPersonalDetails[currentUserEmail].isCurrentUser = true; Onyx.merge(ONYXKEYS.PERSONAL_DETAILS, allPersonalDetails); myPersonalDetails = allPersonalDetails[currentUserEmail]; From 98092d79f8e4e1ec4d1e4a5a96c6baf37604ffa7 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 24 Jun 2022 16:08:07 -0400 Subject: [PATCH 03/38] Update AuthScreen.js to look for new isCurrentUser flag --- src/libs/Navigation/AppNavigator/AuthScreens.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index e667ce6eb81..cffc53999da 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -40,12 +40,6 @@ import LogOutPreviousUserPage from '../../../pages/LogOutPreviousUserPage'; import networkPropTypes from '../../../components/networkPropTypes'; import {withNetwork} from '../../../components/OnyxProvider'; -let currentUserLogin; -Onyx.connect({ - key: ONYXKEYS.SESSION, - callback: val => currentUserLogin = val && val.email, -}); - Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS, callback: (val) => { @@ -53,7 +47,8 @@ Onyx.connect({ return; } - const timezone = lodashGet(val, [currentUserLogin, 'timezone'], {}); + const currentUser = _.findWhere(val, {isCurrentUser: true}); + const timezone = lodashGet(currentUser, 'timezone', {}); const currentTimezone = moment.tz.guess(true); // If the current timezone is different than the user's timezone, and their timezone is set to automatic From 09fe20d28ab87ab22959688f15b2606093057fce Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 24 Jun 2022 16:18:42 -0400 Subject: [PATCH 04/38] Update Report.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/libs/actions/Report.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index f529931b5c8..8091b6dda30 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -51,8 +51,8 @@ Onyx.connect({ let myPersonalDetails; Onyx.connect({ - key: ONYXKEYS.MY_PERSONAL_DETAILS, - callback: val => myPersonalDetails = val, + key: ONYXKEYS.PERSONAL_DETAILS, + callback: val => myPersonalDetails = _.findWhere(val, {isCurrentUser: true}); }); const allReports = {}; From 413872f6bfe493092e9d499b6fdfe4a596eb28bf Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 24 Jun 2022 16:47:36 -0400 Subject: [PATCH 05/38] Replace semicolon that was supposed to be comma --- src/libs/actions/Report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 8091b6dda30..22bb98bca63 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -52,7 +52,7 @@ Onyx.connect({ let myPersonalDetails; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS, - callback: val => myPersonalDetails = _.findWhere(val, {isCurrentUser: true}); + callback: val => myPersonalDetails = _.findWhere(val, {isCurrentUser: true}), }); const allReports = {}; From dc7170ba93d685f58d50d2776639094a58b2ea6a Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sat, 25 Jun 2022 00:14:51 -0400 Subject: [PATCH 06/38] Refactor ReportActionCompose.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/home/report/ReportActionCompose.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index a48ef025fa0..da29f63e7b3 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -96,12 +96,6 @@ const propTypes = { expiresAt: PropTypes.string, }), - /** The personal details of the person who is logged in */ - myPersonalDetails: PropTypes.shape({ - /** Primary login of the user */ - login: PropTypes.string, - }), - ...windowDimensionsPropTypes, ...withLocalizePropTypes, }; @@ -113,7 +107,6 @@ const defaultProps = { reportActions: {}, blockedFromConcierge: {}, personalDetails: {}, - myPersonalDetails: {}, }; class ReportActionCompose extends React.Component { @@ -135,6 +128,7 @@ class ReportActionCompose extends React.Component { this.setTextInputRef = this.setTextInputRef.bind(this); this.getInputPlaceholder = this.getInputPlaceholder.bind(this); this.getIOUOptions = this.getIOUOptions.bind(this); + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); this.state = { isFocused: this.shouldFocusInputOnScreenFocus, @@ -263,7 +257,7 @@ class ReportActionCompose extends React.Component { * @returns {Array} */ getIOUOptions(reportParticipants) { - const participants = _.filter(reportParticipants, email => this.props.myPersonalDetails.login !== email); + const participants = _.filter(reportParticipants, email => this.myPersonalDetails.login !== email); const hasExcludedIOUEmails = lodashIntersection(reportParticipants, CONST.EXPENSIFY_EMAILS).length > 0; const hasMultipleParticipants = participants.length > 1; const iouOptions = []; @@ -696,8 +690,5 @@ export default compose( blockedFromConcierge: { key: ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, }, - myPersonalDetails: { - key: ONYXKEYS.MY_PERSONAL_DETAILS, - }, }), )(ReportActionCompose); From 630e90ef3684919b4adad1ffd3f87d7d081cb21c Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sat, 25 Jun 2022 14:16:05 -0400 Subject: [PATCH 07/38] Refactor RequestCallPage.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/RequestCallPage.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index d7d3e5abb4c..50dc335987b 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -38,8 +38,8 @@ import networkPropTypes from '../components/networkPropTypes'; const propTypes = { ...withLocalizePropTypes, - /** The personal details of the person who is logged in */ - myPersonalDetails: personalDetailsPropType.isRequired, + /** Personal details of all the users */ + personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired, /** Login list for the user that is signed in */ loginList: PropTypes.arrayOf(PropTypes.shape({ @@ -99,7 +99,8 @@ const defaultProps = { class RequestCallPage extends Component { constructor(props) { super(props); - const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(props.myPersonalDetails); + const myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(myPersonalDetails); this.state = { firstName, hasFirstNameError: false, @@ -355,8 +356,8 @@ export default compose( withLocalize, withNetwork(), withOnyx({ - myPersonalDetails: { - key: ONYXKEYS.MY_PERSONAL_DETAILS, + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, }, loginList: { key: ONYXKEYS.LOGIN_LIST, From c6a6d82792d79ba82ebab731464ea47b7a12869b Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sat, 25 Jun 2022 15:54:36 -0400 Subject: [PATCH 08/38] Refactor DateUtils.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/libs/DateUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index 791bd9e8c81..dc620fba89e 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -14,9 +14,10 @@ import * as CurrentDate from './actions/CurrentDate'; let timezone = CONST.DEFAULT_TIME_ZONE; Onyx.connect({ - key: ONYXKEYS.MY_PERSONAL_DETAILS, + key: ONYXKEYS.PERSONAL_DETAILS, callback: (val) => { - timezone = lodashGet(val, 'timezone', CONST.DEFAULT_TIME_ZONE); + const currentUser = _.findWhere(val, {isCurrentUser: true}); + timezone = lodashGet(currentUser, 'timezone', CONST.DEFAULT_TIME_ZONE); }, }); From 9aa47728851e3cf11f03b83e9aaf09df7ee68523 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sun, 26 Jun 2022 09:24:35 -0400 Subject: [PATCH 09/38] Refactor EnablePayments.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/EnablePayments/AdditionalDetailsStep.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index 4ba70e29784..d7a2f0aa903 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -62,8 +62,8 @@ const propTypes = { /** Stores the personal details typed by the user */ walletAdditionalDetailsDraft: walletAdditionalDetailsDraftPropTypes, - /** The personal details of the person who is logged in */ - myPersonalDetails: personalDetailsPropType.isRequired, + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired, }; const defaultProps = { @@ -93,6 +93,7 @@ class AdditionalDetailsStep extends React.Component { super(props); this.activateWallet = this.activateWallet.bind(this); + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); this.requiredFields = [ 'legalFirstName', @@ -233,7 +234,7 @@ class AdditionalDetailsStep extends React.Component { const isErrorVisible = _.size(this.getErrors()) > 0 || lodashGet(this.props, 'walletAdditionalDetails.additionalErrorMessage', '').length > 0; const shouldAskForFullSSN = this.props.walletAdditionalDetails.shouldAskForFullSSN; - const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(this.props.myPersonalDetails); + const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(this.myPersonalDetails); return ( @@ -370,8 +371,8 @@ export default compose( key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, initWithStoredValues: false, }, - myPersonalDetails: { - key: ONYXKEYS.MY_PERSONAL_DETAILS, + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, }, }), )(AdditionalDetailsStep); From a65ca2574312f347f48131a59551c97ec77e2349 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Sun, 26 Jun 2022 09:46:01 -0400 Subject: [PATCH 10/38] Refactor IOUModal.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/iou/IOUModal.js | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/pages/iou/IOUModal.js b/src/pages/iou/IOUModal.js index 561b8a32836..0b8fb495611 100755 --- a/src/pages/iou/IOUModal.js +++ b/src/pages/iou/IOUModal.js @@ -45,13 +45,6 @@ const propTypes = { participants: PropTypes.arrayOf(PropTypes.string), }), - // The personal details of the person who is logged in - myPersonalDetails: PropTypes.shape({ - - // Local Currency Code of the current user - localCurrencyCode: PropTypes.string, - }), - /** Information about the network */ network: networkPropTypes.isRequired, @@ -90,9 +83,6 @@ const defaultProps = { report: { participants: [], }, - myPersonalDetails: { - localCurrencyCode: CONST.CURRENCY.USD, - }, iouType: CONST.IOU.IOU_TYPE.REQUEST, }; @@ -112,6 +102,13 @@ class IOUModal extends Component { this.createTransaction = this.createTransaction.bind(this); this.updateComment = this.updateComment.bind(this); this.sendMoney = this.sendMoney.bind(this); + + // Get my details from the list of personal details and set my local currency to USD if not already set + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + if (!_.has(this.myPersonalDetails, 'localCurrencyCode') || _.isEmpty(this.myPersonalDetails.localCurrencyCode)) { + this.myPersonalDetails.localCurrencyCode = CONST.CURRENCY.USD; + } + const participants = lodashGet(props, 'report.participants', []); const participantsWithDetails = _.map(OptionsListUtils.getPersonalDetailsForLogins(participants, props.personalDetails), personalDetails => ({ login: personalDetails.login, @@ -144,7 +141,7 @@ class IOUModal extends Component { componentDidMount() { this.fetchData(); - IOU.setIOUSelectedCurrency(this.props.myPersonalDetails.localCurrencyCode); + IOU.setIOUSelectedCurrency(this.myPersonalDetails.localCurrencyCode); } componentDidUpdate(prevProps) { @@ -443,7 +440,7 @@ class IOUModal extends Component { onConfirm={this.createTransaction} onSendMoney={this.sendMoney} hasMultipleParticipants={this.props.hasMultipleParticipants} - participants={_.filter(this.state.participants, email => this.props.myPersonalDetails.login !== email.login)} + participants={_.filter(this.state.participants, email => this.myPersonalDetails.login !== email.login)} iouAmount={this.state.amount} comment={this.state.comment} onUpdateComment={this.updateComment} @@ -478,8 +475,5 @@ export default compose( personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS, }, - myPersonalDetails: { - key: ONYXKEYS.MY_PERSONAL_DETAILS, - }, }), )(IOUModal); From c3ba3b0217c9cdfb6c7f68c3181f58cd30c5a09d Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 27 Jun 2022 11:51:50 -0400 Subject: [PATCH 11/38] Refactor IOUCurrencySelection.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/iou/IOUCurrencySelection.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/pages/iou/IOUCurrencySelection.js b/src/pages/iou/IOUCurrencySelection.js index 521267ee4aa..87d95660632 100644 --- a/src/pages/iou/IOUCurrencySelection.js +++ b/src/pages/iou/IOUCurrencySelection.js @@ -23,18 +23,15 @@ import * as IOU from '../../libs/actions/IOU'; import * as CurrencySymbolUtils from '../../libs/CurrencySymbolUtils'; import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; +import personalDetailsPropType from '../personalDetailsPropType'; /** * IOU Currency selection for selecting currency */ const propTypes = { - // The personal details of the person who is logged in - myPersonalDetails: PropTypes.shape({ - - // Local Currency Code of the current user - localCurrencyCode: PropTypes.string, - }), + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropType), /** Holds data related to IOU */ iou: PropTypes.shape({ @@ -62,9 +59,7 @@ const propTypes = { }; const defaultProps = { - myPersonalDetails: { - localCurrencyCode: CONST.CURRENCY.USD, - }, + personalDetails: {}, iou: { selectedCurrencyCode: CONST.CURRENCY.USD, }, @@ -78,10 +73,16 @@ class IOUCurrencySelection extends Component { const {currencyOptions} = OptionsListUtils.getCurrencyListForSections(this.getCurrencyOptions(this.props.currencyList), ''); + // Get my details from the list of personal details and set my local currency to USD if not already set + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + if (!_.has(this.myPersonalDetails, 'localCurrencyCode') || _.isEmpty(this.myPersonalDetails.localCurrencyCode)) { + this.myPersonalDetails.localCurrencyCode = CONST.CURRENCY.USD; + } + this.state = { searchValue: '', currencyData: currencyOptions, - toggledCurrencyCode: this.props.iou.selectedCurrencyCode || this.props.myPersonalDetails.localCurrencyCode, + toggledCurrencyCode: this.props.iou.selectedCurrencyCode || this.myPersonalDetails.localCurrencyCode, }; this.getCurrencyOptions = this.getCurrencyOptions.bind(this); this.toggleOption = this.toggleOption.bind(this); @@ -260,7 +261,7 @@ export default compose( withLocalize, withOnyx({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - myPersonalDetails: {key: ONYXKEYS.MY_PERSONAL_DETAILS}, + personalDetails: {key: ONYXKEYS.PERSONAL_DETAILS}, iou: {key: ONYXKEYS.IOU}, }), withNetwork(), From b1a1eb7523692d6573463b5987f29dab04b548a7 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 27 Jun 2022 14:35:47 -0400 Subject: [PATCH 12/38] Refactor SidebarLinks.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/home/sidebar/SidebarLinks.js | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 9021bbc6674..37812ac8f97 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -57,15 +57,6 @@ const propTypes = { /** List of users' personal details */ personalDetails: PropTypes.objectOf(participantPropTypes), - /** The personal details of the person who is logged in */ - myPersonalDetails: PropTypes.shape({ - /** Display name of the current user from their personal details */ - displayName: PropTypes.string, - - /** Avatar URL of the current user from their personal details */ - avatar: PropTypes.string, - }), - /** Information about the network */ network: networkPropTypes.isRequired, @@ -91,9 +82,6 @@ const defaultProps = { reports: {}, reportsWithDraft: {}, personalDetails: {}, - myPersonalDetails: { - avatar: ReportUtils.getDefaultAvatar(), - }, currentlyViewedReportID: '', priorityMode: CONST.PRIORITY_MODE.DEFAULT, initialReportDataLoaded: false, @@ -172,6 +160,13 @@ class SidebarLinks extends React.Component { constructor(props) { super(props); + + // Get my details from the list of personal details and set default avatar if not already set + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + if (!_.has(this.myPersonalDetails, 'avatar') || _.isEmpty(this.myPersonalDetails.avatar)) { + this.myPersonalDetails.avatar = ReportUtils.getDefaultAvatar(); + } + this.state = { activeReport: { reportID: props.currentlyViewedReportID, @@ -287,7 +282,7 @@ class SidebarLinks extends React.Component { onPress={this.props.onAvatarClick} > Date: Mon, 27 Jun 2022 15:44:59 -0400 Subject: [PATCH 13/38] Refactor ProfilePage.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/settings/Profile/ProfilePage.js | 49 ++++++++++++----------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js index fbeb7b69b16..c16508ece16 100755 --- a/src/pages/settings/Profile/ProfilePage.js +++ b/src/pages/settings/Profile/ProfilePage.js @@ -26,15 +26,15 @@ import Picker from '../../../components/Picker'; import FullNameInputRow from '../../../components/FullNameInputRow'; import CheckboxWithLabel from '../../../components/CheckboxWithLabel'; import AvatarWithImagePicker from '../../../components/AvatarWithImagePicker'; -import currentUserPersonalDetailsPropsTypes from './currentUserPersonalDetailsPropsTypes'; +import personalDetailsPropType from '../../personalDetailsPropType'; import * as ValidationUtils from '../../../libs/ValidationUtils'; import * as ReportUtils from '../../../libs/ReportUtils'; const propTypes = { /* Onyx Props */ - /** The personal details of the person who is logged in */ - myPersonalDetails: PropTypes.shape(currentUserPersonalDetailsPropsTypes), + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropType), /** Login list for the user that is signed in */ loginList: PropTypes.arrayOf(PropTypes.shape({ @@ -52,7 +52,7 @@ const propTypes = { }; const defaultProps = { - myPersonalDetails: {}, + personalDetails: {}, loginList: [], }; @@ -68,20 +68,21 @@ class ProfilePage extends Component { constructor(props) { super(props); - this.defaultAvatar = ReportUtils.getDefaultAvatar(this.props.myPersonalDetails.login); + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + this.defaultAvatar = ReportUtils.getDefaultAvatar(this.myPersonalDetails.login); this.state = { - firstName: props.myPersonalDetails.firstName, + firstName: this.myPersonalDetails.firstName, hasFirstNameError: false, - lastName: props.myPersonalDetails.lastName, + lastName: this.myPersonalDetails.lastName, hasLastNameError: false, - pronouns: props.myPersonalDetails.pronouns, + pronouns: this.myPersonalDetails.pronouns, hasPronounError: false, - hasSelfSelectedPronouns: !_.isEmpty(props.myPersonalDetails.pronouns) && !props.myPersonalDetails.pronouns.startsWith(CONST.PRONOUNS.PREFIX), - selectedTimezone: lodashGet(props.myPersonalDetails.timezone, 'selected', CONST.DEFAULT_TIME_ZONE.selected), - isAutomaticTimezone: lodashGet(props.myPersonalDetails.timezone, 'automatic', CONST.DEFAULT_TIME_ZONE.automatic), + hasSelfSelectedPronouns: !_.isEmpty(this.myPersonalDetails.pronouns) && !this.myPersonalDetails.pronouns.startsWith(CONST.PRONOUNS.PREFIX), + selectedTimezone: lodashGet(this.myPersonalDetails.timezone, 'selected', CONST.DEFAULT_TIME_ZONE.selected), + isAutomaticTimezone: lodashGet(this.myPersonalDetails.timezone, 'automatic', CONST.DEFAULT_TIME_ZONE.automatic), logins: this.getLogins(props.loginList), - avatar: {uri: lodashGet(this.props.myPersonalDetails, 'avatar', ReportUtils.getDefaultAvatar(this.props.myPersonalDetails.login))}, + avatar: {uri: lodashGet(this.myPersonalDetails, 'avatar', ReportUtils.getDefaultAvatar(this.myPersonalDetails.login))}, isAvatarChanged: false, }; @@ -132,7 +133,7 @@ class ProfilePage extends Component { const login = Str.removeSMSDomain(currentLogin.partnerUserID); // If there's already a login type that's validated and/or currentLogin isn't valid then return early - if ((login !== this.props.myPersonalDetails.login) && !_.isEmpty(logins[type]) + if ((login !== this.myPersonalDetails.login) && !_.isEmpty(logins[type]) && (logins[type].validatedDate || !currentLogin.validatedDate)) { return logins; } @@ -155,7 +156,7 @@ class ProfilePage extends Component { * @param {Object} avatar */ updateAvatar(avatar) { - this.setState({avatar: _.isUndefined(avatar) ? {uri: ReportUtils.getDefaultAvatar(this.props.myPersonalDetails.login)} : avatar, isAvatarChanged: true}); + this.setState({avatar: _.isUndefined(avatar) ? {uri: ReportUtils.getDefaultAvatar(this.myPersonalDetails.login)} : avatar, isAvatarChanged: true}); } /** @@ -167,7 +168,7 @@ class ProfilePage extends Component { } // Check if the user has modified their avatar - if ((this.props.myPersonalDetails.avatar !== this.state.avatar.uri) && this.state.isAvatarChanged) { + if ((this.myPersonalDetails.avatar !== this.state.avatar.uri) && this.state.isAvatarChanged) { // If the user removed their profile photo, replace it accordingly with the default avatar if (this.state.avatar.uri.includes('/images/avatars/avatar')) { PersonalDetails.deleteAvatar(this.state.avatar.uri); @@ -210,12 +211,12 @@ class ProfilePage extends Component { })); // Disables button if none of the form values have changed - const isButtonDisabled = (this.props.myPersonalDetails.firstName === this.state.firstName.trim()) - && (this.props.myPersonalDetails.lastName === this.state.lastName.trim()) - && (this.props.myPersonalDetails.timezone.selected === this.state.selectedTimezone) - && (this.props.myPersonalDetails.timezone.automatic === this.state.isAutomaticTimezone) - && (this.props.myPersonalDetails.pronouns === this.state.pronouns.trim()) - && (!this.state.isAvatarChanged || this.props.myPersonalDetails.avatarUploading); + const isButtonDisabled = (this.myPersonalDetails.firstName === this.state.firstName.trim()) + && (this.myPersonalDetails.lastName === this.state.lastName.trim()) + && (this.myPersonalDetails.timezone.selected === this.state.selectedTimezone) + && (this.myPersonalDetails.timezone.automatic === this.state.isAutomaticTimezone) + && (this.myPersonalDetails.pronouns === this.state.pronouns.trim()) + && (!this.state.isAvatarChanged || this.myPersonalDetails.avatarUploading); const pronounsPickerValue = this.state.hasSelfSelectedPronouns ? CONST.PRONOUNS.SELF_SELECT : this.state.pronouns; @@ -230,7 +231,7 @@ class ProfilePage extends Component { /> Date: Mon, 27 Jun 2022 15:45:35 -0400 Subject: [PATCH 14/38] Remove no longer used currentUserPersonalDetailsPropsTypes --- .../currentUserPersonalDetailsPropsTypes.js | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/pages/settings/Profile/currentUserPersonalDetailsPropsTypes.js diff --git a/src/pages/settings/Profile/currentUserPersonalDetailsPropsTypes.js b/src/pages/settings/Profile/currentUserPersonalDetailsPropsTypes.js deleted file mode 100644 index caa4d02d2e9..00000000000 --- a/src/pages/settings/Profile/currentUserPersonalDetailsPropsTypes.js +++ /dev/null @@ -1,34 +0,0 @@ -import PropTypes from 'prop-types'; - -/** The personal details of the person who is logged in */ -const currentUserPersonalDetailsPropsTypes = { - /** Email/Phone login of the current user from their personal details */ - login: PropTypes.string, - - /** Display first name of the current user from their personal details */ - firstName: PropTypes.string, - - /** Display last name of the current user from their personal details */ - lastName: PropTypes.string, - - /** Avatar URL of the current user from their personal details */ - avatar: PropTypes.string, - - /** Flag to set when Avatar uploading */ - avatarUploading: PropTypes.bool, - - /** Pronouns of the current user from their personal details */ - pronouns: PropTypes.string, - - /** Timezone of the current user from their personal details */ - timezone: PropTypes.shape({ - - /** Value of selected timezone */ - selected: PropTypes.string, - - /** Whether timezone is automatically set */ - automatic: PropTypes.bool, - }), -}; - -export default currentUserPersonalDetailsPropsTypes; From 5f9bf566798d079c19a0e990ac5f54a9e97a0435 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 27 Jun 2022 15:58:08 -0400 Subject: [PATCH 15/38] Refactor InitialSettingsPage.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/pages/settings/InitialSettingsPage.js | 31 ++++++++++------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index e9374be7f60..b4b2a5eec90 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -23,18 +23,13 @@ import DateUtils from '../../libs/DateUtils'; import Permissions from '../../libs/Permissions'; import networkPropTypes from '../../components/networkPropTypes'; import {withNetwork} from '../../components/OnyxProvider'; +import personalDetailsPropType from '../personalDetailsPropType'; const propTypes = { /* Onyx Props */ - /** The personal details of the person who is logged in */ - myPersonalDetails: PropTypes.shape({ - /** Display name of the current user from their personal details */ - displayName: PropTypes.string, - - /** Avatar URL of the current user from their personal details */ - avatar: PropTypes.string, - }), + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropType), /** Information about the network */ network: networkPropTypes.isRequired, @@ -73,7 +68,7 @@ const propTypes = { }; const defaultProps = { - myPersonalDetails: {}, + personalDetails: {}, session: {}, policies: {}, userWallet: { @@ -124,10 +119,12 @@ const InitialSettingsPage = (props) => { {style: 'currency', currency: 'USD'}, ); + const myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + // On the very first sign in or after clearing storage these // details will not be present on the first render so we'll just // return nothing for now. - if (_.isEmpty(props.myPersonalDetails)) { + if (_.isEmpty(myPersonalDetails)) { return null; } @@ -160,20 +157,20 @@ const InitialSettingsPage = (props) => { - {props.myPersonalDetails.displayName - ? props.myPersonalDetails.displayName + {myPersonalDetails.displayName + ? myPersonalDetails.displayName : Str.removeSMSDomain(props.session.email)} - {props.myPersonalDetails.displayName && ( + {myPersonalDetails.displayName && ( Date: Mon, 27 Jun 2022 16:22:53 -0400 Subject: [PATCH 16/38] Refactor IOUConfirmationList.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/components/IOUConfirmationList.js | 29 ++++++++++----------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js index 91eaebc3914..a2eb6d08fd2 100755 --- a/src/components/IOUConfirmationList.js +++ b/src/components/IOUConfirmationList.js @@ -21,6 +21,7 @@ import SettlementButton from './SettlementButton'; import ROUTES from '../ROUTES'; import networkPropTypes from './networkPropTypes'; import {withNetwork} from './OnyxProvider'; +import personalDetailsPropType from '../pages/personalDetailsPropType'; const propTypes = { /** Callback to inform parent modal of success */ @@ -70,18 +71,8 @@ const propTypes = { /* Onyx Props */ - /** The personal details of the person who is logged in */ - myPersonalDetails: PropTypes.shape({ - - /** Display name of the current user from their personal details */ - displayName: PropTypes.string, - - /** Avatar URL of the current user from their personal details */ - avatar: PropTypes.string, - - /** Primary login of the user */ - login: PropTypes.string, - }), + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropType), /** Holds data related to IOU view state, rather than the underlying IOU data. */ iou: PropTypes.shape({ @@ -108,7 +99,7 @@ const defaultProps = { }, onUpdateComment: null, comment: '', - myPersonalDetails: {}, + personalDetails: {}, iouType: CONST.IOU.IOU_TYPE.REQUEST, }; @@ -130,6 +121,8 @@ class IOUConfirmationList extends Component { value: props.hasMultipleParticipants ? CONST.IOU.IOU_TYPE.SPLIT : CONST.IOU.IOU_TYPE.REQUEST, }]; + this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); + this.state = { participants: formattedParticipants, }; @@ -212,7 +205,7 @@ class IOUConfirmationList extends Component { const formattedUnselectedParticipants = this.getParticipantsWithoutAmount(unselectedParticipants); const formattedMyPersonalDetails = OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail( - this.props.myPersonalDetails, + this.myPersonalDetails, this.props.numberFormat(this.calculateAmount(selectedParticipants, true) / 100, { style: 'currency', currency: this.props.iou.selectedCurrencyCode, @@ -273,7 +266,7 @@ class IOUConfirmationList extends Component { })); splits.push({ - email: OptionsListUtils.addSMSDomainIfPhoneNumber(this.props.myPersonalDetails.login), + email: OptionsListUtils.addSMSDomainIfPhoneNumber(this.myPersonalDetails.login), // The user is default and we should send in cents to API // USD is temporary and there must be support for other currencies in the future @@ -293,7 +286,7 @@ class IOUConfirmationList extends Component { const selectedParticipants = this.getSelectedParticipants(); return [ ...selectedParticipants, - OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(this.props.myPersonalDetails), + OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(this.myPersonalDetails), ]; } @@ -418,8 +411,8 @@ export default compose( withNetwork(), withOnyx({ iou: {key: ONYXKEYS.IOU}, - myPersonalDetails: { - key: ONYXKEYS.MY_PERSONAL_DETAILS, + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, }, session: { key: ONYXKEYS.SESSION, From 22e11503ddaa6c697acbd6dd38e6adf6fcd7b496 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 27 Jun 2022 16:28:55 -0400 Subject: [PATCH 17/38] No longer save to MY_PERSONAL_DETAILS key in fetchPersonalDetails method --- src/libs/actions/PersonalDetails.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 2747b589d24..c00ba2b40bf 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -125,8 +125,6 @@ function fetchPersonalDetails() { returnValueList: 'personalDetailsList', }) .then((data) => { - let myPersonalDetails = {}; - // If personalDetailsList does not have the current user ensure we initialize their details with an empty // object at least const personalDetailsList = _.isEmpty(data.personalDetailsList) ? {} : data.personalDetailsList; @@ -139,15 +137,6 @@ function fetchPersonalDetails() { // Flag which details belong to the currently logged in user for easy access before storing allPersonalDetails[currentUserEmail].isCurrentUser = true; Onyx.merge(ONYXKEYS.PERSONAL_DETAILS, allPersonalDetails); - - myPersonalDetails = allPersonalDetails[currentUserEmail]; - - // Add the first and last name to the current user's MY_PERSONAL_DETAILS key - myPersonalDetails.firstName = lodashGet(data.personalDetailsList, [currentUserEmail, 'firstName'], ''); - myPersonalDetails.lastName = lodashGet(data.personalDetailsList, [currentUserEmail, 'lastName'], ''); - - // Set my personal details so they can be easily accessed and subscribed to on their own key - Onyx.merge(ONYXKEYS.MY_PERSONAL_DETAILS, myPersonalDetails); }); } From 085ed98ba9eee410cc837e2ed46f67419b7e5d9d Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 27 Jun 2022 16:33:29 -0400 Subject: [PATCH 18/38] Refactor PersonalDetails.js to use PERSONAL_DETAILS instead of MY_PERSONAL_DETAILS --- src/libs/actions/PersonalDetails.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index c00ba2b40bf..8706fdb1c77 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -254,8 +254,6 @@ function mergeLocalPersonalDetails(details) { // displayName is a generated field so we'll use the firstName and lastName + login to update it. mergedDetails.displayName = getDisplayName(currentUserEmail, mergedDetails); - // Update the associated Onyx keys - Onyx.merge(ONYXKEYS.MY_PERSONAL_DETAILS, mergedDetails); Onyx.merge(ONYXKEYS.PERSONAL_DETAILS, {[currentUserEmail]: mergedDetails}); } @@ -317,7 +315,7 @@ function fetchLocalCurrency() { }) .then(getCurrencyList) .then(() => { - Onyx.merge(ONYXKEYS.MY_PERSONAL_DETAILS, {localCurrencyCode: currency}); + Onyx.merge(ONYXKEYS.PERSONAL_DETAILS, {[currentUserEmail]: {localCurrencyCode: currency}}); }) .finally(() => { Onyx.merge(ONYXKEYS.IOU, { From 380dbaf14848fc4a12840f733a9ce95904fba976 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 27 Jun 2022 16:34:11 -0400 Subject: [PATCH 19/38] Remove the MY_PERSONAL_DETAILS onyx key --- src/ONYXKEYS.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 1f47b414ee2..a3427cbe8ef 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -46,9 +46,6 @@ export default { // Keeps track if there is modal currently visible or not MODAL: 'modal', - // Contains the personalDetails of the user as well as their timezone - MY_PERSONAL_DETAILS: 'myPersonalDetails', - // Has information about the network status (offline/online) NETWORK: 'network', From 67e1fd56a79da5f90cbbf6fa28d1f64523ee4d47 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Tue, 28 Jun 2022 13:54:24 -0400 Subject: [PATCH 20/38] Get rid of unnecessary personal details references from IOUCurrencySelection.js --- src/pages/iou/IOUCurrencySelection.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/pages/iou/IOUCurrencySelection.js b/src/pages/iou/IOUCurrencySelection.js index e39d86cc9d0..a8dfad9ff25 100644 --- a/src/pages/iou/IOUCurrencySelection.js +++ b/src/pages/iou/IOUCurrencySelection.js @@ -16,7 +16,6 @@ import * as IOU from '../../libs/actions/IOU'; import * as CurrencySymbolUtils from '../../libs/CurrencySymbolUtils'; import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; -import personalDetailsPropType from '../personalDetailsPropType'; /** * IOU Currency selection for selecting currency @@ -50,12 +49,6 @@ class IOUCurrencySelection extends Component { const {currencyOptions} = OptionsListUtils.getCurrencyListForSections(this.getCurrencyOptions(this.props.currencyList), ''); - // Get my details from the list of personal details and set my local currency to USD if not already set - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - if (!_.has(this.myPersonalDetails, 'localCurrencyCode') || _.isEmpty(this.myPersonalDetails.localCurrencyCode)) { - this.myPersonalDetails.localCurrencyCode = CONST.CURRENCY.USD; - } - this.state = { searchValue: '', currencyData: currencyOptions, From 8aec23905d04d15b942a8bb185db3de5ce5fb52c Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 11 Jul 2022 11:32:25 -0400 Subject: [PATCH 21/38] Create HOC for withPersonalDetails --- src/components/withPersonalDetails.js | 84 +++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/components/withPersonalDetails.js diff --git a/src/components/withPersonalDetails.js b/src/components/withPersonalDetails.js new file mode 100644 index 00000000000..e2a2a3a8381 --- /dev/null +++ b/src/components/withPersonalDetails.js @@ -0,0 +1,84 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; +import getComponentDisplayName from '../libs/getComponentDisplayName'; +import ONYXKEYS from '../ONYXKEYS'; + +const personalDetailsPropTypes = { + // First name of the current user from their personal details + firstName: PropTypes.string, + + // Last name of the current user from their personal details + lastName: PropTypes.string, + + // Display name of the current user from their personal details + displayName: PropTypes.string, + + // Avatar URL of the current user from their personal details + avatar: PropTypes.string, + + // login of the current user from their personal details + login: PropTypes.string, + + // pronouns of the current user from their personal details + pronouns: PropTypes.string, + + // timezone of the current user from their personal details + timezone: PropTypes.shape({ + selected: PropTypes.string, + }), +}; + +export default function (WrappedComponent) { + const WithPersonalDetails = (props) => { + const currentUserEmail = props.session.email; + + return ( + + ); + } + + WithPersonalDetails.displayName = `WithPersonalDetails(${getComponentDisplayName(WrappedComponent)})`; + WithPersonalDetails.propTypes = { + forwardedRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape({current: PropTypes.instanceOf(React.Component)}), + ]), + + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropTypes), + + /** Personal details of the current user */ + currentUserPersonalDetails: personalDetailsPropTypes, + }; + + WithToggleVisibilityView.defaultProps = { + forwardedRef: undefined, + personalDetails: {}, + currentUserPersonalDetails: {}, + }; + + const withPersonalDetails = React.forwardRef((props, ref) => ( + // eslint-disable-next-line react/jsx-props-no-spreading + + )); + + return withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, + }, + session: { + key: ONYXKEYS.SESSION, + }, + })(withPersonalDetails); +} + +export { + personalDetailsPropTypes, +}; From 31ab9390ca71db5cb6dae96e1996b5bc919d0a80 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Mon, 11 Jul 2022 12:08:43 -0400 Subject: [PATCH 22/38] Add session prop and proptype to personal details HOC --- src/components/withPersonalDetails.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/withPersonalDetails.js b/src/components/withPersonalDetails.js index e2a2a3a8381..b9d72835aa6 100644 --- a/src/components/withPersonalDetails.js +++ b/src/components/withPersonalDetails.js @@ -4,7 +4,7 @@ import {withOnyx} from 'react-native-onyx'; import getComponentDisplayName from '../libs/getComponentDisplayName'; import ONYXKEYS from '../ONYXKEYS'; -const personalDetailsPropTypes = { +const personalDetailsPropTypes = PropTypes.shape({ // First name of the current user from their personal details firstName: PropTypes.string, @@ -27,7 +27,7 @@ const personalDetailsPropTypes = { timezone: PropTypes.shape({ selected: PropTypes.string, }), -}; +}); export default function (WrappedComponent) { const WithPersonalDetails = (props) => { @@ -42,7 +42,7 @@ export default function (WrappedComponent) { currentUserPersonalDetails={props.personalDetails[currentUserEmail]} /> ); - } + }; WithPersonalDetails.displayName = `WithPersonalDetails(${getComponentDisplayName(WrappedComponent)})`; WithPersonalDetails.propTypes = { @@ -56,12 +56,18 @@ export default function (WrappedComponent) { /** Personal details of the current user */ currentUserPersonalDetails: personalDetailsPropTypes, + session: PropTypes.shape({ + email: PropTypes.string, + }), }; - WithToggleVisibilityView.defaultProps = { + WithPersonalDetails.defaultProps = { forwardedRef: undefined, personalDetails: {}, currentUserPersonalDetails: {}, + session: { + email: '', + }, }; const withPersonalDetails = React.forwardRef((props, ref) => ( From 1def41dd53e32784ca9cb3ce814bd15f13aff72e Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 17:02:22 -0400 Subject: [PATCH 23/38] rename withPersonalDetails to withCurrentUserPersonalDetails --- .../{withPersonalDetails.js => withCurrentUserPersonalDetails} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/components/{withPersonalDetails.js => withCurrentUserPersonalDetails} (100%) diff --git a/src/components/withPersonalDetails.js b/src/components/withCurrentUserPersonalDetails similarity index 100% rename from src/components/withPersonalDetails.js rename to src/components/withCurrentUserPersonalDetails From 00bd238430354f82c982372516197c9b67cfef67 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 17:45:20 -0400 Subject: [PATCH 24/38] update withCurrentUserPersonalDetails to pass single prop of current users details --- src/components/withCurrentUserPersonalDetails | 90 ------------------- .../withCurrentUserPersonalDetails.js | 72 +++++++++++++++ 2 files changed, 72 insertions(+), 90 deletions(-) delete mode 100644 src/components/withCurrentUserPersonalDetails create mode 100644 src/components/withCurrentUserPersonalDetails.js diff --git a/src/components/withCurrentUserPersonalDetails b/src/components/withCurrentUserPersonalDetails deleted file mode 100644 index b9d72835aa6..00000000000 --- a/src/components/withCurrentUserPersonalDetails +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import {withOnyx} from 'react-native-onyx'; -import getComponentDisplayName from '../libs/getComponentDisplayName'; -import ONYXKEYS from '../ONYXKEYS'; - -const personalDetailsPropTypes = PropTypes.shape({ - // First name of the current user from their personal details - firstName: PropTypes.string, - - // Last name of the current user from their personal details - lastName: PropTypes.string, - - // Display name of the current user from their personal details - displayName: PropTypes.string, - - // Avatar URL of the current user from their personal details - avatar: PropTypes.string, - - // login of the current user from their personal details - login: PropTypes.string, - - // pronouns of the current user from their personal details - pronouns: PropTypes.string, - - // timezone of the current user from their personal details - timezone: PropTypes.shape({ - selected: PropTypes.string, - }), -}); - -export default function (WrappedComponent) { - const WithPersonalDetails = (props) => { - const currentUserEmail = props.session.email; - - return ( - - ); - }; - - WithPersonalDetails.displayName = `WithPersonalDetails(${getComponentDisplayName(WrappedComponent)})`; - WithPersonalDetails.propTypes = { - forwardedRef: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.shape({current: PropTypes.instanceOf(React.Component)}), - ]), - - /** Personal details of all the users, including current user */ - personalDetails: PropTypes.objectOf(personalDetailsPropTypes), - - /** Personal details of the current user */ - currentUserPersonalDetails: personalDetailsPropTypes, - session: PropTypes.shape({ - email: PropTypes.string, - }), - }; - - WithPersonalDetails.defaultProps = { - forwardedRef: undefined, - personalDetails: {}, - currentUserPersonalDetails: {}, - session: { - email: '', - }, - }; - - const withPersonalDetails = React.forwardRef((props, ref) => ( - // eslint-disable-next-line react/jsx-props-no-spreading - - )); - - return withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS, - }, - session: { - key: ONYXKEYS.SESSION, - }, - })(withPersonalDetails); -} - -export { - personalDetailsPropTypes, -}; diff --git a/src/components/withCurrentUserPersonalDetails.js b/src/components/withCurrentUserPersonalDetails.js new file mode 100644 index 00000000000..65b695fc06c --- /dev/null +++ b/src/components/withCurrentUserPersonalDetails.js @@ -0,0 +1,72 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; +import getComponentDisplayName from '../libs/getComponentDisplayName'; +import ONYXKEYS from '../ONYXKEYS'; +import personalDetailsPropType from '../pages/personalDetailsPropType'; + +const withCurrentUserPersonalDetailsPropTypes = { + currentUserPersonalDetails: personalDetailsPropType, +}; + +const withCurrentUserPersonalDetailsDefaultProps = { + currentUserPersonalDetails: {}, +}; + +export default function (WrappedComponent) { + const WithCurrentUserPersonalDetails = (props) => { + const currentUserEmail = props.session.email; + + return ( + + ); + }; + + WithCurrentUserPersonalDetails.displayName = `WithCurrentUserPersonalDetails(${getComponentDisplayName(WrappedComponent)})`; + WithCurrentUserPersonalDetails.propTypes = { + forwardedRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape({current: PropTypes.instanceOf(React.Component)}), + ]), + + /** Personal details of all the users, including current user */ + personalDetails: PropTypes.objectOf(personalDetailsPropType), + + /** Session of the current user */ + session: PropTypes.shape({ + email: PropTypes.string, + }), + }; + + WithCurrentUserPersonalDetails.defaultProps = { + forwardedRef: undefined, + personalDetails: {}, + session: { + email: '', + }, + }; + + const withCurrentUserPersonalDetails = React.forwardRef((props, ref) => ( + // eslint-disable-next-line react/jsx-props-no-spreading + + )); + + return withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, + }, + session: { + key: ONYXKEYS.SESSION, + }, + })(withCurrentUserPersonalDetails); +} + +export { + withCurrentUserPersonalDetailsPropTypes, + withCurrentUserPersonalDetailsDefaultProps, +}; From afa27dfeada9547dc7a8f08cb768743a37ccb419 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 18:19:42 -0400 Subject: [PATCH 25/38] update RequestCallPage to use withCurrentUserPersonalDetails HOC --- src/pages/RequestCallPage.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index 50dc335987b..cb268b33213 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -20,7 +20,7 @@ import Icon from '../components/Icon'; import CONST from '../CONST'; import Growl from '../libs/Growl'; import * as Inbox from '../libs/actions/Inbox'; -import personalDetailsPropType from './personalDetailsPropType'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../components/withCurrentUserPersonalDetails'; import TextInput from '../components/TextInput'; import Text from '../components/Text'; import Section from '../components/Section'; @@ -37,9 +37,7 @@ import networkPropTypes from '../components/networkPropTypes'; const propTypes = { ...withLocalizePropTypes, - - /** Personal details of all the users */ - personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired, + ...withCurrentUserPersonalDetailsPropTypes, /** Login list for the user that is signed in */ loginList: PropTypes.arrayOf(PropTypes.shape({ @@ -94,13 +92,13 @@ const defaultProps = { lastAccessedWorkspacePolicyID: '', blockedFromConcierge: {}, loginList: [], + ...withCurrentUserPersonalDetailsDefaultProps, }; class RequestCallPage extends Component { constructor(props) { super(props); - const myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(myPersonalDetails); + const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(props.currentUserPersonalDetails); this.state = { firstName, hasFirstNameError: false, @@ -355,10 +353,8 @@ RequestCallPage.defaultProps = defaultProps; export default compose( withLocalize, withNetwork(), + withCurrentUserPersonalDetails, withOnyx({ - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS, - }, loginList: { key: ONYXKEYS.LOGIN_LIST, }, From 6fc8e921368c0c3ff8c7a9808093ac54aa6fe4ba Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 18:23:19 -0400 Subject: [PATCH 26/38] update ReportActionCompose to use withCurrentUserPersonalDetails HOC --- src/pages/home/report/ReportActionCompose.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index da29f63e7b3..2183e0ede8d 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -36,6 +36,7 @@ import ReportActionComposeFocusManager from '../../../libs/ReportActionComposeFo import participantPropTypes from '../../../components/participantPropTypes'; import ParticipantLocalTime from './ParticipantLocalTime'; import {withPersonalDetails} from '../../../components/OnyxProvider'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../../components/withCurrentUserPersonalDetails'; import DateUtils from '../../../libs/DateUtils'; import * as User from '../../../libs/actions/User'; import Tooltip from '../../../components/Tooltip'; @@ -98,6 +99,7 @@ const propTypes = { ...windowDimensionsPropTypes, ...withLocalizePropTypes, + ...withCurrentUserPersonalDetailsPropTypes, }; const defaultProps = { @@ -107,6 +109,7 @@ const defaultProps = { reportActions: {}, blockedFromConcierge: {}, personalDetails: {}, + ...withCurrentUserPersonalDetailsDefaultProps, }; class ReportActionCompose extends React.Component { @@ -128,7 +131,6 @@ class ReportActionCompose extends React.Component { this.setTextInputRef = this.setTextInputRef.bind(this); this.getInputPlaceholder = this.getInputPlaceholder.bind(this); this.getIOUOptions = this.getIOUOptions.bind(this); - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); this.state = { isFocused: this.shouldFocusInputOnScreenFocus, @@ -257,7 +259,7 @@ class ReportActionCompose extends React.Component { * @returns {Array} */ getIOUOptions(reportParticipants) { - const participants = _.filter(reportParticipants, email => this.myPersonalDetails.login !== email); + const participants = _.filter(reportParticipants, email => this.props.currentUserPersonalDetails.login !== email); const hasExcludedIOUEmails = lodashIntersection(reportParticipants, CONST.EXPENSIFY_EMAILS).length > 0; const hasMultipleParticipants = participants.length > 1; const iouOptions = []; @@ -677,6 +679,7 @@ export default compose( withNavigationFocus, withLocalize, withPersonalDetails(), + withCurrentUserPersonalDetails, withOnyx({ betas: { key: ONYXKEYS.BETAS, From a6fbd64b38e2ed70a841781ddbc9ad44b9d6061f Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 18:34:13 -0400 Subject: [PATCH 27/38] update Report.js to use current user email instead of current user flag --- src/libs/actions/Report.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index be8a9db37f4..611458f9004 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -52,7 +52,7 @@ Onyx.connect({ let myPersonalDetails; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS, - callback: val => myPersonalDetails = _.findWhere(val, {isCurrentUser: true}), + callback: val => myPersonalDetails = val[currentUserEmail], }); const allReports = {}; From 59168f36d68559eea4a0a09a97e2c4c7b7107faf Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 18:38:55 -0400 Subject: [PATCH 28/38] update AdditionalDetailsStep to use withCurrentUserPersonalDetails HOC --- src/pages/EnablePayments/AdditionalDetailsStep.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index d7a2f0aa903..26729f22fd1 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -28,11 +28,12 @@ import AddressSearch from '../../components/AddressSearch'; import DatePicker from '../../components/DatePicker'; import FormHelper from '../../libs/FormHelper'; import walletAdditionalDetailsDraftPropTypes from './walletAdditionalDetailsDraftPropTypes'; -import personalDetailsPropType from '../personalDetailsPropType'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../components/withCurrentUserPersonalDetails'; import * as PersonalDetails from '../../libs/actions/PersonalDetails'; const propTypes = { ...withLocalizePropTypes, + ...withCurrentUserPersonalDetailsPropTypes, /** Stores additional information about the additional details step e.g. loading state and errors with fields */ walletAdditionalDetails: PropTypes.shape({ @@ -61,9 +62,6 @@ const propTypes = { /** Stores the personal details typed by the user */ walletAdditionalDetailsDraft: walletAdditionalDetailsDraftPropTypes, - - /** Personal details of all the users, including current user */ - personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired, }; const defaultProps = { @@ -86,6 +84,7 @@ const defaultProps = { dob: '', ssn: '', }, + ...withCurrentUserPersonalDetailsDefaultProps, }; class AdditionalDetailsStep extends React.Component { @@ -93,7 +92,6 @@ class AdditionalDetailsStep extends React.Component { super(props); this.activateWallet = this.activateWallet.bind(this); - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); this.requiredFields = [ 'legalFirstName', @@ -234,7 +232,7 @@ class AdditionalDetailsStep extends React.Component { const isErrorVisible = _.size(this.getErrors()) > 0 || lodashGet(this.props, 'walletAdditionalDetails.additionalErrorMessage', '').length > 0; const shouldAskForFullSSN = this.props.walletAdditionalDetails.shouldAskForFullSSN; - const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(this.myPersonalDetails); + const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(this.props.currentUserPersonalDetails); return ( @@ -366,13 +364,11 @@ AdditionalDetailsStep.propTypes = propTypes; AdditionalDetailsStep.defaultProps = defaultProps; export default compose( withLocalize, + withCurrentUserPersonalDetails, withOnyx({ walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, initWithStoredValues: false, }, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS, - }, }), )(AdditionalDetailsStep); From 55568acd9dfaa0b8e0f792f79bf92d49fb0e81bf Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 18:45:37 -0400 Subject: [PATCH 29/38] update IOUModal to use withCurrentUserPersonalDetails HOC --- src/pages/iou/IOUModal.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/pages/iou/IOUModal.js b/src/pages/iou/IOUModal.js index 0b8fb495611..105b8128d5d 100755 --- a/src/pages/iou/IOUModal.js +++ b/src/pages/iou/IOUModal.js @@ -25,6 +25,7 @@ import Tooltip from '../../components/Tooltip'; import CONST from '../../CONST'; import KeyboardAvoidingView from '../../components/KeyboardAvoidingView'; import * as PersonalDetails from '../../libs/actions/PersonalDetails'; +import withCurrentUserPersonalDetails from '../../components/withCurrentUserPersonalDetails'; import ROUTES from '../../ROUTES'; import networkPropTypes from '../../components/networkPropTypes'; import {withNetwork} from '../../components/OnyxProvider'; @@ -75,6 +76,12 @@ const propTypes = { avatar: PropTypes.string, }).isRequired, + /** Personal details of the current user */ + currentUserPersonalDetails: PropTypes.shape({ + // Local Currency Code of the current user + localCurrencyCode: PropTypes.string, + }), + ...withLocalizePropTypes, }; @@ -84,6 +91,9 @@ const defaultProps = { participants: [], }, iouType: CONST.IOU.IOU_TYPE.REQUEST, + currentUserPersonalDetails: { + localCurrencyCode: CONST.CURRENCY.USD, + }, }; // Determines type of step to display within Modal, value provides the title for that page. @@ -103,12 +113,6 @@ class IOUModal extends Component { this.updateComment = this.updateComment.bind(this); this.sendMoney = this.sendMoney.bind(this); - // Get my details from the list of personal details and set my local currency to USD if not already set - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - if (!_.has(this.myPersonalDetails, 'localCurrencyCode') || _.isEmpty(this.myPersonalDetails.localCurrencyCode)) { - this.myPersonalDetails.localCurrencyCode = CONST.CURRENCY.USD; - } - const participants = lodashGet(props, 'report.participants', []); const participantsWithDetails = _.map(OptionsListUtils.getPersonalDetailsForLogins(participants, props.personalDetails), personalDetails => ({ login: personalDetails.login, @@ -141,7 +145,7 @@ class IOUModal extends Component { componentDidMount() { this.fetchData(); - IOU.setIOUSelectedCurrency(this.myPersonalDetails.localCurrencyCode); + IOU.setIOUSelectedCurrency(this.props.currentUserPersonalDetails.localCurrencyCode); } componentDidUpdate(prevProps) { @@ -440,7 +444,7 @@ class IOUModal extends Component { onConfirm={this.createTransaction} onSendMoney={this.sendMoney} hasMultipleParticipants={this.props.hasMultipleParticipants} - participants={_.filter(this.state.participants, email => this.myPersonalDetails.login !== email.login)} + participants={_.filter(this.state.participants, email => this.props.currentUserPersonalDetails.login !== email.login)} iouAmount={this.state.amount} comment={this.state.comment} onUpdateComment={this.updateComment} @@ -465,6 +469,7 @@ IOUModal.defaultProps = defaultProps; export default compose( withLocalize, withNetwork(), + withCurrentUserPersonalDetails, withOnyx({ report: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${lodashGet(route, 'params.reportID', '')}`, From cd60eca571a145a87dfed25e246b6fbed4645099 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 18:53:41 -0400 Subject: [PATCH 30/38] update InitialSettingsPage to use withCurrentUserPersonalDetails HOC --- src/pages/settings/InitialSettingsPage.js | 26 +++++++++-------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index a0d90b0e744..6d1996630d5 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -23,14 +23,11 @@ import DateUtils from '../../libs/DateUtils'; import Permissions from '../../libs/Permissions'; import networkPropTypes from '../../components/networkPropTypes'; import {withNetwork} from '../../components/OnyxProvider'; -import personalDetailsPropType from '../personalDetailsPropType'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../components/withCurrentUserPersonalDetails'; const propTypes = { /* Onyx Props */ - /** Personal details of all the users, including current user */ - personalDetails: PropTypes.objectOf(personalDetailsPropType), - /** Information about the network */ network: networkPropTypes.isRequired, @@ -65,16 +62,17 @@ const propTypes = { betas: PropTypes.arrayOf(PropTypes.string), ...withLocalizePropTypes, + ...withCurrentUserPersonalDetailsPropTypes, }; const defaultProps = { - personalDetails: {}, session: {}, policies: {}, userWallet: { currentBalance: 0, }, betas: [], + ...withCurrentUserPersonalDetailsDefaultProps, }; const defaultMenuItems = [ @@ -119,12 +117,10 @@ const InitialSettingsPage = (props) => { {style: 'currency', currency: 'USD'}, ); - const myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - // On the very first sign in or after clearing storage these // details will not be present on the first render so we'll just // return nothing for now. - if (_.isEmpty(myPersonalDetails)) { + if (_.isEmpty(props.currentUserPersonalDetails)) { return null; } @@ -157,20 +153,20 @@ const InitialSettingsPage = (props) => { - {myPersonalDetails.displayName - ? myPersonalDetails.displayName + {props.currentUserPersonalDetails.displayName + ? props.currentUserPersonalDetails.displayName : Str.removeSMSDomain(props.session.email)} - {myPersonalDetails.displayName && ( + {props.currentUserPersonalDetails.displayName && ( Date: Fri, 15 Jul 2022 19:02:36 -0400 Subject: [PATCH 31/38] update SidebarLinks to use withCurrentUserPersonalDetails HOC --- src/pages/home/sidebar/SidebarLinks.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 37812ac8f97..6e2f425d303 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -27,6 +27,7 @@ import * as App from '../../../libs/actions/App'; import * as ReportUtils from '../../../libs/ReportUtils'; import networkPropTypes from '../../../components/networkPropTypes'; import {withNetwork} from '../../../components/OnyxProvider'; +import withCurrentUserPersonalDetails from '../../../components/withCurrentUserPersonalDetails'; const propTypes = { /** Toggles the navigation menu open and closed */ @@ -57,6 +58,15 @@ const propTypes = { /** List of users' personal details */ personalDetails: PropTypes.objectOf(participantPropTypes), + /** The personal details of the person who is logged in */ + currentUserPersonalDetails: PropTypes.shape({ + /** Display name of the current user from their personal details */ + displayName: PropTypes.string, + + /** Avatar URL of the current user from their personal details */ + avatar: PropTypes.string, + }), + /** Information about the network */ network: networkPropTypes.isRequired, @@ -82,6 +92,9 @@ const defaultProps = { reports: {}, reportsWithDraft: {}, personalDetails: {}, + currentUserPersonalDetails: { + avatar: ReportUtils.getDefaultAvatar(), + }, currentlyViewedReportID: '', priorityMode: CONST.PRIORITY_MODE.DEFAULT, initialReportDataLoaded: false, @@ -161,12 +174,6 @@ class SidebarLinks extends React.Component { constructor(props) { super(props); - // Get my details from the list of personal details and set default avatar if not already set - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - if (!_.has(this.myPersonalDetails, 'avatar') || _.isEmpty(this.myPersonalDetails.avatar)) { - this.myPersonalDetails.avatar = ReportUtils.getDefaultAvatar(); - } - this.state = { activeReport: { reportID: props.currentlyViewedReportID, @@ -282,7 +289,7 @@ class SidebarLinks extends React.Component { onPress={this.props.onAvatarClick} > Date: Fri, 15 Jul 2022 19:14:32 -0400 Subject: [PATCH 32/38] update IOUConfirmationList to use withCurrentUserPersonalDetails HOC --- src/components/IOUConfirmationList.js | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js index 6db0bf66682..731b80b06b8 100755 --- a/src/components/IOUConfirmationList.js +++ b/src/components/IOUConfirmationList.js @@ -16,7 +16,7 @@ import SettlementButton from './SettlementButton'; import ROUTES from '../ROUTES'; import networkPropTypes from './networkPropTypes'; import {withNetwork} from './OnyxProvider'; -import personalDetailsPropType from '../pages/personalDetailsPropType'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from './withCurrentUserPersonalDetails'; const propTypes = { /** Callback to inform parent modal of success */ @@ -64,10 +64,9 @@ const propTypes = { ...withLocalizePropTypes, - /* Onyx Props */ + ...withCurrentUserPersonalDetailsPropTypes, - /** Personal details of all the users, including current user */ - personalDetails: PropTypes.objectOf(personalDetailsPropType), + /* Onyx Props */ /** Holds data related to IOU view state, rather than the underlying IOU data. */ iou: PropTypes.shape({ @@ -94,8 +93,8 @@ const defaultProps = { }, onUpdateComment: null, comment: '', - personalDetails: {}, iouType: CONST.IOU.IOU_TYPE.REQUEST, + ...withCurrentUserPersonalDetailsDefaultProps, }; class IOUConfirmationList extends Component { @@ -116,8 +115,6 @@ class IOUConfirmationList extends Component { value: props.hasMultipleParticipants ? CONST.IOU.IOU_TYPE.SPLIT : CONST.IOU.IOU_TYPE.REQUEST, }]; - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - this.state = { participants: formattedParticipants, }; @@ -183,7 +180,7 @@ class IOUConfirmationList extends Component { const formattedParticipants = _.union(formattedSelectedParticipants, formattedUnselectedParticipants); const formattedMyPersonalDetails = OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail( - this.myPersonalDetails, + this.props.currentUserPersonalDetails, this.props.numberFormat(this.calculateAmount(selectedParticipants, true) / 100, { style: 'currency', currency: this.props.iou.selectedCurrencyCode, @@ -239,7 +236,7 @@ class IOUConfirmationList extends Component { })); splits.push({ - email: OptionsListUtils.addSMSDomainIfPhoneNumber(this.myPersonalDetails.login), + email: OptionsListUtils.addSMSDomainIfPhoneNumber(this.props.currentUserPersonalDetails.login), // The user is default and we should send in cents to API // USD is temporary and there must be support for other currencies in the future @@ -259,7 +256,7 @@ class IOUConfirmationList extends Component { const selectedParticipants = this.getSelectedParticipants(); return [ ...selectedParticipants, - OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(this.myPersonalDetails), + OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(this.props.currentUserPersonalDetails), ]; } @@ -389,11 +386,9 @@ export default compose( withLocalize, withWindowDimensions, withNetwork(), + withCurrentUserPersonalDetails, withOnyx({ iou: {key: ONYXKEYS.IOU}, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS, - }, session: { key: ONYXKEYS.SESSION, }, From e6bbd9c2e2ba67b5c00ef6dfef81d7ec3c266a94 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 19:19:34 -0400 Subject: [PATCH 33/38] update ProfilePage to use withCurrentUserPersonalDetails HOC --- src/pages/settings/Profile/ProfilePage.js | 49 ++++++++++------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js index c16508ece16..ddd59b58d10 100755 --- a/src/pages/settings/Profile/ProfilePage.js +++ b/src/pages/settings/Profile/ProfilePage.js @@ -26,16 +26,13 @@ import Picker from '../../../components/Picker'; import FullNameInputRow from '../../../components/FullNameInputRow'; import CheckboxWithLabel from '../../../components/CheckboxWithLabel'; import AvatarWithImagePicker from '../../../components/AvatarWithImagePicker'; -import personalDetailsPropType from '../../personalDetailsPropType'; +import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../../components/withCurrentUserPersonalDetails'; import * as ValidationUtils from '../../../libs/ValidationUtils'; import * as ReportUtils from '../../../libs/ReportUtils'; const propTypes = { /* Onyx Props */ - /** Personal details of all the users, including current user */ - personalDetails: PropTypes.objectOf(personalDetailsPropType), - /** Login list for the user that is signed in */ loginList: PropTypes.arrayOf(PropTypes.shape({ @@ -49,11 +46,12 @@ const propTypes = { validatedDate: PropTypes.string, })), ...withLocalizePropTypes, + ...withCurrentUserPersonalDetailsPropTypes, }; const defaultProps = { - personalDetails: {}, loginList: [], + ...withCurrentUserPersonalDetailsDefaultProps, }; const timezones = _.chain(moment.tz.names()) @@ -68,21 +66,20 @@ class ProfilePage extends Component { constructor(props) { super(props); - this.myPersonalDetails = _.findWhere(props.personalDetails, {isCurrentUser: true}); - this.defaultAvatar = ReportUtils.getDefaultAvatar(this.myPersonalDetails.login); + this.defaultAvatar = ReportUtils.getDefaultAvatar(this.props.currentUserPersonalDetails.login); this.state = { - firstName: this.myPersonalDetails.firstName, + firstName: this.props.currentUserPersonalDetails.firstName, hasFirstNameError: false, - lastName: this.myPersonalDetails.lastName, + lastName: this.props.currentUserPersonalDetails.lastName, hasLastNameError: false, - pronouns: this.myPersonalDetails.pronouns, + pronouns: this.props.currentUserPersonalDetails.pronouns, hasPronounError: false, - hasSelfSelectedPronouns: !_.isEmpty(this.myPersonalDetails.pronouns) && !this.myPersonalDetails.pronouns.startsWith(CONST.PRONOUNS.PREFIX), - selectedTimezone: lodashGet(this.myPersonalDetails.timezone, 'selected', CONST.DEFAULT_TIME_ZONE.selected), - isAutomaticTimezone: lodashGet(this.myPersonalDetails.timezone, 'automatic', CONST.DEFAULT_TIME_ZONE.automatic), + hasSelfSelectedPronouns: !_.isEmpty(this.props.currentUserPersonalDetails.pronouns) && !this.props.currentUserPersonalDetails.pronouns.startsWith(CONST.PRONOUNS.PREFIX), + selectedTimezone: lodashGet(this.props.currentUserPersonalDetails.timezone, 'selected', CONST.DEFAULT_TIME_ZONE.selected), + isAutomaticTimezone: lodashGet(this.props.currentUserPersonalDetails.timezone, 'automatic', CONST.DEFAULT_TIME_ZONE.automatic), logins: this.getLogins(props.loginList), - avatar: {uri: lodashGet(this.myPersonalDetails, 'avatar', ReportUtils.getDefaultAvatar(this.myPersonalDetails.login))}, + avatar: {uri: lodashGet(this.props.currentUserPersonalDetails, 'avatar', ReportUtils.getDefaultAvatar(this.props.currentUserPersonalDetails.login))}, isAvatarChanged: false, }; @@ -133,7 +130,7 @@ class ProfilePage extends Component { const login = Str.removeSMSDomain(currentLogin.partnerUserID); // If there's already a login type that's validated and/or currentLogin isn't valid then return early - if ((login !== this.myPersonalDetails.login) && !_.isEmpty(logins[type]) + if ((login !== this.props.currentUserPersonalDetails.login) && !_.isEmpty(logins[type]) && (logins[type].validatedDate || !currentLogin.validatedDate)) { return logins; } @@ -156,7 +153,7 @@ class ProfilePage extends Component { * @param {Object} avatar */ updateAvatar(avatar) { - this.setState({avatar: _.isUndefined(avatar) ? {uri: ReportUtils.getDefaultAvatar(this.myPersonalDetails.login)} : avatar, isAvatarChanged: true}); + this.setState({avatar: _.isUndefined(avatar) ? {uri: ReportUtils.getDefaultAvatar(this.props.currentUserPersonalDetails.login)} : avatar, isAvatarChanged: true}); } /** @@ -168,7 +165,7 @@ class ProfilePage extends Component { } // Check if the user has modified their avatar - if ((this.myPersonalDetails.avatar !== this.state.avatar.uri) && this.state.isAvatarChanged) { + if ((this.props.currentUserPersonalDetails.avatar !== this.state.avatar.uri) && this.state.isAvatarChanged) { // If the user removed their profile photo, replace it accordingly with the default avatar if (this.state.avatar.uri.includes('/images/avatars/avatar')) { PersonalDetails.deleteAvatar(this.state.avatar.uri); @@ -211,12 +208,12 @@ class ProfilePage extends Component { })); // Disables button if none of the form values have changed - const isButtonDisabled = (this.myPersonalDetails.firstName === this.state.firstName.trim()) - && (this.myPersonalDetails.lastName === this.state.lastName.trim()) - && (this.myPersonalDetails.timezone.selected === this.state.selectedTimezone) - && (this.myPersonalDetails.timezone.automatic === this.state.isAutomaticTimezone) - && (this.myPersonalDetails.pronouns === this.state.pronouns.trim()) - && (!this.state.isAvatarChanged || this.myPersonalDetails.avatarUploading); + const isButtonDisabled = (this.props.currentUserPersonalDetails.firstName === this.state.firstName.trim()) + && (this.props.currentUserPersonalDetails.lastName === this.state.lastName.trim()) + && (this.props.currentUserPersonalDetails.timezone.selected === this.state.selectedTimezone) + && (this.props.currentUserPersonalDetails.timezone.automatic === this.state.isAutomaticTimezone) + && (this.props.currentUserPersonalDetails.pronouns === this.state.pronouns.trim()) + && (!this.state.isAvatarChanged || this.props.currentUserPersonalDetails.avatarUploading); const pronounsPickerValue = this.state.hasSelfSelectedPronouns ? CONST.PRONOUNS.SELF_SELECT : this.state.pronouns; @@ -231,7 +228,7 @@ class ProfilePage extends Component { /> Date: Fri, 15 Jul 2022 19:27:46 -0400 Subject: [PATCH 34/38] update DateUtils to use current user email instead of current user flag --- src/libs/DateUtils.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index dc620fba89e..3207820d2ab 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -12,11 +12,24 @@ import * as Localize from './Localize'; import * as PersonalDetails from './actions/PersonalDetails'; import * as CurrentDate from './actions/CurrentDate'; +let currentUserEmail; +Onyx.connect({ + key: ONYXKEYS.SESSION, + callback: (val) => { + // When signed out, val is undefined + if (!val) { + return; + } + + currentUserEmail = val.email; + }, +}); + let timezone = CONST.DEFAULT_TIME_ZONE; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS, callback: (val) => { - const currentUser = _.findWhere(val, {isCurrentUser: true}); + const currentUser = val[currentUserEmail]; timezone = lodashGet(currentUser, 'timezone', CONST.DEFAULT_TIME_ZONE); }, }); From 6f371c07ccbef48b66f64a1d8839eed6ab620150 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 19:29:49 -0400 Subject: [PATCH 35/38] use lodash get instead of new variable for current user --- src/libs/DateUtils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index 3207820d2ab..a777ab1ed46 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -29,8 +29,7 @@ let timezone = CONST.DEFAULT_TIME_ZONE; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS, callback: (val) => { - const currentUser = val[currentUserEmail]; - timezone = lodashGet(currentUser, 'timezone', CONST.DEFAULT_TIME_ZONE); + timezone = lodashGet(val, currentUserEmail, 'timezone', CONST.DEFAULT_TIME_ZONE); }, }); From 58f74c85a86dc73f7b8bdce780ec155bc189b240 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 19:32:24 -0400 Subject: [PATCH 36/38] update AuthScreens to use current user email instead of current user flag --- src/libs/Navigation/AppNavigator/AuthScreens.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index cffc53999da..03996873ab4 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -40,6 +40,19 @@ import LogOutPreviousUserPage from '../../../pages/LogOutPreviousUserPage'; import networkPropTypes from '../../../components/networkPropTypes'; import {withNetwork} from '../../../components/OnyxProvider'; +let currentUserEmail; +Onyx.connect({ + key: ONYXKEYS.SESSION, + callback: (val) => { + // When signed out, val is undefined + if (!val) { + return; + } + + currentUserEmail = val.email; + }, +}); + Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS, callback: (val) => { @@ -47,8 +60,7 @@ Onyx.connect({ return; } - const currentUser = _.findWhere(val, {isCurrentUser: true}); - const timezone = lodashGet(currentUser, 'timezone', {}); + const timezone = lodashGet(val, currentUserEmail, 'timezone', {}); const currentTimezone = moment.tz.guess(true); // If the current timezone is different than the user's timezone, and their timezone is set to automatic From ccb9d27fe092eb83e93c15c9c839ff545647c208 Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 19:34:34 -0400 Subject: [PATCH 37/38] dont flag the current user details in personal details --- src/libs/actions/PersonalDetails.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 8706fdb1c77..5585082c0e7 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -133,9 +133,6 @@ function fetchPersonalDetails() { } const allPersonalDetails = formatPersonalDetails(personalDetailsList); - - // Flag which details belong to the currently logged in user for easy access before storing - allPersonalDetails[currentUserEmail].isCurrentUser = true; Onyx.merge(ONYXKEYS.PERSONAL_DETAILS, allPersonalDetails); }); } From 0deaba4568a2bc9078a9880c327a8df7049342dc Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Fri, 15 Jul 2022 19:40:01 -0400 Subject: [PATCH 38/38] Add more values to personal details prop type --- src/pages/personalDetailsPropType.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/personalDetailsPropType.js b/src/pages/personalDetailsPropType.js index 43bfe5e6126..809dd44ce09 100644 --- a/src/pages/personalDetailsPropType.js +++ b/src/pages/personalDetailsPropType.js @@ -13,14 +13,24 @@ export default PropTypes.shape({ // Avatar URL of the current user from their personal details avatar: PropTypes.string, + // Flag to set when Avatar uploading + avatarUploading: PropTypes.bool, + // login of the current user from their personal details login: PropTypes.string, // pronouns of the current user from their personal details pronouns: PropTypes.string, + // local currency for the user + localCurrencyCode: PropTypes.string, + // timezone of the current user from their personal details timezone: PropTypes.shape({ + // Value of selected timezone selected: PropTypes.string, + + // Whether timezone is automatically set + automatic: PropTypes.bool, }), });