Skip to content

Commit

Permalink
Merge pull request #5476 from Expensify/update-staging-from-main
Browse files Browse the repository at this point in the history
  • Loading branch information
OSBotify authored Sep 23, 2021
2 parents f0cad1b + 4d7e70e commit 40399d6
Show file tree
Hide file tree
Showing 23 changed files with 161 additions and 36 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001010108
versionName "1.1.1-8"
versionCode 1001010109
versionName "1.1.1-9"
}
splits {
abi {
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.1.1.8</string>
<string>1.1.1.9</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.1.1.8</string>
<string>1.1.1.9</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "1.1.1-8",
"version": "1.1.1-9",
"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.",
Expand Down
3 changes: 3 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const CONST = {
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
Expand Down Expand Up @@ -213,6 +214,7 @@ const CONST = {
},
ERROR: {
API_OFFLINE: 'session.offlineMessageRetry',
UNKNOWN_ERROR: 'Unknown error',
},
NETWORK: {
METHOD: {
Expand Down Expand Up @@ -343,6 +345,7 @@ const CONST = {
SMS_NUMBER_COUNTRY_CODE: 'US',
ERROR: {
USER_CANCELLED: 'User canceled flow',
USER_TAPPED_BACK: 'User exited by clicking the back button.',
},
},

Expand Down
11 changes: 7 additions & 4 deletions src/components/Onfido/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import './index.css';
import lodashGet from 'lodash/get';
import React from 'react';
import * as OnfidoSDK from 'onfido-sdk-ui';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import onfidoPropTypes from './onfidoPropTypes';
import CONST from '../../CONST';
import Growl from '../../libs/Growl';

const propTypes = {
...withLocalizePropTypes,
Expand All @@ -24,6 +24,9 @@ class Onfido extends React.Component {
forceCrossDevice: true,
showCountrySelection: false,
documentTypes: {
driving_licence: {
country: null,
},
national_identity_card: {
country: null,
},
Expand All @@ -45,9 +48,9 @@ class Onfido extends React.Component {
smsNumberCountryCode: CONST.ONFIDO.SMS_NUMBER_COUNTRY_CODE.US,
showCountrySelection: false,
onComplete: this.props.onSuccess,
onError: () => {
this.props.onUserExit();
Growl.error(this.props.translate('onfidoStep.genericError'));
onError: (error) => {
const errorMessage = lodashGet(error, 'message', CONST.ERROR.UNKNOWN_ERROR);
this.props.onError(errorMessage);
},
onUserExit: this.props.onUserExit,
onModalRequestClose: () => {},
Expand Down
13 changes: 10 additions & 3 deletions src/components/Onfido/index.native.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import _ from 'underscore';
import lodashGet from 'lodash/get';
import React from 'react';
import {
Onfido as OnfidoSDK,
Expand All @@ -8,7 +10,6 @@ import {
import onfidoPropTypes from './onfidoPropTypes';
import CONST from '../../CONST';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import Growl from '../../libs/Growl';

const propTypes = {
...withLocalizePropTypes,
Expand All @@ -32,10 +33,16 @@ class Onfido extends React.Component {
})
.then(this.props.onSuccess)
.catch((error) => {
if (error.message === CONST.ONFIDO.ERROR.USER_CANCELLED) {
const errorMessage = lodashGet(error, 'message', CONST.ERROR.UNKNOWN_ERROR);

// If the user cancels the Onfido flow we won't log this error as it's normal. In the React Native SDK the user exiting the flow will trigger this error which we can use as
// our "user exited the flow" callback. On web, this event has it's own callback passed as a config so we don't need to bother with this there.
if (_.contains([CONST.ONFIDO.ERROR.USER_CANCELLED, CONST.ONFIDO.ERROR.USER_TAPPED_BACK], errorMessage)) {
this.props.onUserExit();
Growl.error(this.props.translate('onfidoStep.genericError'));
return;
}

this.props.onError(errorMessage);
});
}

Expand Down
3 changes: 3 additions & 0 deletions src/components/Onfido/onfidoPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ export default {

/** Called when the user is totally done with Onfido */
onSuccess: PropTypes.func.isRequired,

/** Called when Onfido throws an error */
onError: PropTypes.func.isRequired,
};
2 changes: 2 additions & 0 deletions src/components/PDFView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Document, Page} from 'react-pdf/dist/esm/entry.webpack';
import styles from '../../styles/styles';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
import variables from '../../styles/variables';
import FullScreenLoadingIndicator from '../FullscreenLoadingIndicator';

const propTypes = {
/** URL to full-sized image */
Expand Down Expand Up @@ -53,6 +54,7 @@ class PDFView extends PureComponent {
style={[styles.PDFView, this.props.style]}
>
<Document
loading={<FullScreenLoadingIndicator visible />}
file={this.props.sourceURL}
options={{
cMapUrl: 'cmaps/',
Expand Down
2 changes: 2 additions & 0 deletions src/components/PDFView/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {View} from 'react-native';
import PDF from 'react-native-pdf';
import styles, {getWidthAndHeightStyle} from '../../styles/styles';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
import FullScreenLoadingIndicator from '../FullscreenLoadingIndicator';

const propTypes = {
/** URL to full-sized image */
Expand Down Expand Up @@ -31,6 +32,7 @@ const defaultProps = {
const PDFView = props => (
<View style={[styles.flex1, props.style]}>
<PDF
activityIndicator={<FullScreenLoadingIndicator visible />}
source={{uri: props.sourceURL}}
style={[
styles.imageModalPDF,
Expand Down
3 changes: 1 addition & 2 deletions src/components/Text.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const Text = React.forwardRef(({
...finalStyles,
...s,
}), {});

const componentStyle = {
color,
fontSize,
Expand All @@ -59,7 +58,7 @@ const Text = React.forwardRef(({
...mergedStyles,
};

if (componentStyle.fontSize === variables.fontSizeNormal) {
if (!componentStyle.lineHeight && componentStyle.fontSize === variables.fontSizeNormal) {
componentStyle.lineHeight = variables.fontSizeNormalHeight;
}

Expand Down
3 changes: 2 additions & 1 deletion src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ export default {
noDefaultDepositAccountOrDebitCardAvailable: 'Please add a default deposit bank account or debit card',
fixTheErrors: 'fix the errors',
inTheFormBeforeContinuing: 'in the form before continuing',
validationAmounts: 'The validation amounts you entered are incorrect. Please double-check your bank statement and try again.',
},
},
addPersonalBankAccountPage: {
Expand Down Expand Up @@ -604,7 +605,7 @@ export default {
addEmail: 'Add email',
tagline: 'The smartest corporate card in the room.',
publicCopy: 'In order to use the Expensify Card you must use your company\'s private domain. Go ahead and add your private email address as a secondary login.',
privateCopy: 'Just swipe your Expensify card and your expenses are done, it\'s that simple!',
privateCopy: 'Just swipe your Expensify Card and your expenses are done, it\'s that simple!',
getStarted: 'Get started',
finishSetup: 'Finish setup',
manageCards: 'Manage cards',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ export default {
noDefaultDepositAccountOrDebitCardAvailable: 'Por favor agrega una cuenta bancaria para depósitos o una tarjeta de débito',
fixTheErrors: 'corrige los errores',
inTheFormBeforeContinuing: 'en el formulario antes de continuar',
validationAmounts: 'Los montos de validación que ingresaste son incorrectos. Verifica tu cuenta de banco e intenta de nuevo.',
},
},
addPersonalBankAccountPage: {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ function createOption(personalDetailList, report, draftComments, {
return {
text,
alternateText,
icons: report ? report.icons : [personalDetail.avatar],
icons: lodashGet(report, 'icons', [personalDetail.avatar]),
tooltipText,
participantsList: personalDetailList,

Expand Down
9 changes: 8 additions & 1 deletion src/libs/actions/BankAccounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,14 @@ function validateBankAccount(bankAccountID, validateCode) {
return;
}

// We are generically showing any backend errors that might pop up in the validate step
// If the validation amounts entered were incorrect, show specific error
if (response.message === CONST.BANK_ACCOUNT.ERROR.INCORRECT_VALIDATION_AMOUNTS) {
showBankAccountErrorModal(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
showBankAccountErrorModal(response.message);
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {loading: false});
});
Expand Down
6 changes: 6 additions & 0 deletions src/pages/EnablePayments/OnfidoStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import TextLink from '../../components/TextLink';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import compose from '../../libs/compose';
import Text from '../../components/Text';
import Log from '../../libs/Log';
import Growl from '../../libs/Growl';

const propTypes = {
/** Stores various information used to build the UI and call any APIs */
Expand Down Expand Up @@ -68,6 +70,10 @@ class OnfidoStep extends React.Component {
this.canShowOnfido() ? (
<Onfido
sdkToken={this.props.walletOnfidoData.sdkToken}
onError={(error) => {
Log.hmmm('Onfido error in OnfidoStep', {error});
Growl.error(this.props.translate('onfidoStep.genericError'), 10000);
}}
onUserExit={() => {
Navigation.goBack();
}}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/ReimbursementAccount/CompanyStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,10 @@ class CompanyStep extends React.Component {
containerStyles={[styles.mt4]}
secureTextEntry
textContentType="password"
onChangeText={value => this.clearErrorAndSetValue('password', value)}
onChangeText={(value) => {
this.setState({password: value});
this.clearError('password');
}}
value={this.state.password}
onSubmitEditing={this.submit}
errorText={this.getErrorText('password')}
Expand Down
11 changes: 10 additions & 1 deletion src/pages/ReimbursementAccount/RequestorStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import Onfido from '../../components/Onfido';
import compose from '../../libs/compose';
import ONYXKEYS from '../../ONYXKEYS';
import {getDefaultStateForField} from '../../libs/ReimbursementAccountUtils';
import Log from '../../libs/Log';
import Growl from '../../libs/Growl';
import reimbursementAccountPropTypes from './reimbursementAccountPropTypes';
import ReimbursementAccountForm from './ReimbursementAccountForm';

Expand Down Expand Up @@ -135,7 +137,14 @@ class RequestorStep extends React.Component {
<Onfido
sdkToken={this.props.achData.sdkToken}
onUserExit={() => {
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.REQUESTOR);
// We're taking the user back to the company step. They will need to come back to the requestor step to make the Onfido flow appear again.
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COMPANY);
}}
onError={(error) => {
// In case of any unexpected error we log it to the server, show a growl, and return the user back to the company step so they can try again.
Log.hmmm('Onfido error in RequestorStep', {error});
Growl.error(this.props.translate('onfidoStep.genericError'), 10000);
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COMPANY);
}}
onSuccess={(onfidoData) => {
this.setState({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class PopoverReportActionContextMenu extends React.Component {
vertical: 0,
},
};
this.onPopoverShow = () => {};
this.onPopoverHide = () => {};
this.onPopoverHideActionCallback = () => {};
this.contextMenuAnchor = undefined;
this.showContextMenu = this.showContextMenu.bind(this);
this.hideContextMenu = this.hideContextMenu.bind(this);
Expand All @@ -46,6 +48,7 @@ class PopoverReportActionContextMenu extends React.Component {
this.confirmDeleteAndHideModal = this.confirmDeleteAndHideModal.bind(this);
this.hideDeleteModal = this.hideDeleteModal.bind(this);
this.showDeleteModal = this.showDeleteModal.bind(this);
this.runAndResetOnPopoverShow = this.runAndResetOnPopoverShow.bind(this);
this.runAndResetOnPopoverHide = this.runAndResetOnPopoverHide.bind(this);
this.getContextMenuMeasuredLocation = this.getContextMenuMeasuredLocation.bind(this);
this.isActiveReportAction = this.isActiveReportAction.bind(this);
Expand Down Expand Up @@ -117,7 +120,16 @@ class PopoverReportActionContextMenu extends React.Component {
) {
const nativeEvent = event.nativeEvent || {};
this.contextMenuAnchor = contextMenuAnchor;
this.onPopoverHide = onHide;

// Singleton behaviour of ContextMenu creates race conditions when user requests multiple contextMenus.
// But it is possible that every new request registers new callbacks thus instanceID is used to corelate those callbacks
this.instanceID = Math.random().toString(36).substr(2, 5);

// Register the onHide callback only when Popover is shown to remove the race conditions when there are mutltiple popover open requests
this.onPopoverShow = () => {
onShow();
this.onPopoverHide = onHide;
};
this.getContextMenuMeasuredLocation().then(({x, y}) => {
this.setState({
cursorRelativePosition: {
Expand All @@ -134,7 +146,7 @@ class PopoverReportActionContextMenu extends React.Component {
selection,
isPopoverVisible: true,
reportActionDraftMessage: draftMessage,
}, onShow);
});
});
}

Expand All @@ -159,22 +171,34 @@ class PopoverReportActionContextMenu extends React.Component {
}

/**
* After Popover hides, call the registered onPopoverHide callback and reset it
* After Popover shows, call the registered onPopoverShow callback and reset it
*/
runAndResetOnPopoverShow() {
this.onPopoverShow();

// After we have called the action, reset it.
this.onPopoverShow = () => {};
}

/**
* After Popover hides, call the registered onPopoverHide & onPopoverHideActionCallback callback and reset it
*/
runAndResetOnPopoverHide() {
this.onPopoverHide();
this.onPopoverHideActionCallback();

// After we have called the action, reset it.
this.onPopoverHide = () => {};
this.onPopoverHideActionCallback = () => {};
}

/**
* Hide the ReportActionContextMenu modal popover.
* @param {Function} onHideCallback Callback to be called after popover is completely hidden
* @param {Function} onHideActionCallback Callback to be called after popover is completely hidden
*/
hideContextMenu(onHideCallback) {
if (_.isFunction(onHideCallback)) {
this.onPopoverHide = onHideCallback;
hideContextMenu(onHideActionCallback) {
if (_.isFunction(onHideActionCallback)) {
this.onPopoverHideActionCallback = onHideActionCallback;
}
this.setState({
reportID: 0,
Expand Down Expand Up @@ -230,6 +254,7 @@ class PopoverReportActionContextMenu extends React.Component {
<PopoverWithMeasuredContent
isVisible={this.state.isPopoverVisible}
onClose={this.hideContextMenu}
onModalShow={this.runAndResetOnPopoverShow}
onModalHide={this.runAndResetOnPopoverHide}
anchorPosition={this.state.popoverAnchorPosition}
animationIn="fadeIn"
Expand Down
Loading

0 comments on commit 40399d6

Please sign in to comment.