From eb766699512a2c1325e38d0bfa768741b5aefbf5 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 9 Aug 2022 15:45:14 +0100 Subject: [PATCH 001/123] add the method --- src/libs/actions/Wallet.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index eb75d3969119..0f4154ca5360 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -351,6 +351,10 @@ function updateCurrentStep(currentStep) { Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep}); } +function answerQuestionsForWallet() { + +} + export { fetchOnfidoToken, activateWallet, From 46567a465a18ee4aa88f71cb9cdf0f9f5c8a6948 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 9 Aug 2022 16:08:37 +0100 Subject: [PATCH 002/123] adding the OnyxData --- src/libs/actions/Wallet.js | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index 0f4154ca5360..a5a2d302082b 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -7,6 +7,7 @@ import * as DeprecatedAPI from '../deprecatedAPI'; import CONST from '../../CONST'; import * as PaymentMethods from './PaymentMethods'; import * as Localize from '../Localize'; +import * as API from "../API"; /** * Fetch and save locally the Onfido SDK token and applicantID @@ -351,8 +352,37 @@ function updateCurrentStep(currentStep) { Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep}); } -function answerQuestionsForWallet() { - +/** + * @param {String} idologyAnswers + */ +function answerQuestionsForWallet(idologyAnswers) { + API.write('AnswerQuestionsForWallet', + { + idologyAnswers, + }, + { + optimisticData: [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: true, + }, + }], + successData: [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }], + failureData: [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }], + }); } export { From 77f30ded65b930a2bb1a9905decccf4b7a4dc34e Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 9 Aug 2022 16:15:44 +0100 Subject: [PATCH 003/123] calling api from the right js file --- src/libs/actions/BankAccounts.js | 1 + src/libs/actions/Wallet.js | 1 + src/pages/EnablePayments/IdologyQuestions.js | 11 +++++------ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 8fb86b3c25dd..2b7be34287f4 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -34,6 +34,7 @@ export { fetchOnfidoToken, activateWallet, fetchUserWallet, + answerQuestionsForWallet, } from './Wallet'; function clearPersonalBankAccount() { diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index a5a2d302082b..0749055a2d87 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -395,4 +395,5 @@ export { setAdditionalDetailsQuestions, buildIdologyError, updateCurrentStep, + answerQuestionsForWallet, }; diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index cd8ff54411bd..3d711d4236a6 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -103,12 +103,11 @@ class IdologyQuestions extends React.Component { } } - BankAccounts.activateWallet(CONST.WALLET.STEP.ADDITIONAL_DETAILS, { - idologyAnswers: { - answers, - idNumber: this.props.idNumber, - }, - }); + let idologyAnswers = { + answers, + idNumber: this.props.idNumber, + }; + BankAccounts.answerQuestionsForWallet(idologyAnswers); return {answers, isLoading: true}; } From 29ae567a3eb5977c1b37f5e6eaa3e987d82922ae Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 9 Aug 2022 16:21:08 +0100 Subject: [PATCH 004/123] adding onyxKey --- src/pages/EnablePayments/IdologyQuestions.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 3d711d4236a6..5b45963198a0 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -13,6 +13,9 @@ import Text from '../../components/Text'; import TextLink from '../../components/TextLink'; import FormScrollView from '../../components/FormScrollView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; +import compose from "../../libs/compose"; +import {withOnyx} from "react-native-onyx"; +import ONYXKEYS from "../../ONYXKEYS"; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -108,7 +111,7 @@ class IdologyQuestions extends React.Component { idNumber: this.props.idNumber, }; BankAccounts.answerQuestionsForWallet(idologyAnswers); - return {answers, isLoading: true}; + return {answers}; } // Else, show next question @@ -171,4 +174,8 @@ class IdologyQuestions extends React.Component { IdologyQuestions.propTypes = propTypes; IdologyQuestions.defaultProps = defaultProps; -export default withLocalize(IdologyQuestions); +export default compose(withLocalize(IdologyQuestions), withOnyx({ + additionalDetails: { + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + }, +}))(IdologyQuestions); From 30ad2f148fab6b5645ff3ca1581b0a6b094f744d Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 9 Aug 2022 16:25:20 +0100 Subject: [PATCH 005/123] using the isLoading --- src/pages/EnablePayments/IdologyQuestions.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 5b45963198a0..2583300f6afd 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -33,11 +33,18 @@ const propTypes = { /** ID from Idology, referencing those questions */ idNumber: PropTypes.string, + + additionalDetails: PropTypes.shape({ + isLoading: PropTypes.bool, + }), }; const defaultProps = { questions: [], idNumber: '', + additionalDetails: { + isLoading: false, + }, }; class IdologyQuestions extends React.Component { @@ -57,9 +64,6 @@ class IdologyQuestions extends React.Component { /** Any error message */ errorMessage: '', - - /** Did the user just submitted all his answers? */ - isLoading: false, }; } @@ -163,7 +167,7 @@ class IdologyQuestions extends React.Component { this.form.scrollTo({y: 0, animated: true}); }} message={this.state.errorMessage} - isLoading={this.state.isLoading} + isLoading={this.props.additionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> From 86fe203e690f98c4ef1e568d954a2e17f0121305 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Wed, 10 Aug 2022 15:14:57 +0100 Subject: [PATCH 006/123] linter requested changes --- src/libs/actions/Wallet.js | 2 +- src/pages/EnablePayments/IdologyQuestions.js | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index 0749055a2d87..b2edf801e033 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -7,7 +7,7 @@ import * as DeprecatedAPI from '../deprecatedAPI'; import CONST from '../../CONST'; import * as PaymentMethods from './PaymentMethods'; import * as Localize from '../Localize'; -import * as API from "../API"; +import * as API from '../API'; /** * Fetch and save locally the Onfido SDK token and applicantID diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 2583300f6afd..92d1f47144d8 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -4,18 +4,17 @@ import PropTypes from 'prop-types'; import { View, } from 'react-native'; +import {withOnyx} from 'react-native-onyx'; import RadioButtons from '../../components/RadioButtons'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import styles from '../../styles/styles'; import * as BankAccounts from '../../libs/actions/BankAccounts'; -import CONST from '../../CONST'; import Text from '../../components/Text'; import TextLink from '../../components/TextLink'; import FormScrollView from '../../components/FormScrollView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; -import compose from "../../libs/compose"; -import {withOnyx} from "react-native-onyx"; -import ONYXKEYS from "../../ONYXKEYS"; +import compose from '../../libs/compose'; +import ONYXKEYS from '../../ONYXKEYS'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -110,7 +109,7 @@ class IdologyQuestions extends React.Component { } } - let idologyAnswers = { + const idologyAnswers = { answers, idNumber: this.props.idNumber, }; From c31819fcfbf4d090eb121d576342213a1d9533aa Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Wed, 10 Aug 2022 15:34:06 +0100 Subject: [PATCH 007/123] using the errors and error code --- src/pages/EnablePayments/IdologyQuestions.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 92d1f47144d8..9a0eebdc89fd 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -35,6 +35,8 @@ const propTypes = { additionalDetails: PropTypes.shape({ isLoading: PropTypes.bool, + errors: PropTypes.arrayOf(PropTypes.string), + errorCode: PropTypes.string, }), }; @@ -43,6 +45,8 @@ const defaultProps = { idNumber: '', additionalDetails: { isLoading: false, + errors: [], + errorCode: '', }, }; @@ -160,12 +164,12 @@ class IdologyQuestions extends React.Component { { this.form.scrollTo({y: 0, animated: true}); }} - message={this.state.errorMessage} + message={_.isEmpty(this.props.additionalDetails.errors) ? this.props.additionalDetails.errors.find(x=>x!==undefined) : this.state.errorMessage : } isLoading={this.props.additionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> From ed809baab39a77e1a5e2844cb399f4c10651de71 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Wed, 10 Aug 2022 16:53:29 +0100 Subject: [PATCH 008/123] need to json stringify first? --- src/libs/actions/Wallet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index b2edf801e033..7d59733da7bc 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -356,9 +356,10 @@ function updateCurrentStep(currentStep) { * @param {String} idologyAnswers */ function answerQuestionsForWallet(idologyAnswers) { + const answers = JSON.stringify(idologyAnswers); API.write('AnswerQuestionsForWallet', { - idologyAnswers, + answers, }, { optimisticData: [{ From 7477c23b3ade0a9dce1ac35486f602609bca7b94 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Wed, 10 Aug 2022 16:53:48 +0100 Subject: [PATCH 009/123] I think this is where the error code will be used --- src/pages/EnablePayments/EnablePaymentsPage.js | 15 ++++++++++++++- src/pages/EnablePayments/IdologyQuestions.js | 4 ++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index 53f25dfeffd7..c8d481649e7e 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -21,17 +21,27 @@ import Navigation from '../../libs/Navigation/Navigation'; import FailedKYC from './FailedKYC'; import compose from '../../libs/compose'; import withLocalize from '../../components/withLocalize'; +import PropTypes from "prop-types"; const propTypes = { /** Information about the network from Onyx */ network: networkPropTypes.isRequired, + + additionalDetails: PropTypes.shape({ + errorCode: PropTypes.string, + }), + ...userWalletPropTypes, }; const defaultProps = { // eslint-disable-next-line react/default-props-match-prop-types userWallet: {}, + + additionalDetails: { + errorCode: '', + }, }; class EnablePaymentsPage extends React.Component { @@ -56,7 +66,7 @@ class EnablePaymentsPage extends React.Component { return ; } - if (this.props.userWallet.shouldShowFailedKYC) { + if (this.props.additionalDetails.errorCode === 'kycFailed') { return ( { this.form.scrollTo({y: 0, animated: true}); From eb673763eba4accfca1107374ea882100fce527a Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Fri, 19 Aug 2022 16:25:06 +0100 Subject: [PATCH 010/123] remove import duplicated --- src/pages/EnablePayments/EnablePaymentsPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index feda0930409a..836c3103b7ba 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -22,7 +22,6 @@ import Navigation from '../../libs/Navigation/Navigation'; import FailedKYC from './FailedKYC'; import compose from '../../libs/compose'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; -import PropTypes from "prop-types"; const propTypes = { /** Information about the network from Onyx */ From c67d1844abe0c34b50c8b0702d9e09da56a67038 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Fri, 19 Aug 2022 16:34:08 +0100 Subject: [PATCH 011/123] linter removing extra line (bad merge?) --- src/pages/EnablePayments/EnablePaymentsPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index 836c3103b7ba..a9b5247f2e0f 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -27,7 +27,6 @@ const propTypes = { /** Information about the network from Onyx */ network: networkPropTypes.isRequired, - additionalDetails: PropTypes.shape({ errorCode: PropTypes.string, }), From ed6a04a2cecd11352e8431d887110ab23bdd161f Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Fri, 19 Aug 2022 16:58:20 +0100 Subject: [PATCH 012/123] fixing linter, I think it's good this time --- src/pages/EnablePayments/IdologyQuestions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 3344be78ef83..a92a47f450c4 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { View, } from 'react-native'; -import Onyx, {withOnyx} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import RadioButtons from '../../components/RadioButtons'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import styles from '../../styles/styles'; @@ -169,7 +169,7 @@ class IdologyQuestions extends React.Component { onFixTheErrorsLinkPressed={() => { this.form.scrollTo({y: 0, animated: true}); }} - message={_.isEmpty(this.props.additionalDetails.errors) ? this.props.additionalDetails.errors.find(x=>x!==undefined) : this.state.errorMessage : } + message={_.isEmpty(this.props.additionalDetails.errors) ? _.find(this.props.additionalDetails.errors, error => error !== undefined) : this.state.errorMessage} isLoading={this.props.additionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> From eb1342803056246277d0e462becee502008bf888 Mon Sep 17 00:00:00 2001 From: Eugene Voloshchak Date: Sat, 20 Aug 2022 19:40:09 +0300 Subject: [PATCH 013/123] Localize decimal separator for the rate field --- src/CONST.js | 1 - .../getPermittedDecimalSeparator/index.ios.js | 4 +++ .../getPermittedDecimalSeparator/index.js | 1 + .../reimburse/WorkspaceReimburseView.js | 25 ++++++++++++------- 4 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 src/libs/getPermittedDecimalSeparator/index.ios.js create mode 100644 src/libs/getPermittedDecimalSeparator/index.js diff --git a/src/CONST.js b/src/CONST.js index 0f90121754ea..425832a9a26d 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -706,7 +706,6 @@ const CONST = { CARD_SECURITY_CODE: /^[0-9]{3,4}$/, CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/, PAYPAL_ME_USERNAME: /^[a-zA-Z0-9]+$/, - RATE_VALUE: /^\d{1,8}(\.\d*)?$/, // Adapted from: https://gist.github.com/dperini/729294 // eslint-disable-next-line max-len diff --git a/src/libs/getPermittedDecimalSeparator/index.ios.js b/src/libs/getPermittedDecimalSeparator/index.ios.js new file mode 100644 index 000000000000..d25c2650506a --- /dev/null +++ b/src/libs/getPermittedDecimalSeparator/index.ios.js @@ -0,0 +1,4 @@ + +// On iOS keyboard can only have one symbol at a time (either dot or comma) so we accept both +// Details: https://expensify.slack.com/archives/C01GTK53T8Q/p1658936908481629 +export default () => '.,'; diff --git a/src/libs/getPermittedDecimalSeparator/index.js b/src/libs/getPermittedDecimalSeparator/index.js new file mode 100644 index 000000000000..573e0c9b3225 --- /dev/null +++ b/src/libs/getPermittedDecimalSeparator/index.js @@ -0,0 +1 @@ +export default localizedSeparator => localizedSeparator; diff --git a/src/pages/workspace/reimburse/WorkspaceReimburseView.js b/src/pages/workspace/reimburse/WorkspaceReimburseView.js index 9ae0b280e24f..fe918f163e36 100644 --- a/src/pages/workspace/reimburse/WorkspaceReimburseView.js +++ b/src/pages/workspace/reimburse/WorkspaceReimburseView.js @@ -22,6 +22,7 @@ import * as Policy from '../../../libs/actions/Policy'; import withFullPolicy from '../withFullPolicy'; import CONST from '../../../CONST'; import Button from '../../../components/Button'; +import getPermittedDecimalSeparator from '../../../libs/getPermittedDecimalSeparator'; const propTypes = { /** The policy ID currently being configured */ @@ -77,19 +78,29 @@ class WorkspaceReimburseView extends React.Component { } getRateDisplayValue(value) { - const numValue = parseFloat(value); + const numValue = this.getNumericValue(value); if (Number.isNaN(numValue)) { return ''; } + return numValue.toString().replace('.', this.props.toLocaleDigit('.')).substring(0, value.length); + } + + getNumericValue(value) { + const numValue = parseFloat(value.toString().replace(this.props.toLocaleDigit('.'), '.')); + if (Number.isNaN(numValue)) { + return NaN; + } return numValue.toFixed(3); } setRate(value) { - const isInvalidRateValue = value !== '' && !CONST.REGEX.RATE_VALUE.test(value); + const decimalSeparator = this.props.toLocaleDigit('.'); + const rateValueRegex = RegExp(String.raw`^\d{1,8}([${getPermittedDecimalSeparator(decimalSeparator)}]\d{0,3})?$`, 'i'); + const isInvalidRateValue = value !== '' && !rateValueRegex.test(value); this.setState(prevState => ({ - rateValue: !isInvalidRateValue ? value : prevState.rateValue, + rateValue: !isInvalidRateValue ? this.getRateDisplayValue(value) : prevState.rateValue, }), () => { // Set the corrected value with a delay and sync to the server this.updateRateValueDebounced(this.state.rateValue); @@ -115,20 +126,16 @@ class WorkspaceReimburseView extends React.Component { } updateRateValue(value) { - const numValue = parseFloat(value); + const numValue = this.getNumericValue(value); if (_.isNaN(numValue)) { return; } - this.setState({ - rateValue: numValue.toFixed(3), - }); - Policy.setCustomUnitRate(this.props.policyID, this.state.unitID, { customUnitRateID: this.state.rateID, name: this.state.rateName, - rate: numValue.toFixed(3) * 100, + rate: numValue * 100, }, null); } From d42b51b3ad5bde56882979cef4157a1f71dc6ac2 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Wed, 24 Aug 2022 21:59:15 +0530 Subject: [PATCH 014/123] Fix links for Native platforms --- src/components/AnchorForCommentsOnly.js | 107 ------------------ .../BaseAnchorForCommentsOnly.js | 69 +++++++++++ .../anchorForCommentsOnlyPropTypes.js | 42 +++++++ src/components/AnchorForCommentsOnly/index.js | 11 ++ .../AnchorForCommentsOnly/index.native.js | 20 ++++ .../HTMLRenderers/AnchorRenderer.js | 2 +- 6 files changed, 143 insertions(+), 108 deletions(-) delete mode 100644 src/components/AnchorForCommentsOnly.js create mode 100644 src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js create mode 100644 src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js create mode 100644 src/components/AnchorForCommentsOnly/index.js create mode 100644 src/components/AnchorForCommentsOnly/index.native.js diff --git a/src/components/AnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly.js deleted file mode 100644 index c93ecb416b64..000000000000 --- a/src/components/AnchorForCommentsOnly.js +++ /dev/null @@ -1,107 +0,0 @@ -import _ from 'underscore'; -import React from 'react'; -import {StyleSheet} from 'react-native'; -import lodashGet from 'lodash/get'; -import Str from 'expensify-common/lib/str'; -import PropTypes from 'prop-types'; -import Text from './Text'; -import PressableWithSecondaryInteraction from './PressableWithSecondaryInteraction'; -import * as ReportActionContextMenu from '../pages/home/report/ContextMenu/ReportActionContextMenu'; -import * as ContextMenuActions from '../pages/home/report/ContextMenu/ContextMenuActions'; -import Tooltip from './Tooltip'; -import canUseTouchScreen from '../libs/canUseTouchscreen'; -import styles from '../styles/styles'; -import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; - -const propTypes = { - /** The URL to open */ - href: PropTypes.string, - - /** What headers to send to the linked page (usually noopener and noreferrer) - This is unused in native, but is here for parity with web */ - rel: PropTypes.string, - - /** Used to determine where to open a link ("_blank" is passed for a new tab) - This is unused in native, but is here for parity with web */ - target: PropTypes.string, - - /** Any children to display */ - children: PropTypes.node, - - /** Anchor text of URLs or emails. */ - displayName: PropTypes.string, - - /** Any additional styles to apply */ - // eslint-disable-next-line react/forbid-prop-types - style: PropTypes.any, - - /** Press handler for the link, when not passed, default href is used to create a link like behaviour */ - onPress: PropTypes.func, - - ...windowDimensionsPropTypes, -}; - -const defaultProps = { - href: '', - rel: '', - target: '', - children: null, - style: {}, - displayName: '', - onPress: undefined, -}; - -/* - * This is a default anchor component for regular links. - */ -const BaseAnchorForCommentsOnly = (props) => { - let linkRef; - const rest = _.omit(props, _.keys(propTypes)); - const linkProps = {}; - if (_.isFunction(props.onPress)) { - linkProps.onPress = props.onPress; - } else { - linkProps.href = props.href; - } - const defaultTextStyle = canUseTouchScreen() || props.isSmallScreenWidth ? {} : styles.userSelectText; - - return ( - { - ReportActionContextMenu.showContextMenu( - Str.isValidEmail(props.displayName) ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, - event, - props.href, - lodashGet(linkRef, 'current'), - ); - } - } - > - - linkRef = el} - style={StyleSheet.flatten([props.style, defaultTextStyle])} - accessibilityRole="link" - hrefAttrs={{ - rel: props.rel, - target: props.target, - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...linkProps} - // eslint-disable-next-line react/jsx-props-no-spreading - {...rest} - > - {props.children} - - - - ); -}; - -BaseAnchorForCommentsOnly.propTypes = propTypes; -BaseAnchorForCommentsOnly.defaultProps = defaultProps; -BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly'; - -export default withWindowDimensions(BaseAnchorForCommentsOnly); diff --git a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js new file mode 100644 index 000000000000..e65b423fa517 --- /dev/null +++ b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js @@ -0,0 +1,69 @@ +import _ from 'underscore'; +import React from 'react'; +import {StyleSheet} from 'react-native'; +import lodashGet from 'lodash/get'; +import Str from 'expensify-common/lib/str'; +import Text from '../Text'; +import PressableWithSecondaryInteraction from '../PressableWithSecondaryInteraction'; +import * as ReportActionContextMenu from '../../pages/home/report/ContextMenu/ReportActionContextMenu'; +import * as ContextMenuActions from '../../pages/home/report/ContextMenu/ContextMenuActions'; +import Tooltip from '../Tooltip'; +import canUseTouchScreen from '../../libs/canUseTouchscreen'; +import styles from '../../styles/styles'; +import withWindowDimensions from '../withWindowDimensions'; +import {propTypes, defaultProps} from './anchorForCommentsOnlyPropTypes'; + +/* + * This is a default anchor component for regular links. + */ +const BaseAnchorForCommentsOnly = (props) => { + let linkRef; + const rest = _.omit(props, _.keys(propTypes)); + const linkProps = {}; + if (_.isFunction(props.onPress)) { + linkProps.onPress = props.onPress; + } else { + linkProps.href = props.href; + } + const defaultTextStyle = canUseTouchScreen() || props.isSmallScreenWidth ? {} : styles.userSelectText; + + return ( + { + ReportActionContextMenu.showContextMenu( + Str.isValidEmail(props.displayName) ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, + event, + props.href, + lodashGet(linkRef, 'current'), + ); + } + } + > + + linkRef = el} + style={StyleSheet.flatten([props.style, defaultTextStyle])} + accessibilityRole="link" + hrefAttrs={{ + rel: props.rel, + target: props.target, + }} + // eslint-disable-next-line react/jsx-props-no-spreading + {...linkProps} + // eslint-disable-next-line react/jsx-props-no-spreading + {...rest} + > + {props.children} + + + + ); +}; + +BaseAnchorForCommentsOnly.propTypes = propTypes; +BaseAnchorForCommentsOnly.defaultProps = defaultProps; +BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly'; + +export default withWindowDimensions(BaseAnchorForCommentsOnly); diff --git a/src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js b/src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js new file mode 100644 index 000000000000..7661efaf0af3 --- /dev/null +++ b/src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js @@ -0,0 +1,42 @@ +import PropTypes from 'prop-types'; +import stylePropTypes from '../../styles/stylePropTypes'; +import {windowDimensionsPropTypes} from '../withWindowDimensions'; + +const propTypes = { + /** The URL to open */ + href: PropTypes.string, + + /** What headers to send to the linked page (usually noopener and noreferrer) + This is unused in native, but is here for parity with web */ + rel: PropTypes.string, + + /** Used to determine where to open a link ("_blank" is passed for a new tab) + This is unused in native, but is here for parity with web */ + target: PropTypes.string, + + /** Any children to display */ + children: PropTypes.node, + + /** Anchor text of URLs or emails. */ + displayName: PropTypes.string, + + /** Any additional styles to apply */ + style: stylePropTypes, + + /** Press handler for the link, when not passed, default href is used to create a link like behaviour */ + onPress: PropTypes.func, + + ...windowDimensionsPropTypes, +}; + +const defaultProps = { + href: '', + rel: '', + target: '', + children: null, + style: {}, + displayName: '', + onPress: undefined, +}; + +export {propTypes, defaultProps}; diff --git a/src/components/AnchorForCommentsOnly/index.js b/src/components/AnchorForCommentsOnly/index.js new file mode 100644 index 000000000000..1526e78007fe --- /dev/null +++ b/src/components/AnchorForCommentsOnly/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import * as anchorForCommentsOnlyPropTypes from './anchorForCommentsOnlyPropTypes'; +import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly'; + +// eslint-disable-next-line react/jsx-props-no-spreading +const AnchorForCommentsOnly = props => ; +AnchorForCommentsOnly.propTypes = anchorForCommentsOnlyPropTypes.propTypes; +AnchorForCommentsOnly.defaultProps = anchorForCommentsOnlyPropTypes.defaultProps; +AnchorForCommentsOnly.displayName = 'AnchorForCommentsOnly'; + +export default AnchorForCommentsOnly; diff --git a/src/components/AnchorForCommentsOnly/index.native.js b/src/components/AnchorForCommentsOnly/index.native.js new file mode 100644 index 000000000000..e692ea57afbb --- /dev/null +++ b/src/components/AnchorForCommentsOnly/index.native.js @@ -0,0 +1,20 @@ +import React from 'react'; +import {Linking} from 'react-native'; +import _ from 'underscore'; + +import * as anchorForCommentsOnlyPropTypes from './anchorForCommentsOnlyPropTypes'; +import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly'; + +// eslint-disable-next-line react/jsx-props-no-spreading +const AnchorForCommentsOnly = (props) => { + const onPress = () => (_.isFunction(props.onPress) ? props.onPress() : Linking.openURL(props.href)); + + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +}; + +AnchorForCommentsOnly.propTypes = anchorForCommentsOnlyPropTypes.propTypes; +AnchorForCommentsOnly.defaultProps = anchorForCommentsOnlyPropTypes.defaultProps; +AnchorForCommentsOnly.displayName = 'AnchorForCommentsOnly'; + +export default AnchorForCommentsOnly; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js index 9d395a8779b9..36adfe30f6b5 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js @@ -85,7 +85,7 @@ const AnchorRenderer = (props) => { displayName={displayName} // Only pass the press handler for internal links, for public links fallback to default link handling - onPress={internalNewExpensifyPath || internalExpensifyPath ? navigateToLink : undefined} + onPress={(internalNewExpensifyPath || internalExpensifyPath) ? navigateToLink : undefined} > From fed705a508371e463dc87f77fcbeb4c6d22549e2 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 25 Aug 2022 20:03:33 +0200 Subject: [PATCH 015/123] Remove the last pieces out of state --- src/pages/home/sidebar/SidebarLinks.js | 265 +++++++++++++++++-------- 1 file changed, 179 insertions(+), 86 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 6e4fdeefc63c..f315178b70a7 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -120,82 +120,131 @@ function getUnreadReports(reportsObject) { const memoizeGetUnreadReports = memoizeOne(getUnreadReports); class SidebarLinks extends React.Component { - static getRecentReports(props) { - const activeReportID = parseInt(props.currentlyViewedReportID, 10); - const sidebarOptions = OptionsListUtils.getSidebarOptions( - props.reports, - props.personalDetails, - activeReportID, - props.priorityMode, - props.betas, - props.reportActions, - ); - return sidebarOptions.recentReports; - } + // static getRecentReports(props) { + // const activeReportID = parseInt(props.currentlyViewedReportID, 10); + // const sidebarOptions = OptionsListUtils.getSidebarOptions( + // props.reports, + // props.personalDetails, + // activeReportID, + // props.priorityMode, + // props.betas, + // props.reportActions, + // ); + // return sidebarOptions.recentReports; + // } + + // /** + // * Returns true if the sidebar list should be re-ordered + // * + // * @param {Object} nextProps + // * @param {Boolean} hasActiveDraftHistory + // * @param {Array} orderedReports + // * @param {String} currentlyViewedReportID + // * @param {Array} unreadReports + // * @returns {Boolean} + // */ + // static shouldReorder(nextProps, hasActiveDraftHistory, orderedReports, currentlyViewedReportID, unreadReports) { + // // We do not want to re-order reports in the LHN if the only change is the draft comment in the + // // current report. + // + // // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. + // if (nextProps.isSmallScreenWidth) { + // return true; + // } + // + // // Always update if LHN is empty. + // if (orderedReports.length === 0) { + // return true; + // } + // + // const didActiveReportChange = currentlyViewedReportID !== nextProps.currentlyViewedReportID; + // + // // Always re-order the list whenever the active report is changed + // if (didActiveReportChange) { + // return true; + // } + // + // // If any reports have new unread messages, re-order the list + // const nextUnreadReports = memoizeGetUnreadReports(nextProps.reports || {}); + // if (memoizeCheckForNewUnreadReports(nextUnreadReports, unreadReports)) { + // return true; + // } + // + // // If there is an active report that either had or has a draft, we do not want to re-order the list + // if (nextProps.currentlyViewedReportID && hasActiveDraftHistory) { + // return false; + // } + // + // return true; + // } - /** - * Returns true if the sidebar list should be re-ordered - * - * @param {Object} nextProps - * @param {Boolean} hasActiveDraftHistory - * @param {Array} orderedReports - * @param {String} currentlyViewedReportID - * @param {Array} unreadReports - * @returns {Boolean} - */ - static shouldReorder(nextProps, hasActiveDraftHistory, orderedReports, currentlyViewedReportID, unreadReports) { - // We do not want to re-order reports in the LHN if the only change is the draft comment in the - // current report. + constructor(props) { + super(props); - // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. - if (nextProps.isSmallScreenWidth) { - return true; - } + this.getFilteredReports = _.memoize(this.getFilteredReports); - // Always update if LHN is empty. - if (orderedReports.length === 0) { - return true; - } + this.activeReport = { + reportID: props.currentlyViewedReportID, + }; - const didActiveReportChange = currentlyViewedReportID !== nextProps.currentlyViewedReportID; + this.orderedReports = []; + this.priorityMode = props.priorityMode; + this.unreadReports = memoizeGetUnreadReports(props.reports || {}); + } - // Always re-order the list whenever the active report is changed - if (didActiveReportChange) { - return true; - } + static getDerivedStateFromProps(nextProps, prevState) { + // const isActiveReportSame = prevState.activeReport.reportID === nextProps.currentlyViewedReportID; + // const lastMessageTimestamp = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.lastMessageTimestamp`, 0); - // If any reports have new unread messages, re-order the list - const nextUnreadReports = memoizeGetUnreadReports(nextProps.reports || {}); - if (memoizeCheckForNewUnreadReports(nextUnreadReports, unreadReports)) { - return true; - } + // Determines if the active report has a history of draft comments while active. + // let hasDraftHistory; - // If there is an active report that either had or has a draft, we do not want to re-order the list - if (nextProps.currentlyViewedReportID && hasActiveDraftHistory) { - return false; - } + // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. + // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. + // Otherwise, update the flag from the prop value. + // if (isActiveReportSame && prevState.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { + // hasDraftHistory = false; + // } else if (isActiveReportSame && prevState.activeReport.hasDraftHistory) { + // hasDraftHistory = true; + // } else { + // hasDraftHistory = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.hasDraft`, false); + // } - return true; - } + // const shouldReorder = SidebarLinks.shouldReorder(nextProps, hasDraftHistory, prevState.orderedReports, prevState.activeReport.reportID, prevState.unreadReports); + // const switchingPriorityModes = nextProps.priorityMode !== prevState.priorityMode; - constructor(props) { - super(props); + // Build the report options we want to show + // const recentReports = SidebarLinks.getRecentReports(nextProps); - this.state = { - activeReport: { - reportID: props.currentlyViewedReportID, - hasDraftHistory: lodashGet(props.reports, `${ONYXKEYS.COLLECTION.REPORT}${props.currentlyViewedReportID}.hasDraft`, false), - lastMessageTimestamp: lodashGet(props.reports, `${ONYXKEYS.COLLECTION.REPORT}${props.currentlyViewedReportID}.lastMessageTimestamp`, 0), - }, - orderedReports: [], - priorityMode: props.priorityMode, - unreadReports: memoizeGetUnreadReports(props.reports || {}), - }; + // Determine whether we need to keep the previous LHN order + // const orderedReports = shouldReorder || switchingPriorityModes + // ? recentReports + // : _.chain(prevState.orderedReports) + // + // // To preserve the order of the conversations, we map over the previous state's order of reports. + // // Then match and replace older reports with the newer report conversations from recentReports + // .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) + // + // // Because we are using map, we have to filter out any undefined reports. This happens if recentReports + // // does not have all the conversations in prevState.orderedReports + // .filter(orderedReport => orderedReport !== undefined) + // .value(); + + // return { + // orderedReports, + // priorityMode: nextProps.priorityMode, + // activeReport: { + // reportID: nextProps.currentlyViewedReportID, + // hasDraftHistory, + // lastMessageTimestamp, + // }, + // unreadReports: memoizeGetUnreadReports(nextProps.reports || {}), + // }; } - static getDerivedStateFromProps(nextProps, prevState) { - const isActiveReportSame = prevState.activeReport.reportID === nextProps.currentlyViewedReportID; - const lastMessageTimestamp = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.lastMessageTimestamp`, 0); + getFilteredReports(unfilteredReports) { + const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; + const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); // Determines if the active report has a history of draft comments while active. let hasDraftHistory; @@ -203,44 +252,88 @@ class SidebarLinks extends React.Component { // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. // Otherwise, update the flag from the prop value. - if (isActiveReportSame && prevState.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { + if (isActiveReportSame && this.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { hasDraftHistory = false; - } else if (isActiveReportSame && prevState.activeReport.hasDraftHistory) { + } else if (isActiveReportSame && this.activeReport.hasDraftHistory) { hasDraftHistory = true; } else { - hasDraftHistory = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.hasDraft`, false); + hasDraftHistory = lodashGet(this.props.reports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.hasDraft`, false); } - const shouldReorder = SidebarLinks.shouldReorder(nextProps, hasDraftHistory, prevState.orderedReports, prevState.activeReport.reportID, prevState.unreadReports); - const switchingPriorityModes = nextProps.priorityMode !== prevState.priorityMode; + const shouldReorder = this.shouldReorder(hasDraftHistory); + const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; // Build the report options we want to show - const recentReports = SidebarLinks.getRecentReports(nextProps); + const recentReports = this.getRecentReports(); - // Determine whether we need to keep the previous LHN order - const orderedReports = shouldReorder || switchingPriorityModes + this.orderedReports = shouldReorder || switchingPriorityModes ? recentReports - : _.chain(prevState.orderedReports) + : _.chain(this.orderedReports) - // To preserve the order of the conversations, we map over the previous state's order of reports. - // Then match and replace older reports with the newer report conversations from recentReports + // To preserve the order of the conversations, we map over the previous state's order of reports. + // Then match and replace older reports with the newer report conversations from recentReports .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) - // Because we are using map, we have to filter out any undefined reports. This happens if recentReports - // does not have all the conversations in prevState.orderedReports + // Because we are using map, we have to filter out any undefined reports. This happens if recentReports + // does not have all the conversations in prevState.orderedReports .filter(orderedReport => orderedReport !== undefined) .value(); - return { - orderedReports, - priorityMode: nextProps.priorityMode, - activeReport: { - reportID: nextProps.currentlyViewedReportID, - hasDraftHistory, - lastMessageTimestamp, - }, - unreadReports: memoizeGetUnreadReports(nextProps.reports || {}), + this.priorityMode = this.props.priorityMode; + this.activeReport = { + reportID: this.props.currentlyViewedReportID, + hasDraftHistory, + lastMessageTimestamp, }; + this.unreadReports = memoizeGetUnreadReports(unfilteredReports || {}); + } + + getRecentReports() { + const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); + const sidebarOptions = OptionsListUtils.getSidebarOptions( + this.props.reports, + this.props.personalDetails, + activeReportID, + this.props.priorityMode, + this.props.betas, + this.props.reportActions, + ); + return sidebarOptions.recentReports; + } + + shouldReorder(hasDraftHistory) { + // We do not want to re-order reports in the LHN if the only change is the draft comment in the + // current report. + + // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. + if (this.props.isSmallScreenWidth) { + return true; + } + + // Always update if LHN is empty. + if (this.orderedReports.length === 0) { + return true; + } + + const didActiveReportChange = this.activeReport.reportID !== this.props.currentlyViewedReportID; + + // Always re-order the list whenever the active report is changed + if (didActiveReportChange) { + return true; + } + + // If any reports have new unread messages, re-order the list + const nextUnreadReports = memoizeGetUnreadReports(this.props.reports || {}); + if (memoizeCheckForNewUnreadReports(nextUnreadReports, this.unreadReports)) { + return true; + } + + // If there is an active report that either had or has a draft, we do not want to re-order the list + if (this.props.currentlyViewedReportID && hasDraftHistory) { + return false; + } + + return true; } showSearchPage() { From 44a2ff60ed4f00429dd6e1759a49c39fd16ef079 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 07:27:42 +0100 Subject: [PATCH 016/123] Simplify the check for unread reports --- src/pages/home/sidebar/SidebarLinks.js | 179 +++++++++++++------------ 1 file changed, 92 insertions(+), 87 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index f315178b70a7..b4fb87f8e254 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -93,31 +93,31 @@ const defaultProps = { isSyncingData: false, }; -/** - * @param {Object} nextUnreadReports - * @param {Object} unreadReports - * @returns {Boolean} - */ -function checkForNewUnreadReports(nextUnreadReports, unreadReports) { - return nextUnreadReports.length > 0 - && _.some(nextUnreadReports, - nextUnreadReport => !_.some(unreadReports, unreadReport => unreadReport.reportID === nextUnreadReport.reportID)); -} -const memoizeCheckForNewUnreadReports = memoizeOne(checkForNewUnreadReports); - -/** - * @param {Object} reportsObject - * @returns {Array} - */ -function getUnreadReports(reportsObject) { - const reports = _.values(reportsObject); - if (reports.length === 0) { - return []; - } - const unreadReports = _.filter(reports, report => report && report.unreadActionCount > 0); - return unreadReports; -} -const memoizeGetUnreadReports = memoizeOne(getUnreadReports); +// /** +// * @param {Object} nextUnreadReports +// * @param {Object} unreadReports +// * @returns {Boolean} +// */ +// function checkForNewUnreadReports(nextUnreadReports, unreadReports) { +// return nextUnreadReports.length > 0 +// && _.some(nextUnreadReports, +// nextUnreadReport => !_.some(unreadReports, unreadReport => unreadReport.reportID === nextUnreadReport.reportID)); +// } +// const memoizeCheckForNewUnreadReports = memoizeOne(checkForNewUnreadReports); +// +// /** +// * @param {Object} reportsObject +// * @returns {Array} +// */ +// function getUnreadReports(reportsObject) { +// const reports = _.values(reportsObject); +// if (reports.length === 0) { +// return []; +// } +// const unreadReports = _.filter(reports, report => report && report.unreadActionCount > 0); +// return unreadReports; +// } +// const memoizeGetUnreadReports = memoizeOne(getUnreadReports); class SidebarLinks extends React.Component { // static getRecentReports(props) { @@ -192,55 +192,55 @@ class SidebarLinks extends React.Component { this.unreadReports = memoizeGetUnreadReports(props.reports || {}); } - static getDerivedStateFromProps(nextProps, prevState) { - // const isActiveReportSame = prevState.activeReport.reportID === nextProps.currentlyViewedReportID; - // const lastMessageTimestamp = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.lastMessageTimestamp`, 0); - - // Determines if the active report has a history of draft comments while active. - // let hasDraftHistory; - - // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. - // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. - // Otherwise, update the flag from the prop value. - // if (isActiveReportSame && prevState.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { - // hasDraftHistory = false; - // } else if (isActiveReportSame && prevState.activeReport.hasDraftHistory) { - // hasDraftHistory = true; - // } else { - // hasDraftHistory = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.hasDraft`, false); - // } - - // const shouldReorder = SidebarLinks.shouldReorder(nextProps, hasDraftHistory, prevState.orderedReports, prevState.activeReport.reportID, prevState.unreadReports); - // const switchingPriorityModes = nextProps.priorityMode !== prevState.priorityMode; - - // Build the report options we want to show - // const recentReports = SidebarLinks.getRecentReports(nextProps); - - // Determine whether we need to keep the previous LHN order - // const orderedReports = shouldReorder || switchingPriorityModes - // ? recentReports - // : _.chain(prevState.orderedReports) - // - // // To preserve the order of the conversations, we map over the previous state's order of reports. - // // Then match and replace older reports with the newer report conversations from recentReports - // .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) - // - // // Because we are using map, we have to filter out any undefined reports. This happens if recentReports - // // does not have all the conversations in prevState.orderedReports - // .filter(orderedReport => orderedReport !== undefined) - // .value(); - - // return { - // orderedReports, - // priorityMode: nextProps.priorityMode, - // activeReport: { - // reportID: nextProps.currentlyViewedReportID, - // hasDraftHistory, - // lastMessageTimestamp, - // }, - // unreadReports: memoizeGetUnreadReports(nextProps.reports || {}), - // }; - } + // static getDerivedStateFromProps(nextProps, prevState) { + // // const isActiveReportSame = prevState.activeReport.reportID === nextProps.currentlyViewedReportID; + // // const lastMessageTimestamp = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.lastMessageTimestamp`, 0); + // + // // Determines if the active report has a history of draft comments while active. + // // let hasDraftHistory; + // + // // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. + // // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. + // // Otherwise, update the flag from the prop value. + // // if (isActiveReportSame && prevState.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { + // // hasDraftHistory = false; + // // } else if (isActiveReportSame && prevState.activeReport.hasDraftHistory) { + // // hasDraftHistory = true; + // // } else { + // // hasDraftHistory = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.hasDraft`, false); + // // } + // + // // const shouldReorder = SidebarLinks.shouldReorder(nextProps, hasDraftHistory, prevState.orderedReports, prevState.activeReport.reportID, prevState.unreadReports); + // // const switchingPriorityModes = nextProps.priorityMode !== prevState.priorityMode; + // + // // Build the report options we want to show + // // const recentReports = SidebarLinks.getRecentReports(nextProps); + // + // // Determine whether we need to keep the previous LHN order + // // const orderedReports = shouldReorder || switchingPriorityModes + // // ? recentReports + // // : _.chain(prevState.orderedReports) + // // + // // // To preserve the order of the conversations, we map over the previous state's order of reports. + // // // Then match and replace older reports with the newer report conversations from recentReports + // // .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) + // // + // // // Because we are using map, we have to filter out any undefined reports. This happens if recentReports + // // // does not have all the conversations in prevState.orderedReports + // // .filter(orderedReport => orderedReport !== undefined) + // // .value(); + // + // // return { + // // orderedReports, + // // priorityMode: nextProps.priorityMode, + // // activeReport: { + // // reportID: nextProps.currentlyViewedReportID, + // // hasDraftHistory, + // // lastMessageTimestamp, + // // }, + // // unreadReports: memoizeGetUnreadReports(nextProps.reports || {}), + // // }; + // } getFilteredReports(unfilteredReports) { const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; @@ -302,38 +302,43 @@ class SidebarLinks extends React.Component { } shouldReorder(hasDraftHistory) { - // We do not want to re-order reports in the LHN if the only change is the draft comment in the - // current report. - // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. + // Because: TBD + // @TODO try and figure out why if (this.props.isSmallScreenWidth) { return true; } // Always update if LHN is empty. + // Because: TBD + // @TODO try and figure out why if (this.orderedReports.length === 0) { return true; } - const didActiveReportChange = this.activeReport.reportID !== this.props.currentlyViewedReportID; - // Always re-order the list whenever the active report is changed - if (didActiveReportChange) { - return true; - } - - // If any reports have new unread messages, re-order the list - const nextUnreadReports = memoizeGetUnreadReports(this.props.reports || {}); - if (memoizeCheckForNewUnreadReports(nextUnreadReports, this.unreadReports)) { + // Because: TBD + // @TODO try and figure out why + if (this.activeReport.reportID !== this.props.currentlyViewedReportID) { return true; } // If there is an active report that either had or has a draft, we do not want to re-order the list + // because the position of the report in the list won't change if (this.props.currentlyViewedReportID && hasDraftHistory) { return false; } - return true; + // If any reports have new unread messages, the list needs to be reordered + // because the unread reports need to be placed at the top of the list + const hasNewUnreadReports = _.some(this.props.reports, (report) => { + return report.unreadActionCount > 0 && !this.unreadReports[report.reportID]; + }); + if (hasNewUnreadReports) { + return true; + } + + return false; } showSearchPage() { From 57a4c2e3bba88581e34315d50e80967fe280149e Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 07:38:43 +0100 Subject: [PATCH 017/123] Simplify the map of unread reports --- src/pages/home/sidebar/SidebarLinks.js | 32 ++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index b4fb87f8e254..382569468b64 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -189,7 +189,7 @@ class SidebarLinks extends React.Component { this.orderedReports = []; this.priorityMode = props.priorityMode; - this.unreadReports = memoizeGetUnreadReports(props.reports || {}); + this.unreadReports = this.getUnreadReports(props.reports); } // static getDerivedStateFromProps(nextProps, prevState) { @@ -285,7 +285,31 @@ class SidebarLinks extends React.Component { hasDraftHistory, lastMessageTimestamp, }; - this.unreadReports = memoizeGetUnreadReports(unfilteredReports || {}); + this.unreadReports = this.getUnreadReports(unfilteredReports); + } + + /** + * Create a map of unread reports that looks like this: + * { + * 1: true, + * 2: true, + * } + * This is so that when the new props are compared to the old props, it's + * fast to look up if there are any new unread reports. + * + * @param {Object[]} reports + * @returns {Object} + */ + getUnreadReports(reports) { + return _.reduce(unfilteredReports, (finalUnreadReportMap, report) => { + if (report.unreadActionCount > 0) { + return { + [report.reportID]: true, + ...finalUnreadReportMap, + }; + } + return finalUnreadReportMap; + }, {}); } getRecentReports() { @@ -331,9 +355,7 @@ class SidebarLinks extends React.Component { // If any reports have new unread messages, the list needs to be reordered // because the unread reports need to be placed at the top of the list - const hasNewUnreadReports = _.some(this.props.reports, (report) => { - return report.unreadActionCount > 0 && !this.unreadReports[report.reportID]; - }); + const hasNewUnreadReports = _.some(this.props.reports, report => report.unreadActionCount > 0 && !this.unreadReports[report.reportID]); if (hasNewUnreadReports) { return true; } From 4b40492308160b8eba91d27be6e3d591384225f6 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 07:39:30 +0100 Subject: [PATCH 018/123] Correct outdated comment --- src/pages/home/sidebar/SidebarLinks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 382569468b64..c0c0442009a7 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -368,7 +368,7 @@ class SidebarLinks extends React.Component { } render() { - // Wait until the reports and personalDetails are actually loaded before displaying the LHN + // Wait until the personalDetails are actually loaded before displaying the LHN if (_.isEmpty(this.props.personalDetails)) { return null; } From 00ebe57e4d931d93a4b40dbe9fbc4a0b5b6eac97 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 07:42:02 +0100 Subject: [PATCH 019/123] Rename method to be more apparent --- src/pages/home/sidebar/SidebarLinks.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index c0c0442009a7..60a99f90da8f 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -260,7 +260,7 @@ class SidebarLinks extends React.Component { hasDraftHistory = lodashGet(this.props.reports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.hasDraft`, false); } - const shouldReorder = this.shouldReorder(hasDraftHistory); + const shouldReorder = this.shouldReorderReports(hasDraftHistory); const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; // Build the report options we want to show @@ -301,7 +301,7 @@ class SidebarLinks extends React.Component { * @returns {Object} */ getUnreadReports(reports) { - return _.reduce(unfilteredReports, (finalUnreadReportMap, report) => { + return _.reduce(reports, (finalUnreadReportMap, report) => { if (report.unreadActionCount > 0) { return { [report.reportID]: true, @@ -325,7 +325,7 @@ class SidebarLinks extends React.Component { return sidebarOptions.recentReports; } - shouldReorder(hasDraftHistory) { + shouldReorderReports(hasDraftHistory) { // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. // Because: TBD // @TODO try and figure out why From 103b126e819c6112813cc64c9e18a72ebf96939d Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 07:49:52 +0100 Subject: [PATCH 020/123] Access filtered report options direction from render --- src/pages/home/sidebar/SidebarLinks.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 60a99f90da8f..1783f60faa73 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -264,7 +264,7 @@ class SidebarLinks extends React.Component { const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; // Build the report options we want to show - const recentReports = this.getRecentReports(); + const recentReports = this.getRecentReportsOptionListItems(); this.orderedReports = shouldReorder || switchingPriorityModes ? recentReports @@ -286,6 +286,8 @@ class SidebarLinks extends React.Component { lastMessageTimestamp, }; this.unreadReports = this.getUnreadReports(unfilteredReports); + + return this.orderedReports; } /** @@ -312,7 +314,7 @@ class SidebarLinks extends React.Component { }, {}); } - getRecentReports() { + getRecentReportsOptionListItems() { const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); const sidebarOptions = OptionsListUtils.getSidebarOptions( this.props.reports, @@ -377,7 +379,7 @@ class SidebarLinks extends React.Component { const sections = [{ title: '', indexOffset: 0, - data: this.state.orderedReports || [], + data: this.getFilteredReports(this.props.reports), shouldShow: true, }]; From bb57fb055365b9d173e0675adb377024af2aeccb Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 17:33:03 +0200 Subject: [PATCH 021/123] Remove the import of unused library --- src/pages/home/sidebar/SidebarLinks.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 1783f60faa73..1afda46fecba 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -4,7 +4,6 @@ import _ from 'underscore'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import lodashGet from 'lodash/get'; -import memoizeOne from 'memoize-one'; import styles from '../../../styles/styles'; import * as StyleUtils from '../../../styles/StyleUtils'; import ONYXKEYS from '../../../ONYXKEYS'; @@ -431,7 +430,7 @@ class SidebarLinks extends React.Component { {paddingBottom: StyleUtils.getSafeAreaMargins(this.props.insets).marginBottom}, ]} sections={sections} - focusedIndex={_.findIndex(this.state.orderedReports, ( + focusedIndex={_.findIndex(this.orderedReports, ( option => option.reportID === activeReportID ))} onSelectRow={(option) => { From f3a7fa083fad9746ad174cf52748c129ee5c1529 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 17:33:13 +0200 Subject: [PATCH 022/123] Fix a prop warning --- src/pages/home/report/ReportActionsList.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index a78f672d3901..f5559585d2d3 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -50,7 +50,7 @@ const propTypes = { mostRecentIOUReportSequenceNumber: PropTypes.number, /** Are we loading more report actions? */ - isLoadingMoreReportActions: PropTypes.bool.isRequired, + isLoadingMoreReportActions: PropTypes.bool, /** Callback executed on list layout */ onLayout: PropTypes.func.isRequired, @@ -68,6 +68,7 @@ const propTypes = { const defaultProps = { personalDetails: {}, mostRecentIOUReportSequenceNumber: undefined, + isLoadingMoreReportActions: false, }; class ReportActionsList extends React.Component { From 35cfd235dae8e900b88760e7c5a8443e43f4e69a Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 17:49:03 +0200 Subject: [PATCH 023/123] Add some performance timing for filtering the reports --- src/CONST.js | 1 + src/pages/home/sidebar/SidebarLinks.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CONST.js b/src/CONST.js index a6b7586c217b..0add0513eecc 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -343,6 +343,7 @@ const CONST = { SWITCH_REPORT: 'switch_report', SIDEBAR_LOADED: 'sidebar_loaded', PERSONAL_DETAILS_FORMATTED: 'personal_details_formatted', + SIDEBAR_LINKS_FILTER_REPORTS: 'sidebar_links_filter_reports', COLD: 'cold', REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500, TOOLTIP_SENSE: 1000, diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 1afda46fecba..c0f3bc48cad0 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -27,6 +27,7 @@ import * as ReportUtils from '../../../libs/ReportUtils'; import networkPropTypes from '../../../components/networkPropTypes'; import {withNetwork} from '../../../components/OnyxProvider'; import withCurrentUserPersonalDetails from '../../../components/withCurrentUserPersonalDetails'; +import Timing from '../../../libs/actions/Timing'; const propTypes = { /** Toggles the navigation menu open and closed */ @@ -180,7 +181,7 @@ class SidebarLinks extends React.Component { constructor(props) { super(props); - this.getFilteredReports = _.memoize(this.getFilteredReports); + this.getFilteredReports = this.getFilteredReports.bind(this); this.activeReport = { reportID: props.currentlyViewedReportID, @@ -375,12 +376,14 @@ class SidebarLinks extends React.Component { } const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); + Timing.start(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); const sections = [{ title: '', indexOffset: 0, data: this.getFilteredReports(this.props.reports), shouldShow: true, }]; + Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); return ( From 8e8ba1f926819fe8bb3502f87bd3acb59a9e5db7 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 17:51:28 +0200 Subject: [PATCH 024/123] Rename method to be more clear --- src/pages/home/sidebar/SidebarLinks.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index c0f3bc48cad0..d09ff1192f05 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -181,7 +181,7 @@ class SidebarLinks extends React.Component { constructor(props) { super(props); - this.getFilteredReports = this.getFilteredReports.bind(this); + this.getFilteredAndOrderedReports = this.getFilteredAndOrderedReports.bind(this); this.activeReport = { reportID: props.currentlyViewedReportID, @@ -242,7 +242,7 @@ class SidebarLinks extends React.Component { // // }; // } - getFilteredReports(unfilteredReports) { + getFilteredAndOrderedReports(unfilteredReports) { const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); @@ -266,7 +266,7 @@ class SidebarLinks extends React.Component { // Build the report options we want to show const recentReports = this.getRecentReportsOptionListItems(); - this.orderedReports = shouldReorder || switchingPriorityModes + const orderedReports = shouldReorder || switchingPriorityModes ? recentReports : _.chain(this.orderedReports) @@ -279,6 +279,10 @@ class SidebarLinks extends React.Component { .filter(orderedReport => orderedReport !== undefined) .value(); + // Store these pieces of data on the class so that the next time this method is called + // the previous values can be compared against to tell if something changed which would + // cause the reports to be reordered + this.orderedReports = orderedReports; this.priorityMode = this.props.priorityMode; this.activeReport = { reportID: this.props.currentlyViewedReportID, @@ -380,7 +384,7 @@ class SidebarLinks extends React.Component { const sections = [{ title: '', indexOffset: 0, - data: this.getFilteredReports(this.props.reports), + data: this.getFilteredAndOrderedReports(this.props.reports), shouldShow: true, }]; Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); From 6a26a03708c7352b2473c1e76d862e0c365fac74 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 20:16:43 +0200 Subject: [PATCH 025/123] Remove mobile preoptimization --- src/pages/home/sidebar/SidebarLinks.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index d09ff1192f05..0ecee2ff2018 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -332,13 +332,6 @@ class SidebarLinks extends React.Component { } shouldReorderReports(hasDraftHistory) { - // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. - // Because: TBD - // @TODO try and figure out why - if (this.props.isSmallScreenWidth) { - return true; - } - // Always update if LHN is empty. // Because: TBD // @TODO try and figure out why From d97377655124db1839a00dbbbd044acbdcb9a5f4 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Sat, 27 Aug 2022 20:25:22 +0200 Subject: [PATCH 026/123] Correct the language in a comment --- src/pages/home/sidebar/SidebarLinks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 0ecee2ff2018..e51054b6e072 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -270,12 +270,12 @@ class SidebarLinks extends React.Component { ? recentReports : _.chain(this.orderedReports) - // To preserve the order of the conversations, we map over the previous state's order of reports. + // To preserve the order of the conversations, we map over the previous ordered reports. // Then match and replace older reports with the newer report conversations from recentReports .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) // Because we are using map, we have to filter out any undefined reports. This happens if recentReports - // does not have all the conversations in prevState.orderedReports + // does not have all the conversations in the previous set of orderedReports .filter(orderedReport => orderedReport !== undefined) .value(); From ccf63b3452783ad7bb936e6313286be8c37afc2e Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 12:52:02 +0200 Subject: [PATCH 027/123] correcting the name to walletAdditionalDetails --- src/pages/EnablePayments/IdologyQuestions.js | 21 ++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index a92a47f450c4..78ed9ac162a6 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -33,9 +33,14 @@ const propTypes = { /** ID from Idology, referencing those questions */ idNumber: PropTypes.string, - additionalDetails: PropTypes.shape({ + walletAdditionalDetails: PropTypes.shape({ + /** Are we waiting for a response? */ isLoading: PropTypes.bool, - errors: PropTypes.arrayOf(PropTypes.string), + + /** Any additional error message to show */ + errors: PropTypes.objectOf(PropTypes.string), + + /** What error do we need to handle */ errorCode: PropTypes.string, }), }; @@ -43,9 +48,9 @@ const propTypes = { const defaultProps = { questions: [], idNumber: '', - additionalDetails: { + walletAdditionalDetails: { isLoading: false, - errors: [], + errors: {}, errorCode: '', }, }; @@ -164,13 +169,13 @@ class IdologyQuestions extends React.Component { { this.form.scrollTo({y: 0, animated: true}); }} - message={_.isEmpty(this.props.additionalDetails.errors) ? _.find(this.props.additionalDetails.errors, error => error !== undefined) : this.state.errorMessage} - isLoading={this.props.additionalDetails.isLoading} + message={_.isEmpty(this.props.walletAdditionalDetails.errors) ? _.find(this.props.walletAdditionalDetails.errors, error => error !== undefined) : this.state.errorMessage} + isLoading={this.props.walletAdditionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> @@ -182,7 +187,7 @@ class IdologyQuestions extends React.Component { IdologyQuestions.propTypes = propTypes; IdologyQuestions.defaultProps = defaultProps; export default compose(withLocalize(IdologyQuestions), withOnyx({ - additionalDetails: { + walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, }, }))(IdologyQuestions); From 66fc73481047948d9d4c9a37cf62e9a8c87df295 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 16:24:30 +0200 Subject: [PATCH 028/123] adding some TODO so when I'm done. I can remove this mehtod --- src/libs/actions/Wallet.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index ee66288ff4e3..42c21a4f86db 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -247,6 +247,7 @@ function updatePersonalDetails(personalDetails) { * @param {Object} [parameters.idologyAnswers] * @param {Boolean} [parameters.hasAcceptedTerms] */ +// TODO: this is no longer used, so I need to remove it, for now I need to understand how it works function activateWallet(currentStep, parameters) { let personalDetails; let idologyAnswers; @@ -257,6 +258,7 @@ function activateWallet(currentStep, parameters) { throw new Error('Invalid currentStep passed to activateWallet()'); } + // TODO: need to check what this does setWalletShouldShowFailedKYC(false); if (currentStep === CONST.WALLET.STEP.ONFIDO) { onfidoData = parameters.onfidoData; @@ -303,6 +305,7 @@ function activateWallet(currentStep, parameters) { return; } + // TODO: not sure if we need to do this, and if we do, is it this GH? if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) { if (response.title === CONST.WALLET.ERROR.KBA_NEEDED) { setAdditionalDetailsQuestions(response.data.questions, response.data.idNumber); From b9c7d676997e4dc206bc3d47657f03eef3c594b7 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 16:25:05 +0200 Subject: [PATCH 029/123] adding some handling for what happens when the answers were correct. --- src/libs/actions/BankAccounts.js | 1 + src/libs/actions/Wallet.js | 1 + src/pages/EnablePayments/IdologyQuestions.js | 30 ++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 4d3b0b71b36c..3c7fc568ff72 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -31,6 +31,7 @@ export { answerQuestionsForWallet, verifyIdentity, acceptWalletTerms, + setAdditionalDetailsLoading, } from './Wallet'; function clearPersonalBankAccount() { diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index 42c21a4f86db..223637d770ff 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -580,4 +580,5 @@ export { updatePersonalDetails, verifyIdentity, acceptWalletTerms, + setAdditionalDetailsLoading, }; diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 78ed9ac162a6..90ff21191a67 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -15,6 +15,8 @@ import FormScrollView from '../../components/FormScrollView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; +import CONST from "../../CONST"; +import * as PaymentMethods from "../../libs/actions/PaymentMethods"; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -43,6 +45,16 @@ const propTypes = { /** What error do we need to handle */ errorCode: PropTypes.string, }), + + /** User wallet props */ + userWallet: PropTypes.shape({ + + /** The step in the wallet configuration we are in. */ + currentStep: PropTypes.string, + + /** What tier does the user has for their wallet */ + tierName: PropTypes.string, + }), }; const defaultProps = { @@ -53,6 +65,10 @@ const defaultProps = { errors: {}, errorCode: '', }, + userWallet: { + currentStep: '', + tierName: '', + }, }; class IdologyQuestions extends React.Component { @@ -75,6 +91,17 @@ class IdologyQuestions extends React.Component { }; } + componentDidUpdate(prevProps) { + if (this.props.userWallet.tierName !== CONST.WALLET.TIER_NAME.GOLD) { + return; + } + + if (this.props.walletAdditionalDetails.isLoading) { + PaymentMethods.continueSetup(); + BankAccounts.setAdditionalDetailsLoading(false); + } + } + /** * Put question answer in the state. * @param {Number} questionIndex @@ -190,4 +217,7 @@ export default compose(withLocalize(IdologyQuestions), withOnyx({ walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, }, + userWallet: { + key: ONYXKEYS.USER_WALLET, + } }))(IdologyQuestions); From d9153aa550562b435d2bb47bba83d5397d0fcbc6 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 17:01:50 +0200 Subject: [PATCH 030/123] fix jest hopefully --- src/pages/EnablePayments/IdologyQuestions.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 90ff21191a67..ae5bdc65240e 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -213,11 +213,14 @@ class IdologyQuestions extends React.Component { IdologyQuestions.propTypes = propTypes; IdologyQuestions.defaultProps = defaultProps; -export default compose(withLocalize(IdologyQuestions), withOnyx({ - walletAdditionalDetails: { - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - }, - userWallet: { - key: ONYXKEYS.USER_WALLET, - } -}))(IdologyQuestions); +export default compose( + withLocalize(IdologyQuestions), + withOnyx({ + walletAdditionalDetails: { + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + }, + userWallet: { + key: ONYXKEYS.USER_WALLET, + }, + }), +)(IdologyQuestions); From f0d04dbe88d275e74bb1959334bfbd4054620a71 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 17:21:02 +0200 Subject: [PATCH 031/123] adding some more logic --- src/pages/EnablePayments/IdologyQuestions.js | 31 ++++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index ae5bdc65240e..1e24dc1c1c14 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -17,6 +17,12 @@ import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; import CONST from "../../CONST"; import * as PaymentMethods from "../../libs/actions/PaymentMethods"; +import lodashGet from "lodash/get"; +import * as PersonalDetails from "../../libs/actions/PersonalDetails"; +import ScreenWrapper from "../../components/ScreenWrapper"; +import HeaderWithCloseButton from "../../components/HeaderWithCloseButton"; +import Navigation from "../../libs/Navigation/Navigation"; +import FailedKYC from "./FailedKYC"; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -85,9 +91,6 @@ class IdologyQuestions extends React.Component { /** Answers from the user */ answers: [], - - /** Any error message */ - errorMessage: '', }; } @@ -114,7 +117,6 @@ class IdologyQuestions extends React.Component { answers[questionIndex] = {question: question.type, answer}; return { answers, - errorMessage: '', }; }); } @@ -127,6 +129,7 @@ class IdologyQuestions extends React.Component { // User must pick an answer if (!prevState.answers[prevState.questionNumber]) { return { + // TODO: I think this should be a merge of the Aditional Details, as an error, that would update everything errorMessage: this.props.translate('additionalDetailsStep.selectAnswer'), }; } @@ -174,6 +177,22 @@ class IdologyQuestions extends React.Component { value: answer, }; })); + const errors = lodashGet(this.props, 'walletAdditionalDetails.errors', {}); + const isErrorVisible = _.size(this.getErrors()) > 0 || !_.isEmpty(errors); + const errorMessage = _.isEmpty(errors) ? '' : _.last(_.values(errors)); + + if (this.props.walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.KYC) { + return ( + // TODO: not sure if this is the correct design + + Navigation.dismissModal()} + /> + + + ); + } return ( @@ -196,12 +215,12 @@ class IdologyQuestions extends React.Component { { this.form.scrollTo({y: 0, animated: true}); }} - message={_.isEmpty(this.props.walletAdditionalDetails.errors) ? _.find(this.props.walletAdditionalDetails.errors, error => error !== undefined) : this.state.errorMessage} + message={errorMessage} isLoading={this.props.walletAdditionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> From de24b0031f2c5912c97bf250b8967f8b7126dc89 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 17:25:42 +0200 Subject: [PATCH 032/123] localize is not a mehtod --- src/pages/EnablePayments/IdologyQuestions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 1e24dc1c1c14..161843345235 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -233,7 +233,7 @@ class IdologyQuestions extends React.Component { IdologyQuestions.propTypes = propTypes; IdologyQuestions.defaultProps = defaultProps; export default compose( - withLocalize(IdologyQuestions), + withLocalize, withOnyx({ walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, From b770d0ce445cb7b11b9a1a90db9c9e082de2c9b2 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 30 Aug 2022 17:26:32 +0200 Subject: [PATCH 033/123] Remove old code --- src/pages/home/sidebar/SidebarLinks.js | 134 ------------------------- 1 file changed, 134 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index e51054b6e072..da5c9e4ab86c 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -93,91 +93,7 @@ const defaultProps = { isSyncingData: false, }; -// /** -// * @param {Object} nextUnreadReports -// * @param {Object} unreadReports -// * @returns {Boolean} -// */ -// function checkForNewUnreadReports(nextUnreadReports, unreadReports) { -// return nextUnreadReports.length > 0 -// && _.some(nextUnreadReports, -// nextUnreadReport => !_.some(unreadReports, unreadReport => unreadReport.reportID === nextUnreadReport.reportID)); -// } -// const memoizeCheckForNewUnreadReports = memoizeOne(checkForNewUnreadReports); -// -// /** -// * @param {Object} reportsObject -// * @returns {Array} -// */ -// function getUnreadReports(reportsObject) { -// const reports = _.values(reportsObject); -// if (reports.length === 0) { -// return []; -// } -// const unreadReports = _.filter(reports, report => report && report.unreadActionCount > 0); -// return unreadReports; -// } -// const memoizeGetUnreadReports = memoizeOne(getUnreadReports); - class SidebarLinks extends React.Component { - // static getRecentReports(props) { - // const activeReportID = parseInt(props.currentlyViewedReportID, 10); - // const sidebarOptions = OptionsListUtils.getSidebarOptions( - // props.reports, - // props.personalDetails, - // activeReportID, - // props.priorityMode, - // props.betas, - // props.reportActions, - // ); - // return sidebarOptions.recentReports; - // } - - // /** - // * Returns true if the sidebar list should be re-ordered - // * - // * @param {Object} nextProps - // * @param {Boolean} hasActiveDraftHistory - // * @param {Array} orderedReports - // * @param {String} currentlyViewedReportID - // * @param {Array} unreadReports - // * @returns {Boolean} - // */ - // static shouldReorder(nextProps, hasActiveDraftHistory, orderedReports, currentlyViewedReportID, unreadReports) { - // // We do not want to re-order reports in the LHN if the only change is the draft comment in the - // // current report. - // - // // We don't need to limit draft comment flashing for small screen widths as LHN is not visible. - // if (nextProps.isSmallScreenWidth) { - // return true; - // } - // - // // Always update if LHN is empty. - // if (orderedReports.length === 0) { - // return true; - // } - // - // const didActiveReportChange = currentlyViewedReportID !== nextProps.currentlyViewedReportID; - // - // // Always re-order the list whenever the active report is changed - // if (didActiveReportChange) { - // return true; - // } - // - // // If any reports have new unread messages, re-order the list - // const nextUnreadReports = memoizeGetUnreadReports(nextProps.reports || {}); - // if (memoizeCheckForNewUnreadReports(nextUnreadReports, unreadReports)) { - // return true; - // } - // - // // If there is an active report that either had or has a draft, we do not want to re-order the list - // if (nextProps.currentlyViewedReportID && hasActiveDraftHistory) { - // return false; - // } - // - // return true; - // } - constructor(props) { super(props); @@ -192,56 +108,6 @@ class SidebarLinks extends React.Component { this.unreadReports = this.getUnreadReports(props.reports); } - // static getDerivedStateFromProps(nextProps, prevState) { - // // const isActiveReportSame = prevState.activeReport.reportID === nextProps.currentlyViewedReportID; - // // const lastMessageTimestamp = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.lastMessageTimestamp`, 0); - // - // // Determines if the active report has a history of draft comments while active. - // // let hasDraftHistory; - // - // // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. - // // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. - // // Otherwise, update the flag from the prop value. - // // if (isActiveReportSame && prevState.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { - // // hasDraftHistory = false; - // // } else if (isActiveReportSame && prevState.activeReport.hasDraftHistory) { - // // hasDraftHistory = true; - // // } else { - // // hasDraftHistory = lodashGet(nextProps.reports, `${ONYXKEYS.COLLECTION.REPORT}${nextProps.currentlyViewedReportID}.hasDraft`, false); - // // } - // - // // const shouldReorder = SidebarLinks.shouldReorder(nextProps, hasDraftHistory, prevState.orderedReports, prevState.activeReport.reportID, prevState.unreadReports); - // // const switchingPriorityModes = nextProps.priorityMode !== prevState.priorityMode; - // - // // Build the report options we want to show - // // const recentReports = SidebarLinks.getRecentReports(nextProps); - // - // // Determine whether we need to keep the previous LHN order - // // const orderedReports = shouldReorder || switchingPriorityModes - // // ? recentReports - // // : _.chain(prevState.orderedReports) - // // - // // // To preserve the order of the conversations, we map over the previous state's order of reports. - // // // Then match and replace older reports with the newer report conversations from recentReports - // // .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) - // // - // // // Because we are using map, we have to filter out any undefined reports. This happens if recentReports - // // // does not have all the conversations in prevState.orderedReports - // // .filter(orderedReport => orderedReport !== undefined) - // // .value(); - // - // // return { - // // orderedReports, - // // priorityMode: nextProps.priorityMode, - // // activeReport: { - // // reportID: nextProps.currentlyViewedReportID, - // // hasDraftHistory, - // // lastMessageTimestamp, - // // }, - // // unreadReports: memoizeGetUnreadReports(nextProps.reports || {}), - // // }; - // } - getFilteredAndOrderedReports(unfilteredReports) { const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); From 962697294e61ef5625e90c0f582295a4571ad2f7 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 30 Aug 2022 17:33:51 +0200 Subject: [PATCH 034/123] Rename method to make more sense and add comments --- src/pages/home/sidebar/SidebarLinks.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index fb53b5e15021..31ad2b18b9b9 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -117,13 +117,16 @@ class SidebarLinks extends React.Component { hasDraftHistory = lodashGet(this.props.reports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.hasDraft`, false); } - const shouldReorder = this.shouldReorderReports(hasDraftHistory); const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; // Build the report options we want to show const recentReports = this.getRecentReportsOptionListItems(); - const orderedReports = shouldReorder || switchingPriorityModes + // If the order of the reports is different from the last render (or if priority mode is changing) + // then orderedReports is the same as the freshly calculated recentReports. + // If the order of the reports is the same as the last render + // then the data for each report is updated from the data in the new props (not sure why this is necessary) + const orderedReports = this.isReportOrderDifferentThanLastRender(hasDraftHistory) || switchingPriorityModes ? recentReports : _.chain(this.orderedReports) @@ -188,7 +191,7 @@ class SidebarLinks extends React.Component { return sidebarOptions.recentReports; } - shouldReorderReports(hasDraftHistory) { + isReportOrderDifferentThanLastRender(hasDraftHistory) { // Always update if LHN is empty. // Because: TBD // @TODO try and figure out why From 31b42d936e59f63925678a704c1c749334ed0238 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Tue, 30 Aug 2022 17:37:13 +0200 Subject: [PATCH 035/123] fixing linter --- src/pages/EnablePayments/IdologyQuestions.js | 31 ++++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 161843345235..13de3aac942c 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -5,6 +5,7 @@ import { View, } from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import RadioButtons from '../../components/RadioButtons'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import styles from '../../styles/styles'; @@ -15,14 +16,11 @@ import FormScrollView from '../../components/FormScrollView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; -import CONST from "../../CONST"; -import * as PaymentMethods from "../../libs/actions/PaymentMethods"; -import lodashGet from "lodash/get"; -import * as PersonalDetails from "../../libs/actions/PersonalDetails"; -import ScreenWrapper from "../../components/ScreenWrapper"; -import HeaderWithCloseButton from "../../components/HeaderWithCloseButton"; -import Navigation from "../../libs/Navigation/Navigation"; -import FailedKYC from "./FailedKYC"; +import CONST from '../../CONST'; +import * as PaymentMethods from '../../libs/actions/PaymentMethods'; +import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; +import Navigation from '../../libs/Navigation/Navigation'; +import FailedKYC from './FailedKYC'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -94,7 +92,7 @@ class IdologyQuestions extends React.Component { }; } - componentDidUpdate(prevProps) { + componentDidUpdate() { if (this.props.userWallet.tierName !== CONST.WALLET.TIER_NAME.GOLD) { return; } @@ -183,6 +181,7 @@ class IdologyQuestions extends React.Component { if (this.props.walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.KYC) { return ( + // TODO: not sure if this is the correct design Date: Tue, 30 Aug 2022 17:40:08 +0200 Subject: [PATCH 036/123] Add comments to the logic for ordering reports --- src/pages/home/sidebar/SidebarLinks.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 31ad2b18b9b9..b5d73c968de9 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -192,33 +192,33 @@ class SidebarLinks extends React.Component { } isReportOrderDifferentThanLastRender(hasDraftHistory) { - // Always update if LHN is empty. - // Because: TBD - // @TODO try and figure out why - if (this.orderedReports.length === 0) { + // If the number of reports changed, then the report order is different + if (this.orderedReports.length !== this.props.reports.length) { return true; } - // Always re-order the list whenever the active report is changed - // Because: TBD - // @TODO try and figure out why + // If the active report changed, then the report order is different if (this.activeReport.reportID !== this.props.currentlyViewedReportID) { return true; } - // If there is an active report that either had or has a draft, we do not want to re-order the list - // because the position of the report in the list won't change + // If the active report has a draft, the order of the reports doesn't change + // because it would cause the reports to reorder when a user starts typing a comment + // and that is an annoying UX (too much stuff jumping around) if (this.props.currentlyViewedReportID && hasDraftHistory) { return false; } - // If any reports have new unread messages, the list needs to be reordered + // If the unread reports have changed, then the report order changes // because the unread reports need to be placed at the top of the list + // @TODO: This can probably be optimized const hasNewUnreadReports = _.some(this.props.reports, report => report.unreadActionCount > 0 && !this.unreadReports[report.reportID]); if (hasNewUnreadReports) { return true; } + // By default, assume that the order of the reports doesn't change + // in order to optimize the rendering return false; } From 16cad5d6588585f6b53bf64b8b5f6cd9947c7dc1 Mon Sep 17 00:00:00 2001 From: Eugene Voloshchak Date: Tue, 30 Aug 2022 21:38:52 +0300 Subject: [PATCH 037/123] Accept both decimal separators on mWeb iOS --- src/libs/getPermittedDecimalSeparator/index.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libs/getPermittedDecimalSeparator/index.js b/src/libs/getPermittedDecimalSeparator/index.js index 573e0c9b3225..9ac4156bc3ff 100644 --- a/src/libs/getPermittedDecimalSeparator/index.js +++ b/src/libs/getPermittedDecimalSeparator/index.js @@ -1 +1,11 @@ -export default localizedSeparator => localizedSeparator; +import getOperatingSystem from '../getOperatingSystem'; +import getPermittedDecimalSeparatorIOS from './index.ios'; +import CONST from '../../CONST'; + +export default (localizedSeparator) => { + if (getOperatingSystem() === CONST.OS.IOS) { + return getPermittedDecimalSeparatorIOS(); + } + + return localizedSeparator; +}; From 56d6d3416125f9d36bc2af37a263e69cd6ea00ec Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 30 Aug 2022 20:45:12 +0200 Subject: [PATCH 038/123] Add a todo --- src/pages/home/sidebar/SidebarLinks.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index b5d73c968de9..392c74e9a50b 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -125,7 +125,8 @@ class SidebarLinks extends React.Component { // If the order of the reports is different from the last render (or if priority mode is changing) // then orderedReports is the same as the freshly calculated recentReports. // If the order of the reports is the same as the last render - // then the data for each report is updated from the data in the new props (not sure why this is necessary) + // then the data for each report is updated from the data in the new props + // @TODO: not sure why this is necessary and see if it can be removed or do something more intuitive const orderedReports = this.isReportOrderDifferentThanLastRender(hasDraftHistory) || switchingPriorityModes ? recentReports : _.chain(this.orderedReports) From 160da4eb48617374ac42867c8ef7c390dd90caed Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Wed, 31 Aug 2022 18:14:53 +0400 Subject: [PATCH 039/123] Remove TODOs and cleanup --- src/libs/actions/BankAccounts.js | 1 - src/libs/actions/Wallet.js | 6 +----- src/pages/EnablePayments/EnablePaymentsPage.js | 10 +--------- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 3c7fc568ff72..4d3b0b71b36c 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -31,7 +31,6 @@ export { answerQuestionsForWallet, verifyIdentity, acceptWalletTerms, - setAdditionalDetailsLoading, } from './Wallet'; function clearPersonalBankAccount() { diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index 223637d770ff..e8a838fc79c4 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -247,7 +247,6 @@ function updatePersonalDetails(personalDetails) { * @param {Object} [parameters.idologyAnswers] * @param {Boolean} [parameters.hasAcceptedTerms] */ -// TODO: this is no longer used, so I need to remove it, for now I need to understand how it works function activateWallet(currentStep, parameters) { let personalDetails; let idologyAnswers; @@ -258,7 +257,6 @@ function activateWallet(currentStep, parameters) { throw new Error('Invalid currentStep passed to activateWallet()'); } - // TODO: need to check what this does setWalletShouldShowFailedKYC(false); if (currentStep === CONST.WALLET.STEP.ONFIDO) { onfidoData = parameters.onfidoData; @@ -305,7 +303,6 @@ function activateWallet(currentStep, parameters) { return; } - // TODO: not sure if we need to do this, and if we do, is it this GH? if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) { if (response.title === CONST.WALLET.ERROR.KBA_NEEDED) { setAdditionalDetailsQuestions(response.data.questions, response.data.idNumber); @@ -532,7 +529,7 @@ function updateCurrentStep(currentStep) { } /** - * @param {String} idologyAnswers + * @param {Object} idologyAnswers */ function answerQuestionsForWallet(idologyAnswers) { const answers = JSON.stringify(idologyAnswers); @@ -580,5 +577,4 @@ export { updatePersonalDetails, verifyIdentity, acceptWalletTerms, - setAdditionalDetailsLoading, }; diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index 0e098fa5a820..3647343f9e89 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -27,10 +27,6 @@ const propTypes = { /** Information about the network from Onyx */ network: networkPropTypes.isRequired, - additionalDetails: PropTypes.shape({ - errorCode: PropTypes.string, - }), - /** The user's wallet */ userWallet: PropTypes.objectOf(userWalletPropTypes), @@ -39,10 +35,6 @@ const propTypes = { const defaultProps = { userWallet: {}, - - additionalDetails: { - errorCode: '', - }, }; class EnablePaymentsPage extends React.Component { @@ -63,7 +55,7 @@ class EnablePaymentsPage extends React.Component { return ; } - if (this.props.additionalDetails.errorCode === CONST.WALLET.ERROR.KYC) { + if (this.props.userWallet.errorCode === CONST.WALLET.ERROR.KYC) { return ( Date: Wed, 31 Aug 2022 18:36:05 +0400 Subject: [PATCH 040/123] Clean up props and remove un-needed logic --- .../EnablePayments/EnablePaymentsPage.js | 3 -- src/pages/EnablePayments/IdologyQuestions.js | 54 +++++-------------- 2 files changed, 12 insertions(+), 45 deletions(-) diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index 3647343f9e89..314419df9a56 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -101,9 +101,6 @@ export default compose( walletAdditionalDetailsDraft: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS_DRAFT, }, - additionalDetails: { - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - }, }), withNetwork(), )(EnablePaymentsPage); diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 13de3aac942c..af2dcf3853eb 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -21,6 +21,7 @@ import * as PaymentMethods from '../../libs/actions/PaymentMethods'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import Navigation from '../../libs/Navigation/Navigation'; import FailedKYC from './FailedKYC'; +import userWalletPropTypes from './userWalletPropTypes'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -51,28 +52,14 @@ const propTypes = { }), /** User wallet props */ - userWallet: PropTypes.shape({ - - /** The step in the wallet configuration we are in. */ - currentStep: PropTypes.string, - - /** What tier does the user has for their wallet */ - tierName: PropTypes.string, - }), + userWallet: PropTypes.shape(userWalletPropTypes), }; const defaultProps = { questions: [], idNumber: '', - walletAdditionalDetails: { - isLoading: false, - errors: {}, - errorCode: '', - }, - userWallet: { - currentStep: '', - tierName: '', - }, + walletAdditionalDetails: {}, + userWallet: {}, }; class IdologyQuestions extends React.Component { @@ -89,6 +76,9 @@ class IdologyQuestions extends React.Component { /** Answers from the user */ answers: [], + + /** Any error message */ + errorMessage: '', }; } @@ -96,11 +86,6 @@ class IdologyQuestions extends React.Component { if (this.props.userWallet.tierName !== CONST.WALLET.TIER_NAME.GOLD) { return; } - - if (this.props.walletAdditionalDetails.isLoading) { - PaymentMethods.continueSetup(); - BankAccounts.setAdditionalDetailsLoading(false); - } } /** @@ -115,6 +100,7 @@ class IdologyQuestions extends React.Component { answers[questionIndex] = {question: question.type, answer}; return { answers, + errorMessage, }; }); } @@ -127,7 +113,6 @@ class IdologyQuestions extends React.Component { // User must pick an answer if (!prevState.answers[prevState.questionNumber]) { return { - // TODO: I think this should be a merge of the Aditional Details, as an error, that would update everything errorMessage: this.props.translate('additionalDetailsStep.selectAnswer'), }; } @@ -146,11 +131,10 @@ class IdologyQuestions extends React.Component { } } - const idologyAnswers = { + BankAccounts.answerQuestionsForWallet({ answers, idNumber: this.props.idNumber, - }; - BankAccounts.answerQuestionsForWallet(idologyAnswers); + }); return {answers}; } @@ -176,22 +160,8 @@ class IdologyQuestions extends React.Component { }; })); const errors = lodashGet(this.props, 'walletAdditionalDetails.errors', {}); - const isErrorVisible = _.size(this.getErrors()) > 0 || !_.isEmpty(errors); - const errorMessage = _.isEmpty(errors) ? '' : _.last(_.values(errors)); - - if (this.props.walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.KYC) { - return ( - - // TODO: not sure if this is the correct design - - Navigation.dismissModal()} - /> - - - ); - } + const isErrorVisible = this.state.errorMessage || _.size(this.getErrors()) > 0 || !_.isEmpty(errors); + const errorMessage = _.isEmpty(errors) ? this.state.errorMessage : _.last(_.values(errors)); return ( From 44e258cf9e7568629104055bf774fdad92f67448 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 31 Aug 2022 17:10:32 +0200 Subject: [PATCH 041/123] Fix proptype warnings --- src/pages/home/ReportScreen.js | 5 ++--- src/pages/home/report/ReportActionCompose.js | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 717963c3dd49..2f5c2742eb24 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -60,7 +60,7 @@ const propTypes = { isLoadingReportActions: PropTypes.bool, /** ID for the report */ - reportID: PropTypes.string, + reportID: PropTypes.number, }), /** Array of report actions for this report */ @@ -111,8 +111,7 @@ const defaultProps = { * @returns {Number} */ function getReportID(route) { - const params = route.params; - return Number.parseInt(params.reportID, 10); + return route.params.reportID.toString(); } class ReportScreen extends React.Component { diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 61369be57010..a82101de219f 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -57,7 +57,7 @@ const propTypes = { comment: PropTypes.string, /** The ID of the report actions will be created for */ - reportID: PropTypes.number.isRequired, + reportID: PropTypes.string.isRequired, /** Details about any modals being used */ modal: PropTypes.shape({ From f42ed2a20b95a4ebb24d720956232bcc4f0d6b7e Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Wed, 31 Aug 2022 19:27:49 +0400 Subject: [PATCH 042/123] Fix command params for answerQuestionsForWallet --- src/libs/actions/Wallet.js | 7 +++--- src/pages/EnablePayments/IdologyQuestions.js | 24 ++++---------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index e8a838fc79c4..b8b883a67e28 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -531,11 +531,12 @@ function updateCurrentStep(currentStep) { /** * @param {Object} idologyAnswers */ -function answerQuestionsForWallet(idologyAnswers) { - const answers = JSON.stringify(idologyAnswers); +function answerQuestionsForWallet(answers, idNumber) { + const idologyAnswers = JSON.stringify(answers); API.write('AnswerQuestionsForWallet', { - answers, + idologyAnswers, + idNumber }, { optimisticData: [{ diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index af2dcf3853eb..5dc3beb5d697 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -21,7 +21,6 @@ import * as PaymentMethods from '../../libs/actions/PaymentMethods'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import Navigation from '../../libs/Navigation/Navigation'; import FailedKYC from './FailedKYC'; -import userWalletPropTypes from './userWalletPropTypes'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -50,16 +49,12 @@ const propTypes = { /** What error do we need to handle */ errorCode: PropTypes.string, }), - - /** User wallet props */ - userWallet: PropTypes.shape(userWalletPropTypes), }; const defaultProps = { questions: [], idNumber: '', walletAdditionalDetails: {}, - userWallet: {}, }; class IdologyQuestions extends React.Component { @@ -82,12 +77,6 @@ class IdologyQuestions extends React.Component { }; } - componentDidUpdate() { - if (this.props.userWallet.tierName !== CONST.WALLET.TIER_NAME.GOLD) { - return; - } - } - /** * Put question answer in the state. * @param {Number} questionIndex @@ -100,7 +89,7 @@ class IdologyQuestions extends React.Component { answers[questionIndex] = {question: question.type, answer}; return { answers, - errorMessage, + errorMessage: '', }; }); } @@ -131,10 +120,7 @@ class IdologyQuestions extends React.Component { } } - BankAccounts.answerQuestionsForWallet({ - answers, - idNumber: this.props.idNumber, - }); + BankAccounts.answerQuestionsForWallet(answers, this.props.idNumber); return {answers}; } @@ -160,7 +146,7 @@ class IdologyQuestions extends React.Component { }; })); const errors = lodashGet(this.props, 'walletAdditionalDetails.errors', {}); - const isErrorVisible = this.state.errorMessage || _.size(this.getErrors()) > 0 || !_.isEmpty(errors); + const isErrorVisible = this.state.errorMessage || !_.isEmpty(errors); const errorMessage = _.isEmpty(errors) ? this.state.errorMessage : _.last(_.values(errors)); return ( @@ -179,6 +165,7 @@ class IdologyQuestions extends React.Component { {question.prompt} this.chooseAnswer(questionIndex, answer)} /> @@ -207,8 +194,5 @@ export default compose( walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, }, - userWallet: { - key: ONYXKEYS.USER_WALLET, - }, }), )(IdologyQuestions); From 3595d65aedc9f4ff2a4531695389e078ed181b40 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Wed, 31 Aug 2022 21:39:42 +0400 Subject: [PATCH 043/123] Don't show redundant error --- src/pages/EnablePayments/IdologyQuestions.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 5dc3beb5d697..b726b417cd06 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -145,9 +145,6 @@ class IdologyQuestions extends React.Component { value: answer, }; })); - const errors = lodashGet(this.props, 'walletAdditionalDetails.errors', {}); - const isErrorVisible = this.state.errorMessage || !_.isEmpty(errors); - const errorMessage = _.isEmpty(errors) ? this.state.errorMessage : _.last(_.values(errors)); return ( @@ -171,12 +168,12 @@ class IdologyQuestions extends React.Component { { this.form.scrollTo({y: 0, animated: true}); }} - message={errorMessage} + message={this.state.errorMessage} isLoading={this.props.walletAdditionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> From f1f621ee99fafe8ff50a0175954da1cad780707e Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Wed, 31 Aug 2022 21:42:07 +0400 Subject: [PATCH 044/123] Fix lint errors --- src/libs/actions/Wallet.js | 5 +++-- src/pages/EnablePayments/IdologyQuestions.js | 6 ------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index b8b883a67e28..a4e75f49d010 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -529,14 +529,15 @@ function updateCurrentStep(currentStep) { } /** - * @param {Object} idologyAnswers + * @param {Object} answers + * @param {String} idNumber */ function answerQuestionsForWallet(answers, idNumber) { const idologyAnswers = JSON.stringify(answers); API.write('AnswerQuestionsForWallet', { idologyAnswers, - idNumber + idNumber, }, { optimisticData: [{ diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index b726b417cd06..6d3cf2677339 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -5,7 +5,6 @@ import { View, } from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; import RadioButtons from '../../components/RadioButtons'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import styles from '../../styles/styles'; @@ -16,11 +15,6 @@ import FormScrollView from '../../components/FormScrollView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; -import CONST from '../../CONST'; -import * as PaymentMethods from '../../libs/actions/PaymentMethods'; -import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; -import Navigation from '../../libs/Navigation/Navigation'; -import FailedKYC from './FailedKYC'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; From bc6be2ddedfa075a8a816a1079fde5dc06ba16ce Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Thu, 1 Sep 2022 09:44:04 +0400 Subject: [PATCH 045/123] Add offline indicator and display error messages --- src/pages/EnablePayments/IdologyQuestions.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.js index 6d3cf2677339..c4368c8cb9c6 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.js @@ -5,6 +5,7 @@ import { View, } from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import RadioButtons from '../../components/RadioButtons'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import styles from '../../styles/styles'; @@ -15,6 +16,7 @@ import FormScrollView from '../../components/FormScrollView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; +import OfflineIndicator from '../../components/OfflineIndicator'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; @@ -140,6 +142,10 @@ class IdologyQuestions extends React.Component { }; })); + const errors = lodashGet(this.props, 'walletAdditionalDetails.errors', {}); + const isErrorVisible = this.state.errorMessage || !_.isEmpty(errors); + const errorMessage = _.isEmpty(errors) ? this.state.errorMessage : _.last(_.values(errors)); + return ( @@ -162,15 +168,16 @@ class IdologyQuestions extends React.Component { { this.form.scrollTo({y: 0, animated: true}); }} - message={this.state.errorMessage} + message={errorMessage} isLoading={this.props.walletAdditionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> + ); From bd05cecc019cb26d946b57d55e7fc897e9fc1359 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 11:21:13 +0200 Subject: [PATCH 046/123] Remove unnecessary binding --- src/pages/home/sidebar/SidebarLinks.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 3ad2041655ce..d9365e5d2327 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -91,8 +91,6 @@ class SidebarLinks extends React.Component { constructor(props) { super(props); - this.getFilteredAndOrderedReports = this.getFilteredAndOrderedReports.bind(this); - this.activeReport = { reportID: props.currentlyViewedReportID, }; @@ -237,14 +235,15 @@ class SidebarLinks extends React.Component { } const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); - Timing.start(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); + // Timing.start(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); const sections = [{ title: '', indexOffset: 0, data: this.getFilteredAndOrderedReports(this.props.reports), shouldShow: true, }]; - Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); + // const sections = []; + // Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); return ( From 475f0eddd25867b68df048bc8e0d42074587a149 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 11:22:00 +0200 Subject: [PATCH 047/123] Remove debug code that is not needed --- src/pages/home/sidebar/SidebarLinks.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index d9365e5d2327..3b5c9e8b5521 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -235,15 +235,14 @@ class SidebarLinks extends React.Component { } const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); - // Timing.start(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); + Timing.start(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); const sections = [{ title: '', indexOffset: 0, data: this.getFilteredAndOrderedReports(this.props.reports), shouldShow: true, }]; - // const sections = []; - // Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); + Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); return ( From 80615c9446ef933bb36b1d35791de1cb9775c3cb Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 11:40:38 +0200 Subject: [PATCH 048/123] Fix proptype warning --- src/components/OptionsSelector/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/OptionsSelector/index.js b/src/components/OptionsSelector/index.js index 14495ecae24d..9415c4e3b279 100644 --- a/src/components/OptionsSelector/index.js +++ b/src/components/OptionsSelector/index.js @@ -1,6 +1,7 @@ import React, {forwardRef} from 'react'; import BaseOptionsSelector from './BaseOptionsSelector'; import {propTypes, defaultProps} from './optionsSelectorPropTypes'; +import withLocalize from '../withLocalize'; const OptionsSelector = forwardRef((props, ref) => ( Date: Thu, 1 Sep 2022 11:41:29 +0200 Subject: [PATCH 049/123] Don't cast activeReportID to string --- src/libs/OptionsListUtils.js | 4 ++-- src/pages/home/sidebar/SidebarLinks.js | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index d17c4bb4d330..0139a3ad247d 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -349,7 +349,7 @@ function isCurrentUser(userDetails) { * * @param {Object} reports * @param {Object} personalDetails - * @param {Number} activeReportID + * @param {String} activeReportID * @param {Object} options * @returns {Object} * @private @@ -428,7 +428,7 @@ function getOptions(reports, personalDetails, activeReportID, { const shouldFilterReportIfRead = hideReadReports && report.unreadActionCount === 0; const shouldFilterReport = shouldFilterReportIfEmpty || shouldFilterReportIfRead; - if (report.reportID !== activeReportID + if (report.reportID.toString() !== activeReportID.toString() && !report.isPinned && !hasDraftComment && shouldFilterReport diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 3b5c9e8b5521..1b0148e6b53c 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -101,6 +101,8 @@ class SidebarLinks extends React.Component { } getFilteredAndOrderedReports(unfilteredReports) { + return this.getRecentReportsOptionListItems(); + const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); @@ -181,7 +183,7 @@ class SidebarLinks extends React.Component { } getRecentReportsOptionListItems() { - const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); + const activeReportID = this.props.currentlyViewedReportID; const sidebarOptions = OptionsListUtils.getSidebarOptions( this.props.reports, this.props.personalDetails, From 8512aa094133c2155e74ff5a2e295f41a7439ca0 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 11:46:47 +0200 Subject: [PATCH 050/123] Remove all data processing --- src/pages/home/sidebar/SidebarLinks.js | 194 ++++++++++++------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 1b0148e6b53c..41a49e37076b 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -91,71 +91,71 @@ class SidebarLinks extends React.Component { constructor(props) { super(props); - this.activeReport = { - reportID: props.currentlyViewedReportID, - }; - - this.orderedReports = []; - this.priorityMode = props.priorityMode; - this.unreadReports = this.getUnreadReports(props.reports); + // this.activeReport = { + // reportID: props.currentlyViewedReportID, + // }; + // + // this.orderedReports = []; + // this.priorityMode = props.priorityMode; + // this.unreadReports = this.getUnreadReports(props.reports); } getFilteredAndOrderedReports(unfilteredReports) { return this.getRecentReportsOptionListItems(); - const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; - const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); - - // Determines if the active report has a history of draft comments while active. - let hasDraftHistory; - - // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. - // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. - // Otherwise, update the flag from the prop value. - if (isActiveReportSame && this.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { - hasDraftHistory = false; - } else if (isActiveReportSame && this.activeReport.hasDraftHistory) { - hasDraftHistory = true; - } else { - hasDraftHistory = lodashGet(this.props.reports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.hasDraft`, false); - } - - const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; - - // Build the report options we want to show - const recentReports = this.getRecentReportsOptionListItems(); - - // If the order of the reports is different from the last render (or if priority mode is changing) - // then orderedReports is the same as the freshly calculated recentReports. - // If the order of the reports is the same as the last render - // then the data for each report is updated from the data in the new props - // @TODO: not sure why this is necessary and see if it can be removed or do something more intuitive - const orderedReports = this.isReportOrderDifferentThanLastRender(hasDraftHistory) || switchingPriorityModes - ? recentReports - : _.chain(this.orderedReports) - - // To preserve the order of the conversations, we map over the previous ordered reports. - // Then match and replace older reports with the newer report conversations from recentReports - .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) - - // Because we are using map, we have to filter out any undefined reports. This happens if recentReports - // does not have all the conversations in the previous set of orderedReports - .compact() - .value(); - - // Store these pieces of data on the class so that the next time this method is called - // the previous values can be compared against to tell if something changed which would - // cause the reports to be reordered - this.orderedReports = orderedReports; - this.priorityMode = this.props.priorityMode; - this.activeReport = { - reportID: this.props.currentlyViewedReportID, - hasDraftHistory, - lastMessageTimestamp, - }; - this.unreadReports = this.getUnreadReports(unfilteredReports); - - return this.orderedReports; + // const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; + // const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); + // + // // Determines if the active report has a history of draft comments while active. + // let hasDraftHistory; + // + // // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. + // // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. + // // Otherwise, update the flag from the prop value. + // if (isActiveReportSame && this.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { + // hasDraftHistory = false; + // } else if (isActiveReportSame && this.activeReport.hasDraftHistory) { + // hasDraftHistory = true; + // } else { + // hasDraftHistory = lodashGet(this.props.reports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.hasDraft`, false); + // } + // + // const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; + // + // // Build the report options we want to show + // const recentReports = this.getRecentReportsOptionListItems(); + // + // // If the order of the reports is different from the last render (or if priority mode is changing) + // // then orderedReports is the same as the freshly calculated recentReports. + // // If the order of the reports is the same as the last render + // // then the data for each report is updated from the data in the new props + // // @TODO: not sure why this is necessary and see if it can be removed or do something more intuitive + // const orderedReports = this.isReportOrderDifferentThanLastRender(hasDraftHistory) || switchingPriorityModes + // ? recentReports + // : _.chain(this.orderedReports) + // + // // To preserve the order of the conversations, we map over the previous ordered reports. + // // Then match and replace older reports with the newer report conversations from recentReports + // .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) + // + // // Because we are using map, we have to filter out any undefined reports. This happens if recentReports + // // does not have all the conversations in the previous set of orderedReports + // .compact() + // .value(); + // + // // Store these pieces of data on the class so that the next time this method is called + // // the previous values can be compared against to tell if something changed which would + // // cause the reports to be reordered + // this.orderedReports = orderedReports; + // this.priorityMode = this.props.priorityMode; + // this.activeReport = { + // reportID: this.props.currentlyViewedReportID, + // hasDraftHistory, + // lastMessageTimestamp, + // }; + // this.unreadReports = this.getUnreadReports(unfilteredReports); + // + // return this.orderedReports; } /** @@ -171,15 +171,15 @@ class SidebarLinks extends React.Component { * @returns {Object} */ getUnreadReports(reports) { - return _.reduce(reports, (finalUnreadReportMap, report) => { - if (report.unreadActionCount > 0) { - return { - [report.reportID]: true, - ...finalUnreadReportMap, - }; - } - return finalUnreadReportMap; - }, {}); + // return _.reduce(reports, (finalUnreadReportMap, report) => { + // if (report.unreadActionCount > 0) { + // return { + // [report.reportID]: true, + // ...finalUnreadReportMap, + // }; + // } + // return finalUnreadReportMap; + // }, {}); } getRecentReportsOptionListItems() { @@ -196,34 +196,34 @@ class SidebarLinks extends React.Component { } isReportOrderDifferentThanLastRender(hasDraftHistory) { - // If the number of reports changed, then the report order is different - if (this.orderedReports.length !== this.props.reports.length) { - return true; - } - - // If the active report changed, then the report order is different - if (this.activeReport.reportID !== this.props.currentlyViewedReportID) { - return true; - } - - // If the active report has a draft, the order of the reports doesn't change - // because it would cause the reports to reorder when a user starts typing a comment - // and that is an annoying UX (too much stuff jumping around) - if (this.props.currentlyViewedReportID && hasDraftHistory) { - return false; - } - - // If the unread reports have changed, then the report order changes - // because the unread reports need to be placed at the top of the list - // @TODO: This can probably be optimized - const hasNewUnreadReports = _.some(this.props.reports, report => report.unreadActionCount > 0 && !this.unreadReports[report.reportID]); - if (hasNewUnreadReports) { - return true; - } - - // By default, assume that the order of the reports doesn't change - // in order to optimize the rendering - return false; + // // If the number of reports changed, then the report order is different + // if (this.orderedReports.length !== this.props.reports.length) { + // return true; + // } + // + // // If the active report changed, then the report order is different + // if (this.activeReport.reportID !== this.props.currentlyViewedReportID) { + // return true; + // } + // + // // If the active report has a draft, the order of the reports doesn't change + // // because it would cause the reports to reorder when a user starts typing a comment + // // and that is an annoying UX (too much stuff jumping around) + // if (this.props.currentlyViewedReportID && hasDraftHistory) { + // return false; + // } + // + // // If the unread reports have changed, then the report order changes + // // because the unread reports need to be placed at the top of the list + // // @TODO: This can probably be optimized + // const hasNewUnreadReports = _.some(this.props.reports, report => report.unreadActionCount > 0 && !this.unreadReports[report.reportID]); + // if (hasNewUnreadReports) { + // return true; + // } + // + // // By default, assume that the order of the reports doesn't change + // // in order to optimize the rendering + // return false; } showSearchPage() { From ee56ec42828b1440824922a210ba973809be48ae Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 11:53:10 +0200 Subject: [PATCH 051/123] Add report actions to the propTypes --- src/pages/home/sidebar/SidebarLinks.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 41a49e37076b..15d9652bb058 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -26,6 +26,7 @@ import * as App from '../../../libs/actions/App'; import * as ReportUtils from '../../../libs/ReportUtils'; import withCurrentUserPersonalDetails from '../../../components/withCurrentUserPersonalDetails'; import Timing from '../../../libs/actions/Timing'; +import reportActionPropTypes from '../report/reportActionPropTypes'; const propTypes = { /** Toggles the navigation menu open and closed */ @@ -53,6 +54,9 @@ const propTypes = { hasDraft: PropTypes.bool, })), + /** All report actions for all reports */ + reportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), + /** List of users' personal details */ personalDetails: PropTypes.objectOf(participantPropTypes), @@ -79,6 +83,7 @@ const propTypes = { const defaultProps = { reports: {}, + reportActions: {}, personalDetails: {}, currentUserPersonalDetails: { avatar: ReportUtils.getDefaultAvatar(), @@ -100,6 +105,27 @@ class SidebarLinks extends React.Component { // this.unreadReports = this.getUnreadReports(props.reports); } + componentDidUpdate(prevProps) { + if (!_.isEqual(prevProps.reports, this.props.reports)) { + console.log('!!! props.reports') + } + if (!_.isEqual(prevProps.personalDetails, this.props.personalDetails)) { + console.log('!!! props.personalDetails') + } + if (!_.isEqual(prevProps.currentUserPersonalDetails, this.props.currentUserPersonalDetails)) { + console.log('!!! props.currentUserPersonalDetails') + } + if (!_.isEqual(prevProps.currentlyViewedReportID, this.props.currentlyViewedReportID)) { + console.log('!!! props.currentlyViewedReportID') + } + if (!_.isEqual(prevProps.priorityMode, this.props.priorityMode)) { + console.log('!!! props.priorityMode') + } + if (!_.isEqual(prevProps.reportActions, this.props.reportActions)) { + console.log('!!! props.reportActions') + } + } + getFilteredAndOrderedReports(unfilteredReports) { return this.getRecentReportsOptionListItems(); From e7f7b338ad12650602c48add0d309f1d313a3774 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 11:59:35 +0200 Subject: [PATCH 052/123] WIP on profiling what makes things rerender when switching reports --- src/pages/home/sidebar/SidebarLinks.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 15d9652bb058..5017b8b9c25f 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -108,22 +108,45 @@ class SidebarLinks extends React.Component { componentDidUpdate(prevProps) { if (!_.isEqual(prevProps.reports, this.props.reports)) { console.log('!!! props.reports') + return; } if (!_.isEqual(prevProps.personalDetails, this.props.personalDetails)) { console.log('!!! props.personalDetails') + return; } if (!_.isEqual(prevProps.currentUserPersonalDetails, this.props.currentUserPersonalDetails)) { console.log('!!! props.currentUserPersonalDetails') + return; } if (!_.isEqual(prevProps.currentlyViewedReportID, this.props.currentlyViewedReportID)) { console.log('!!! props.currentlyViewedReportID') + return; } if (!_.isEqual(prevProps.priorityMode, this.props.priorityMode)) { console.log('!!! props.priorityMode') + return; } if (!_.isEqual(prevProps.reportActions, this.props.reportActions)) { console.log('!!! props.reportActions') + return; } + if (!_.isEqual(prevProps.isSmallScreenWidth, this.props.isSmallScreenWidth)) { + console.log('!!! props.isSmallScreenWidth') + return; + } + if (!_.isEqual(prevProps.insets, this.props.insets)) { + console.log('!!! props.insets') + return; + } + if (!_.isEqual(prevProps.onAvatarClick, this.props.onAvatarClick)) { + console.log('!!! props.onAvatarClick') + return; + } + if (!_.isEqual(prevProps.onLinkClick, this.props.onLinkClick)) { + console.log('!!! props.onLinkClick') + return; + } + console.log('!!! unknown') } getFilteredAndOrderedReports(unfilteredReports) { From 8057f213b78b3d40ef88086dd01bcb305be9ca2f Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 12:10:42 +0200 Subject: [PATCH 053/123] Fix proptype warning --- src/components/Tooltip/TooltipRenderedOnPageBody.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/Tooltip/TooltipRenderedOnPageBody.js b/src/components/Tooltip/TooltipRenderedOnPageBody.js index d2c40a74b477..3bfcc71fd4c9 100644 --- a/src/components/Tooltip/TooltipRenderedOnPageBody.js +++ b/src/components/Tooltip/TooltipRenderedOnPageBody.js @@ -27,11 +27,11 @@ const propTypes = { /** Any additional amount to manually adjust the horizontal position of the tooltip. A positive value shifts the tooltip to the right, and a negative value shifts it to the left. */ - shiftHorizontal: PropTypes.number.isRequired, + shiftHorizontal: PropTypes.number, /** Any additional amount to manually adjust the vertical position of the tooltip. A positive value shifts the tooltip down, and a negative value shifts it up. */ - shiftVertical: PropTypes.number.isRequired, + shiftVertical: PropTypes.number, /** Text to be shown in the tooltip */ text: PropTypes.string.isRequired, @@ -43,6 +43,11 @@ const propTypes = { numberOfLines: PropTypes.number.isRequired, }; +const defaultProps = { + shiftHorizontal: 0, + shiftVertical: 0, +}; + // Props will change frequently. // On every tooltip hover, we update the position in state which will result in re-rendering. // We also update the state on layout changes which will be triggered often. @@ -132,5 +137,6 @@ class TooltipRenderedOnPageBody extends React.PureComponent { } TooltipRenderedOnPageBody.propTypes = propTypes; +TooltipRenderedOnPageBody.defaultProps = defaultProps; export default TooltipRenderedOnPageBody; From ff4994827b932856e3a4b99aa5e723c4dab6fec9 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 12:51:02 +0200 Subject: [PATCH 054/123] WIP optimizing create option --- src/libs/OptionsListUtils.js | 49 ++++++++++++++------------ src/libs/ReportUtils.js | 7 ++-- src/pages/home/sidebar/SidebarLinks.js | 44 ----------------------- 3 files changed, 31 insertions(+), 69 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0139a3ad247d..bf208198dae4 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -224,29 +224,31 @@ function createOption(logins, personalDetails, report, reportActions = {}, { const isArchivedRoom = ReportUtils.isArchivedRoom(report); const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom || isPolicyExpenseChat; const personalDetail = personalDetailList[0]; - const hasOutstandingIOU = lodashGet(report, 'hasOutstandingIOU', false); - const iouReport = hasOutstandingIOU - ? lodashGet(iouReports, `${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, {}) - : {}; - - const lastActorDetails = report ? _.find(personalDetailList, {login: report.lastActorEmail}) : null; - const lastMessageTextFromReport = ReportUtils.isReportMessageAttachment({text: lodashGet(report, 'lastMessageText', ''), html: lodashGet(report, 'lastMessageHtml', '')}) - ? `[${Localize.translateLocal('common.attachment')}]` - : Str.htmlDecode(lodashGet(report, 'lastMessageText', '')); + const hasOutstandingIOU = report && report.hasOutstandingIOU || false; + const iouReport = hasOutstandingIOU && iouReports[`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`] || {}; + const lastActorDetails = report && personalDetailMap[report.lastActorEmail] || null; + let lastMessageTextFromReport = ''; + if (report) { + if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml})) { + lastMessageTextFromReport = `[${Localize.translateLocal('common.attachment')}]`; + } else { + lastMessageTextFromReport = Str.htmlDecode(report ? report.lastMessageText : ''); + } + } let lastMessageText = report && hasMultipleParticipants && lastActorDetails ? `${lastActorDetails.displayName}: ` : ''; lastMessageText += report ? lastMessageTextFromReport : ''; if (isPolicyExpenseChat && isArchivedRoom) { - const archiveReason = lodashGet(lastReportActions[report.reportID], 'originalMessage.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); + const archiveReason = lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason || CONST.REPORT.ARCHIVE_REASON.DEFAULT; lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, { - displayName: lodashGet(lastActorDetails, 'displayName', report.lastActorEmail), + displayName: archiveReason.displayName || report.lastActorEmail, policyName: ReportUtils.getPolicyName(report, policies), }); } - const tooltipText = ReportUtils.getReportParticipantsTitle(lodashGet(report, ['participants'], [])); + const tooltipText = report && ReportUtils.getReportParticipantsTitle(report.participants || []) || null; const subtitle = ReportUtils.getChatRoomSubtitle(report, policies); const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); let alternateText; @@ -263,9 +265,9 @@ function createOption(logins, personalDetails, report, reportActions = {}, { text: reportName, alternateText, brickRoadIndicator: getBrickRoadIndicatorStatusForReport(report, reportActions), - icons: ReportUtils.getIcons(report, personalDetails, policies, lodashGet(personalDetail, ['avatar'])), + icons: ReportUtils.getIcons(report, personalDetails, policies, personalDetail.avatar), tooltipText, - ownerEmail: lodashGet(report, ['ownerEmail']), + ownerEmail: report ? report.ownerEmail : null, subtitle, participantsList: personalDetailList, @@ -276,14 +278,14 @@ function createOption(logins, personalDetails, report, reportActions = {}, { phoneNumber: !hasMultipleParticipants ? personalDetail.phoneNumber : null, payPalMeAddress: !hasMultipleParticipants ? personalDetail.payPalMeAddress : null, isUnread: report ? report.unreadActionCount > 0 : null, - hasDraftComment: lodashGet(report, 'hasDraft', false), + hasDraftComment: report ? report.hasDraft : false, keyForList: report ? String(report.reportID) : personalDetail.login, searchText: getSearchText(report, reportName, personalDetailList, isChatRoom || isPolicyExpenseChat), - isPinned: lodashGet(report, 'isPinned', false), + isPinned: report ? report.isPinned : false, hasOutstandingIOU, - iouReportID: lodashGet(report, 'iouReportID'), - isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, - iouReportAmount: lodashGet(iouReport, 'total', 0), + iouReportID: report ? report.iouReportID : null, + isIOUReportOwner: iouReport ? iouReport.ownerEmail === currentUserLogin : false, + iouReportAmount: iouReport ? iouReport.total : 0, isChatRoom, isArchivedRoom, shouldShowSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat && !isArchivedRoom, @@ -405,7 +407,7 @@ function getOptions(reports, personalDetails, activeReportID, { const isChatRoom = ReportUtils.isChatRoom(report); const isDefaultRoom = ReportUtils.isDefaultRoom(report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); - const logins = lodashGet(report, ['participants'], []); + const logins = report.participants || []; // Report data can sometimes be incomplete. If we have no logins or reportID then we will skip this entry. const shouldFilterNoParticipants = _.isEmpty(logins) && !isChatRoom && !isDefaultRoom && !isPolicyExpenseChat; @@ -413,9 +415,10 @@ function getOptions(reports, personalDetails, activeReportID, { return; } - const hasDraftComment = lodashGet(report, 'hasDraft', false); - const iouReportOwner = lodashGet(report, 'hasOutstandingIOU', false) - ? lodashGet(iouReports, [`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, 'ownerEmail'], '') + const hasDraftComment = report.hasDraft || false; + const iouReport = report.iouReportID && iouReports[`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`]; + const iouReportOwner = report.hasOutstandingIOU && iouReport + ? iouReport.ownerEmail : ''; const reportContainsIOUDebt = iouReportOwner && iouReportOwner !== currentUserLogin; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 5cef373dd1ad..a058a0bb7bf8 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -244,8 +244,11 @@ function isArchivedRoom(report) { * @returns {String} */ function getPolicyName(report, policies) { - const defaultValue = report.oldPolicyName || Localize.translateLocal('workspace.common.unavailable'); - return lodashGet(policies, [`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'name'], defaultValue); + const policyName = policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] && policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`].name || false; + if (!policyName) { + return report.oldPolicyName || Localize.translateLocal('workspace.common.unavailable'); + } + return policyName; } /** diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 5017b8b9c25f..e35c1e9acce4 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -105,50 +105,6 @@ class SidebarLinks extends React.Component { // this.unreadReports = this.getUnreadReports(props.reports); } - componentDidUpdate(prevProps) { - if (!_.isEqual(prevProps.reports, this.props.reports)) { - console.log('!!! props.reports') - return; - } - if (!_.isEqual(prevProps.personalDetails, this.props.personalDetails)) { - console.log('!!! props.personalDetails') - return; - } - if (!_.isEqual(prevProps.currentUserPersonalDetails, this.props.currentUserPersonalDetails)) { - console.log('!!! props.currentUserPersonalDetails') - return; - } - if (!_.isEqual(prevProps.currentlyViewedReportID, this.props.currentlyViewedReportID)) { - console.log('!!! props.currentlyViewedReportID') - return; - } - if (!_.isEqual(prevProps.priorityMode, this.props.priorityMode)) { - console.log('!!! props.priorityMode') - return; - } - if (!_.isEqual(prevProps.reportActions, this.props.reportActions)) { - console.log('!!! props.reportActions') - return; - } - if (!_.isEqual(prevProps.isSmallScreenWidth, this.props.isSmallScreenWidth)) { - console.log('!!! props.isSmallScreenWidth') - return; - } - if (!_.isEqual(prevProps.insets, this.props.insets)) { - console.log('!!! props.insets') - return; - } - if (!_.isEqual(prevProps.onAvatarClick, this.props.onAvatarClick)) { - console.log('!!! props.onAvatarClick') - return; - } - if (!_.isEqual(prevProps.onLinkClick, this.props.onLinkClick)) { - console.log('!!! props.onLinkClick') - return; - } - console.log('!!! unknown') - } - getFilteredAndOrderedReports(unfilteredReports) { return this.getRecentReportsOptionListItems(); From 7c51a86bfc9dcb992f0add3bc5e2c65eb7d482d6 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 14:16:08 +0200 Subject: [PATCH 055/123] WIP optimizing create option --- src/libs/OptionsListUtils.js | 23 ++++++++++++----------- src/libs/ReportUtils.js | 10 ++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index bf208198dae4..919255e52df2 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -154,28 +154,29 @@ function getParticipantNames(personalDetailList) { * @return {String} */ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolicyExpenseChat) { - const searchTerms = []; + let searchTerms = []; if (!isChatRoomOrPolicyExpenseChat) { - _.each(personalDetailList, (personalDetail) => { - searchTerms.push(personalDetail.displayName); - searchTerms.push(personalDetail.login.replace(/\./g, '')); - }); + for (let i = 0; i < personalDetailList.length; i++) { + const personalDetail = personalDetailList[i]; + searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login.replace(/\./g, '')]); + } } if (report) { - searchTerms.push(...reportName); - searchTerms.push(..._.map(reportName.split(','), name => name.trim())); + Array.prototype.push.apply(searchTerms, reportName.split('')); + Array.prototype.push.apply(searchTerms, reportName.split(',')); if (isChatRoomOrPolicyExpenseChat) { const chatRoomSubtitle = ReportUtils.getChatRoomSubtitle(report, policies); - searchTerms.push(...chatRoomSubtitle); - searchTerms.push(..._.map(chatRoomSubtitle.split(','), name => name.trim())); + Array.prototype.push.apply(searchTerms, chatRoomSubtitle.split('')); + Array.prototype.push.apply(searchTerms, chatRoomSubtitle.split(',')); } else { - searchTerms.push(...report.participants); + searchTerms = searchTerms.concat(report.participants); } } - return _.unique(searchTerms).join(' '); + const finalSearchTerms = _.unique(searchTerms).join(' '); + return finalSearchTerms; } /** diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index a058a0bb7bf8..55aa46ff2ea8 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -498,7 +498,7 @@ function getReportName(report, personalDetailsForParticipants = {}, policies = { } if (isPolicyExpenseChat(report)) { - const reportOwnerPersonalDetails = lodashGet(personalDetailsForParticipants, report.ownerEmail); + const reportOwnerPersonalDetails = personalDetailsForParticipants[report.ownerEmail]; const reportOwnerDisplayName = getDisplayNameForParticipant(reportOwnerPersonalDetails) || report.ownerEmail || report.reportName; formattedName = report.isOwnPolicyExpenseChat ? getPolicyName(report, policies) : reportOwnerDisplayName; } @@ -513,11 +513,9 @@ function getReportName(report, personalDetailsForParticipants = {}, policies = { // Not a room or PolicyExpenseChat, generate title from participants const participants = _.without(lodashGet(report, 'participants', []), sessionEmail); - const displayNamesWithTooltips = getDisplayNamesWithTooltips( - _.isEmpty(personalDetailsForParticipants) ? participants : personalDetailsForParticipants, - participants.length > 1, - ); - return _.map(displayNamesWithTooltips, ({displayName}) => displayName).join(', '); + const isMultipleParticipantReport = participants.length > 1; + const participantsToGetTheNamesOf = _.isEmpty(personalDetailsForParticipants) ? participants : personalDetailsForParticipants; + return _.map(participantsToGetTheNamesOf, participant => getDisplayNameForParticipant(participant, isMultipleParticipantReport)).join(', '); } /** From fd60c45f2d3728f53694b6ff1480ed036be371e2 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 14:34:29 +0200 Subject: [PATCH 056/123] WIP optimizing create option --- src/libs/OptionsListUtils.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 919255e52df2..a4eb25e9d6c8 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -143,6 +143,27 @@ function getParticipantNames(personalDetailList) { return participantNames; } +/** + * A very optimized method to remove unique items from an array. + * Taken from https://stackoverflow.com/a/9229821/9114791 + * + * @param {Array} items + * @returns {Array} + */ +function uniqFast(items) { + const seenItems = {}; + const result = []; + let j = 0; + for (let i = 0; i < items.length; i++) { + const item = items[i]; + if (seenItems[item] !== 1) { + seenItems[item] = 1; + result[j++] = item; + } + } + return result; +} + /** * Returns a string with all relevant search terms. * Default should be serachable by policy/domain name but not by participants. @@ -175,7 +196,7 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic } } - const finalSearchTerms = _.unique(searchTerms).join(' '); + const finalSearchTerms = uniqFast(searchTerms).join(' '); return finalSearchTerms; } From 9fad973fa9a0130be828a3bfbaddddeaf4debf6f Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 15:29:51 +0200 Subject: [PATCH 057/123] Finished optimizing createOption --- src/libs/OptionsListUtils.js | 157 +++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 61 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index a4eb25e9d6c8..6351b6165bac 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -239,80 +239,115 @@ function createOption(logins, personalDetails, report, reportActions = {}, { showChatPreviewLine = false, forcePolicyNamePreview = false, }) { - const isChatRoom = ReportUtils.isChatRoom(report); - const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + const result = { + text: null, + alternateText: null, + brickRoadIndicator: null, + icons: null, + tooltipText: null, + ownerEmail: null, + subtitle: null, + participantsList: null, + login: null, + reportID: null, + phoneNumber: null, + payPalMeAddress: null, + isUnread: null, + hasDraftComment: false, + keyForList: null, + searchText: null, + isPinned: false, + hasOutstandingIOU: false, + iouReportID: null, + isIOUReportOwner: null, + iouReportAmount: 0, + isChatRoom: false, + isArchivedRoom: false, + shouldShowSubscript: false, + isPolicyExpenseChat: false, + }; + const personalDetailMap = getPersonalDetailsForLogins(logins, personalDetails); const personalDetailList = _.values(personalDetailMap); - const isArchivedRoom = ReportUtils.isArchivedRoom(report); - const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom || isPolicyExpenseChat; const personalDetail = personalDetailList[0]; - const hasOutstandingIOU = report && report.hasOutstandingIOU || false; - const iouReport = hasOutstandingIOU && iouReports[`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`] || {}; - const lastActorDetails = report && personalDetailMap[report.lastActorEmail] || null; - let lastMessageTextFromReport = ''; + let hasMultipleParticipants = personalDetailList.length > 1; + let subtitle; + if (report) { + result.isChatRoom = ReportUtils.isChatRoom(report); + result.isArchivedRoom = ReportUtils.isArchivedRoom(report); + result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + result.shouldShowSubscript = result.isPolicyExpenseChat && !report.isOwnPolicyExpenseChat && !result.isArchivedRoom; + result.brickRoadIndicator = getBrickRoadIndicatorStatusForReport(report, reportActions); + result.ownerEmail = report.ownerEmail; + result.reportID = report.reportID; + result.isUnread = report.unreadActionCount > 0; + result.hasDraftComment = report.hasDraft; + result.isPinned = report.isPinned; + result.iouReportID = report.iouReportID; + result.keyForList = String(report.reportID); + result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participants || []); + result.hasOutstandingIOU = report.hasOutstandingIOU; + + hasMultipleParticipants = personalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat; + subtitle = ReportUtils.getChatRoomSubtitle(report, policies); + + let lastMessageTextFromReport = ''; if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml})) { lastMessageTextFromReport = `[${Localize.translateLocal('common.attachment')}]`; } else { lastMessageTextFromReport = Str.htmlDecode(report ? report.lastMessageText : ''); } + + const lastActorDetails = personalDetailMap[report.lastActorEmail] || null; + let lastMessageText = hasMultipleParticipants && lastActorDetails + ? `${lastActorDetails.displayName}: ` + : ''; + lastMessageText += report ? lastMessageTextFromReport : ''; + + if (result.isPolicyExpenseChat && result.isArchivedRoom) { + const archiveReason = lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason || CONST.REPORT.ARCHIVE_REASON.DEFAULT; + lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, { + displayName: archiveReason.displayName || report.lastActorEmail, + policyName: ReportUtils.getPolicyName(report, policies), + }); + } + + if (result.isChatRoom || result.isPolicyExpenseChat) { + result.alternateText = (showChatPreviewLine && !forcePolicyNamePreview && lastMessageText) + ? lastMessageText + : subtitle; + } else { + result.alternateText = (showChatPreviewLine && lastMessageText) + ? lastMessageText + : Str.removeSMSDomain(personalDetail.login); + } + } else { + result.keyForList = personalDetail.login; } - let lastMessageText = report && hasMultipleParticipants && lastActorDetails - ? `${lastActorDetails.displayName}: ` - : ''; - lastMessageText += report ? lastMessageTextFromReport : ''; - - if (isPolicyExpenseChat && isArchivedRoom) { - const archiveReason = lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason || CONST.REPORT.ARCHIVE_REASON.DEFAULT; - lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, { - displayName: archiveReason.displayName || report.lastActorEmail, - policyName: ReportUtils.getPolicyName(report, policies), - }); + + if (result.hasOutstandingIOU) { + const iouReport = iouReports[`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`] || null; + if (iouReport) { + result.isIOUReportOwner = iouReport.ownerEmail === currentUserLogin; + result.iouReportAmount = iouReport.total; + } } - const tooltipText = report && ReportUtils.getReportParticipantsTitle(report.participants || []) || null; - const subtitle = ReportUtils.getChatRoomSubtitle(report, policies); - const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); - let alternateText; - if (isChatRoom || isPolicyExpenseChat) { - alternateText = (showChatPreviewLine && !forcePolicyNamePreview && lastMessageText) - ? lastMessageText - : subtitle; - } else { - alternateText = (showChatPreviewLine && lastMessageText) - ? lastMessageText - : Str.removeSMSDomain(personalDetail.login); + if (!hasMultipleParticipants) { + result.login = personalDetail.login; + result.phoneNumber = personalDetail.phoneNumber; + result.payPalMeAddress = personalDetail.payPalMeAddress; } - return { - text: reportName, - alternateText, - brickRoadIndicator: getBrickRoadIndicatorStatusForReport(report, reportActions), - icons: ReportUtils.getIcons(report, personalDetails, policies, personalDetail.avatar), - tooltipText, - ownerEmail: report ? report.ownerEmail : null, - subtitle, - participantsList: personalDetailList, - - // It doesn't make sense to provide a login in the case of a report with multiple participants since - // there isn't any one single login to refer to for a report. - login: !hasMultipleParticipants ? personalDetail.login : null, - reportID: report ? report.reportID : null, - phoneNumber: !hasMultipleParticipants ? personalDetail.phoneNumber : null, - payPalMeAddress: !hasMultipleParticipants ? personalDetail.payPalMeAddress : null, - isUnread: report ? report.unreadActionCount > 0 : null, - hasDraftComment: report ? report.hasDraft : false, - keyForList: report ? String(report.reportID) : personalDetail.login, - searchText: getSearchText(report, reportName, personalDetailList, isChatRoom || isPolicyExpenseChat), - isPinned: report ? report.isPinned : false, - hasOutstandingIOU, - iouReportID: report ? report.iouReportID : null, - isIOUReportOwner: iouReport ? iouReport.ownerEmail === currentUserLogin : false, - iouReportAmount: iouReport ? iouReport.total : 0, - isChatRoom, - isArchivedRoom, - shouldShowSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat && !isArchivedRoom, - isPolicyExpenseChat, - }; + + const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); + result.text = reportName; + result.subtitle = subtitle; + result.participantsList = personalDetailList; + result.icons = ReportUtils.getIcons(report, personalDetails, policies, personalDetail.avatar); + result.searchText = getSearchText(report, reportName, personalDetailList, result.isChatRoom || result.isPolicyExpenseChat); + + return result; } /** From ceb2ea954cec4810eab77506a8794a146d9080cf Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 15:32:11 +0200 Subject: [PATCH 058/123] Remove memoization and imports --- src/libs/OptionsListUtils.js | 5 +---- src/pages/home/sidebar/SidebarLinks.js | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 6351b6165bac..80f726988832 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -3,7 +3,6 @@ import _ from 'underscore'; import Onyx from 'react-native-onyx'; import lodashGet from 'lodash/get'; import lodashOrderBy from 'lodash/orderBy'; -import memoizeOne from 'memoize-one'; import Str from 'expensify-common/lib/str'; import ONYXKEYS from '../ONYXKEYS'; import CONST from '../CONST'; @@ -817,7 +816,7 @@ function getMemberInviteOptions( * @param {Object} reportActions * @returns {Object} */ -function calculateSidebarOptions(reports, personalDetails, activeReportID, priorityMode, betas, reportActions) { +function getSidebarOptions(reports, personalDetails, activeReportID, priorityMode, betas, reportActions) { let sideBarOptions = { prioritizeIOUDebts: true, prioritizeReportsWithDraftComments: true, @@ -841,8 +840,6 @@ function calculateSidebarOptions(reports, personalDetails, activeReportID, prior }); } -const getSidebarOptions = memoizeOne(calculateSidebarOptions); - /** * Helper method that returns the text to be used for the header's message and title (if any) * diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index e35c1e9acce4..fa202bbc36c2 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -3,7 +3,6 @@ import {View, TouchableOpacity} from 'react-native'; import _ from 'underscore'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; import styles from '../../../styles/styles'; import * as StyleUtils from '../../../styles/StyleUtils'; import ONYXKEYS from '../../../ONYXKEYS'; From 2ef3622b00336316e72acf4789ab8424079308dd Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 16:10:08 +0200 Subject: [PATCH 059/123] Memoize getting the option list items --- src/pages/home/sidebar/SidebarLinks.js | 149 +++---------------------- 1 file changed, 18 insertions(+), 131 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index fa202bbc36c2..f4bdda7ec179 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -3,6 +3,7 @@ import {View, TouchableOpacity} from 'react-native'; import _ from 'underscore'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import memoizeOne from 'memoize-one'; import styles from '../../../styles/styles'; import * as StyleUtils from '../../../styles/StyleUtils'; import ONYXKEYS from '../../../ONYXKEYS'; @@ -94,142 +95,21 @@ const defaultProps = { class SidebarLinks extends React.Component { constructor(props) { super(props); - - // this.activeReport = { - // reportID: props.currentlyViewedReportID, - // }; - // - // this.orderedReports = []; - // this.priorityMode = props.priorityMode; - // this.unreadReports = this.getUnreadReports(props.reports); - } - - getFilteredAndOrderedReports(unfilteredReports) { - return this.getRecentReportsOptionListItems(); - - // const isActiveReportSame = this.activeReport.reportID === this.props.currentlyViewedReportID; - // const lastMessageTimestamp = lodashGet(unfilteredReports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.lastMessageTimestamp`, 0); - // - // // Determines if the active report has a history of draft comments while active. - // let hasDraftHistory; - // - // // If the active report has not changed and the message has been sent, set the draft history flag to false so LHN can reorder. - // // Otherwise, if the active report has not changed and the flag was previously true, preserve the state so LHN cannot reorder. - // // Otherwise, update the flag from the prop value. - // if (isActiveReportSame && this.activeReport.lastMessageTimestamp !== lastMessageTimestamp) { - // hasDraftHistory = false; - // } else if (isActiveReportSame && this.activeReport.hasDraftHistory) { - // hasDraftHistory = true; - // } else { - // hasDraftHistory = lodashGet(this.props.reports, `${ONYXKEYS.COLLECTION.REPORT}${this.props.currentlyViewedReportID}.hasDraft`, false); - // } - // - // const switchingPriorityModes = this.props.priorityMode !== this.priorityMode; - // - // // Build the report options we want to show - // const recentReports = this.getRecentReportsOptionListItems(); - // - // // If the order of the reports is different from the last render (or if priority mode is changing) - // // then orderedReports is the same as the freshly calculated recentReports. - // // If the order of the reports is the same as the last render - // // then the data for each report is updated from the data in the new props - // // @TODO: not sure why this is necessary and see if it can be removed or do something more intuitive - // const orderedReports = this.isReportOrderDifferentThanLastRender(hasDraftHistory) || switchingPriorityModes - // ? recentReports - // : _.chain(this.orderedReports) - // - // // To preserve the order of the conversations, we map over the previous ordered reports. - // // Then match and replace older reports with the newer report conversations from recentReports - // .map(orderedReport => _.find(recentReports, recentReport => orderedReport.reportID === recentReport.reportID)) - // - // // Because we are using map, we have to filter out any undefined reports. This happens if recentReports - // // does not have all the conversations in the previous set of orderedReports - // .compact() - // .value(); - // - // // Store these pieces of data on the class so that the next time this method is called - // // the previous values can be compared against to tell if something changed which would - // // cause the reports to be reordered - // this.orderedReports = orderedReports; - // this.priorityMode = this.props.priorityMode; - // this.activeReport = { - // reportID: this.props.currentlyViewedReportID, - // hasDraftHistory, - // lastMessageTimestamp, - // }; - // this.unreadReports = this.getUnreadReports(unfilteredReports); - // - // return this.orderedReports; - } - - /** - * Create a map of unread reports that looks like this: - * { - * 1: true, - * 2: true, - * } - * This is so that when the new props are compared to the old props, it's - * fast to look up if there are any new unread reports. - * - * @param {Object[]} reports - * @returns {Object} - */ - getUnreadReports(reports) { - // return _.reduce(reports, (finalUnreadReportMap, report) => { - // if (report.unreadActionCount > 0) { - // return { - // [report.reportID]: true, - // ...finalUnreadReportMap, - // }; - // } - // return finalUnreadReportMap; - // }, {}); + this.getRecentReportsOptionListItems = memoizeOne(this.getRecentReportsOptionListItems.bind(this)); } - getRecentReportsOptionListItems() { - const activeReportID = this.props.currentlyViewedReportID; + getRecentReportsOptionListItems(activeReportID, priorityMode, unorderedReports, personalDetails, betas, reportActions) { const sidebarOptions = OptionsListUtils.getSidebarOptions( - this.props.reports, - this.props.personalDetails, + unorderedReports, + personalDetails, activeReportID, - this.props.priorityMode, - this.props.betas, - this.props.reportActions, + priorityMode, + betas, + reportActions, ); return sidebarOptions.recentReports; } - isReportOrderDifferentThanLastRender(hasDraftHistory) { - // // If the number of reports changed, then the report order is different - // if (this.orderedReports.length !== this.props.reports.length) { - // return true; - // } - // - // // If the active report changed, then the report order is different - // if (this.activeReport.reportID !== this.props.currentlyViewedReportID) { - // return true; - // } - // - // // If the active report has a draft, the order of the reports doesn't change - // // because it would cause the reports to reorder when a user starts typing a comment - // // and that is an annoying UX (too much stuff jumping around) - // if (this.props.currentlyViewedReportID && hasDraftHistory) { - // return false; - // } - // - // // If the unread reports have changed, then the report order changes - // // because the unread reports need to be placed at the top of the list - // // @TODO: This can probably be optimized - // const hasNewUnreadReports = _.some(this.props.reports, report => report.unreadActionCount > 0 && !this.unreadReports[report.reportID]); - // if (hasNewUnreadReports) { - // return true; - // } - // - // // By default, assume that the order of the reports doesn't change - // // in order to optimize the rendering - // return false; - } - showSearchPage() { Navigation.navigate(ROUTES.SEARCH); } @@ -240,12 +120,19 @@ class SidebarLinks extends React.Component { return null; } - const activeReportID = parseInt(this.props.currentlyViewedReportID, 10); Timing.start(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); + const optionListItems = this.getRecentReportsOptionListItems( + this.props.currentlyViewedReportID, + this.props.priorityMode, + this.props.reports, + this.props.personalDetails, + this.props.betas, + this.props.reportActions, + ); const sections = [{ title: '', indexOffset: 0, - data: this.getFilteredAndOrderedReports(this.props.reports), + data: optionListItems, shouldShow: true, }]; Timing.end(CONST.TIMING.SIDEBAR_LINKS_FILTER_REPORTS); @@ -297,7 +184,7 @@ class SidebarLinks extends React.Component { ]} sections={sections} focusedIndex={_.findIndex(this.orderedReports, ( - option => option.reportID === activeReportID + option => option.reportID.toString() === this.props.currentlyViewedReportID.toString() ))} onSelectRow={(option) => { Navigation.navigate(ROUTES.getReportRoute(option.reportID)); From 9ceb909b0c8c13553d4ad9d39d608af513cfa141 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 1 Sep 2022 16:30:05 +0200 Subject: [PATCH 060/123] Fix lint issues --- src/libs/OptionsListUtils.js | 3 ++- src/libs/ReportUtils.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 80f726988832..a1e5027bf9fd 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -305,7 +305,8 @@ function createOption(logins, personalDetails, report, reportActions = {}, { lastMessageText += report ? lastMessageTextFromReport : ''; if (result.isPolicyExpenseChat && result.isArchivedRoom) { - const archiveReason = lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason || CONST.REPORT.ARCHIVE_REASON.DEFAULT; + const archiveReason = (lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason) + || CONST.REPORT.ARCHIVE_REASON.DEFAULT; lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, { displayName: archiveReason.displayName || report.lastActorEmail, policyName: ReportUtils.getPolicyName(report, policies), diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 55aa46ff2ea8..ac36f15649a3 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -244,7 +244,7 @@ function isArchivedRoom(report) { * @returns {String} */ function getPolicyName(report, policies) { - const policyName = policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] && policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`].name || false; + const policyName = (policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] && policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`].name) || false; if (!policyName) { return report.oldPolicyName || Localize.translateLocal('workspace.common.unavailable'); } From 6eb03cf72146f02bd06d7c2367f983d0c9a1d4bd Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 09:36:20 +0100 Subject: [PATCH 061/123] Remove unused HOC --- src/components/OptionsSelector/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/OptionsSelector/index.js b/src/components/OptionsSelector/index.js index eea20274561e..9f7c924e427f 100644 --- a/src/components/OptionsSelector/index.js +++ b/src/components/OptionsSelector/index.js @@ -11,4 +11,4 @@ const OptionsSelector = forwardRef((props, ref) => ( OptionsSelector.displayName = 'OptionsSelector'; -export default withLocalize(OptionsSelector); +export default OptionsSelector; From 42ece5b3f399e8d2d563768f7ef0af1326d78dbf Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 09:50:36 +0100 Subject: [PATCH 062/123] Add error boundary to rendered component in tests --- tests/unit/LHNOrderTest.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/unit/LHNOrderTest.js b/tests/unit/LHNOrderTest.js index 3e411f7ca251..e085d6001289 100644 --- a/tests/unit/LHNOrderTest.js +++ b/tests/unit/LHNOrderTest.js @@ -158,18 +158,37 @@ Onyx.init({ }); function getDefaultRenderedSidebarLinks() { + class ErrorBoundary extends React.Component { + // Error boundaries have to implement this method. It's for providing a fallback UI, but + // we don't need that for unit testing, so this is basically a no-op. + static getDerivedStateFromError(error) { + return {error}; + } + + componentDidCatch(error, errorInfo) { + console.error(error, errorInfo); + } + + render() { + // eslint-disable-next-line react/prop-types + return this.props.children; + } + } + // Wrap the SideBarLinks inside of LocaleContextProvider so that all the locale props // are passed to the component. If this is not done, then all the locale props are missing // and there are a lot of render warnings. It needs to be done like this because normally in // our app (App.js) is when the react application is wrapped in the context providers return render(( - {}} - insets={fakeInsets} - onAvatarClick={() => {}} - isSmallScreenWidth={false} - /> + + {}} + insets={fakeInsets} + onAvatarClick={() => {}} + isSmallScreenWidth={false} + /> + )); } From 66d147d3987747860caf2eaf5b32634dd66a4b01 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 16:20:35 +0100 Subject: [PATCH 063/123] Add an early return to protect against null reports --- src/libs/OptionsListUtils.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index e3505ad53a67..fb969a157c48 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -462,6 +462,9 @@ function getOptions(reports, personalDetails, activeReportID, { const allReportOptions = []; _.each(orderedReports, (report) => { + if (!report) { + return null; + } const isChatRoom = ReportUtils.isChatRoom(report); const isDefaultRoom = ReportUtils.isDefaultRoom(report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); @@ -469,7 +472,7 @@ function getOptions(reports, personalDetails, activeReportID, { // Report data can sometimes be incomplete. If we have no logins or reportID then we will skip this entry. const shouldFilterNoParticipants = _.isEmpty(logins) && !isChatRoom && !isDefaultRoom && !isPolicyExpenseChat; - if (!report || !report.reportID || shouldFilterNoParticipants) { + if (!report.reportID || shouldFilterNoParticipants) { return; } From d03e6fbed7c5720cac8c6d7a569ba50af6611064 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 16:29:03 +0100 Subject: [PATCH 064/123] Add a method comment about performance --- src/libs/OptionsListUtils.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index fb969a157c48..e2a0567cdd4b 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -167,6 +167,10 @@ function uniqFast(items) { * Returns a string with all relevant search terms. * Default should be serachable by policy/domain name but not by participants. * + * This method must be incredibly performant. It was found to be a big performance bottleneck + * when dealing with accounts that have thousands of reports. For loops are more efficient than _.each + * Array.prototype.push.apply is faster than using the spread operator, and concat() is faster than push(). + * * @param {Object} report * @param {String} reportName * @param {Array} personalDetailList From 47aa0b8f3ab00f50c1381aad0d9b4221f7da037f Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 16:31:37 +0100 Subject: [PATCH 065/123] Keep policy name as a string and simplify the return --- src/libs/ReportUtils.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 53e80e0ab32f..45d317e355b4 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -246,11 +246,11 @@ function isArchivedRoom(report) { * @returns {String} */ function getPolicyName(report, policies) { - const policyName = (policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] && policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`].name) || false; - if (!policyName) { - return report.oldPolicyName || Localize.translateLocal('workspace.common.unavailable'); - } - return policyName; + const policyName = ( + policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] + && policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`].name + ) || ''; + return policyName || report.oldPolicyName || Localize.translateLocal('workspace.common.unavailable'); } /** From 99532c20083b3d648c715a978826f727fbd6b60f Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 16:59:45 +0100 Subject: [PATCH 066/123] Simplify the return statement --- src/libs/OptionsListUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index e2a0567cdd4b..a4c4d93642a5 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -199,8 +199,7 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic } } - const finalSearchTerms = uniqFast(searchTerms).join(' '); - return finalSearchTerms; + return uniqFast(searchTerms).join(' '); } /** @@ -259,6 +258,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { hasDraftComment: false, keyForList: null, searchText: null, + isDefaultRoom: false, isPinned: false, hasOutstandingIOU: false, iouReportID: null, From 988e7c6d3b40e6068fcc2a30922b718f565b27c2 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 5 Sep 2022 17:20:16 +0100 Subject: [PATCH 067/123] Fix the check for unread reports --- src/libs/OptionsListUtils.js | 2 +- src/libs/ReportUtils.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index a4c4d93642a5..96e9eb92d895 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -285,7 +285,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { result.brickRoadIndicator = getBrickRoadIndicatorStatusForReport(report, reportActions); result.ownerEmail = report.ownerEmail; result.reportID = report.reportID; - result.isUnread = report.unreadActionCount > 0; + result.isUnread = ReportUtils.isUnread(report); result.hasDraftComment = report.hasDraft; result.isPinned = report.isPinned; result.iouReportID = report.iouReportID; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 45d317e355b4..4ce8ecf45def 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -626,8 +626,8 @@ function buildOptimisticIOUReportAction(type, amount, comment, paymentType = '', * @returns {Boolean} */ function isUnread(report) { - const lastReadSequenceNumber = lodashGet(report, 'lastReadSequenceNumber', 0); - const maxSequenceNumber = lodashGet(report, 'maxSequenceNumber', 0); + const lastReadSequenceNumber = report.lastReadSequenceNumber || 0; + const maxSequenceNumber = report.maxSequenceNumber || 0; return lastReadSequenceNumber < maxSequenceNumber; } From 74f1dc6ebe4f9f9bc04e0afc4fc1d16f821504dd Mon Sep 17 00:00:00 2001 From: Varsha Date: Mon, 5 Sep 2022 21:58:08 +0530 Subject: [PATCH 068/123] center loading indicator --- src/pages/AddPersonalBankAccountPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/AddPersonalBankAccountPage.js b/src/pages/AddPersonalBankAccountPage.js index dc5245702c88..248811ba7348 100644 --- a/src/pages/AddPersonalBankAccountPage.js +++ b/src/pages/AddPersonalBankAccountPage.js @@ -164,7 +164,7 @@ class AddPersonalBankAccountPage extends React.Component { ) : ( - + { this.setState({ From 8db975937f8768348fc57b6d58a40c1763a67319 Mon Sep 17 00:00:00 2001 From: luan <103875612+b1tjoy@users.noreply.github.com> Date: Tue, 6 Sep 2022 17:40:23 +0800 Subject: [PATCH 069/123] upgrade RNGestureHandler to 2.6.0 in Podfile.lock --- ios/Podfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6d84eedf9a97..9113be1cf99a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -582,7 +582,7 @@ PODS: - Firebase/Performance (= 8.8.0) - React-Core - RNFBApp - - RNGestureHandler (2.5.0): + - RNGestureHandler (2.6.0): - React-Core - RNPermissions (3.6.1): - React-Core @@ -1000,7 +1000,7 @@ SPEC CHECKSUMS: RNFBApp: 729c0666395b1953198dc4a1ec6deb8fbe1c302e RNFBCrashlytics: 2061ca863e8e2fa1aae9b12477d7dfa8e88ca0f9 RNFBPerf: 389914cda4000fe0d996a752532a591132cbf3f9 - RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50 + RNGestureHandler: 920eb17f5b1e15dae6e5ed1904045f8f90e0b11e RNPermissions: dcdb7b99796bbeda6975a6e79ad519c41b251b1c RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c RNReanimated: 2cf7451318bb9cc430abeec8d67693f9cf4e039c From 403632528ff64bf7ff00aa4349dbd1d287f99bea Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 6 Sep 2022 05:01:37 -0600 Subject: [PATCH 070/123] Update src/libs/OptionsListUtils.js Co-authored-by: Marc Glasser --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 96e9eb92d895..d9f0c658cfaf 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -467,7 +467,7 @@ function getOptions(reports, personalDetails, activeReportID, { const allReportOptions = []; _.each(orderedReports, (report) => { if (!report) { - return null; + return; } const isChatRoom = ReportUtils.isChatRoom(report); const isDefaultRoom = ReportUtils.isDefaultRoom(report); From 6c855239f1efbc7ab9a079c177292309297c2ca1 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 6 Sep 2022 15:13:56 +0100 Subject: [PATCH 071/123] rm deprecated validateBankAccount --- src/libs/actions/BankAccounts.js | 1 - .../actions/ReimbursementAccount/index.js | 2 - .../validateBankAccount.js | 54 ------------------- src/libs/deprecatedAPI.js | 6 --- 4 files changed, 63 deletions(-) delete mode 100644 src/libs/actions/ReimbursementAccount/validateBankAccount.js diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 43b8b7d2c056..c597429a2614 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -13,7 +13,6 @@ export { setBankAccountFormValidationErrors, resetReimbursementAccount, resetFreePlanBankAccount, - validateBankAccount, hideBankAccountErrors, setWorkspaceIDForReimbursementAccount, setBankAccountSubStep, diff --git a/src/libs/actions/ReimbursementAccount/index.js b/src/libs/actions/ReimbursementAccount/index.js index 40481a15a06a..50bbae591692 100644 --- a/src/libs/actions/ReimbursementAccount/index.js +++ b/src/libs/actions/ReimbursementAccount/index.js @@ -1,6 +1,5 @@ import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../../ONYXKEYS'; -import validateBankAccount from './validateBankAccount'; import setupWithdrawalAccount from './setupWithdrawalAccount'; import fetchFreePlanVerifiedBankAccount from './fetchFreePlanVerifiedBankAccount'; import resetFreePlanBankAccount from './resetFreePlanBankAccount'; @@ -57,7 +56,6 @@ export { setupWithdrawalAccount, fetchFreePlanVerifiedBankAccount, resetFreePlanBankAccount, - validateBankAccount, setBankAccountSubStep, hideBankAccountErrors, setWorkspaceIDForReimbursementAccount, diff --git a/src/libs/actions/ReimbursementAccount/validateBankAccount.js b/src/libs/actions/ReimbursementAccount/validateBankAccount.js deleted file mode 100644 index ace044899289..000000000000 --- a/src/libs/actions/ReimbursementAccount/validateBankAccount.js +++ /dev/null @@ -1,54 +0,0 @@ -import Onyx from 'react-native-onyx'; -import ONYXKEYS from '../../../ONYXKEYS'; -import * as DeprecatedAPI from '../../deprecatedAPI'; -import BankAccount from '../../models/BankAccount'; -import CONST from '../../../CONST'; -import * as Localize from '../../Localize'; -import * as errors from './errors'; - -/** - * @param {Number} bankAccountID - * @param {String} validateCode - */ -function validateBankAccount(bankAccountID, validateCode) { - Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {loading: true}); - - DeprecatedAPI.BankAccount_Validate({bankAccountID, validateCode}) - .then((response) => { - if (response.jsonCode === 200) { - Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, null); - DeprecatedAPI.User_IsUsingExpensifyCard() - .then(({isUsingExpensifyCard}) => { - const reimbursementAccount = { - loading: false, - error: '', - achData: {state: BankAccount.STATE.OPEN}, - }; - - reimbursementAccount.achData.currentStep = CONST.BANK_ACCOUNT.STEP.ENABLE; - Onyx.merge(ONYXKEYS.USER, {isUsingExpensifyCard}); - Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, reimbursementAccount); - }); - return; - } - - // User has input the validate code incorrectly many times so we will return early in this case and not let them enter the amounts again. - if (response.message === CONST.BANK_ACCOUNT.ERROR.MAX_VALIDATION_ATTEMPTS_REACHED) { - Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {loading: false, maxAttemptsReached: true}); - return; - } - - // If the validation amounts entered were incorrect, show specific error - if (response.message === CONST.BANK_ACCOUNT.ERROR.INCORRECT_VALIDATION_AMOUNTS) { - errors.showBankAccountErrorModal(Localize.translateLocal('bankAccount.error.validationAmounts')); - Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {loading: false}); - return; - } - - // We are generically showing any other backend errors that might pop up in the validate step - errors.showBankAccountErrorModal(response.message); - Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {loading: false}); - }); -} - -export default validateBankAccount; diff --git a/src/libs/deprecatedAPI.js b/src/libs/deprecatedAPI.js index 26a25ff2c9e7..ee971b76b0ba 100644 --- a/src/libs/deprecatedAPI.js +++ b/src/libs/deprecatedAPI.js @@ -412,12 +412,6 @@ function Policy_Employees_Merge(parameters) { return Network.post(commandName, {...parameters, returnPersonalDetails: true}); } -function BankAccount_Validate(parameters) { - const commandName = 'ValidateBankAccount'; - requireParameters(['bankAccountID', 'validateCode'], parameters, commandName); - return Network.post(commandName, parameters, CONST.NETWORK.METHOD.POST); -} - /** * @param {*} parameters * @returns {Promise} From d46606ed1a61c1845faa5da1fab89a295d734204 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 6 Sep 2022 15:20:48 +0100 Subject: [PATCH 072/123] create new api method --- src/CONST.js | 1 + src/libs/actions/BankAccounts.js | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/CONST.js b/src/CONST.js index a575a51cf1c6..867b719bdb5d 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -97,6 +97,7 @@ const CONST = { STATE: { VERIFYING: 'VERIFYING', PENDING: 'PENDING', + OPEN: 'OPEN', }, MAX_LENGTH: { SSN: 4, diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index c597429a2614..eb85cb28f20a 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -113,9 +113,43 @@ function deletePaymentBankAccount(bankAccountID) { }); } +/** + * @param {Number} bankAccountID + * @param {String} validateCode + */ +function validateBankAccount(bankAccountID, validateCode) { + API.write('ValidateBankAccountWithTransactions', { + bankAccountID, + validateCode, + }, { + optimisticData: [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + errors: null, + achData: { + state: CONST.BANK_ACCOUNT.STATE.OPEN, + currentStep: CONST.BANK_ACCOUNT.STEP.ENABLE, + }, + }, + }], + failureData: [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + achData: { + state: CONST.BANK_ACCOUNT.STATE.VERIFYING, + currentStep: CONST.BANK_ACCOUNT.STEP.VALIDATION, + }, + }, + }], + }); +} + export { addPersonalBankAccount, deletePaymentBankAccount, clearPersonalBankAccount, clearPlaid, + validateBankAccount, }; From 513ac116c03b584acc74e33622702c396fe1aa8d Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 6 Sep 2022 15:35:22 +0100 Subject: [PATCH 073/123] fix lint --- src/libs/deprecatedAPI.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/deprecatedAPI.js b/src/libs/deprecatedAPI.js index ee971b76b0ba..1604ccb27765 100644 --- a/src/libs/deprecatedAPI.js +++ b/src/libs/deprecatedAPI.js @@ -597,7 +597,6 @@ function GetStatementPDF(parameters) { export { BankAccount_SetupWithdrawal, - BankAccount_Validate, ChangePassword, CreateChatReport, CreateLogin, From 85b2f50d5230e6685ea81835cb484551cf58c47b Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 6 Sep 2022 15:52:21 +0100 Subject: [PATCH 074/123] fix lint --- src/pages/ReimbursementAccount/ValidationStep.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/ReimbursementAccount/ValidationStep.js b/src/pages/ReimbursementAccount/ValidationStep.js index 4a827780018c..e78aafee36d8 100644 --- a/src/pages/ReimbursementAccount/ValidationStep.js +++ b/src/pages/ReimbursementAccount/ValidationStep.js @@ -27,6 +27,7 @@ import Section from '../../components/Section'; import CONST from '../../CONST'; import Button from '../../components/Button'; import MenuItem from '../../components/MenuItem'; +import OfflineWithFeedback from '../../components/OfflineWithFeedback'; const propTypes = { ...withLocalizePropTypes, @@ -175,6 +176,10 @@ class ValidationStep extends React.Component { shouldShowBackButton shouldShowStepCounter={!isVerifying} /> + {/* */} {maxAttemptsReached && ( From 2857702c458d9f660ccdba5a7cb8229d91b55c4f Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 6 Sep 2022 15:53:17 +0100 Subject: [PATCH 075/123] rm unused component --- src/pages/ReimbursementAccount/ValidationStep.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/pages/ReimbursementAccount/ValidationStep.js b/src/pages/ReimbursementAccount/ValidationStep.js index e78aafee36d8..4a827780018c 100644 --- a/src/pages/ReimbursementAccount/ValidationStep.js +++ b/src/pages/ReimbursementAccount/ValidationStep.js @@ -27,7 +27,6 @@ import Section from '../../components/Section'; import CONST from '../../CONST'; import Button from '../../components/Button'; import MenuItem from '../../components/MenuItem'; -import OfflineWithFeedback from '../../components/OfflineWithFeedback'; const propTypes = { ...withLocalizePropTypes, @@ -176,10 +175,6 @@ class ValidationStep extends React.Component { shouldShowBackButton shouldShowStepCounter={!isVerifying} /> - {/* */} {maxAttemptsReached && ( From f6b88c55124202c9b0f50d275866c1cb46ebd15e Mon Sep 17 00:00:00 2001 From: Varsha Date: Wed, 7 Sep 2022 00:02:34 +0530 Subject: [PATCH 076/123] center loading indicator step1 --- src/pages/ReimbursementAccount/BankAccountStep.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index 88525a81a211..a38a8b915403 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -275,7 +275,7 @@ class BankAccountStep extends React.Component { )} {subStep === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID && ( - + { From d58f41bcfcbc0c906b27dc2831b6b9a3e23970d9 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 7 Sep 2022 13:16:55 +0100 Subject: [PATCH 077/123] add proptypes, loading state, change to pattern c --- src/libs/actions/BankAccounts.js | 18 +++++++++--------- .../ReimbursementAccountForm.js | 2 +- .../reimbursementAccountPropTypes.js | 6 ++++++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index eb85cb28f20a..eb95a22e1d7e 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -126,21 +126,21 @@ function validateBankAccount(bankAccountID, validateCode) { onyxMethod: CONST.ONYX.METHOD.MERGE, key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, value: { - errors: null, - achData: { - state: CONST.BANK_ACCOUNT.STATE.OPEN, - currentStep: CONST.BANK_ACCOUNT.STEP.ENABLE, - }, + isLoading: true, + }, + }], + successData: [{ + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: false, }, }], failureData: [{ onyxMethod: CONST.ONYX.METHOD.MERGE, key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, value: { - achData: { - state: CONST.BANK_ACCOUNT.STATE.VERIFYING, - currentStep: CONST.BANK_ACCOUNT.STEP.VALIDATION, - }, + isLoading: false, }, }], }); diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js index 4969ccd77c45..25179e16e8c2 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js @@ -60,7 +60,7 @@ class ReimbursementAccountForm extends React.Component { }} message={this.props.reimbursementAccount.error} isMessageHtml={this.props.reimbursementAccount.isErrorHtml} - isLoading={this.props.reimbursementAccount.loading} + isLoading={this.props.reimbursementAccount.loading || this.props.reimbursementAccount.isLoading} /> ); diff --git a/src/pages/ReimbursementAccount/reimbursementAccountPropTypes.js b/src/pages/ReimbursementAccount/reimbursementAccountPropTypes.js index 2f9595d8baf0..79e7dff36a3d 100644 --- a/src/pages/ReimbursementAccount/reimbursementAccountPropTypes.js +++ b/src/pages/ReimbursementAccount/reimbursementAccountPropTypes.js @@ -31,5 +31,11 @@ export default PropTypes.shape({ errors: PropTypes.objectOf(PropTypes.oneOfType([ PropTypes.bool, PropTypes.arrayOf(PropTypes.objectOf(PropTypes.bool)), + + /** + * Errors from api calls on the specific user + * {: 'error message', : 'error message 2'} + */ + PropTypes.string, ])), }); From 55c9fdd4e7a87126466bdee9902066e48ce943f9 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 7 Sep 2022 15:29:09 +0100 Subject: [PATCH 078/123] display errors --- src/pages/ReimbursementAccount/ReimbursementAccountForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js index 25179e16e8c2..f7e29bdd2ced 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js @@ -58,7 +58,7 @@ class ReimbursementAccountForm extends React.Component { onFixTheErrorsLinkPressed={() => { this.form.scrollTo({y: 0, animated: true}); }} - message={this.props.reimbursementAccount.error} + message={this.props.reimbursementAccount.error || _.values(this.props.reimbursementAccount.errors)[0]} isMessageHtml={this.props.reimbursementAccount.isErrorHtml} isLoading={this.props.reimbursementAccount.loading || this.props.reimbursementAccount.isLoading} /> From dd75b944a9c0de00e1aa25ae600364ffc16ebfc4 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 7 Sep 2022 15:30:20 +0100 Subject: [PATCH 079/123] rm error on resubmit --- src/libs/actions/BankAccounts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index eb95a22e1d7e..38c63a9a7723 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -127,6 +127,7 @@ function validateBankAccount(bankAccountID, validateCode) { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, value: { isLoading: true, + errors: null, }, }], successData: [{ From a7e2ac213c721829dc2f110728dc553fb7aa259b Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Wed, 7 Sep 2022 17:13:27 +0100 Subject: [PATCH 080/123] Update Policy.js --- src/libs/actions/Policy.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index 64f190168720..2694844c6917 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -887,15 +887,30 @@ function createWorkspace() { key: `${ONYXKEYS.COLLECTION.REPORT}${announceChatReportID}`, value: {pendingAction: null}, }, + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${announceChatReportID}`, + value: {pendingAction: null}, + }, { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${adminsChatReportID}`, value: {pendingAction: null}, }, + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`, + value: {pendingAction: null}, + }, { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, value: {pendingAction: null}, + } + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: {pendingAction: null}, }], failureData: [{ onyxMethod: CONST.ONYX.METHOD.SET, @@ -913,7 +928,7 @@ function createWorkspace() { value: null, }, { - onyxMethod: CONST.ONYX.METHOD.MERGE, + onyxMethod: CONST.ONYX.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${announceChatReportID}`, value: null, }, @@ -923,7 +938,7 @@ function createWorkspace() { value: null, }, { - onyxMethod: CONST.ONYX.METHOD.MERGE, + onyxMethod: CONST.ONYX.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`, value: null, }, @@ -933,7 +948,7 @@ function createWorkspace() { value: null, }, { - onyxMethod: CONST.ONYX.METHOD.MERGE, + onyxMethod: CONST.ONYX.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, value: null, }], From 9985634bfba9416d8bd63a1a4bf731d306d37061 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Wed, 7 Sep 2022 17:24:25 +0100 Subject: [PATCH 081/123] Update Policy.js --- src/libs/actions/Policy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index 2694844c6917..6d4b2cc26b59 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -906,7 +906,7 @@ function createWorkspace() { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, value: {pendingAction: null}, - } + }, { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, From a41a30a15ad8d44087d554b6f92750d37600d66c Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 8 Sep 2022 08:38:34 +0100 Subject: [PATCH 082/123] Fix the active report equality check --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index d9f0c658cfaf..55640f8bfbbc 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -497,7 +497,7 @@ function getOptions(reports, personalDetails, activeReportID, { const shouldFilterReportIfRead = hideReadReports && !ReportUtils.isUnread(report); const shouldFilterReport = shouldFilterReportIfEmpty || shouldFilterReportIfRead; - if (report.reportID !== activeReportID + if (report.reportID.toString() !== activeReportID.toString() && (!report.isPinned || isDefaultRoom) && !hasDraftComment && shouldFilterReport From 6b87f562e4d4879e03ba6b4179b028d400b08e70 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 8 Sep 2022 11:43:18 +0100 Subject: [PATCH 083/123] Fix the active report equality check --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 55640f8bfbbc..483e58ea9668 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -497,7 +497,7 @@ function getOptions(reports, personalDetails, activeReportID, { const shouldFilterReportIfRead = hideReadReports && !ReportUtils.isUnread(report); const shouldFilterReport = shouldFilterReportIfEmpty || shouldFilterReportIfRead; - if (report.reportID.toString() !== activeReportID.toString() + if (report.reportID.toString() !== activeReportID && (!report.isPinned || isDefaultRoom) && !hasDraftComment && shouldFilterReport From 629c4c4a66963ed36752edf4de81b140d73e22f8 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 8 Sep 2022 11:46:53 +0100 Subject: [PATCH 084/123] Add a comment about why we use an error boundary --- tests/unit/LHNOrderTest.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/unit/LHNOrderTest.js b/tests/unit/LHNOrderTest.js index e085d6001289..3a0194f0f480 100644 --- a/tests/unit/LHNOrderTest.js +++ b/tests/unit/LHNOrderTest.js @@ -158,6 +158,11 @@ Onyx.init({ }); function getDefaultRenderedSidebarLinks() { + // An ErrorBoundary needs to be added to the rendering so that any errors that happen while the component + // renders are logged to the console. Without an error boundary, Jest only reports the error like "The above error + // occurred in your component", except, there is no "above error". It's just swallowed up by Jest somewhere. + // With the ErrorBoundary, those errors are caught and logged to the console so you can find exactly which error + // might be causing a rendering issue when developing tests. class ErrorBoundary extends React.Component { // Error boundaries have to implement this method. It's for providing a fallback UI, but // we don't need that for unit testing, so this is basically a no-op. From 55bd67fa48766351c6bb2bbd5633312814f1039e Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 8 Sep 2022 11:47:55 +0100 Subject: [PATCH 085/123] Fix return data type --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 86bcc92bdd36..5c5182a6880e 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -104,7 +104,7 @@ const defaultProps = { * @param {Object} route * @param {Object} route.params * @param {String} route.params.reportID - * @returns {Number} + * @returns {String} */ function getReportID(route) { return route.params.reportID.toString(); From 84b1be42fb202270ef7cc81960cd0a2f1c88d148 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 8 Sep 2022 12:00:00 +0100 Subject: [PATCH 086/123] Remove an unnecessary string cast --- src/pages/home/sidebar/SidebarLinks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index be36fef880e4..1257d29cbdb8 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -180,8 +180,8 @@ class SidebarLinks extends React.Component { {paddingBottom: StyleUtils.getSafeAreaMargins(this.props.insets).marginBottom}, ]} sections={sections} - focusedIndex={_.findIndex(this.orderedReports, ( - option => option.reportID.toString() === this.props.currentlyViewedReportID.toString() + focusedIndex={_.findIndex(optionListItems, ( + option => option.reportID.toString() === this.props.currentlyViewedReportID ))} onSelectRow={(option) => { Navigation.navigate(ROUTES.getReportRoute(option.reportID)); From 5ca3b5ebb7b53c236a0376e3069c2a92ff9ed00f Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 8 Sep 2022 12:06:28 +0100 Subject: [PATCH 087/123] Add JSDocs --- src/pages/home/sidebar/SidebarLinks.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 1257d29cbdb8..462d14e9f3ba 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -95,6 +95,15 @@ class SidebarLinks extends React.Component { this.getRecentReportsOptionListItems = memoizeOne(this.getRecentReportsOptionListItems.bind(this)); } + /** + * @param {String} activeReportID + * @param {String} priorityMode + * @param {Object[]} unorderedReports + * @param {Object} personalDetails + * @param {String[]} betas + * @param {Object} reportActions + * @returns {Object[]} + */ getRecentReportsOptionListItems(activeReportID, priorityMode, unorderedReports, personalDetails, betas, reportActions) { const sidebarOptions = OptionsListUtils.getSidebarOptions( unorderedReports, From 82f80adafc311a725e61d6c1c499e5365a558b5a Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Fri, 9 Sep 2022 09:57:23 +0100 Subject: [PATCH 088/123] update the first entry --- src/libs/actions/Policy.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index 6d4b2cc26b59..d5036145090d 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -890,7 +890,11 @@ function createWorkspace() { { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${announceChatReportID}`, - value: {pendingAction: null}, + value: { + 0: { + pendingAction: null, + }, + }, }, { onyxMethod: CONST.ONYX.METHOD.MERGE, @@ -900,7 +904,11 @@ function createWorkspace() { { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`, - value: {pendingAction: null}, + value: { + 0: { + pendingAction: null, + }, + }, }, { onyxMethod: CONST.ONYX.METHOD.MERGE, @@ -910,7 +918,11 @@ function createWorkspace() { { onyxMethod: CONST.ONYX.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: {pendingAction: null}, + value: { + 0: { + pendingAction: null, + }, + }, }], failureData: [{ onyxMethod: CONST.ONYX.METHOD.SET, From 7b7bad66083773cd05f4b471019f279ae8790b93 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sat, 10 Sep 2022 13:43:32 +0530 Subject: [PATCH 089/123] install storybook webpack 5 --- package-lock.json | 809 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + 2 files changed, 810 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 86d00a5728d9..3544000e2f7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -105,6 +105,8 @@ "@storybook/addon-essentials": "^6.5.9", "@storybook/addon-react-native-web": "0.0.19--canary.37.cb55428.0", "@storybook/addons": "^6.5.9", + "@storybook/builder-webpack5": "^6.5.10", + "@storybook/manager-webpack5": "^6.5.10", "@storybook/react": "^6.5.9", "@storybook/theming": "^6.5.9", "@svgr/webpack": "^5.5.0", @@ -8407,6 +8409,188 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/@storybook/builder-webpack5": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-6.5.10.tgz", + "integrity": "sha512-Hcsm/TzGRXHndgQCftt+pzI7GQJRqAv8A8ie5b3aFcodhJfK0qzZsQD4Y4ZWxXh1I/xe5t74Kl2qUJ40PX+geA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/preview-web": "6.5.10", + "@storybook/router": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.5.10", + "@storybook/theming": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "babel-loader": "^8.0.0", + "babel-plugin-named-exports-order": "^0.0.2", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "html-webpack-plugin": "^5.0.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stable": "^0.1.8", + "style-loader": "^2.0.0", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.4.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "16.11.58", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.58.tgz", + "integrity": "sha512-uMVxJ111wpHzkx/vshZFb6Qni3BOMnlWLq7q9jrwej7Yw/KvjsEbpxCCxw+hLKxexFMc8YmpG8J9tnEe/rKsIg==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/terser-webpack-plugin": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= v10.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-virtual-modules": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", + "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", + "dev": true + }, "node_modules/@storybook/channel-postmessage": { "version": "6.5.10", "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.5.10.tgz", @@ -11221,6 +11405,237 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/@storybook/manager-webpack5": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack5/-/manager-webpack5-6.5.10.tgz", + "integrity": "sha512-uRo+6e5MiVOtyFVMYIKVqvpDveCjHyzXBfetSYR7rKEZoaDMEnLLiuF7DIH12lzxwmzCJ1gIc4lf5HFiTMNkgw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/core-client": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/theming": "6.5.10", + "@storybook/ui": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "express": "^4.17.1", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^5.0.0", + "node-fetch": "^2.6.7", + "process": "^0.11.10", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^2.0.0", + "telejson": "^6.0.8", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-virtual-modules": "^0.4.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/@types/node": { + "version": "16.11.58", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.58.tgz", + "integrity": "sha512-uMVxJ111wpHzkx/vshZFb6Qni3BOMnlWLq7q9jrwej7Yw/KvjsEbpxCCxw+hLKxexFMc8YmpG8J9tnEe/rKsIg==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/terser-webpack-plugin": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= v10.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/webpack-virtual-modules": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", + "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", + "dev": true + }, "node_modules/@storybook/mdx1-csf": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz", @@ -15062,6 +15477,12 @@ "node": ">= 8.0.0" } }, + "node_modules/babel-plugin-named-exports-order": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-named-exports-order/-/babel-plugin-named-exports-order-0.0.2.tgz", + "integrity": "sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw==", + "dev": true + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", @@ -15778,6 +16199,12 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -29241,6 +29668,18 @@ "tmpl": "1.0.5" } }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -29390,6 +29829,31 @@ "node": ">= 0.6" } }, + "node_modules/mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/memfs": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", @@ -32244,6 +32708,15 @@ "node": ">=6" } }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", @@ -44475,7 +44948,7 @@ "@oguzhnatly/react-native-image-manipulator": { "version": "git+ssh://git@github.com/Expensify/react-native-image-manipulator.git#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050", "integrity": "sha512-PvrSoCq5PS1MA5ZWUpB0khfzH6sM8SI6YiVl4i2SItPr7IeRxiWfI4n45VhBCCElc1z5GhAwTZOBaIzXTX7/og==", - "from": "@oguzhnatly/react-native-image-manipulator@https://github.com/Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050" + "from": "@oguzhnatly/react-native-image-manipulator@github:Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050" }, "@onfido/active-video-capture": { "version": "0.0.1", @@ -47691,6 +48164,134 @@ } } }, + "@storybook/builder-webpack5": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-6.5.10.tgz", + "integrity": "sha512-Hcsm/TzGRXHndgQCftt+pzI7GQJRqAv8A8ie5b3aFcodhJfK0qzZsQD4Y4ZWxXh1I/xe5t74Kl2qUJ40PX+geA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/preview-web": "6.5.10", + "@storybook/router": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.5.10", + "@storybook/theming": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "babel-loader": "^8.0.0", + "babel-plugin-named-exports-order": "^0.0.2", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "html-webpack-plugin": "^5.0.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stable": "^0.1.8", + "style-loader": "^2.0.0", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.4.1" + }, + "dependencies": { + "@types/node": { + "version": "16.11.58", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.58.tgz", + "integrity": "sha512-uMVxJ111wpHzkx/vshZFb6Qni3BOMnlWLq7q9jrwej7Yw/KvjsEbpxCCxw+hLKxexFMc8YmpG8J9tnEe/rKsIg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser-webpack-plugin": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + } + }, + "webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + }, + "webpack-virtual-modules": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", + "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", + "dev": true + } + } + }, "@storybook/channel-postmessage": { "version": "6.5.10", "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.5.10.tgz", @@ -49970,6 +50571,167 @@ } } }, + "@storybook/manager-webpack5": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack5/-/manager-webpack5-6.5.10.tgz", + "integrity": "sha512-uRo+6e5MiVOtyFVMYIKVqvpDveCjHyzXBfetSYR7rKEZoaDMEnLLiuF7DIH12lzxwmzCJ1gIc4lf5HFiTMNkgw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/core-client": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/theming": "6.5.10", + "@storybook/ui": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "express": "^4.17.1", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^5.0.0", + "node-fetch": "^2.6.7", + "process": "^0.11.10", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^2.0.0", + "telejson": "^6.0.8", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-virtual-modules": "^0.4.1" + }, + "dependencies": { + "@types/node": { + "version": "16.11.58", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.58.tgz", + "integrity": "sha512-uMVxJ111wpHzkx/vshZFb6Qni3BOMnlWLq7q9jrwej7Yw/KvjsEbpxCCxw+hLKxexFMc8YmpG8J9tnEe/rKsIg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser-webpack-plugin": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + } + }, + "webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + }, + "webpack-virtual-modules": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", + "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", + "dev": true + } + } + }, "@storybook/mdx1-csf": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz", @@ -52973,6 +53735,12 @@ "resolve": "^1.13.1" } }, + "babel-plugin-named-exports-order": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-named-exports-order/-/babel-plugin-named-exports-order-0.0.2.tgz", + "integrity": "sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw==", + "dev": true + }, "babel-plugin-polyfill-corejs2": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", @@ -53583,6 +54351,12 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, + "browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, "browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -63849,6 +64623,15 @@ "tmpl": "1.0.5" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -63963,6 +64746,24 @@ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true }, + "mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + } + } + }, "memfs": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", @@ -66233,6 +67034,12 @@ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true + }, "p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", diff --git a/package.json b/package.json index 84b08c8b96fe..85be9649caed 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,8 @@ "@storybook/addon-essentials": "^6.5.9", "@storybook/addon-react-native-web": "0.0.19--canary.37.cb55428.0", "@storybook/addons": "^6.5.9", + "@storybook/builder-webpack5": "^6.5.10", + "@storybook/manager-webpack5": "^6.5.10", "@storybook/react": "^6.5.9", "@storybook/theming": "^6.5.9", "@svgr/webpack": "^5.5.0", From 9c7b4126813bd70e51973ee7f1cfae2e49a7bd96 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sat, 10 Sep 2022 13:44:04 +0530 Subject: [PATCH 090/123] configure storybook to use webpack 5 --- .storybook/main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.storybook/main.js b/.storybook/main.js index ad5effb2dbf6..456725e35191 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -12,4 +12,7 @@ module.exports = { './public', '../assets/css', ], + core: { + builder: "webpack5" + } }; From deb697cc662249269941d7bd61d6f4ff39f916c5 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sat, 10 Sep 2022 14:00:18 +0530 Subject: [PATCH 091/123] fix lint errors --- .storybook/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.storybook/main.js b/.storybook/main.js index 456725e35191..9df86b68be3f 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -13,6 +13,6 @@ module.exports = { '../assets/css', ], core: { - builder: "webpack5" - } + builder: 'webpack5' + }, }; From f7cfd8581c46217cb832a3e189c7b462504f9823 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sat, 10 Sep 2022 14:04:38 +0530 Subject: [PATCH 092/123] fix lint errors --- .storybook/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.storybook/main.js b/.storybook/main.js index 9df86b68be3f..d34252604b41 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -13,6 +13,6 @@ module.exports = { '../assets/css', ], core: { - builder: 'webpack5' + builder: 'webpack5', }, }; From e8aef52a5f18814bb7729e071df638478426077a Mon Sep 17 00:00:00 2001 From: luan <103875612+b1tjoy@users.noreply.github.com> Date: Mon, 12 Sep 2022 19:26:38 +0800 Subject: [PATCH 093/123] format link as markdown link --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 986804658b17..7c5dbadad342 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", "dotenv": "^8.2.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#e0ec0b9abca4d7b417ba0b016f8725856cfeeece", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#662e70f1f75ace4ab81365be312efbf28f16e0a3", "fbjs": "^3.0.2", "file-loader": "^6.0.0", "html-entities": "^1.3.1", @@ -22142,8 +22142,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#e0ec0b9abca4d7b417ba0b016f8725856cfeeece", - "integrity": "sha512-RXp32klPtDw6UK57f3Ku0Gw1wOq9STfMRaF8gH8XZ7pa0kTOA53itpvGfHr81Xuk960oIowt4SIo3zbzG+GK2w==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#662e70f1f75ace4ab81365be312efbf28f16e0a3", + "integrity": "sha512-FiHBWAGkJ9UC+cpdB2bDY+2lAOklvFAIDzga9c2z3iTzEvhYYf2uCeTIjDFYIJviEibBkiIUELjDr9wwcepmNA==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -58490,9 +58490,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#e0ec0b9abca4d7b417ba0b016f8725856cfeeece", - "integrity": "sha512-RXp32klPtDw6UK57f3Ku0Gw1wOq9STfMRaF8gH8XZ7pa0kTOA53itpvGfHr81Xuk960oIowt4SIo3zbzG+GK2w==", - "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#e0ec0b9abca4d7b417ba0b016f8725856cfeeece", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#662e70f1f75ace4ab81365be312efbf28f16e0a3", + "integrity": "sha512-FiHBWAGkJ9UC+cpdB2bDY+2lAOklvFAIDzga9c2z3iTzEvhYYf2uCeTIjDFYIJviEibBkiIUELjDr9wwcepmNA==", + "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#662e70f1f75ace4ab81365be312efbf28f16e0a3", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", diff --git a/package.json b/package.json index 79801c1101cf..2b8381368930 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", "dotenv": "^8.2.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#e0ec0b9abca4d7b417ba0b016f8725856cfeeece", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#662e70f1f75ace4ab81365be312efbf28f16e0a3", "fbjs": "^3.0.2", "file-loader": "^6.0.0", "html-entities": "^1.3.1", From 4579ab205dfc56d60b6b323636b61808907269b1 Mon Sep 17 00:00:00 2001 From: Mohammad Luthfi Fathur Rahman Date: Mon, 12 Sep 2022 22:06:34 +0700 Subject: [PATCH 094/123] adding screen listener to participants page --- src/libs/Navigation/AppNavigator/AuthScreens.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index a363dd84ba95..11767b963a8a 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -268,6 +268,7 @@ class AuthScreens extends React.Component { name="Participants" options={modalScreenOptions} component={ModalStackNavigators.ReportParticipantsModalStackNavigator} + listeners={modalScreenListeners} /> Date: Tue, 13 Sep 2022 08:38:42 +0700 Subject: [PATCH 095/123] adding screen listener to IOU detail page --- src/libs/Navigation/AppNavigator/AuthScreens.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 11767b963a8a..a2f9d082e3c3 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -292,6 +292,7 @@ class AuthScreens extends React.Component { name="IOU_Details" options={modalScreenOptions} component={ModalStackNavigators.IOUDetailsModalStackNavigator} + listeners={modalScreenListeners} /> Date: Tue, 13 Sep 2022 10:05:20 +0100 Subject: [PATCH 096/123] Add helper method to build Onyx data for VBBA setup --- src/libs/actions/BankAccounts.js | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 43b8b7d2c056..3ba9b9f88ec7 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -41,6 +41,48 @@ function clearPlaid() { Onyx.set(ONYXKEYS.PLAID_LINK_TOKEN, ''); } +/** + * Helper method to build the Onyx data required during setup of a Verified Business Bank Account + * + * @returns {Object} + */ +function getVBBADataForOnyx() { + return { + optimisticData: [ + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: true, + errors: null, + }, + }, + ], + successData: [ + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: false, + errors: null, + }, + }, + ], + failureData: [ + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: false, + errors: { + [DateUtils.getMicroseconds()]: Localize.translateLocal('paymentsPage.addBankAccountFailure'), + }, + }, + }, + ], + }; +} + /** * Adds a bank account via Plaid * From 1999128c0a8c86042e936878af78360db6d547e9 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 13 Sep 2022 11:22:33 +0100 Subject: [PATCH 097/123] Fix lint errors --- src/libs/actions/BankAccounts.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 3ba9b9f88ec7..d2242b028962 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -3,6 +3,7 @@ import CONST from '../../CONST'; import * as API from '../API'; import ONYXKEYS from '../../ONYXKEYS'; import * as Localize from '../Localize'; +import DateUtils from '../DateUtils'; export { setupWithdrawalAccount, @@ -43,9 +44,11 @@ function clearPlaid() { /** * Helper method to build the Onyx data required during setup of a Verified Business Bank Account - * + * * @returns {Object} */ +// We'll remove the below once this function is used by the VBBA commands that are yet to be implemented +/* eslint-disable no-unused-vars */ function getVBBADataForOnyx() { return { optimisticData: [ From 2dd0888d676736d5ed98a7e1fb5302231ff4d878 Mon Sep 17 00:00:00 2001 From: Alex Beaman Date: Tue, 13 Sep 2022 13:52:07 +0200 Subject: [PATCH 098/123] Update package-lock with image manipulator fork --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 94a10ec734cc..51d098c57b64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44475,7 +44475,7 @@ "@oguzhnatly/react-native-image-manipulator": { "version": "git+ssh://git@github.com/Expensify/react-native-image-manipulator.git#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050", "integrity": "sha512-PvrSoCq5PS1MA5ZWUpB0khfzH6sM8SI6YiVl4i2SItPr7IeRxiWfI4n45VhBCCElc1z5GhAwTZOBaIzXTX7/og==", - "from": "@oguzhnatly/react-native-image-manipulator@https://github.com/Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050" + "from": "@oguzhnatly/react-native-image-manipulator@github:Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050" }, "@onfido/active-video-capture": { "version": "0.0.1", From 0a84843aa3bad17ac862c7f0f27b3570534f20b9 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Tue, 13 Sep 2022 13:01:51 -0700 Subject: [PATCH 099/123] remove usages of onyxRates --- src/libs/actions/Policy.js | 8 ++++---- .../workspace/reimburse/WorkspaceReimburseView.js | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index d8af8be7d7f1..5fac77a56380 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -529,7 +529,7 @@ function clearCustomUnitErrors(policyID, customUnitID, customUnitRateID) { [customUnitID]: { errors: null, pendingAction: null, - onyxRates: { + rates: { [customUnitRateID]: { errors: null, pendingAction: null, @@ -626,7 +626,7 @@ function updateCustomUnitRate(policyID, currentCustomUnitRate, customUnitID, new value: { customUnits: { [customUnitID]: { - onyxRates: { + rates: { [newCustomUnitRate.customUnitRateID]: { ...newCustomUnitRate, errors: null, @@ -646,7 +646,7 @@ function updateCustomUnitRate(policyID, currentCustomUnitRate, customUnitID, new value: { customUnits: { [customUnitID]: { - onyxRates: { + rates: { [newCustomUnitRate.customUnitRateID]: { pendingAction: null, }, @@ -664,7 +664,7 @@ function updateCustomUnitRate(policyID, currentCustomUnitRate, customUnitID, new value: { customUnits: { [customUnitID]: { - onyxRates: { + rates: { [currentCustomUnitRate.customUnitRateID]: { ...currentCustomUnitRate, errors: { diff --git a/src/pages/workspace/reimburse/WorkspaceReimburseView.js b/src/pages/workspace/reimburse/WorkspaceReimburseView.js index cead7dbc828a..37ddbfee899c 100644 --- a/src/pages/workspace/reimburse/WorkspaceReimburseView.js +++ b/src/pages/workspace/reimburse/WorkspaceReimburseView.js @@ -40,7 +40,7 @@ const propTypes = { attributes: PropTypes.shape({ unit: PropTypes.string, }), - onyxRates: PropTypes.objectOf( + rates: PropTypes.objectOf( PropTypes.shape({ customUnitRateID: PropTypes.string, name: PropTypes.string, @@ -63,7 +63,7 @@ class WorkspaceReimburseView extends React.Component { constructor(props) { super(props); const distanceCustomUnit = _.find(lodashGet(props, 'policy.customUnits', {}), unit => unit.name === 'Distance'); - const customUnitRate = _.find(lodashGet(distanceCustomUnit, 'onyxRates', {}), rate => rate.name === 'Default Rate'); + const customUnitRate = _.find(lodashGet(distanceCustomUnit, 'rates', {}), rate => rate.name === 'Default Rate'); this.state = { unitID: lodashGet(distanceCustomUnit, 'customUnitID', ''), @@ -99,7 +99,7 @@ class WorkspaceReimburseView extends React.Component { .values() .findWhere({name: CONST.CUSTOM_UNITS.NAME_DISTANCE}) .value(); - const customUnitRate = _.find(lodashGet(distanceCustomUnit, 'onyxRates', {}), rate => rate.name === 'Default Rate'); + const customUnitRate = _.find(lodashGet(distanceCustomUnit, 'rates', {}), rate => rate.name === 'Default Rate'); this.setState({ unitID: lodashGet(distanceCustomUnit, 'customUnitID', ''), unitName: lodashGet(distanceCustomUnit, 'name', ''), @@ -177,7 +177,7 @@ class WorkspaceReimburseView extends React.Component { }); const distanceCustomUnit = _.find(lodashGet(this.props, 'policy.customUnits', {}), unit => unit.name === 'Distance'); - const currentCustomUnitRate = lodashGet(distanceCustomUnit, ['onyxRates', this.state.unitRateID], {}); + const currentCustomUnitRate = lodashGet(distanceCustomUnit, ['rates', this.state.unitRateID], {}); Policy.updateCustomUnitRate(this.props.policyID, currentCustomUnitRate, this.state.unitID, { ...currentCustomUnitRate, rate: numValue.toFixed(3) * CONST.POLICY.CUSTOM_UNIT_RATE_BASE_OFFSET, @@ -223,10 +223,10 @@ class WorkspaceReimburseView extends React.Component { Policy.clearCustomUnitErrors(this.props.policyID, this.state.unitID, this.state.unitRateID)} > From f67be5a222e5f751423c771f3f827f764aaf0f5f Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Tue, 13 Sep 2022 16:14:42 -0700 Subject: [PATCH 100/123] Revert "Refactor withFullPolicy" --- src/components/AvatarWithIndicator.js | 4 +- src/components/RoomNameInput.js | 4 ++ src/pages/ReportSettingsPage.js | 15 +++++ .../workspace/WorkspaceBankAccountPage.js | 4 +- src/pages/workspace/WorkspaceInitialPage.js | 8 +-- src/pages/workspace/WorkspaceInvitePage.js | 8 +-- src/pages/workspace/WorkspaceMembersPage.js | 8 +-- src/pages/workspace/WorkspaceNewRoomPage.js | 8 ++- .../workspace/WorkspacePageWithSections.js | 4 +- src/pages/workspace/WorkspaceSettingsPage.js | 8 +-- .../reimburse/WorkspaceReimburseView.js | 4 +- .../{withPolicy.js => withFullPolicy.js} | 56 +++++++++++++------ 12 files changed, 88 insertions(+), 43 deletions(-) rename src/pages/workspace/{withPolicy.js => withFullPolicy.js} (64%) diff --git a/src/components/AvatarWithIndicator.js b/src/components/AvatarWithIndicator.js index 1bd517cfd642..afa59dfbdd9e 100644 --- a/src/components/AvatarWithIndicator.js +++ b/src/components/AvatarWithIndicator.js @@ -11,7 +11,7 @@ import policyMemberPropType from '../pages/policyMemberPropType'; import bankAccountPropTypes from './bankAccountPropTypes'; import cardPropTypes from './cardPropTypes'; import userWalletPropTypes from '../pages/EnablePayments/userWalletPropTypes'; -import {policyPropTypes} from '../pages/workspace/withPolicy'; +import {fullPolicyPropTypes} from '../pages/workspace/withFullPolicy'; import walletTermsPropTypes from '../pages/EnablePayments/walletTermsPropTypes'; import * as PolicyUtils from '../libs/PolicyUtils'; import * as PaymentMethods from '../libs/actions/PaymentMethods'; @@ -30,7 +30,7 @@ const propTypes = { policiesMemberList: PropTypes.objectOf(policyMemberPropType), /** All the user's policies (from Onyx via withFullPolicy) */ - policies: PropTypes.objectOf(policyPropTypes.policy), + policies: PropTypes.objectOf(fullPolicyPropTypes.policy), /** List of bank accounts */ bankAccountList: PropTypes.objectOf(bankAccountPropTypes), diff --git a/src/components/RoomNameInput.js b/src/components/RoomNameInput.js index 55e1a2296a7a..8bd14fe9408c 100644 --- a/src/components/RoomNameInput.js +++ b/src/components/RoomNameInput.js @@ -5,6 +5,7 @@ import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import compose from '../libs/compose'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import withFullPolicy, {fullPolicyDefaultProps, fullPolicyPropTypes} from '../pages/workspace/withFullPolicy'; import TextInput from './TextInput'; const propTypes = { @@ -21,6 +22,7 @@ const propTypes = { errorText: PropTypes.string, ...withLocalizePropTypes, + ...fullPolicyPropTypes, /* Onyx Props */ @@ -51,6 +53,7 @@ const defaultProps = { initialValue: '', disabled: false, errorText: '', + ...fullPolicyDefaultProps, forwardedRef: () => {}, }; @@ -111,6 +114,7 @@ RoomNameInput.defaultProps = defaultProps; export default compose( withLocalize, + withFullPolicy, withOnyx({ reports: { key: ONYXKEYS.COLLECTION.REPORT, diff --git a/src/pages/ReportSettingsPage.js b/src/pages/ReportSettingsPage.js index 0fe5d285fb92..9efc59dc940e 100644 --- a/src/pages/ReportSettingsPage.js +++ b/src/pages/ReportSettingsPage.js @@ -18,6 +18,7 @@ import Text from '../components/Text'; import Button from '../components/Button'; import RoomNameInput from '../components/RoomNameInput'; import Picker from '../components/Picker'; +import withFullPolicy, {fullPolicyDefaultProps, fullPolicyPropTypes} from './workspace/withFullPolicy'; import * as ValidationUtils from '../libs/ValidationUtils'; import OfflineWithFeedback from '../components/OfflineWithFeedback'; @@ -30,6 +31,7 @@ const propTypes = { }), }).isRequired, + ...fullPolicyPropTypes, ...withLocalizePropTypes, /* Onyx Props */ @@ -77,6 +79,17 @@ const propTypes = { }).isRequired, }; +const defaultProps = { + ...fullPolicyDefaultProps, + report: { + reportID: 0, + reportName: '', + policyID: '', + notificationPreference: '', + visibility: '', + }, +}; + class ReportSettingsPage extends Component { constructor(props) { super(props); @@ -274,9 +287,11 @@ class ReportSettingsPage extends Component { } ReportSettingsPage.propTypes = propTypes; +ReportSettingsPage.defaultProps = defaultProps; export default compose( withLocalize, + withFullPolicy, withOnyx({ report: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`, diff --git a/src/pages/workspace/WorkspaceBankAccountPage.js b/src/pages/workspace/WorkspaceBankAccountPage.js index 64bd69cb9bd3..6b95d4685ddd 100644 --- a/src/pages/workspace/WorkspaceBankAccountPage.js +++ b/src/pages/workspace/WorkspaceBankAccountPage.js @@ -21,7 +21,7 @@ import Section from '../../components/Section'; import WorkspaceResetBankAccountModal from './WorkspaceResetBankAccountModal'; import styles from '../../styles/styles'; import CONST from '../../CONST'; -import withPolicy from './withPolicy'; +import withFullPolicy from './withFullPolicy'; import Button from '../../components/Button'; import MenuItem from '../../components/MenuItem'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; @@ -131,5 +131,5 @@ export default compose( key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, }), - withPolicy, + withFullPolicy, )(WorkspaceBankAccountPage); diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index cbcccda54c62..6445933dec42 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -20,7 +20,7 @@ import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import compose from '../../libs/compose'; import Avatar from '../../components/Avatar'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; -import withPolicy, {policyPropTypes, policyDefaultProps} from './withPolicy'; +import withFullPolicy, {fullPolicyPropTypes, fullPolicyDefaultProps} from './withFullPolicy'; import * as Policy from '../../libs/actions/Policy'; import * as PolicyUtils from '../../libs/PolicyUtils'; import CONST from '../../CONST'; @@ -30,7 +30,7 @@ import policyMemberPropType from '../policyMemberPropType'; import OfflineWithFeedback from '../../components/OfflineWithFeedback'; const propTypes = { - ...policyPropTypes, + ...fullPolicyPropTypes, ...withLocalizePropTypes, /** The employee list of this policy (coming from Onyx) */ @@ -38,7 +38,7 @@ const propTypes = { }; const defaultProps = { - ...policyDefaultProps, + ...fullPolicyDefaultProps, policyMemberList: {}, }; @@ -248,7 +248,7 @@ WorkspaceInitialPage.defaultProps = defaultProps; export default compose( withLocalize, - withPolicy, + withFullPolicy, withOnyx({ policyMemberList: { key: ({policy}) => `${ONYXKEYS.COLLECTION.POLICY_MEMBER_LIST}${policy.id}`, diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js index 86fcc48b9757..dbefba433b49 100644 --- a/src/pages/workspace/WorkspaceInvitePage.js +++ b/src/pages/workspace/WorkspaceInvitePage.js @@ -20,7 +20,7 @@ import CONST from '../../CONST'; import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator'; import * as Link from '../../libs/actions/Link'; import Text from '../../components/Text'; -import withPolicy, {policyPropTypes, policyDefaultProps} from './withPolicy'; +import withFullPolicy, {fullPolicyPropTypes, fullPolicyDefaultProps} from './withFullPolicy'; import {withNetwork} from '../../components/OnyxProvider'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; import networkPropTypes from '../../components/networkPropTypes'; @@ -53,12 +53,12 @@ const propTypes = { }), }).isRequired, - ...policyPropTypes, + ...fullPolicyPropTypes, ...withLocalizePropTypes, ...networkPropTypes, }; -const defaultProps = policyDefaultProps; +const defaultProps = fullPolicyDefaultProps; class WorkspaceInvitePage extends React.Component { constructor(props) { @@ -352,7 +352,7 @@ WorkspaceInvitePage.defaultProps = defaultProps; export default compose( withLocalize, - withPolicy, + withFullPolicy, withNetwork(), withOnyx({ personalDetails: { diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index 1de2d1759565..db12309ce7b7 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -25,7 +25,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../../components/ import OptionRow from '../../components/OptionRow'; import CheckboxWithTooltip from '../../components/CheckboxWithTooltip'; import Hoverable from '../../components/Hoverable'; -import withPolicy, {policyPropTypes, policyDefaultProps} from './withPolicy'; +import withFullPolicy, {fullPolicyPropTypes, fullPolicyDefaultProps} from './withFullPolicy'; import CONST from '../../CONST'; import OfflineWithFeedback from '../../components/OfflineWithFeedback'; import {withNetwork} from '../../components/OnyxProvider'; @@ -45,13 +45,13 @@ const propTypes = { }), }).isRequired, - ...policyPropTypes, + ...fullPolicyPropTypes, ...withLocalizePropTypes, ...windowDimensionsPropTypes, ...networkPropTypes, }; -const defaultProps = policyDefaultProps; +const defaultProps = fullPolicyDefaultProps; class WorkspaceMembersPage extends React.Component { constructor(props) { @@ -367,7 +367,7 @@ WorkspaceMembersPage.defaultProps = defaultProps; export default compose( withLocalize, withWindowDimensions, - withPolicy, + withFullPolicy, withNetwork(), withOnyx({ personalDetails: { diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 440362bb91eb..1dae4d8d5b67 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -3,6 +3,7 @@ import {ScrollView, View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; +import withFullPolicy, {fullPolicyDefaultProps, fullPolicyPropTypes} from './withFullPolicy'; import * as Report from '../../libs/actions/Report'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import compose from '../../libs/compose'; @@ -34,17 +35,17 @@ const propTypes = { policyID: PropTypes.string, }).isRequired, - /** List of betas available to current user */ - betas: PropTypes.arrayOf(PropTypes.string), - /** Are we loading the createPolicyRoom command */ isLoadingCreatePolicyRoom: PropTypes.bool, + ...fullPolicyPropTypes, + ...withLocalizePropTypes, }; const defaultProps = { betas: [], isLoadingCreatePolicyRoom: false, + ...fullPolicyDefaultProps, }; class WorkspaceNewRoomPage extends React.Component { @@ -202,6 +203,7 @@ WorkspaceNewRoomPage.propTypes = propTypes; WorkspaceNewRoomPage.defaultProps = defaultProps; export default compose( + withFullPolicy, withOnyx({ betas: { key: ONYXKEYS.BETAS, diff --git a/src/pages/workspace/WorkspacePageWithSections.js b/src/pages/workspace/WorkspacePageWithSections.js index 7c0ecacc0d8a..d6fc3b3a09e6 100644 --- a/src/pages/workspace/WorkspacePageWithSections.js +++ b/src/pages/workspace/WorkspacePageWithSections.js @@ -15,7 +15,7 @@ import * as BankAccounts from '../../libs/actions/BankAccounts'; import BankAccount from '../../libs/models/BankAccount'; import reimbursementAccountPropTypes from '../ReimbursementAccount/reimbursementAccountPropTypes'; import userPropTypes from '../settings/userPropTypes'; -import withPolicy from './withPolicy'; +import withFullPolicy from './withFullPolicy'; import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; @@ -131,6 +131,6 @@ export default compose( key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, }), - withPolicy, + withFullPolicy, withNetwork(), )(WorkspacePageWithSections); diff --git a/src/pages/workspace/WorkspaceSettingsPage.js b/src/pages/workspace/WorkspaceSettingsPage.js index 40c370abb92b..a35c1fc690a2 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.js +++ b/src/pages/workspace/WorkspaceSettingsPage.js @@ -19,18 +19,18 @@ import Picker from '../../components/Picker'; import TextInput from '../../components/TextInput'; import FixedFooter from '../../components/FixedFooter'; import WorkspacePageWithSections from './WorkspacePageWithSections'; -import withPolicy, {policyPropTypes, policyDefaultProps} from './withPolicy'; +import withFullPolicy, {fullPolicyPropTypes, fullPolicyDefaultProps} from './withFullPolicy'; import {withNetwork} from '../../components/OnyxProvider'; import OfflineWithFeedback from '../../components/OfflineWithFeedback'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; const propTypes = { - ...policyPropTypes, + ...fullPolicyPropTypes, ...withLocalizePropTypes, }; const defaultProps = { - ...policyDefaultProps, + ...fullPolicyDefaultProps, }; class WorkspaceSettingsPage extends React.Component { @@ -162,7 +162,7 @@ WorkspaceSettingsPage.propTypes = propTypes; WorkspaceSettingsPage.defaultProps = defaultProps; export default compose( - withPolicy, + withFullPolicy, withOnyx({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, }), diff --git a/src/pages/workspace/reimburse/WorkspaceReimburseView.js b/src/pages/workspace/reimburse/WorkspaceReimburseView.js index cead7dbc828a..053e49348872 100644 --- a/src/pages/workspace/reimburse/WorkspaceReimburseView.js +++ b/src/pages/workspace/reimburse/WorkspaceReimburseView.js @@ -17,7 +17,7 @@ import * as Link from '../../../libs/actions/Link'; import compose from '../../../libs/compose'; import ONYXKEYS from '../../../ONYXKEYS'; import * as Policy from '../../../libs/actions/Policy'; -import withPolicy from '../withPolicy'; +import withFullPolicy from '../withFullPolicy'; import CONST from '../../../CONST'; import Button from '../../../components/Button'; import {withNetwork} from '../../../components/OnyxProvider'; @@ -302,7 +302,7 @@ class WorkspaceReimburseView extends React.Component { WorkspaceReimburseView.propTypes = propTypes; export default compose( - withPolicy, + withFullPolicy, withLocalize, withNetwork(), withOnyx({ diff --git a/src/pages/workspace/withPolicy.js b/src/pages/workspace/withFullPolicy.js similarity index 64% rename from src/pages/workspace/withPolicy.js rename to src/pages/workspace/withFullPolicy.js index 34182871eb4f..45f608d685b2 100644 --- a/src/pages/workspace/withPolicy.js +++ b/src/pages/workspace/withFullPolicy.js @@ -2,6 +2,7 @@ import _ from 'underscore'; import lodashGet from 'lodash/get'; import React from 'react'; import PropTypes from 'prop-types'; +import Str from 'expensify-common/lib/str'; import {withOnyx} from 'react-native-onyx'; import {useNavigationState} from '@react-navigation/native'; import CONST from '../../CONST'; @@ -10,6 +11,9 @@ import * as Policy from '../../libs/actions/Policy'; import ONYXKEYS from '../../ONYXKEYS'; import policyMemberPropType from '../policyMemberPropType'; +let previousRouteName = ''; +let previousRoutePolicyID = ''; + /** * @param {Object} route * @returns {String} @@ -18,7 +22,20 @@ function getPolicyIDFromRoute(route) { return lodashGet(route, 'params.policyID', ''); } -const policyPropTypes = { +/** + * @param {String} routeName + * @param {String} policyID + * @returns {Boolean} + */ +function isPreviousRouteInSameWorkspace(routeName, policyID) { + return ( + Str.startsWith(routeName, 'Workspace') + && Str.startsWith(previousRouteName, 'Workspace') + && policyID === previousRoutePolicyID + ); +} + +const fullPolicyPropTypes = { /** The policy object for the current route */ policy: PropTypes.shape({ /** The ID of the policy */ @@ -61,12 +78,12 @@ const policyPropTypes = { policyMemberList: PropTypes.objectOf(policyMemberPropType), }; -const policyDefaultProps = { +const fullPolicyDefaultProps = { policy: {}, }; /* - * HOC for connecting a policy in Onyx corresponding to the policyID in route params + * HOC for loading a full policy. It checks the route params and if current route has a policyID that the previous route did not, it full-loads that policy. */ export default function (WrappedComponent) { const propTypes = { @@ -74,39 +91,46 @@ export default function (WrappedComponent) { * That way, if a ref is passed to a component wrapped in the HOC, the ref is a reference to the wrapped component, not the HOC. */ forwardedRef: PropTypes.func, - ...policyPropTypes, + ...fullPolicyPropTypes, }; const defaultProps = { forwardedRef: () => {}, - ...policyDefaultProps, + ...fullPolicyDefaultProps, }; - const WithPolicy = (props) => { + const WithFullPolicy = (props) => { const currentRoute = _.last(useNavigationState(state => state.routes || [])); const policyID = getPolicyIDFromRoute(currentRoute); + const isFromFullPolicy = lodashGet(props, 'policy.isFromFullPolicy', false) || lodashGet(props, `policy.policy_${policyID}.isFromFullPolicy`, false); - if (_.isString(policyID) && !_.isEmpty(policyID)) { + if (_.isString(policyID) && !_.isEmpty(policyID) && (!isFromFullPolicy || !isPreviousRouteInSameWorkspace(currentRoute.name, policyID))) { + Policy.loadFullPolicy(policyID); Policy.updateLastAccessedWorkspace(policyID); } - const rest = _.omit(props, ['forwardedRef']); + previousRouteName = currentRoute.name; + previousRoutePolicyID = policyID; + + const rest = _.omit(props, ['forwardedRef', 'policy', 'policyMemberList']); return ( ); }; - WithPolicy.propTypes = propTypes; - WithPolicy.defaultProps = defaultProps; - WithPolicy.displayName = `withFullPolicy(${getComponentDisplayName(WrappedComponent)})`; - const withPolicy = React.forwardRef((props, ref) => ( + WithFullPolicy.propTypes = propTypes; + WithFullPolicy.defaultProps = defaultProps; + WithFullPolicy.displayName = `withFullPolicy(${getComponentDisplayName(WrappedComponent)})`; + const withFullPolicy = React.forwardRef((props, ref) => ( // eslint-disable-next-line react/jsx-props-no-spreading - + )); return withOnyx({ @@ -116,10 +140,10 @@ export default function (WrappedComponent) { policyMemberList: { key: props => `${ONYXKEYS.COLLECTION.POLICY_MEMBER_LIST}${getPolicyIDFromRoute(props.route)}`, }, - })(withPolicy); + })(withFullPolicy); } export { - policyPropTypes, - policyDefaultProps, + fullPolicyPropTypes, + fullPolicyDefaultProps, }; From dbde7cb6698270cdb3e3474822208f1363adba8d Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 13 Sep 2022 23:33:46 +0000 Subject: [PATCH 101/123] Update version to 1.2.0-1 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 6d255b30bbd0..1c763bbe0322 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020000 - versionName "1.2.0-0" + versionCode 1001020001 + versionName "1.2.0-1" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index abfba4e7a42e..bdd67ee9596f 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.0 + 1.2.0.1 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index cee9276b44e3..ffe355408294 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.0 + 1.2.0.1 diff --git a/package-lock.json b/package-lock.json index 51d098c57b64..d5f14734b6aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-0", + "version": "1.2.0-1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-0", + "version": "1.2.0-1", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 952b00a1de18..2c15140ec557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-0", + "version": "1.2.0-1", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From bab2d0b853c1ac07290fa45421924d9eb75e4c34 Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Wed, 14 Sep 2022 11:48:35 -0700 Subject: [PATCH 102/123] Empty PR to CP to staging, to trigger new staging deploy From f4392a51e5be969ad86c0bee4746ce4e0831345c Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 14 Sep 2022 20:16:53 +0000 Subject: [PATCH 103/123] Update version to 1.2.0-2 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 1c763bbe0322..79bde43a3489 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020001 - versionName "1.2.0-1" + versionCode 1001020002 + versionName "1.2.0-2" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index bdd67ee9596f..3822af1db3c1 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.1 + 1.2.0.2 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index ffe355408294..822157be53fe 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.1 + 1.2.0.2 diff --git a/package-lock.json b/package-lock.json index 1d2e6ea45ed5..781d6fe121e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-1", + "version": "1.2.0-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-1", + "version": "1.2.0-2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 297038eb0441..6483e40e3cab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-1", + "version": "1.2.0-2", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From efc144b57a68e3263c71be5b896d8de14f572817 Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Wed, 14 Sep 2022 13:32:22 -0700 Subject: [PATCH 104/123] Dummy change to allow new staging CP --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb3a256efd22..20d4921fc261 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,7 @@ This application is built with the following principles. 1. **Cross Platform 99.9999%** 1. A feature isn't done until it works on all platforms. Accordingly, don't even bother writing a platform-specific code block because you're just going to need to undo it. - 1. If the reason you can't write cross platform code is because there is a bug in ReactNative that is preventing it from working, the correct action is to fix RN and submit a PR upstream -- not to hack around RN bugs with platform-specific code paths. + 1. If the reason you can't write cross-platform code is because there is a bug in ReactNative that is preventing it from working, the correct action is to fix RN and submit a PR upstream -- not to hack around RN bugs with platform-specific code paths. 1. If there is a feature that simply doesn't exist on all platforms and thus doesn't exist in RN, rather than doing if (platform=iOS) { }, instead write a "shim" library that is implemented with NOOPs on the other platforms. For example, rather than injecting platform-specific multi-tab code (which can only work on browsers, because it's the only platform with multiple tabs), write a TabManager class that just is NOOP for non-browser platforms. This encapsulates the platform-specific code into a platform library, rather than sprinkling through the business logic. 1. Put all platform specific code in dedicated files and folders, like /platform, and reject any PR that attempts to put platform-specific code anywhere else. This maintains a strict separation between business logic and platform code. From 71a75717835b8ad3758baf1988b82a5c74e8db4b Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 14 Sep 2022 20:40:45 +0000 Subject: [PATCH 105/123] Update version to 1.2.0-3 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 79bde43a3489..ce4081548358 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020002 - versionName "1.2.0-2" + versionCode 1001020003 + versionName "1.2.0-3" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 3822af1db3c1..87d627262c98 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.2 + 1.2.0.3 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 822157be53fe..2cb28eee4959 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.2 + 1.2.0.3 diff --git a/package-lock.json b/package-lock.json index 781d6fe121e5..d84fad11ceaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-2", + "version": "1.2.0-3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-2", + "version": "1.2.0-3", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 6483e40e3cab..4b41be8d1189 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-2", + "version": "1.2.0-3", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From ab9fb29779fd252c0ee3bfaa58d50d9b0a29e981 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 14 Sep 2022 15:12:52 -0600 Subject: [PATCH 106/123] add errorutils --- src/pages/ReimbursementAccount/ReimbursementAccountForm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js index f7e29bdd2ced..5b44e4b55571 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js @@ -13,6 +13,7 @@ import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButto import CONST from '../../CONST'; import FormScrollView from '../../components/FormScrollView'; import * as BankAccounts from '../../libs/actions/BankAccounts'; +import * as ErrorUtils from '../../libs/ErrorUtils'; const propTypes = { /** Data for the bank account actively being set up */ @@ -58,7 +59,7 @@ class ReimbursementAccountForm extends React.Component { onFixTheErrorsLinkPressed={() => { this.form.scrollTo({y: 0, animated: true}); }} - message={this.props.reimbursementAccount.error || _.values(this.props.reimbursementAccount.errors)[0]} + message={this.props.reimbursementAccount.error || ErrorUtils.getLastestErrorMessage(this.props.reimbursementAccount.errors)} isMessageHtml={this.props.reimbursementAccount.isErrorHtml} isLoading={this.props.reimbursementAccount.loading || this.props.reimbursementAccount.isLoading} /> From f6dd0d7b8da5b9f2aedce6a6e23faa401842e4f8 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 14 Sep 2022 15:15:03 -0600 Subject: [PATCH 107/123] fix function name --- src/pages/ReimbursementAccount/ReimbursementAccountForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js index 5b44e4b55571..3542131a5710 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js @@ -59,7 +59,7 @@ class ReimbursementAccountForm extends React.Component { onFixTheErrorsLinkPressed={() => { this.form.scrollTo({y: 0, animated: true}); }} - message={this.props.reimbursementAccount.error || ErrorUtils.getLastestErrorMessage(this.props.reimbursementAccount.errors)} + message={this.props.reimbursementAccount.error || ErrorUtils.getLatestErrorMessage(this.props.reimbursementAccount.errors)} isMessageHtml={this.props.reimbursementAccount.isErrorHtml} isLoading={this.props.reimbursementAccount.loading || this.props.reimbursementAccount.isLoading} /> From 3c097924a3403d1db36f3e8fded9b668f36143b3 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 14 Sep 2022 15:56:47 -0600 Subject: [PATCH 108/123] use correct error path, create getErrorMessage --- src/pages/ReimbursementAccount/ReimbursementAccountForm.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js index 3542131a5710..48c24e620a29 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountForm.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountForm.js @@ -34,6 +34,11 @@ class ReimbursementAccountForm extends React.Component { BankAccounts.resetReimbursementAccount(); } + getErrorMessage() { + const latestErrorMessage = ErrorUtils.getLatestErrorMessage(this.props.reimbursementAccount); + return this.props.reimbursementAccount.error || (typeof latestErrorMessage === 'string' ? latestErrorMessage : ''); + } + render() { const isErrorVisible = _.size(lodashGet(this.props, 'reimbursementAccount.errors', {})) > 0 || lodashGet(this.props, 'reimbursementAccount.error', '').length > 0; @@ -59,7 +64,7 @@ class ReimbursementAccountForm extends React.Component { onFixTheErrorsLinkPressed={() => { this.form.scrollTo({y: 0, animated: true}); }} - message={this.props.reimbursementAccount.error || ErrorUtils.getLatestErrorMessage(this.props.reimbursementAccount.errors)} + message={this.getErrorMessage()} isMessageHtml={this.props.reimbursementAccount.isErrorHtml} isLoading={this.props.reimbursementAccount.loading || this.props.reimbursementAccount.isLoading} /> From fc4f8c6b9facd6af9a34711f43f622be8cf59e21 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 15 Sep 2022 11:27:14 +0100 Subject: [PATCH 109/123] do not pass default avatar when building option --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 2ab2d89ee9c8..b56c08f7ca5a 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -349,7 +349,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { result.text = reportName; result.subtitle = subtitle; result.participantsList = personalDetailList; - result.icons = ReportUtils.getIcons(report, personalDetails, policies, personalDetail.avatar); + result.icons = ReportUtils.getIcons(report, personalDetails, policies); result.searchText = getSearchText(report, reportName, personalDetailList, result.isChatRoom || result.isPolicyExpenseChat); return result; From 53c53a69d0fff8dc58aae580cf384ac75c3f0697 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 15 Sep 2022 10:44:15 +0000 Subject: [PATCH 110/123] Update version to 1.2.0-4 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index ce4081548358..b683c8e32809 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020003 - versionName "1.2.0-3" + versionCode 1001020004 + versionName "1.2.0-4" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 87d627262c98..cea7a6ce044c 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.3 + 1.2.0.4 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 2cb28eee4959..3a11abf9877f 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.3 + 1.2.0.4 diff --git a/package-lock.json b/package-lock.json index d84fad11ceaa..85d48adab0bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-3", + "version": "1.2.0-4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-3", + "version": "1.2.0-4", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4b41be8d1189..af9bb8549e34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-3", + "version": "1.2.0-4", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From a8bc73441f747f054bab73309777d5639295cffc Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Thu, 15 Sep 2022 15:09:53 +0100 Subject: [PATCH 111/123] Update param type --- src/libs/actions/Wallet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index a4e75f49d010..262eee68e9f9 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -529,7 +529,7 @@ function updateCurrentStep(currentStep) { } /** - * @param {Object} answers + * @param {Array} answers * @param {String} idNumber */ function answerQuestionsForWallet(answers, idNumber) { From 5ed68a88b722a944020c1739ed53bf17388ecc19 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Thu, 15 Sep 2022 09:13:47 -0600 Subject: [PATCH 112/123] rm unused consts --- src/CONST.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index dc1a653bcd4e..c0b07509bd72 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -52,8 +52,6 @@ const CONST = { MAX_ROUTING_NUMBER: '402 Maximum Size Exceeded routingNumber', MISSING_INCORPORATION_STATE: '402 Missing incorporationState in additionalData', MISSING_INCORPORATION_TYPE: '402 Missing incorporationType in additionalData', - MAX_VALIDATION_ATTEMPTS_REACHED: 'Validation for this bank account has been disabled due to too many incorrect attempts. Please contact us.', - INCORRECT_VALIDATION_AMOUNTS: 'The validate code you entered is incorrect, please try again.', }, STEP: { // In the order they appear in the VBA flow From 37060d0349a1912d0b378134b019d046409bef91 Mon Sep 17 00:00:00 2001 From: Ionatan Wiznia Date: Thu, 15 Sep 2022 17:27:11 +0200 Subject: [PATCH 113/123] Improve logging for api requests --- src/libs/Middleware/Logging.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/libs/Middleware/Logging.js b/src/libs/Middleware/Logging.js index fe63e16291ad..4586eeb2a8a5 100644 --- a/src/libs/Middleware/Logging.js +++ b/src/libs/Middleware/Logging.js @@ -58,7 +58,7 @@ function Logging(response, request) { // Cancelled requests are normal and can happen when a user logs out. No extra handling is needed here besides // remove the request from the PersistedRequests if the request exists. if (error.name === CONST.ERROR.REQUEST_CANCELLED) { - Log.info('[Network] Error: Request canceled', false, request); + Log.info('[Network] API request error: Request canceled', false, request); if (persisted) { PersistedRequests.remove(request); } @@ -66,11 +66,17 @@ function Logging(response, request) { // Re-throw this error so the next handler can manage it throw error; } + const logParams = { + message: error.message, + status: error.status, + title: error.title, + request, + }; if (error.message === CONST.ERROR.FAILED_TO_FETCH) { // Throw when we get a "Failed to fetch" error so we can retry. Very common if a user is offline or experiencing an unlikely scenario like // incorrect url, bad cors headers returned by the server, DNS lookup failure etc. - Log.hmmm('[Network] Error: Failed to fetch', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: Failed to fetch', logParams); } else if (_.contains([ CONST.ERROR.IOS_NETWORK_CONNECTION_LOST, CONST.ERROR.NETWORK_REQUEST_FAILED, @@ -80,37 +86,33 @@ function Logging(response, request) { ], error.message)) { // These errors seem to happen for native devices with interrupted connections. Often we will see logs about Pusher disconnecting together with these. // This type of error may also indicate a problem with SSL certs. - Log.hmmm('[Network] Error: Connection interruption likely', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: Connection interruption likely', logParams); } else if (_.contains([CONST.ERROR.FIREFOX_DOCUMENT_LOAD_ABORTED, CONST.ERROR.SAFARI_DOCUMENT_LOAD_ABORTED], error.message)) { // This message can be observed page load is interrupted (closed or navigated away). - Log.hmmm('[Network] Error: User likely navigated away from or closed browser', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: User likely navigated away from or closed browser', logParams); } else if (error.message === CONST.ERROR.IOS_LOAD_FAILED) { // Not yet clear why this message occurs, but it is specific to iOS and tends to happen around the same time as a Pusher code 1006 // which is when a websocket disconnects. So it seems likely to be a spotty connection scenario. - Log.hmmm('[Network] Error: iOS Load Failed error', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: iOS Load Failed error', logParams); } else if (error.message === CONST.ERROR.SAFARI_CANNOT_PARSE_RESPONSE) { // Another cryptic Apple error message. Unclear why this can happen, but some speculation it can be fixed by a browser restart. - Log.hmmm('[Network] Error: Safari "cannot parse response"', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: Safari "cannot parse response"', logParams); } else if (error.message === CONST.ERROR.GATEWAY_TIMEOUT) { // This error seems to only throw on dev when localhost:8080 tries to access the production web server. It's unclear whether this can happen on production or if // it's a sign that the web server is down. - Log.hmmm('[Network] Error: Gateway Timeout error', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: Gateway Timeout error', logParams); } else if (request.command === 'AuthenticatePusher') { // AuthenticatePusher requests can return with fetch errors and no message. It happens because we return a non 200 header like 403 Forbidden. // This is common to see if we are subscribing to a bad channel related to something the user shouldn't be able to access. There's no additional information // we can get about these requests. - Log.hmmm('[Network] Error: AuthenticatePusher', {message: error.message, status: error.status}); + Log.hmmm('[Network] API request error: AuthenticatePusher', logParams); } else if (error.message === CONST.ERROR.EXPENSIFY_SERVICE_INTERRUPTED) { // Expensify site is down completely OR // Auth (database connection) is down / bedrock has timed out while making a request. We currently can't tell the difference between Auth down and bedrock timing out. - Log.hmmm('[Network] Error: Expensify service interrupted or timed out', {error: error.title, status: error.status}); + Log.hmmm('[Network] API request error: Expensify service interrupted or timed out', logParams); } else { // If we get any error that is not known log an alert so we can learn more about it and document it here. - Log.alert(`${CONST.ERROR.ENSURE_BUGBOT} unknown error caught while processing request - ${error.message}`, { - command: request.command, - message: error.message, - status: error.status, - }, false); + Log.alert(`${CONST.ERROR.ENSURE_BUGBOT} unknown API request error caught while processing request`, logParams, false); } throw new Error(CONST.ERROR.XHR_FAILED); From c38bd3d62cce54c2e9398e38e8036bb65c0650cf Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 15 Sep 2022 18:30:15 +0100 Subject: [PATCH 114/123] Fix the c+ checklist template --- .../javascript/contributorChecklist/contributorChecklist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/javascript/contributorChecklist/contributorChecklist.js b/.github/actions/javascript/contributorChecklist/contributorChecklist.js index 62036078d24c..552e1c374071 100644 --- a/.github/actions/javascript/contributorChecklist/contributorChecklist.js +++ b/.github/actions/javascript/contributorChecklist/contributorChecklist.js @@ -65,7 +65,7 @@ const completedContributorPlusChecklist = `- [x] I have verified the author chec - [x] Android / Chrome - [x] MacOS / Chrome - [x] MacOS / Desktop -- [x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed) +- [x] If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack - [x] I verified proper code patterns were followed (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code)) - [x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. \`toggleReport\` and not \`onIconClick\`). - [x] I verified that comments were added to code that is not self explanatory From be75ac25965f2ffcb656d2df5fc9cf5ffd726a96 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 15 Sep 2022 17:31:00 +0000 Subject: [PATCH 115/123] Update version to 1.2.0-5 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index b683c8e32809..2bc3c6839023 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020004 - versionName "1.2.0-4" + versionCode 1001020005 + versionName "1.2.0-5" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index cea7a6ce044c..25250fb78772 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.4 + 1.2.0.5 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 3a11abf9877f..e9b832b4f5cc 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.4 + 1.2.0.5 diff --git a/package-lock.json b/package-lock.json index 85d48adab0bc..c0c4cbb1ac54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-4", + "version": "1.2.0-5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-4", + "version": "1.2.0-5", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index af9bb8549e34..b466d4d45bbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-4", + "version": "1.2.0-5", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From c1c41bd975f1654a60c219efd059aab031f43198 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 15 Sep 2022 18:41:54 +0100 Subject: [PATCH 116/123] Build the actions --- .github/actions/javascript/contributorChecklist/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/javascript/contributorChecklist/index.js b/.github/actions/javascript/contributorChecklist/index.js index 1041b6906cfd..94d6cf8e0829 100644 --- a/.github/actions/javascript/contributorChecklist/index.js +++ b/.github/actions/javascript/contributorChecklist/index.js @@ -75,7 +75,7 @@ const completedContributorPlusChecklist = `- [x] I have verified the author chec - [x] Android / Chrome - [x] MacOS / Chrome - [x] MacOS / Desktop -- [x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed) +- [x] If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack - [x] I verified proper code patterns were followed (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code)) - [x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. \`toggleReport\` and not \`onIconClick\`). - [x] I verified that comments were added to code that is not self explanatory From 536f5395cb28cfb0bc3e6359c31f3c3cef728265 Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Thu, 15 Sep 2022 13:44:21 -0700 Subject: [PATCH 117/123] Use existing personal detail's avatar when it exists --- src/libs/OptionsListUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index b56c08f7ca5a..6d58122f0423 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -272,7 +272,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { const personalDetailMap = getPersonalDetailsForLogins(logins, personalDetails); const personalDetailList = _.values(personalDetailMap); - const personalDetail = personalDetailList[0]; + const personalDetail = personalDetailList[0] || {}; let hasMultipleParticipants = personalDetailList.length > 1; let subtitle; @@ -349,7 +349,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { result.text = reportName; result.subtitle = subtitle; result.participantsList = personalDetailList; - result.icons = ReportUtils.getIcons(report, personalDetails, policies); + result.icons = ReportUtils.getIcons(report, personalDetails, policies, personalDetail.avatar); result.searchText = getSearchText(report, reportName, personalDetailList, result.isChatRoom || result.isPolicyExpenseChat); return result; From 6328e5e9f7227c716ef141819c868e183da3d21d Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Thu, 15 Sep 2022 14:35:49 -0700 Subject: [PATCH 118/123] Add missing `alternateText` option in option --- src/libs/OptionsListUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 6d58122f0423..cc8a2b38b994 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -343,6 +343,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { result.login = personalDetail.login; result.phoneNumber = personalDetail.phoneNumber; result.payPalMeAddress = personalDetail.payPalMeAddress; + result.alternateText = Str.removeSMSDomain(personalDetail.login); } const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); From b25ec27b641fe8468011316a1704456d63ddbebf Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 15 Sep 2022 21:46:15 +0000 Subject: [PATCH 119/123] Update version to 1.2.0-6 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 2bc3c6839023..4f708c805d62 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020005 - versionName "1.2.0-5" + versionCode 1001020006 + versionName "1.2.0-6" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 25250fb78772..b61ebf609f94 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.5 + 1.2.0.6 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index e9b832b4f5cc..3ebed1a25b84 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.5 + 1.2.0.6 diff --git a/package-lock.json b/package-lock.json index c0c4cbb1ac54..0d14d4ef4171 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-5", + "version": "1.2.0-6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-5", + "version": "1.2.0-6", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index b466d4d45bbc..7b4887d093e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-5", + "version": "1.2.0-6", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 947a4fc6950e5a17bbe14143cdc5eb7b1555a36d Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 15 Sep 2022 22:32:31 +0000 Subject: [PATCH 120/123] Update version to 1.2.0-7 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 4f708c805d62..2494c07a08e7 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020006 - versionName "1.2.0-6" + versionCode 1001020007 + versionName "1.2.0-7" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b61ebf609f94..c5ab77c495f8 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.6 + 1.2.0.7 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 3ebed1a25b84..4552d4e4c02d 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.6 + 1.2.0.7 diff --git a/package-lock.json b/package-lock.json index 0d14d4ef4171..54086977ed84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-6", + "version": "1.2.0-7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-6", + "version": "1.2.0-7", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 7b4887d093e9..cfbca0601256 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-6", + "version": "1.2.0-7", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 193b8a342927c62d7cfc9b13afea66acd1400c9f Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Thu, 15 Sep 2022 15:55:54 -0700 Subject: [PATCH 121/123] Only use personal detail login as `alternateText` if we're not making the option for a report --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index cc8a2b38b994..9f86d55add8f 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -329,6 +329,7 @@ function createOption(logins, personalDetails, report, reportActions = {}, { } } else { result.keyForList = personalDetail.login; + result.alternateText = Str.removeSMSDomain(personalDetail.login); } if (result.hasOutstandingIOU) { @@ -343,7 +344,6 @@ function createOption(logins, personalDetails, report, reportActions = {}, { result.login = personalDetail.login; result.phoneNumber = personalDetail.phoneNumber; result.payPalMeAddress = personalDetail.payPalMeAddress; - result.alternateText = Str.removeSMSDomain(personalDetail.login); } const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); From e1efe56208b5185cd9f97d12ace1ba872f149f24 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 15 Sep 2022 23:19:28 +0000 Subject: [PATCH 122/123] Update version to 1.2.0-8 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 2494c07a08e7..77885e4bc00e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020007 - versionName "1.2.0-7" + versionCode 1001020008 + versionName "1.2.0-8" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index c5ab77c495f8..9ab467740b11 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.7 + 1.2.0.8 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 4552d4e4c02d..92ecd597d886 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0.7 + 1.2.0.8 diff --git a/package-lock.json b/package-lock.json index 54086977ed84..150485a684ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-7", + "version": "1.2.0-8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-7", + "version": "1.2.0-8", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index cfbca0601256..cc68c11ce720 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-7", + "version": "1.2.0-8", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 8abe3dd36d813505185ed71ee777adde4924f695 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Fri, 16 Sep 2022 01:28:51 +0000 Subject: [PATCH 123/123] Update version to 1.2.1-0 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 4 ++-- ios/NewExpensifyTests/Info.plist | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 77885e4bc00e..4ee66d3fb79d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001020008 - versionName "1.2.0-8" + versionCode 1001020100 + versionName "1.2.1-0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 9ab467740b11..99e91a3df77c 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.0 + 1.2.1 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.0.8 + 1.2.1.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 92ecd597d886..272bb944f4ff 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.0 + 1.2.1 CFBundleSignature ???? CFBundleVersion - 1.2.0.8 + 1.2.1.0 diff --git a/package-lock.json b/package-lock.json index 150485a684ea..50f91287d1fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.0-8", + "version": "1.2.1-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.0-8", + "version": "1.2.1-0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index cc68c11ce720..fb1a983ae489 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.0-8", + "version": "1.2.1-0", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",