From d14002e29612f094aaf2d164e9927cef9befd304 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Mon, 23 Oct 2023 10:31:42 +0200 Subject: [PATCH 001/193] Rename wallet.js --- src/libs/actions/{Wallet.js => Wallet.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/libs/actions/{Wallet.js => Wallet.ts} (100%) diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.ts similarity index 100% rename from src/libs/actions/Wallet.js rename to src/libs/actions/Wallet.ts From 43eb52dd707d5815f34f1fa5b506fb3be55a2454 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Mon, 23 Oct 2023 11:27:57 +0200 Subject: [PATCH 002/193] [TS migration] Migrate 'Wallet.js' lib to TypeScript --- src/libs/actions/Wallet.ts | 120 +++++++++++----------- src/types/onyx/WalletAdditionalDetails.ts | 14 ++- src/types/onyx/WalletTerms.ts | 2 + src/types/onyx/index.ts | 3 +- 4 files changed, 74 insertions(+), 65 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 183920eccf21..fe4a2609eac5 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -1,6 +1,11 @@ -import Onyx from 'react-native-onyx'; +import Onyx, {OnyxUpdate} from 'react-native-onyx'; +import {ValueOf} from 'type-fest'; +import CONST from '../../CONST'; import ONYXKEYS from '../../ONYXKEYS'; +import * as OnyxCommon from '../../types/onyx/OnyxCommon'; import * as API from '../API'; +import {WalletAdditionalQuestionsDetails} from '../../types/onyx'; +import WalletOnfido from '../../types/onyx/WalletOnfido'; /** * Fetch and save locally the Onfido SDK token and applicantID @@ -9,20 +14,22 @@ import * as API from '../API'; * identity check. Note: This happens in Web-Secure when we call Activate_Wallet during the OnfidoStep. */ function openOnfidoFlow() { + const optimisticData: OnyxUpdate[] = [ + { + // Use Onyx.set() since we are resetting the Onfido flow completely. + onyxMethod: Onyx.METHOD.SET, + key: ONYXKEYS.WALLET_ONFIDO, + value: { + isLoading: true, + } as WalletOnfido, + }, + ]; + API.read( 'OpenOnfidoFlow', {}, { - optimisticData: [ - { - // Use Onyx.set() since we are resetting the Onfido flow completely. - onyxMethod: Onyx.METHOD.SET, - key: ONYXKEYS.WALLET_ONFIDO, - value: { - isLoading: true, - }, - }, - ], + optimisticData, successData: [ { onyxMethod: Onyx.METHOD.MERGE, @@ -45,57 +52,55 @@ function openOnfidoFlow() { ); } -/** - * @param {Array} questions - * @param {String} [idNumber] - */ -function setAdditionalDetailsQuestions(questions, idNumber) { +function setAdditionalDetailsQuestions(questions: WalletAdditionalQuestionsDetails, idNumber: string) { Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {questions, idNumber}); } -/** - * @param {Object} errorFields - */ -function setAdditionalDetailsErrors(errorFields) { +function setAdditionalDetailsErrors(errorFields: OnyxCommon.ErrorFields) { Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {errorFields: null}); Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {errorFields}); } -/** - * @param {String} additionalErrorMessage - */ -function setAdditionalDetailsErrorMessage(additionalErrorMessage) { +function setAdditionalDetailsErrorMessage(additionalErrorMessage: string) { Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {additionalErrorMessage}); } /** + * Save the source that triggered the KYC wall and optionally the chat report ID associated with the IOU - * - * @param {String} source - * @param {String} chatReportID */ -function setKYCWallSource(source, chatReportID = '') { +function setKYCWallSource(source: string, chatReportID = '') { Onyx.merge(ONYXKEYS.WALLET_TERMS, {source, chatReportID}); } +type PersonalDetails = { + phoneNumber?: string; + legalFirstName?: string; + legalLastName?: string; + addressStreet?: string; + addressCity?: string; + addressState?: string; + addressZip?: string; + dob?: string; + ssn?: string; +}; + /** * Validates a user's provided details against a series of checks - * - * @param {Object} personalDetails */ -function updatePersonalDetails(personalDetails) { +function updatePersonalDetails(personalDetails: PersonalDetails) { if (!personalDetails) { return; } - const firstName = personalDetails.legalFirstName || ''; - const lastName = personalDetails.legalLastName || ''; - const dob = personalDetails.dob || ''; - const addressStreet = personalDetails.addressStreet || ''; - const addressCity = personalDetails.addressCity || ''; - const addressState = personalDetails.addressState || ''; - const addressZip = personalDetails.addressZip || ''; - const ssn = personalDetails.ssn || ''; - const phoneNumber = personalDetails.phoneNumber || ''; + const firstName = personalDetails.legalFirstName ?? ''; + const lastName = personalDetails.legalLastName ?? ''; + const dob = personalDetails.dob ?? ''; + const addressStreet = personalDetails.addressStreet ?? ''; + const addressCity = personalDetails.addressCity ?? ''; + const addressState = personalDetails.addressState ?? ''; + const addressZip = personalDetails.addressZip ?? ''; + const ssn = personalDetails.ssn ?? ''; + const phoneNumber = personalDetails.phoneNumber ?? ''; API.write( 'UpdatePersonalDetailsForWallet', { @@ -143,16 +148,17 @@ function updatePersonalDetails(personalDetails) { ); } +type IdentityVerification = { + onfidoData: string; +}; + /** * Creates an identity check by calling Onfido's API with data returned from the SDK * * The API will always return the updated userWallet in the response as a convenience so we can avoid an additional * API request to fetch the userWallet after we call VerifyIdentity - * - * @param {Object} parameters - * @param {String} [parameters.onfidoData] - JSON string */ -function verifyIdentity(parameters) { +function verifyIdentity(parameters: IdentityVerification) { const onfidoData = parameters.onfidoData; API.write( @@ -203,14 +209,17 @@ function verifyIdentity(parameters) { ); } +type WalletTerms = { + hasAcceptedTerms: boolean; + chatReportID: number; +}; + /** * Complete the "Accept Terms" step of the wallet activation flow. * - * @param {Object} parameters - * @param {Boolean} parameters.hasAcceptedTerms - * @param {Number} parameters.chatReportID When accepting the terms of wallet to pay an IOU, indicates the parent chat ID of the IOU + * @param parameters.chatReportID When accepting the terms of wallet to pay an IOU, indicates the parent chat ID of the IOU */ -function acceptWalletTerms(parameters) { +function acceptWalletTerms(parameters: WalletTerms) { const optimisticData = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -255,7 +264,7 @@ function acceptWalletTerms(parameters) { * @property {('SILVER'|'GOLD')} tierName - will be GOLD when fully activated. SILVER is able to receive funds only. */ function openInitialSettingsPage() { - API.read('OpenInitialSettingsPage'); + API.read('OpenInitialSettingsPage', {}); } /** @@ -268,21 +277,14 @@ function openInitialSettingsPage() { * @property {('SILVER'|'GOLD')} tierName - will be GOLD when fully activated. SILVER is able to receive funds only. */ function openEnablePaymentsPage() { - API.read('OpenEnablePaymentsPage'); + API.read('OpenEnablePaymentsPage', {}); } -/** - * @param {String} currentStep - */ -function updateCurrentStep(currentStep) { +function updateCurrentStep(currentStep: ValueOf) { Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep}); } -/** - * @param {Array} answers - * @param {String} idNumber - */ -function answerQuestionsForWallet(answers, idNumber) { +function answerQuestionsForWallet(answers: unknown[], idNumber: string) { const idologyAnswers = JSON.stringify(answers); API.write( 'AnswerQuestionsForWallet', diff --git a/src/types/onyx/WalletAdditionalDetails.ts b/src/types/onyx/WalletAdditionalDetails.ts index e766ba4cfe50..eb804bdf2c2c 100644 --- a/src/types/onyx/WalletAdditionalDetails.ts +++ b/src/types/onyx/WalletAdditionalDetails.ts @@ -1,12 +1,14 @@ import * as OnyxCommon from './OnyxCommon'; +type WalletAdditionalQuestionsDetails = { + prompt: string; + type: string; + answer: string[]; +}; + type WalletAdditionalDetails = { /** Questions returned by Idology */ - questions?: { - prompt: string; - type: string; - answer: string[]; - }; + questions?: WalletAdditionalQuestionsDetails; /** ExpectID ID number related to those questions */ idNumber?: string; @@ -16,8 +18,10 @@ type WalletAdditionalDetails = { /** Which field needs attention? */ errorFields?: OnyxCommon.ErrorFields; + additionalErrorMessage?: string; isLoading?: boolean; errors?: OnyxCommon.Errors; }; export default WalletAdditionalDetails; +export type {WalletAdditionalQuestionsDetails}; diff --git a/src/types/onyx/WalletTerms.ts b/src/types/onyx/WalletTerms.ts index 5394f126c33c..ae79645a3751 100644 --- a/src/types/onyx/WalletTerms.ts +++ b/src/types/onyx/WalletTerms.ts @@ -6,6 +6,8 @@ type WalletTerms = { /** When the user accepts the Wallet's terms in order to pay an IOU, this is the ID of the chatReport the IOU is linked to */ chatReportID?: string; + + source?: string; }; export default WalletTerms; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 4603c4579343..c0cd7447de6a 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -18,7 +18,7 @@ import BlockedFromConcierge from './BlockedFromConcierge'; import PlaidData from './PlaidData'; import UserWallet from './UserWallet'; import WalletOnfido from './WalletOnfido'; -import WalletAdditionalDetails from './WalletAdditionalDetails'; +import WalletAdditionalDetails, {WalletAdditionalQuestionsDetails} from './WalletAdditionalDetails'; import WalletTerms from './WalletTerms'; import BankAccount from './BankAccount'; import Card from './Card'; @@ -70,6 +70,7 @@ export type { UserWallet, WalletOnfido, WalletAdditionalDetails, + WalletAdditionalQuestionsDetails, WalletTerms, BankAccount, Card, From 1d8e5ad4cf0318b0e98ab63540c99b431d4dfa97 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Tue, 24 Oct 2023 14:44:38 +0200 Subject: [PATCH 003/193] Resolve typecheck problems in Wallet.ts --- src/libs/actions/Wallet.ts | 257 ++++++++++++++++++--------------- src/types/onyx/WalletOnfido.ts | 4 +- 2 files changed, 142 insertions(+), 119 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index fe4a2609eac5..800efb90e40f 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -5,7 +5,6 @@ import ONYXKEYS from '../../ONYXKEYS'; import * as OnyxCommon from '../../types/onyx/OnyxCommon'; import * as API from '../API'; import {WalletAdditionalQuestionsDetails} from '../../types/onyx'; -import WalletOnfido from '../../types/onyx/WalletOnfido'; /** * Fetch and save locally the Onfido SDK token and applicantID @@ -21,7 +20,27 @@ function openOnfidoFlow() { key: ONYXKEYS.WALLET_ONFIDO, value: { isLoading: true, - } as WalletOnfido, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ONFIDO, + value: { + isLoading: false, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ONFIDO, + value: { + isLoading: false, + }, }, ]; @@ -30,24 +49,8 @@ function openOnfidoFlow() { {}, { optimisticData, - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ONFIDO, - value: { - isLoading: false, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ONFIDO, - value: { - isLoading: false, - }, - }, - ], + successData, + failureData, }, ); } @@ -101,6 +104,39 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { const addressZip = personalDetails.addressZip ?? ''; const ssn = personalDetails.ssn ?? ''; const phoneNumber = personalDetails.phoneNumber ?? ''; + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: true, + errors: null, + errorFields: null, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }, + ]; + API.write( 'UpdatePersonalDetailsForWallet', { @@ -115,35 +151,9 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { phoneNumber, }, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - value: { - isLoading: true, - errors: null, - errorFields: null, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - value: { - isLoading: false, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - value: { - isLoading: false, - }, - }, - ], + optimisticData, + successData, + failureData, }, ); } @@ -161,50 +171,56 @@ type IdentityVerification = { function verifyIdentity(parameters: IdentityVerification) { const onfidoData = parameters.onfidoData; + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ONFIDO, + value: { + isLoading: true, + errors: null, + fixableErrors: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.USER_WALLET, + value: { + shouldShowFailedKYC: false, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ONFIDO, + value: { + isLoading: false, + errors: null, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ONFIDO, + value: { + isLoading: false, + hasAcceptedPrivacyPolicy: false, + }, + }, + ]; + API.write( 'VerifyIdentity', { onfidoData, }, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ONFIDO, - value: { - isLoading: true, - errors: null, - fixableErrors: null, - }, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.USER_WALLET, - value: { - shouldShowFailedKYC: false, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ONFIDO, - value: { - isLoading: false, - errors: null, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ONFIDO, - value: { - isLoading: false, - hasAcceptedPrivacyPolicy: false, - }, - }, - ], + optimisticData, + successData, + failureData, }, ); } @@ -220,7 +236,7 @@ type WalletTerms = { * @param parameters.chatReportID When accepting the terms of wallet to pay an IOU, indicates the parent chat ID of the IOU */ function acceptWalletTerms(parameters: WalletTerms) { - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.USER_WALLET, @@ -230,7 +246,7 @@ function acceptWalletTerms(parameters: WalletTerms) { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.WALLET_TERMS, @@ -240,7 +256,7 @@ function acceptWalletTerms(parameters: WalletTerms) { }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.USER_WALLET, @@ -286,6 +302,37 @@ function updateCurrentStep(currentStep: ValueOf) { function answerQuestionsForWallet(answers: unknown[], idNumber: string) { const idologyAnswers = JSON.stringify(answers); + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: true, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }, + ]; + API.write( 'AnswerQuestionsForWallet', { @@ -293,33 +340,9 @@ function answerQuestionsForWallet(answers: unknown[], idNumber: string) { idNumber, }, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - value: { - isLoading: true, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - value: { - isLoading: false, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - value: { - isLoading: false, - }, - }, - ], + optimisticData, + successData, + failureData, }, ); } diff --git a/src/types/onyx/WalletOnfido.ts b/src/types/onyx/WalletOnfido.ts index 7a65c0f710ef..b604feaeb0a3 100644 --- a/src/types/onyx/WalletOnfido.ts +++ b/src/types/onyx/WalletOnfido.ts @@ -2,10 +2,10 @@ import * as OnyxCommon from './OnyxCommon'; type WalletOnfido = { /** Unique identifier returned from openOnfidoFlow then re-sent to ActivateWallet with Onfido response data */ - applicantID: string; + applicantID?: string; /** Token used to initialize the Onfido SDK token */ - sdkToken: string; + sdkToken?: string; /** Loading state to provide feedback when we are waiting for a request to finish */ isLoading?: boolean; From a6542eb4ecfd05ad1f48f8876edb5e78b0b6b91f Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Tue, 24 Oct 2023 15:21:37 +0200 Subject: [PATCH 004/193] Lint fixes --- src/libs/actions/Wallet.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index be373e078e28..649ff5800a69 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -94,15 +94,15 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { if (!personalDetails) { return; } - const firstName = personalDetails.legalFirstName || ''; - const lastName = personalDetails.legalLastName || ''; - const dob = personalDetails.dob || ''; - const addressStreet = personalDetails.addressStreet || ''; - const addressCity = personalDetails.addressCity || ''; - const addressState = personalDetails.addressState || ''; - const addressZip = personalDetails.addressZip || ''; - const ssn = personalDetails.ssn || ''; - const phoneNumber = personalDetails.phoneNumber || ''; + const firstName = personalDetails.legalFirstName ?? ''; + const lastName = personalDetails.legalLastName ?? ''; + const dob = personalDetails.dob ?? ''; + const addressStreet = personalDetails.addressStreet ?? ''; + const addressCity = personalDetails.addressCity ?? ''; + const addressState = personalDetails.addressState ?? ''; + const addressZip = personalDetails.addressZip ?? ''; + const ssn = personalDetails.ssn ?? ''; + const phoneNumber = personalDetails.phoneNumber ?? ''; const optimisticData: OnyxUpdate[] = [ { From 124a2db73887da701691b3c338165852fb44ca70 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 26 Oct 2023 09:26:39 +0200 Subject: [PATCH 005/193] Fixes after review for Wallet.ts --- src/libs/actions/Wallet.ts | 27 +++++++++++++++------------ src/types/onyx/WalletTerms.ts | 2 ++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 649ff5800a69..b8709703af3f 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -307,6 +307,11 @@ function updateCurrentStep(currentStep: ValueOf) { Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep}); } +type AnswerQuestionsForWallet = { + idologyAnswers: string; + idNumber: string; +}; + function answerQuestionsForWallet(answers: unknown[], idNumber: string) { const idologyAnswers = JSON.stringify(answers); @@ -340,18 +345,16 @@ function answerQuestionsForWallet(answers: unknown[], idNumber: string) { }, ]; - API.write( - 'AnswerQuestionsForWallet', - { - idologyAnswers, - idNumber, - }, - { - optimisticData, - successData, - failureData, - }, - ); + const parameters: AnswerQuestionsForWallet = { + idologyAnswers, + idNumber, + }; + + API.write('AnswerQuestionsForWallet', parameters, { + optimisticData, + successData, + failureData, + }); } export { diff --git a/src/types/onyx/WalletTerms.ts b/src/types/onyx/WalletTerms.ts index ae295a690f33..7f7c9bd8dd81 100644 --- a/src/types/onyx/WalletTerms.ts +++ b/src/types/onyx/WalletTerms.ts @@ -7,8 +7,10 @@ type WalletTerms = { /** When the user accepts the Wallet's terms in order to pay an IOU, this is the ID of the chatReport the IOU is linked to */ chatReportID?: string; + /** Source that triggered the KYC wall */ source?: string; + /** Loading state to provide feedback when we are waiting for a request to finish */ isLoading?: boolean; }; From f9877490ba0efcef493aa412ee31ad161ea9dab3 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 26 Oct 2023 09:34:07 +0200 Subject: [PATCH 006/193] Move type to function body --- src/libs/actions/Wallet.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index b8709703af3f..ee879577ad51 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -307,11 +307,6 @@ function updateCurrentStep(currentStep: ValueOf) { Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep}); } -type AnswerQuestionsForWallet = { - idologyAnswers: string; - idNumber: string; -}; - function answerQuestionsForWallet(answers: unknown[], idNumber: string) { const idologyAnswers = JSON.stringify(answers); @@ -345,6 +340,11 @@ function answerQuestionsForWallet(answers: unknown[], idNumber: string) { }, ]; + type AnswerQuestionsForWallet = { + idologyAnswers: string; + idNumber: string; + }; + const parameters: AnswerQuestionsForWallet = { idologyAnswers, idNumber, From a235b21d3aeb6e5248ebc02528d728e439fc4c7f Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Fri, 27 Oct 2023 11:28:28 +0200 Subject: [PATCH 007/193] Refactor API requests in wallet.ts --- src/libs/actions/Wallet.ts | 79 ++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index ee879577ad51..c4b64bb5ac62 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -136,25 +136,23 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { }, ]; - API.write( - 'UpdatePersonalDetailsForWallet', - { - legalFirstName: firstName, - legalLastName: lastName, - dob, - addressStreet, - addressCity, - addressState, - addressZip, - ssn, - phoneNumber, - }, - { - optimisticData, - successData, - failureData, - }, - ); + const parameters: Required = { + legalFirstName: firstName, + legalLastName: lastName, + dob, + addressStreet, + addressCity, + addressState, + addressZip, + ssn, + phoneNumber, + }; + + API.write('UpdatePersonalDetailsForWallet', parameters, { + optimisticData, + successData, + failureData, + }); } type IdentityVerification = { @@ -211,17 +209,15 @@ function verifyIdentity(parameters: IdentityVerification) { }, ]; - API.write( - 'VerifyIdentity', - { - onfidoData, - }, - { - optimisticData, - successData, - failureData, - }, - ); + const requestParams: IdentityVerification = { + onfidoData, + }; + + API.write('VerifyIdentity', requestParams, { + optimisticData, + successData, + failureData, + }); } type WalletTerms = { @@ -274,17 +270,21 @@ function acceptWalletTerms(parameters: WalletTerms) { }, ]; - API.write('AcceptWalletTerms', {hasAcceptedTerms: parameters.hasAcceptedTerms, reportID: parameters.chatReportID}, {optimisticData, successData, failureData}); + type WalletTermsParameters = { + hasAcceptedTerms: boolean; + reportID: number; + }; + + const requestParams: WalletTermsParameters = {hasAcceptedTerms: parameters.hasAcceptedTerms, reportID: parameters.chatReportID}; + + API.write('AcceptWalletTerms', requestParams, {optimisticData, successData, failureData}); } /** * Fetches data when the user opens the InitialSettingsPage * - * @typedef {Object} UserWallet - * @property {Number} availableBalance - * @property {Number} currentBalance - * @property {String} currentStep - used to track which step of the "activate wallet" flow a user is in - * @property {('SILVER'|'GOLD')} tierName - will be GOLD when fully activated. SILVER is able to receive funds only. + * @property currentStep - used to track which step of the "activate wallet" flow a user is in + * @property tierName - will be GOLD when fully activated. SILVER is able to receive funds only. */ function openInitialSettingsPage() { API.read('OpenInitialSettingsPage', {}); @@ -293,11 +293,8 @@ function openInitialSettingsPage() { /** * Fetches data when the user opens the EnablePaymentsPage * - * @typedef {Object} UserWallet - * @property {Number} availableBalance - * @property {Number} currentBalance - * @property {String} currentStep - used to track which step of the "activate wallet" flow a user is in - * @property {('SILVER'|'GOLD')} tierName - will be GOLD when fully activated. SILVER is able to receive funds only. + * @property currentStep - used to track which step of the "activate wallet" flow a user is in + * @property tierName - will be GOLD when fully activated. SILVER is able to receive funds only. */ function openEnablePaymentsPage() { API.read('OpenEnablePaymentsPage', {}); From 5fc507267c14a0936fcab06fcbe6b8070feb0af7 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Fri, 27 Oct 2023 11:31:34 +0200 Subject: [PATCH 008/193] Remove jsdoc --- src/libs/actions/Wallet.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index c4b64bb5ac62..70b973dd7e67 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -282,9 +282,6 @@ function acceptWalletTerms(parameters: WalletTerms) { /** * Fetches data when the user opens the InitialSettingsPage - * - * @property currentStep - used to track which step of the "activate wallet" flow a user is in - * @property tierName - will be GOLD when fully activated. SILVER is able to receive funds only. */ function openInitialSettingsPage() { API.read('OpenInitialSettingsPage', {}); @@ -292,9 +289,6 @@ function openInitialSettingsPage() { /** * Fetches data when the user opens the EnablePaymentsPage - * - * @property currentStep - used to track which step of the "activate wallet" flow a user is in - * @property tierName - will be GOLD when fully activated. SILVER is able to receive funds only. */ function openEnablePaymentsPage() { API.read('OpenEnablePaymentsPage', {}); From 24478fe09d74e749ec7b437dc5e4d823a041576a Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Sun, 29 Oct 2023 19:40:59 +0100 Subject: [PATCH 009/193] Resolve prettier problems --- src/libs/actions/Wallet.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index a5082e83f625..1259160db2e5 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -2,9 +2,9 @@ import Onyx, {OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; import ONYXKEYS from '@src/ONYXKEYS'; import {ValueOf} from 'type-fest'; -import CONST from '../../CONST'; -import * as OnyxCommon from '../../types/onyx/OnyxCommon'; -import {WalletAdditionalQuestionsDetails} from '../../types/onyx'; +import CONST from '@src/CONST'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import {WalletAdditionalQuestionsDetails} from '@src/types/onyx'; /** * Fetch and save locally the Onfido SDK token and applicantID From 6980fe2d376f2880ea1358aa70341c52df034fe3 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Sun, 29 Oct 2023 19:44:31 +0100 Subject: [PATCH 010/193] Fix imports for Wallet.ts --- src/libs/actions/Wallet.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 1259160db2e5..20e77538b4cf 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -1,10 +1,10 @@ import Onyx, {OnyxUpdate} from 'react-native-onyx'; -import * as API from '@libs/API'; -import ONYXKEYS from '@src/ONYXKEYS'; import {ValueOf} from 'type-fest'; +import * as API from '@libs/API'; import CONST from '@src/CONST'; -import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import ONYXKEYS from '@src/ONYXKEYS'; import {WalletAdditionalQuestionsDetails} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; /** * Fetch and save locally the Onfido SDK token and applicantID From ac322019c79ba029fa714f55e2f5d11999228819 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Mon, 30 Oct 2023 10:28:03 +0100 Subject: [PATCH 011/193] Rename parameters to requestParams in Wallet.ts --- src/libs/actions/Wallet.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 20e77538b4cf..7a2a02cfd73e 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -136,7 +136,7 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { }, ]; - const parameters: Required = { + const requestParams: Required = { legalFirstName: firstName, legalLastName: lastName, dob, @@ -148,7 +148,7 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { phoneNumber, }; - API.write('UpdatePersonalDetailsForWallet', parameters, { + API.write('UpdatePersonalDetailsForWallet', requestParams, { optimisticData, successData, failureData, @@ -336,12 +336,12 @@ function answerQuestionsForWallet(answers: unknown[], idNumber: string) { idNumber: string; }; - const parameters: AnswerQuestionsForWallet = { + const requestParams: AnswerQuestionsForWallet = { idologyAnswers, idNumber, }; - API.write('AnswerQuestionsForWallet', parameters, { + API.write('AnswerQuestionsForWallet', requestParams, { optimisticData, successData, failureData, From f158e5c115472ed9751dff971389d79d03fcef7b Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Mon, 30 Oct 2023 20:18:33 +0100 Subject: [PATCH 012/193] fix delay --- src/libs/DateUtils.ts | 16 ++++++++++++++++ src/libs/HttpUtils.js | 22 ++++++++++++++++++++++ src/libs/ReportUtils.js | 2 +- src/libs/actions/Network.ts | 6 +++++- src/libs/actions/Report.js | 2 +- src/types/onyx/Network.ts | 3 +++ 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 13853189ed26..a1e156a9b7cc 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -55,6 +55,12 @@ Onyx.connect({ }, }); +let networkTimeSkew: number = 0; +Onyx.connect({ + key: ONYXKEYS.NETWORK, + callback: (value) => (networkTimeSkew = value?.timeSkew), +}); + /** * Gets the locale string and setting default locale for date-fns */ @@ -304,6 +310,15 @@ function getDateStringFromISOTimestamp(isoTimestamp: string): string { return dateString; } +/** + * Returns the current time plus skew in milliseconds in the format expected by the database + * + * @returns {String} + */ +function getDBTimeWithSkew() { + return getDBTime(new Date().valueOf() + networkTimeSkew); +} + /** * receive date like 2020-05-16 05:34:14 and format it to show in string like "Until 05:34 PM" */ @@ -374,6 +389,7 @@ const DateUtils = { isTomorrow, isYesterday, formatWithUTCTimeZone, + getDBTimeWithSkew, }; export default DateUtils; diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index 2df7421ea91c..fca7fdf76bb9 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -22,6 +22,16 @@ Onyx.connect({ // We use the AbortController API to terminate pending request in `cancelPendingRequests` let cancellationController = new AbortController(); +/** + * The API commands that require the skew calculation + */ +const addSkewList = ['OpenReport', 'ReconnectApp', 'OpenApp']; + +/** + * Regex to get API command from the command + */ +const regex = /[?&]command=([^&]+)/; + /** * Send an HTTP request, and attempt to resolve the json response. * If there is a network error, we'll set the application offline. @@ -33,12 +43,24 @@ let cancellationController = new AbortController(); * @returns {Promise} */ function processHTTPRequest(url, method = 'get', body = null, canCancel = true) { + const startTime = new Date().valueOf(); return fetch(url, { // We hook requests to the same Controller signal, so we can cancel them all at once signal: canCancel ? cancellationController.signal : undefined, method, body, }) + .then((response) => { + const match = url.match(regex)[1]; + if (addSkewList.includes(match) && response.headers) { + const serverTime = new Date(response.headers.get('Date')).valueOf(); + const endTime = new Date().valueOf(); + const latency = (endTime - startTime) / 2; + const skew = serverTime - startTime + latency; + NetworkActions.setTimeSkew(skew); + } + return response; + }) .then((response) => { // Test mode where all requests will succeed in the server, but fail to return a response if (shouldFailAllRequests || shouldForceOffline) { diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 8cadc6dcc8ec..862ed1da4379 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2206,7 +2206,7 @@ function buildOptimisticAddCommentReportAction(text, file) { ], automatic: false, avatar: lodashGet(allPersonalDetails, [currentUserAccountID, 'avatar'], UserUtils.getDefaultAvatarURL(currentUserAccountID)), - created: DateUtils.getDBTime(), + created: DateUtils.getDBTimeWithSkew(), message: [ { translationKey: isAttachment ? CONST.TRANSLATION_KEYS.ATTACHMENT : '', diff --git a/src/libs/actions/Network.ts b/src/libs/actions/Network.ts index 17580c214376..e71094eded05 100644 --- a/src/libs/actions/Network.ts +++ b/src/libs/actions/Network.ts @@ -5,6 +5,10 @@ function setIsOffline(isOffline: boolean) { Onyx.merge(ONYXKEYS.NETWORK, {isOffline}); } +function setTimeSkew(skew: number) { + Onyx.merge(ONYXKEYS.NETWORK, {timeSkew: skew}); +} + function setShouldForceOffline(shouldForceOffline: boolean) { Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline}); } @@ -16,4 +20,4 @@ function setShouldFailAllRequests(shouldFailAllRequests: boolean) { Onyx.merge(ONYXKEYS.NETWORK, {shouldFailAllRequests}); } -export {setIsOffline, setShouldForceOffline, setShouldFailAllRequests}; +export {setIsOffline, setShouldForceOffline, setShouldFailAllRequests, setTimeSkew}; diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 3f7dc76b174d..363f159fd7f2 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -315,7 +315,7 @@ function addActions(reportID, text = '', file) { // Always prefer the file as the last action over text const lastAction = attachmentAction || reportCommentAction; - const currentTime = DateUtils.getDBTime(); + const currentTime = DateUtils.getDBTimeWithSkew(); const lastCommentText = ReportUtils.formatReportLastMessageText(lastAction.message[0].text); diff --git a/src/types/onyx/Network.ts b/src/types/onyx/Network.ts index 5af4c1170c3f..32b084bbf2f7 100644 --- a/src/types/onyx/Network.ts +++ b/src/types/onyx/Network.ts @@ -7,6 +7,9 @@ type Network = { /** Whether we should fail all network requests */ shouldFailAllRequests?: boolean; + + /** Skew between the client and server clocks */ + timeSkew?: number; }; export default Network; From 5704405e083297510919af0f44cc3a08319f43d2 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Mon, 30 Oct 2023 20:21:34 +0100 Subject: [PATCH 013/193] added lib --- src/libs/HttpUtils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index fca7fdf76bb9..f555991f19c6 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -3,6 +3,7 @@ import _ from 'underscore'; import alert from '@components/Alert'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import * as NetworkActions from './actions/Network'; import * as ApiUtils from './ApiUtils'; import HttpsError from './Errors/HttpsError'; @@ -44,6 +45,7 @@ const regex = /[?&]command=([^&]+)/; */ function processHTTPRequest(url, method = 'get', body = null, canCancel = true) { const startTime = new Date().valueOf(); + return fetch(url, { // We hook requests to the same Controller signal, so we can cancel them all at once signal: canCancel ? cancellationController.signal : undefined, From 9738d5231a98f3148a93b2eefb78e5163960b3ab Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Tue, 31 Oct 2023 15:35:09 +0100 Subject: [PATCH 014/193] lint fix --- src/libs/DateUtils.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index a1e156a9b7cc..0b127009484e 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -55,7 +55,7 @@ Onyx.connect({ }, }); -let networkTimeSkew: number = 0; +let networkTimeSkew = 0; Onyx.connect({ key: ONYXKEYS.NETWORK, callback: (value) => (networkTimeSkew = value?.timeSkew), @@ -312,10 +312,8 @@ function getDateStringFromISOTimestamp(isoTimestamp: string): string { /** * Returns the current time plus skew in milliseconds in the format expected by the database - * - * @returns {String} */ -function getDBTimeWithSkew() { +function getDBTimeWithSkew(): string { return getDBTime(new Date().valueOf() + networkTimeSkew); } From e4722b1957949da556b846583b09a5291ce4acc2 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Tue, 31 Oct 2023 15:44:36 +0100 Subject: [PATCH 015/193] ts check fix --- src/libs/DateUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 0b127009484e..f4346f6ff7c0 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -55,7 +55,7 @@ Onyx.connect({ }, }); -let networkTimeSkew = 0; +let networkTimeSkew: number | undefined = 0; Onyx.connect({ key: ONYXKEYS.NETWORK, callback: (value) => (networkTimeSkew = value?.timeSkew), From 10983780352ae87ffdb123d608169ca4dd4f5fbb Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Tue, 31 Oct 2023 15:49:50 +0100 Subject: [PATCH 016/193] ts check fix --- src/libs/DateUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index f4346f6ff7c0..b87d5d6e8973 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -55,10 +55,10 @@ Onyx.connect({ }, }); -let networkTimeSkew: number | undefined = 0; +let networkTimeSkew = 0; Onyx.connect({ key: ONYXKEYS.NETWORK, - callback: (value) => (networkTimeSkew = value?.timeSkew), + callback: (value) => (networkTimeSkew = value?.timeSkew || 0), }); /** From 0428382bcf6640a77f8057791a823e9674c2170f Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Tue, 31 Oct 2023 18:20:20 +0100 Subject: [PATCH 017/193] lint fix --- src/libs/DateUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index b87d5d6e8973..63f87a97eed2 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -58,7 +58,7 @@ Onyx.connect({ let networkTimeSkew = 0; Onyx.connect({ key: ONYXKEYS.NETWORK, - callback: (value) => (networkTimeSkew = value?.timeSkew || 0), + callback: (value) => (networkTimeSkew = value?.timeSkew ?? 0), }); /** From fbe9c2836315fc74b4170c345c32efe66a8d03bd Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Thu, 2 Nov 2023 16:08:22 +0100 Subject: [PATCH 018/193] fix --- src/libs/DateUtils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 695dcd573291..62a760e8427a 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -348,7 +348,10 @@ function getDateStringFromISOTimestamp(isoTimestamp: string): string { * Returns the current time plus skew in milliseconds in the format expected by the database */ function getDBTimeWithSkew(): string { - return getDBTime(new Date().valueOf() + networkTimeSkew); + if (networkTimeSkew > 0) { + return getDBTime(new Date().valueOf() + networkTimeSkew); + } + return getDBTime(); } /** From f1c7f95561124d89da64ddb14167f649df09557d Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Mon, 13 Nov 2023 14:26:01 +0100 Subject: [PATCH 019/193] Fix: move types & remove unknown --- src/libs/actions/Wallet.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 7a2a02cfd73e..9e72226c3a67 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -6,6 +6,16 @@ import ONYXKEYS from '@src/ONYXKEYS'; import {WalletAdditionalQuestionsDetails} from '@src/types/onyx'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +type WalletTerms = { + hasAcceptedTerms: boolean; + chatReportID: number; +}; + +type WalletQuestion = { + question: string; + answer: string; +}; + /** * Fetch and save locally the Onfido SDK token and applicantID * - The sdkToken is used to initialize the Onfido SDK client @@ -91,9 +101,6 @@ type PersonalDetails = { * Validates a user's provided details against a series of checks */ function updatePersonalDetails(personalDetails: PersonalDetails) { - if (!personalDetails) { - return; - } const firstName = personalDetails.legalFirstName ?? ''; const lastName = personalDetails.legalLastName ?? ''; const dob = personalDetails.dob ?? ''; @@ -220,11 +227,6 @@ function verifyIdentity(parameters: IdentityVerification) { }); } -type WalletTerms = { - hasAcceptedTerms: boolean; - chatReportID: number; -}; - /** * Complete the "Accept Terms" step of the wallet activation flow. * @@ -270,12 +272,12 @@ function acceptWalletTerms(parameters: WalletTerms) { }, ]; - type WalletTermsParameters = { + type AcceptWalletTermsParams = { hasAcceptedTerms: boolean; reportID: number; }; - const requestParams: WalletTermsParameters = {hasAcceptedTerms: parameters.hasAcceptedTerms, reportID: parameters.chatReportID}; + const requestParams: AcceptWalletTermsParams = {hasAcceptedTerms: parameters.hasAcceptedTerms, reportID: parameters.chatReportID}; API.write('AcceptWalletTerms', requestParams, {optimisticData, successData, failureData}); } @@ -298,7 +300,7 @@ function updateCurrentStep(currentStep: ValueOf) { Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep}); } -function answerQuestionsForWallet(answers: unknown[], idNumber: string) { +function answerQuestionsForWallet(answers: WalletQuestion[], idNumber: string) { const idologyAnswers = JSON.stringify(answers); const optimisticData: OnyxUpdate[] = [ From 532a64d0a5a822b8fd0950d2b4b57d7644c596a1 Mon Sep 17 00:00:00 2001 From: Artem Makushov <39777589+waterim@users.noreply.github.com> Date: Mon, 13 Nov 2023 18:04:17 +0100 Subject: [PATCH 020/193] Update src/libs/HttpUtils.js Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/libs/HttpUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index f555991f19c6..b8fa11ae325f 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -31,7 +31,7 @@ const addSkewList = ['OpenReport', 'ReconnectApp', 'OpenApp']; /** * Regex to get API command from the command */ -const regex = /[?&]command=([^&]+)/; +const APICommandRegex = /[?&]command=([^&]+)/; /** * Send an HTTP request, and attempt to resolve the json response. From 405a8ad33a93acd30288054a2a2bc21810957ebe Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Mon, 13 Nov 2023 18:32:05 +0100 Subject: [PATCH 021/193] fix tests --- src/libs/HttpUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index b8fa11ae325f..93deaffe412f 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -53,7 +53,7 @@ function processHTTPRequest(url, method = 'get', body = null, canCancel = true) body, }) .then((response) => { - const match = url.match(regex)[1]; + const match = url.match(APICommandRegex)[1]; if (addSkewList.includes(match) && response.headers) { const serverTime = new Date(response.headers.get('Date')).valueOf(); const endTime = new Date().valueOf(); From cc8fd021a75df65731e1c0c51c1e915363784603 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Tue, 14 Nov 2023 15:12:53 +0100 Subject: [PATCH 022/193] fix: move types --- src/libs/actions/Wallet.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 9e72226c3a67..48dc71c0b565 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -16,6 +16,22 @@ type WalletQuestion = { answer: string; }; +type IdentityVerification = { + onfidoData: string; +}; + +type PersonalDetails = { + phoneNumber?: string; + legalFirstName?: string; + legalLastName?: string; + addressStreet?: string; + addressCity?: string; + addressState?: string; + addressZip?: string; + dob?: string; + ssn?: string; +}; + /** * Fetch and save locally the Onfido SDK token and applicantID * - The sdkToken is used to initialize the Onfido SDK client @@ -85,18 +101,6 @@ function setKYCWallSource(source: string, chatReportID = '') { Onyx.merge(ONYXKEYS.WALLET_TERMS, {source, chatReportID}); } -type PersonalDetails = { - phoneNumber?: string; - legalFirstName?: string; - legalLastName?: string; - addressStreet?: string; - addressCity?: string; - addressState?: string; - addressZip?: string; - dob?: string; - ssn?: string; -}; - /** * Validates a user's provided details against a series of checks */ @@ -162,10 +166,6 @@ function updatePersonalDetails(personalDetails: PersonalDetails) { }); } -type IdentityVerification = { - onfidoData: string; -}; - /** * Creates an identity check by calling Onfido's API with data returned from the SDK * From ea2ba21257e96091e45da326a1cc5780cf281192 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 29 Nov 2023 15:48:32 +0100 Subject: [PATCH 023/193] fix --- src/libs/HttpUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/HttpUtils.ts b/src/libs/HttpUtils.ts index dbb0717c571a..3fe92b5b1a89 100644 --- a/src/libs/HttpUtils.ts +++ b/src/libs/HttpUtils.ts @@ -56,7 +56,7 @@ function processHTTPRequest(url: string, method: RequestType = 'get', body: Form const endTime = new Date().valueOf(); const latency = (endTime - startTime) / 2; const skew = serverTime - startTime + latency; - NetworkActions.setTimeSkew(skew); + NetworkActions.setTimeSkew(dateHeaderValue ? skew : 0); } return response; }) From 5737385bbd685b78234b58c14ea1236628c841b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Wed, 29 Nov 2023 16:02:30 +0100 Subject: [PATCH 024/193] useEffects refactoring --- .../MoneyRequestParticipantsPage.js | 22 +++--- .../MoneyRequestParticipantsSelector.js | 72 +++++++++---------- 2 files changed, 44 insertions(+), 50 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js index 9a114de98ea7..375904b3e44e 100644 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage.js @@ -1,7 +1,7 @@ import lodashGet from 'lodash/get'; import lodashSize from 'lodash/size'; import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -62,28 +62,28 @@ function MoneyRequestParticipantsPage({iou, selectedTab, route, transaction}) { const isSendRequest = iouType === CONST.IOU.TYPE.SEND; const isScanRequest = MoneyRequestUtils.isScanRequest(selectedTab); const isSplitRequest = iou.id === CONST.IOU.TYPE.SPLIT; - const [headerTitle, setHeaderTitle] = useState(); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints); const isInvalidWaypoint = lodashSize(validatedWaypoints) < 2; - useEffect(() => { + const headerTitle = useMemo(() => { if (isDistanceRequest) { - setHeaderTitle(translate('common.distance')); - return; + return translate('common.distance'); } if (isSendRequest) { - setHeaderTitle(translate('common.send')); - return; + return translate('common.send'); } if (isScanRequest) { - setHeaderTitle(translate('tabSelector.scan')); - return; + return translate('tabSelector.scan'); + } + + if (iou.splitRequest) { + return translate('iou.split'); } - setHeaderTitle(iou.isSplitRequest ? translate('iou.split') : translate('tabSelector.manual')); - }, [iou.isSplitRequest, isDistanceRequest, translate, isScanRequest, isSendRequest]); + return translate('tabSelector.manual'); + }, [iou, isDistanceRequest, translate, isScanRequest, isSendRequest]); const navigateToConfirmationStep = (moneyRequestType) => { IOU.setMoneyRequestId(moneyRequestType); diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index 61ca7853cc27..9f6b0244fa9a 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -1,6 +1,6 @@ import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import React, {useCallback, useMemo, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; @@ -97,12 +97,39 @@ function MoneyRequestParticipantsSelector({ }) { const styles = useThemeStyles(); const [searchTerm, setSearchTerm] = useState(''); - const [newChatOptions, setNewChatOptions] = useState({ - recentReports: [], - personalDetails: [], - userToInvite: null, - }); const {isOffline} = useNetwork(); + const newChatOptions = useMemo(() => { + const chatOptions = OptionsListUtils.getFilteredOptions( + reports, + personalDetails, + betas, + searchTerm, + participants, + CONST.EXPENSIFY_EMAILS, + + // If we are using this component in the "Request money" flow then we pass the includeOwnedWorkspaceChats argument so that the current user + // sees the option to request money from their admin on their own Workspace Chat. + iouType === CONST.IOU.TYPE.REQUEST, + + // We don't want to include any P2P options like personal details or reports that are not workspace chats for certain features. + !isDistanceRequest, + false, + {}, + [], + false, + {}, + [], + // We don't want the user to be able to invite individuals when they are in the "Distance request" flow for now. + // This functionality is being built here: https://github.com/Expensify/App/issues/23291 + !isDistanceRequest, + true, + ); + return { + recentReports: chatOptions.recentReports, + personalDetails: chatOptions.personalDetails, + userToInvite: chatOptions.userToInvite, + }; + }, [betas, reports, participants, personalDetails, searchTerm, iouType, isDistanceRequest]); const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; @@ -224,39 +251,6 @@ function MoneyRequestParticipantsSelector({ ); const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails); - useEffect(() => { - const chatOptions = OptionsListUtils.getFilteredOptions( - reports, - personalDetails, - betas, - searchTerm, - participants, - CONST.EXPENSIFY_EMAILS, - - // If we are using this component in the "Request money" flow then we pass the includeOwnedWorkspaceChats argument so that the current user - // sees the option to request money from their admin on their own Workspace Chat. - iouType === CONST.IOU.TYPE.REQUEST, - - // We don't want to include any P2P options like personal details or reports that are not workspace chats for certain features. - !isDistanceRequest, - false, - {}, - [], - false, - {}, - [], - // We don't want the user to be able to invite individuals when they are in the "Distance request" flow for now. - // This functionality is being built here: https://github.com/Expensify/App/issues/23291 - !isDistanceRequest, - true, - ); - setNewChatOptions({ - recentReports: chatOptions.recentReports, - personalDetails: chatOptions.personalDetails, - userToInvite: chatOptions.userToInvite, - }); - }, [betas, reports, participants, personalDetails, translate, searchTerm, setNewChatOptions, iouType, isDistanceRequest]); - // When search term updates we will fetch any reports const setSearchTermAndSearchInServer = useCallback((text = '') => { if (text.length) { From fec08cfc5464774dfb7c39a775a7eb60f52b3da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Thu, 30 Nov 2023 10:30:20 +0100 Subject: [PATCH 025/193] logic refactoring --- src/components/SelectionList/BaseListItem.js | 16 ++++- .../SelectionList/BaseSelectionList.js | 12 ++++ .../SelectionList/selectionListPropTypes.js | 3 + src/libs/OptionsListUtils.js | 2 + .../MoneyRequestParticipantsSelector.js | 67 +++++++++++-------- 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/components/SelectionList/BaseListItem.js b/src/components/SelectionList/BaseListItem.js index a37f2fe4ddc0..bef1a63fb3ed 100644 --- a/src/components/SelectionList/BaseListItem.js +++ b/src/components/SelectionList/BaseListItem.js @@ -23,6 +23,7 @@ function BaseListItem({ shouldPreventDefaultFocusOnSelectRow = false, canSelectMultiple = false, onSelectRow, + onRowPress, onDismissError = () => {}, }) { const theme = useTheme(); @@ -39,7 +40,7 @@ function BaseListItem({ errorRowStyles={styles.ph5} > onSelectRow(item)} + onPress={() => onRowPress(item)} disabled={isDisabled} accessibilityLabel={item.text} role={CONST.ACCESSIBILITY_ROLE.BUTTON} @@ -59,7 +60,16 @@ function BaseListItem({ ]} > {canSelectMultiple && ( - + onSelectRow(item)} + disabled={isDisabled} + hoverDimmingValue={1} + hoverStyle={styles.hoveredComponentBG} + dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}} + onMouseDown={shouldPreventDefaultFocusOnSelectRow ? (e) => e.preventDefault() : undefined} + > )} - + )} { + if (!onRowPress) { + selectRow(item, true); + return; + } + onRowPress(item); + }; + const renderItem = ({item, index, section}) => { const normalizedIndex = index + lodashGet(section, 'indexOffset', 0); const isDisabled = section.isDisabled || item.isDisabled; @@ -308,6 +318,7 @@ function BaseSelectionList({ showTooltip={showTooltip} canSelectMultiple={canSelectMultiple} onSelectRow={() => selectRow(item, true)} + onRowPress={handleRowPress} onDismissError={onDismissError} shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} /> @@ -405,6 +416,7 @@ function BaseSelectionList({ }} label={textInputLabel} accessibilityLabel={textInputLabel} + hint={textInputHint} role={CONST.ACCESSIBILITY_ROLE.TEXT} value={textInputValue} placeholder={textInputPlaceholder} diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js index 0c2fe83d025f..8ed8197476d2 100644 --- a/src/components/SelectionList/selectionListPropTypes.js +++ b/src/components/SelectionList/selectionListPropTypes.js @@ -16,6 +16,9 @@ const commonListItemPropTypes = { canSelectMultiple: PropTypes.bool, /** Callback to fire when the item is pressed */ + onRowPress: PropTypes.func, + + /** Callback to fire when the item is selected */ onSelectRow: PropTypes.func.isRequired, /** Callback to fire when an error is dismissed */ diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index c616587c3983..ebc791606844 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -219,6 +219,7 @@ function getParticipantsOption(participant, personalDetails) { ], phoneNumber: lodashGet(detail, 'phoneNumber', ''), selected: participant.selected, + isSelected: participant.selected, searchText: participant.searchText, }; } @@ -574,6 +575,7 @@ function getPolicyExpenseReportOption(report) { option.text = ReportUtils.getPolicyName(expenseReport); option.alternateText = Localize.translateLocal('workspace.common.workspace'); option.selected = report.selected; + option.isSelected = report.selected; return option; } diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index 9f6b0244fa9a..0967b4962723 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -8,6 +8,7 @@ import Button from '@components/Button'; import FormHelpMessage from '@components/FormHelpMessage'; import OptionsSelector from '@components/OptionsSelector'; import refPropTypes from '@components/refPropTypes'; +import SelectionList from '@components/SelectionList'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useNetwork from '@hooks/useNetwork'; import * as Report from '@libs/actions/Report'; @@ -274,6 +275,8 @@ function MoneyRequestParticipantsSelector({ navigateToSplit(); }, [shouldShowSplitBillErrorMessage, navigateToSplit]); + const shouldShowSplitButton = isAllowedToSplit && !shouldShowSplitBillErrorMessage && participants.length > 0; + const footerContent = ( {shouldShowSplitBillErrorMessage && ( @@ -283,44 +286,52 @@ function MoneyRequestParticipantsSelector({ message="iou.error.splitBillMultipleParticipantsErrorMessage" /> )} -