From 0a220e3fd8f0f2aebb3f3c9796ca5265a147ba03 Mon Sep 17 00:00:00 2001 From: vladnobenladen Date: Wed, 17 Aug 2022 23:29:43 -0600 Subject: [PATCH 01/71] fix "Split bill- Own contact gets highlighted when you press down arrow and the highlight goes out of the screen when press down arrow" --- src/components/ArrowKeyFocusManager.js | 22 ++++++++++++------- .../OptionsSelector/BaseOptionsSelector.js | 7 ++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/components/ArrowKeyFocusManager.js b/src/components/ArrowKeyFocusManager.js index dcb915d46bcd..26c22488777b 100644 --- a/src/components/ArrowKeyFocusManager.js +++ b/src/components/ArrowKeyFocusManager.js @@ -10,6 +10,9 @@ const propTypes = { PropTypes.node, ]).isRequired, + /** Array of disabled indexes. */ + disabledIndexes: PropTypes.arrayOf(PropTypes.number), + /** The current focused index. */ focusedIndex: PropTypes.number.isRequired, @@ -20,6 +23,10 @@ const propTypes = { onFocusedIndexChanged: PropTypes.func.isRequired, }; +const defaultProps = { + disabledIndexes: [], +}; + class ArrowKeyFocusManager extends Component { componentDidMount() { const arrowUpConfig = CONST.KEYBOARD_SHORTCUTS.ARROW_UP; @@ -30,11 +37,10 @@ class ArrowKeyFocusManager extends Component { return; } - let newFocusedIndex = this.props.focusedIndex - 1; + let newFocusedIndex = this.props.focusedIndex > 0 ? this.props.focusedIndex - 1 : this.props.maxIndex; - // Wrap around to the bottom of the list - if (newFocusedIndex < 0) { - newFocusedIndex = this.props.maxIndex; + while (this.props.disabledIndexes.includes(newFocusedIndex)) { + newFocusedIndex = newFocusedIndex > 0 ? newFocusedIndex - 1 : this.props.maxIndex; } this.props.onFocusedIndexChanged(newFocusedIndex); @@ -45,11 +51,10 @@ class ArrowKeyFocusManager extends Component { return; } - let newFocusedIndex = this.props.focusedIndex + 1; + let newFocusedIndex = this.props.focusedIndex < this.props.maxIndex ? this.props.focusedIndex + 1 : 0; - // Wrap around to the top of the list - if (newFocusedIndex > this.props.maxIndex) { - newFocusedIndex = 0; + while (this.props.disabledIndexes.includes(newFocusedIndex)) { + newFocusedIndex = newFocusedIndex < this.props.maxIndex ? newFocusedIndex + 1 : 0; } this.props.onFocusedIndexChanged(newFocusedIndex); @@ -72,5 +77,6 @@ class ArrowKeyFocusManager extends Component { } ArrowKeyFocusManager.propTypes = propTypes; +ArrowKeyFocusManager.defaultProps = defaultProps; export default ArrowKeyFocusManager; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index ec2588185de6..0cdf65518bbf 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -144,6 +144,8 @@ class BaseOptionsSelector extends Component { */ flattenSections() { const allOptions = []; + this.disabledOptionsIndexes = []; + let index = 0; _.each(this.props.sections, (section, sectionIndex) => { _.each(section.data, (option, optionIndex) => { allOptions.push({ @@ -151,6 +153,10 @@ class BaseOptionsSelector extends Component { sectionIndex, index: optionIndex, }); + if (section.isDisabled || option.isDisabled) { + this.disabledOptionsIndexes.push(index); + } + index += 1; }); }); return allOptions; @@ -265,6 +271,7 @@ class BaseOptionsSelector extends Component { ) : ; return ( {} : this.updateFocusedIndex} From af713fbf9412be5c1d753ebc5b2a353a3f4ea71f Mon Sep 17 00:00:00 2001 From: Md Neyaz Ahmad Date: Mon, 22 Aug 2022 12:55:53 +0530 Subject: [PATCH 02/71] Setup staging environment api server --- src/CONFIG.js | 1 + src/CONST.js | 1 + src/components/TestToolMenu.js | 3 ++- src/libs/HttpUtils.js | 12 +++++++++--- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/CONFIG.js b/src/CONFIG.js index a60b17e1e75b..445516060c4d 100644 --- a/src/CONFIG.js +++ b/src/CONFIG.js @@ -52,6 +52,7 @@ export default { CONCIERGE_URL: conciergeUrl, }, IS_IN_PRODUCTION: Platform.OS === 'web' ? process.env.NODE_ENV === 'production' : !__DEV__, + IS_IN_STAGING: ENVIRONMENT === CONST.ENVIRONMENT.STAGING, IS_USING_LOCAL_WEB: useNgrok || expensifyURLRoot.includes('dev'), PUSHER: { APP_KEY: lodashGet(Config, 'PUSHER_APP_KEY', '268df511a204fbb60884'), diff --git a/src/CONST.js b/src/CONST.js index 0f90121754ea..4da5552e094f 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -233,6 +233,7 @@ const CONST = { FEES_URL: `${USE_EXPENSIFY_URL}/fees`, CFPB_PREPAID_URL: 'https://cfpb.gov/prepaid', STAGING_SECURE_URL: 'https://staging-secure.expensify.com/', + STAGING_URL: 'https://staging.expensify.com/', STAGING_NEW_EXPENSIFY_URL: 'https://staging.new.expensify.com', // Use Environment.getEnvironmentURL to get the complete URL with port number diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index f04ae6a26b92..50fd11850687 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import styles from '../styles/styles'; import Switch from './Switch'; import Text from './Text'; @@ -41,7 +42,7 @@ const TestToolMenu = props => ( This enables QA and internal testers to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. */} User.setShouldUseSecureStaging(!props.user.shouldUseSecureStaging)} /> diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index 3e93e318232e..e4d678b7dd60 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -1,4 +1,5 @@ import Onyx from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import _ from 'underscore'; import CONFIG from '../CONFIG'; import CONST from '../CONST'; @@ -8,7 +9,7 @@ import HttpsError from './Errors/HttpsError'; let shouldUseSecureStaging = false; Onyx.connect({ key: ONYXKEYS.USER, - callback: val => shouldUseSecureStaging = (val && _.isBoolean(val.shouldUseSecureStaging)) ? val.shouldUseSecureStaging : false, + callback: val => shouldUseSecureStaging = lodashGet(val, 'shouldUseSecureStaging', true), }); let shouldFailAllRequests = false; @@ -94,9 +95,14 @@ function xhr(command, data, type = CONST.NETWORK.METHOD.POST, shouldUseSecure = formData.append(key, val); }); - let apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL : CONFIG.EXPENSIFY.URL_API_ROOT; - if (shouldUseSecure && shouldUseSecureStaging) { + let apiRoot = CONFIG.IS_IN_STAGING ? CONST.STAGING_URL : CONFIG.EXPENSIFY.URL_API_ROOT; + + if (shouldUseSecure) { + apiRoot = CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL; + } + + if (shouldUseSecure && CONFIG.IS_IN_STAGING && shouldUseSecureStaging) { apiRoot = CONST.STAGING_SECURE_URL; } From 704d6548269a0aea2ad204da3248b3ad8f80f3f0 Mon Sep 17 00:00:00 2001 From: vladnobenladen Date: Mon, 22 Aug 2022 05:22:29 -0600 Subject: [PATCH 03/71] fix "highlight goes out of screen when press down arrow" --- src/components/OptionsSelector/BaseOptionsSelector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 0cdf65518bbf..f6aa63aecaaa 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -273,7 +273,7 @@ class BaseOptionsSelector extends Component { {} : this.updateFocusedIndex} > From 39cd6a9266beaa631a4da59f5576af506e531449 Mon Sep 17 00:00:00 2001 From: Md Neyaz Ahmad Date: Mon, 22 Aug 2022 18:49:53 +0530 Subject: [PATCH 04/71] Rename variable names --- src/components/TestToolMenu.js | 10 +++++----- src/libs/HttpUtils.js | 6 +++--- src/libs/actions/User.js | 8 ++++---- src/pages/settings/PreferencesPage.js | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 50fd11850687..5caf75cad3fb 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -19,7 +19,7 @@ const propTypes = { /** User object in Onyx */ user: PropTypes.shape({ /** Whether we should use the staging version of the secure API server */ - shouldUseSecureStaging: PropTypes.bool, + useStagingServer: PropTypes.bool, }), /** Network object in Onyx */ @@ -28,7 +28,7 @@ const propTypes = { const defaultProps = { user: { - shouldUseSecureStaging: false, + useStagingServer: false, }, }; @@ -40,10 +40,10 @@ const TestToolMenu = props => ( {/* Option to switch from using the staging secure endpoint or the production secure endpoint. This enables QA and internal testers to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. */} - + User.setShouldUseSecureStaging(!props.user.shouldUseSecureStaging)} + isOn={lodashGet(props, 'user.useStagingServer', true)} + onToggle={() => User.setUseStagingServer(!props.user.useStagingServer)} /> diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index e4d678b7dd60..e0d9cd351bbe 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -6,10 +6,10 @@ import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import HttpsError from './Errors/HttpsError'; -let shouldUseSecureStaging = false; +let useStagingServer = false; Onyx.connect({ key: ONYXKEYS.USER, - callback: val => shouldUseSecureStaging = lodashGet(val, 'shouldUseSecureStaging', true), + callback: val => useStagingServer = lodashGet(val, 'useStagingServer', true), }); let shouldFailAllRequests = false; @@ -102,7 +102,7 @@ function xhr(command, data, type = CONST.NETWORK.METHOD.POST, shouldUseSecure = apiRoot = CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL; } - if (shouldUseSecure && CONFIG.IS_IN_STAGING && shouldUseSecureStaging) { + if (shouldUseSecure && CONFIG.IS_IN_STAGING && useStagingServer) { apiRoot = CONST.STAGING_SECURE_URL; } diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index a7b71d9fd3b5..371a3a27cb38 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -426,10 +426,10 @@ function updateChatPriorityMode(mode) { } /** - * @param {Boolean} shouldUseSecureStaging + * @param {Boolean} useStagingServer */ -function setShouldUseSecureStaging(shouldUseSecureStaging) { - Onyx.merge(ONYXKEYS.USER, {shouldUseSecureStaging}); +function setUseStagingServer(useStagingServer) { + Onyx.merge(ONYXKEYS.USER, {useStagingServer}); } function clearUserErrorMessage() { @@ -484,7 +484,7 @@ export { isBlockedFromConcierge, subscribeToUserEvents, updatePreferredSkinTone, - setShouldUseSecureStaging, + setUseStagingServer, clearUserErrorMessage, subscribeToExpensifyCardUpdates, updateFrequentlyUsedEmojis, diff --git a/src/pages/settings/PreferencesPage.js b/src/pages/settings/PreferencesPage.js index c96edfffddd5..29c8bcd3f394 100755 --- a/src/pages/settings/PreferencesPage.js +++ b/src/pages/settings/PreferencesPage.js @@ -30,7 +30,7 @@ const propTypes = { user: PropTypes.shape({ /** Whether or not the user is subscribed to news updates */ isSubscribedToNewsletter: PropTypes.bool, - shouldUseSecureStaging: PropTypes.bool, + useStagingServer: PropTypes.bool, }), ...withLocalizePropTypes, From 539de7018d643abbc709bf8cf0bd0b5617638291 Mon Sep 17 00:00:00 2001 From: Md Neyaz Ahmad Date: Mon, 22 Aug 2022 18:56:09 +0530 Subject: [PATCH 05/71] Refactor HttpUtils --- src/libs/HttpUtils.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index e0d9cd351bbe..650b20e4571c 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -96,14 +96,10 @@ function xhr(command, data, type = CONST.NETWORK.METHOD.POST, shouldUseSecure = formData.append(key, val); }); - let apiRoot = CONFIG.IS_IN_STAGING ? CONST.STAGING_URL : CONFIG.EXPENSIFY.URL_API_ROOT; + let apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL : CONFIG.EXPENSIFY.URL_API_ROOT; - if (shouldUseSecure) { - apiRoot = CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL; - } - - if (shouldUseSecure && CONFIG.IS_IN_STAGING && useStagingServer) { - apiRoot = CONST.STAGING_SECURE_URL; + if (CONFIG.IS_IN_STAGING) { + apiRoot = shouldUseSecure && useStagingServer ? CONST.STAGING_SECURE_URL : CONST.STAGING_URL; } return processHTTPRequest(`${apiRoot}api?command=${command}`, type, formData, data.canCancel); From 6659103d2a0024166bb51597577d0ccce888c315 Mon Sep 17 00:00:00 2001 From: Md Neyaz Ahmad Date: Mon, 22 Aug 2022 19:09:08 +0530 Subject: [PATCH 06/71] Update staging server condition --- src/libs/HttpUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index 650b20e4571c..451c1e153b78 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -98,8 +98,8 @@ function xhr(command, data, type = CONST.NETWORK.METHOD.POST, shouldUseSecure = let apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL : CONFIG.EXPENSIFY.URL_API_ROOT; - if (CONFIG.IS_IN_STAGING) { - apiRoot = shouldUseSecure && useStagingServer ? CONST.STAGING_SECURE_URL : CONST.STAGING_URL; + if (CONFIG.IS_IN_STAGING && useStagingServer) { + apiRoot = shouldUseSecure ? CONST.STAGING_SECURE_URL : CONST.STAGING_URL; } return processHTTPRequest(`${apiRoot}api?command=${command}`, type, formData, data.canCancel); From 342481d97c0bb674430c504c758c78fad0dd34f0 Mon Sep 17 00:00:00 2001 From: vladnobenladen Date: Tue, 23 Aug 2022 12:59:05 -0600 Subject: [PATCH 07/71] handle case of all options are disabled --- src/components/ArrowKeyFocusManager.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/ArrowKeyFocusManager.js b/src/components/ArrowKeyFocusManager.js index 26c22488777b..5e411fd075bd 100644 --- a/src/components/ArrowKeyFocusManager.js +++ b/src/components/ArrowKeyFocusManager.js @@ -37,10 +37,14 @@ class ArrowKeyFocusManager extends Component { return; } - let newFocusedIndex = this.props.focusedIndex > 0 ? this.props.focusedIndex - 1 : this.props.maxIndex; + const currentFocusedIndex = this.props.focusedIndex > 0 ? this.props.focusedIndex - 1 : this.props.maxIndex; + let newFocusedIndex = currentFocusedIndex; while (this.props.disabledIndexes.includes(newFocusedIndex)) { newFocusedIndex = newFocusedIndex > 0 ? newFocusedIndex - 1 : this.props.maxIndex; + if (newFocusedIndex === currentFocusedIndex) { // all indexes are disabled + return; // no-op + } } this.props.onFocusedIndexChanged(newFocusedIndex); @@ -51,10 +55,14 @@ class ArrowKeyFocusManager extends Component { return; } - let newFocusedIndex = this.props.focusedIndex < this.props.maxIndex ? this.props.focusedIndex + 1 : 0; + const currentFocusedIndex = this.props.focusedIndex < this.props.maxIndex ? this.props.focusedIndex + 1 : 0; + let newFocusedIndex = currentFocusedIndex; while (this.props.disabledIndexes.includes(newFocusedIndex)) { newFocusedIndex = newFocusedIndex < this.props.maxIndex ? newFocusedIndex + 1 : 0; + if (newFocusedIndex === currentFocusedIndex) { // all indexes are disabled + return; // no-op + } } this.props.onFocusedIndexChanged(newFocusedIndex); From d44c976c99530797e3816cb51d4ee39157efb889 Mon Sep 17 00:00:00 2001 From: vladnobenladen Date: Wed, 24 Aug 2022 22:58:38 -0600 Subject: [PATCH 08/71] handle case of single option --- src/components/ArrowKeyFocusManager.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/ArrowKeyFocusManager.js b/src/components/ArrowKeyFocusManager.js index 5e411fd075bd..98d777f38f35 100644 --- a/src/components/ArrowKeyFocusManager.js +++ b/src/components/ArrowKeyFocusManager.js @@ -33,10 +33,6 @@ class ArrowKeyFocusManager extends Component { const arrowDownConfig = CONST.KEYBOARD_SHORTCUTS.ARROW_DOWN; this.unsubscribeArrowUpKey = KeyboardShortcut.subscribe(arrowUpConfig.shortcutKey, () => { - if (this.props.maxIndex < 1) { - return; - } - const currentFocusedIndex = this.props.focusedIndex > 0 ? this.props.focusedIndex - 1 : this.props.maxIndex; let newFocusedIndex = currentFocusedIndex; @@ -51,10 +47,6 @@ class ArrowKeyFocusManager extends Component { }, arrowUpConfig.descriptionKey, arrowUpConfig.modifiers, true); this.unsubscribeArrowDownKey = KeyboardShortcut.subscribe(arrowDownConfig.shortcutKey, () => { - if (this.props.maxIndex < 1) { - return; - } - const currentFocusedIndex = this.props.focusedIndex < this.props.maxIndex ? this.props.focusedIndex + 1 : 0; let newFocusedIndex = currentFocusedIndex; From 9551d6f12aba64c3aefc56e62e16ea13fea5db02 Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Thu, 25 Aug 2022 15:26:24 +0200 Subject: [PATCH 09/71] Add new prop types, use `OfflineWithFeedback` on base payment page --- src/pages/EnablePayments/TermsStep.js | 12 +++++------- src/pages/EnablePayments/walletTermsPropTypes.js | 7 +++++++ .../Payments/PaymentsPage/BasePaymentsPage.js | 12 +++++++++++- .../Payments/PaymentsPage/paymentsPagePropTypes.js | 5 +++++ 4 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 src/pages/EnablePayments/walletTermsPropTypes.js diff --git a/src/pages/EnablePayments/TermsStep.js b/src/pages/EnablePayments/TermsStep.js index 7c470c3b74c6..41c5285c5b12 100644 --- a/src/pages/EnablePayments/TermsStep.js +++ b/src/pages/EnablePayments/TermsStep.js @@ -17,20 +17,18 @@ import Text from '../../components/Text'; import ShortTermsForm from './TermsPage/ShortTermsForm'; import LongTermsForm from './TermsPage/LongTermsForm'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; +import walletTermsPropTypes from './walletTermsPropTypes'; const propTypes = { /** Comes from Onyx. Information about the terms for the wallet */ - walletTerms: PropTypes.shape({ - /** Any additional error message to show */ - errors: PropTypes.objectOf(PropTypes.string), - }), + // eslint-disable-next-line react/no-unused-prop-types + walletTerms: PropTypes.objectOf(walletTermsPropTypes), + ...withLocalizePropTypes, }; const defaultProps = { - walletTerms: { - errors: null, - }, + walletTerms: {}, }; class TermsStep extends React.Component { diff --git a/src/pages/EnablePayments/walletTermsPropTypes.js b/src/pages/EnablePayments/walletTermsPropTypes.js new file mode 100644 index 000000000000..068b83f96943 --- /dev/null +++ b/src/pages/EnablePayments/walletTermsPropTypes.js @@ -0,0 +1,7 @@ +import PropTypes from 'prop-types'; + +/** */ +export default PropTypes.shape({ + /** Any error message to show */ + errors: PropTypes.objectOf(PropTypes.string), +}); diff --git a/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js b/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js index 148f27fa8672..f4575504f176 100644 --- a/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js @@ -275,7 +275,14 @@ class BasePaymentsPage extends React.Component { {Permissions.canUseWallet(this.props.betas) && ( <> - + {}} + errorRowStyles={[styles.ml10, styles.mr2]} + > + + {this.props.userWallet.currentBalance > 0 && ( Date: Thu, 25 Aug 2022 15:37:35 +0200 Subject: [PATCH 10/71] Red brick road for WalletTerms errors --- src/components/AvatarWithIndicator.js | 11 ++++++++++- src/pages/settings/InitialSettingsPage.js | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/AvatarWithIndicator.js b/src/components/AvatarWithIndicator.js index 2de828d4ef2e..2d462a882b5c 100644 --- a/src/components/AvatarWithIndicator.js +++ b/src/components/AvatarWithIndicator.js @@ -11,6 +11,7 @@ import policyMemberPropType from '../pages/policyMemberPropType'; import bankAccountPropTypes from './bankAccountPropTypes'; import cardPropTypes from './cardPropTypes'; import userWalletPropTypes from '../pages/EnablePayments/userWalletPropTypes'; +import walletTermsPropTypes from '../pages/EnablePayments/walletTermsPropTypes'; import * as Policy from '../libs/actions/Policy'; import * as PaymentMethods from '../libs/actions/PaymentMethods'; @@ -35,6 +36,9 @@ const propTypes = { /** The user's wallet (coming from Onyx) */ userWallet: PropTypes.objectOf(userWalletPropTypes), + + /** Information about the user accepting the terms for payments */ + walletTerms: PropTypes.objectOf(walletTermsPropTypes), }; const defaultProps = { @@ -44,6 +48,7 @@ const defaultProps = { bankAccountList: {}, cardList: {}, userWallet: {}, + walletTerms: {}, }; const AvatarWithIndicator = (props) => { @@ -57,6 +62,7 @@ const AvatarWithIndicator = (props) => { const hasPolicyMemberError = _.some(props.policiesMemberList, policyMembers => Policy.hasPolicyMemberError(policyMembers)); const hasPaymentMethodError = PaymentMethods.hasPaymentMethodError(props.bankAccountList, props.cardList); const hasWalletError = !_.isEmpty(props.userWallet.errors); + const hasWalletTermsError = !_.isEmpty(props.walletTerms.errors); return ( @@ -65,7 +71,7 @@ const AvatarWithIndicator = (props) => { source={props.source} size={props.size} /> - {(hasPolicyMemberError || hasPaymentMethodError || hasWalletError) && ( + {(hasPolicyMemberError || hasPaymentMethodError || hasWalletError || hasWalletTermsError) && ( )} @@ -90,4 +96,7 @@ export default withOnyx({ userWallet: { key: ONYXKEYS.USER_WALLET, }, + walletTerms: { + key: ONYXKEYS.WALLET_TERMS, + }, })(AvatarWithIndicator); diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index 785e00322716..4e8eb23ab4f6 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -29,6 +29,7 @@ import policyMemberPropType from '../policyMemberPropType'; import * as PaymentMethods from '../../libs/actions/PaymentMethods'; import bankAccountPropTypes from '../../components/bankAccountPropTypes'; import cardPropTypes from '../../components/cardPropTypes'; +import walletTermsPropTypes from '../EnablePayments/walletTermsPropTypes'; const propTypes = { /* Onyx Props */ @@ -72,6 +73,9 @@ const propTypes = { /** List of betas available to current user */ betas: PropTypes.arrayOf(PropTypes.string), + /** Information about the user accepting the terms for payments */ + walletTerms: PropTypes.objectOf(walletTermsPropTypes), + ...withLocalizePropTypes, ...withCurrentUserPersonalDetailsPropTypes, }; @@ -84,6 +88,7 @@ const defaultProps = { }, betas: [], policyMembers: {}, + walletTerms: {}, ...withCurrentUserPersonalDetailsDefaultProps, }; @@ -120,7 +125,7 @@ const InitialSettingsPage = (props) => { translationKey: 'common.payments', icon: Expensicons.Wallet, action: () => { Navigation.navigate(ROUTES.SETTINGS_PAYMENTS); }, - brickRoadIndicator: PaymentMethods.hasPaymentMethodError(props.bankAccountList, props.cardList) || !_.isEmpty(props.userWallet.errors) ? 'error' : null, + brickRoadIndicator: PaymentMethods.hasPaymentMethodError(props.bankAccountList, props.cardList) || !_.isEmpty(props.userWallet.errors) || !_.isEmpty(props.walletTerms.errors) ? 'error' : null, }, { translationKey: 'initialSettingsPage.about', @@ -241,5 +246,8 @@ export default compose( cardList: { key: ONYXKEYS.CARD_LIST, }, + walletTerms: { + key: ONYXKEYS.WALLET_TERMS, + }, }), )(InitialSettingsPage); From c4d6940a9aa902c54c9ac0110fa10ede1e1cad2e Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Thu, 25 Aug 2022 15:59:33 +0200 Subject: [PATCH 11/71] Support clearing RBR wallet term errors --- src/libs/actions/PaymentMethods.js | 8 ++++++++ .../settings/Payments/PaymentsPage/BasePaymentsPage.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 9d648b489815..dceb2e87243d 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -321,6 +321,13 @@ function clearWalletError() { Onyx.merge(ONYXKEYS.USER_WALLET, {errors: null}); } +/** + * Clear any error(s) related to the user's wallet terms + */ +function clearWalletTermsError() { + Onyx.merge(ONYXKEYS.WALLET_TERMS, {errors: null}); +} + function deletePaymentCard(fundID) { API.write('DeletePaymentCard', { fundID, @@ -355,4 +362,5 @@ export { clearDeletePaymentMethodError, clearAddPaymentMethodError, clearWalletError, + clearWalletTermsError, }; diff --git a/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js b/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js index f4575504f176..f8ca36f575c1 100644 --- a/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js @@ -278,7 +278,7 @@ class BasePaymentsPage extends React.Component { {}} + onClose={PaymentMethods.clearWalletTermsError} errorRowStyles={[styles.ml10, styles.mr2]} > From 5c55d900b6abd3f4b9be27d0a1b3582c4081bb9a Mon Sep 17 00:00:00 2001 From: Francois Laithier Date: Thu, 25 Aug 2022 17:50:38 +0200 Subject: [PATCH 12/71] Make 'Continue' button text depend on source action --- src/components/KYCWall/BaseKYCWall.js | 2 ++ src/components/KYCWall/kycWallPropTypes.js | 4 +++ src/components/SettlementButton.js | 1 + src/languages/en.js | 2 ++ src/languages/es.js | 2 ++ src/libs/actions/Wallet.js | 10 +++++++ src/pages/EnablePayments/ActivateStep.js | 26 ++++++++++++++++--- .../EnablePayments/userWalletPropTypes.js | 3 +++ .../Payments/PaymentsPage/BasePaymentsPage.js | 1 + 9 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index d1bb9309579d..4c691b45ca54 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -11,6 +11,7 @@ import * as PaymentMethods from '../../libs/actions/PaymentMethods'; import ONYXKEYS from '../../ONYXKEYS'; import Log from '../../libs/Log'; import {propTypes, defaultProps} from './kycWallPropTypes'; +import * as Wallet from '../../libs/actions/Wallet'; // This component allows us to block various actions by forcing the user to first add a default payment method and successfully make it through our Know Your Customer flow // before continuing to take whatever action they originally intended to take. It requires a button as a child and a native event so we can get the coordinates and use it @@ -35,6 +36,7 @@ class KYCWall extends React.Component { if (this.props.shouldListenForResize) { this.dimensionsSubscription = Dimensions.addEventListener('change', this.setMenuPosition); } + Wallet.setKYCWallSourceAction(this.props.sourceAction); } componentWillUnmount() { diff --git a/src/components/KYCWall/kycWallPropTypes.js b/src/components/KYCWall/kycWallPropTypes.js index d2d5933fbc73..1441c74b7fa1 100644 --- a/src/components/KYCWall/kycWallPropTypes.js +++ b/src/components/KYCWall/kycWallPropTypes.js @@ -22,6 +22,9 @@ const propTypes = { /** The user's wallet */ userWallet: PropTypes.objectOf(userWalletPropTypes), + + /** The user action that led to opening the KYC wall */ + sourceAction: PropTypes.oneOf(['transferBalance', 'iou']), }; const defaultProps = { @@ -29,6 +32,7 @@ const defaultProps = { popoverPlacement: 'top', shouldListenForResize: false, isDisabled: false, + sourceAction: '', }; export {propTypes, defaultProps}; diff --git a/src/components/SettlementButton.js b/src/components/SettlementButton.js index 251a64d80c5c..38cf25cea25a 100644 --- a/src/components/SettlementButton.js +++ b/src/components/SettlementButton.js @@ -80,6 +80,7 @@ class SettlementButton extends React.Component { addBankAccountRoute={this.props.addBankAccountRoute} addDebitCardRoute={this.props.addDebitCardRoute} isDisabled={this.props.network.isOffline} + sourceAction="iou" > {triggerKYCFlow => ( @@ -55,7 +67,7 @@ class ActivateStep extends React.Component {