diff --git a/.github/workflows/cherryPick.yml b/.github/workflows/cherryPick.yml
index 14f20f707d2b..f26bbd7148b2 100644
--- a/.github/workflows/cherryPick.yml
+++ b/.github/workflows/cherryPick.yml
@@ -190,7 +190,8 @@ jobs:
channel: '#announce',
attachments: [{
color: "#DB4545",
- text: `@mobile-deployers 💥 Failed to CP https://github.com/Expensify/App/pull/${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 💥`,
+ pretext: ``,
+ text: `💥 Failed to CP https://github.com/Expensify/App/pull/${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 💥`,
}]
}
env:
diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml
index 93eb6980ca54..65976854ae58 100644
--- a/.github/workflows/platformDeploy.yml
+++ b/.github/workflows/platformDeploy.yml
@@ -223,11 +223,17 @@ jobs:
APPLE_DEMO_EMAIL: ${{ secrets.APPLE_DEMO_EMAIL }}
APPLE_DEMO_PASSWORD: ${{ secrets.APPLE_DEMO_PASSWORD }}
+ - name: Set iOS version in ENV
+ if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }}
+ run: |
+ echo "IOS_VERSION=$(echo '${{ github.event.release.tag_name }}' | tr '-' '.')" >> $GITHUB_ENV
+ echo "iOS version is: ${{ env.IOS_VERSION }}"
+
- name: Run Fastlane for App Store release
if: ${{ env.SHOULD_DEPLOY_PRODUCTION == 'true' }}
run: bundle exec fastlane ios production
env:
- VERSION: ${{ env.NEW_IOS_VERSION }}
+ VERSION: ${{ env.IOS_VERSION }}
web:
name: Build and deploy Web
diff --git a/android/app/build.gradle b/android/app/build.gradle
index c0dc4bb8f28e..4876e31ed2c2 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -150,8 +150,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001009002
- versionName "1.0.90-2"
+ versionCode 1001009003
+ versionName "1.0.90-3"
}
splits {
abi {
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index f86243f49880..553d4a2bf228 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -142,7 +142,7 @@ platform :ios do
api_key_path: "./ios/ios-fastlane-json-key.json",
build_number: ENV["VERSION"],
submit_for_review: true,
- automatic_release: false,
+ automatic_release: true,
skip_metadata: true,
skip_screenshots: true,
skip_binary_upload: true,
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 1df1d1dfeb3f..588af784d614 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -30,7 +30,7 @@
CFBundleVersion
- 1.0.90.2
+ 1.0.90.3
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index c5e85d08550c..330352b540c4 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.0.90.2
+ 1.0.90.3
diff --git a/package-lock.json b/package-lock.json
index 8b47f82dbc97..f99821e734fb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.0.90-2",
+ "version": "1.0.90-3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index ae0048ef0934..63cc8441ce7e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.0.90-2",
+ "version": "1.0.90-3",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
diff --git a/src/components/Button.js b/src/components/Button.js
index be1f13ac5131..52586b44d7e2 100644
--- a/src/components/Button.js
+++ b/src/components/Button.js
@@ -1,17 +1,21 @@
import _ from 'underscore';
import React, {Component} from 'react';
-import {Pressable, ActivityIndicator} from 'react-native';
+import {Pressable, ActivityIndicator, View} from 'react-native';
import PropTypes from 'prop-types';
import styles from '../styles/styles';
import themeColors from '../styles/themes/default';
import OpacityView from './OpacityView';
import Text from './Text';
import KeyboardShortcut from '../libs/KeyboardShortcut';
+import Icon from './Icon';
const propTypes = {
/** The text for the button label */
text: PropTypes.string,
+ /** The icon asset to display to the left of the text */
+ icon: PropTypes.func,
+
/** Small sized button */
small: PropTypes.bool,
@@ -57,6 +61,7 @@ const propTypes = {
const defaultProps = {
text: '',
+ icon: null,
isLoading: false,
isDisabled: false,
small: false,
@@ -107,24 +112,42 @@ class Button extends Component {
return ;
}
- return this.props.isLoading
- ? (
-
- ) : (
-
- {this.props.text}
-
+ if (this.props.isLoading) {
+ return ;
+ }
+
+ const textComponent = (
+
+ {this.props.text}
+
+ );
+
+ if (this.props.icon) {
+ return (
+
+
+
+
+ {textComponent}
+
);
+ }
+
+ return textComponent;
}
render() {
diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js
index 3be35546855a..b3e946a3f347 100755
--- a/src/components/IOUConfirmationList.js
+++ b/src/components/IOUConfirmationList.js
@@ -8,6 +8,7 @@ import styles from '../styles/styles';
import Text from './Text';
import themeColors from '../styles/themes/default';
import {
+ addSMSDomainIfPhoneNumber,
getIOUConfirmationOptionsFromMyPersonalDetail,
getIOUConfirmationOptionsFromParticipants,
} from '../libs/OptionsListUtils';
@@ -225,7 +226,7 @@ class IOUConfirmationList extends Component {
}
const selectedParticipants = this.getSelectedParticipants();
const splits = _.map(selectedParticipants, participant => ({
- email: participant.login,
+ email: addSMSDomainIfPhoneNumber(participant.login),
// We should send in cents to API
// Cents is temporary and there must be support for other currencies in the future
@@ -233,7 +234,7 @@ class IOUConfirmationList extends Component {
}));
splits.push({
- email: this.props.myPersonalDetails.login,
+ email: addSMSDomainIfPhoneNumber(this.props.myPersonalDetails.login),
// The user is default and we should send in cents to API
// USD is temporary and there must be support for other currencies in the future
diff --git a/src/components/InboxCallButton.js b/src/components/InboxCallButton.js
index ef271cfca57f..690a4e4bfd5c 100644
--- a/src/components/InboxCallButton.js
+++ b/src/components/InboxCallButton.js
@@ -1,18 +1,13 @@
import React from 'react';
-import {
- View, Pressable,
-} from 'react-native';
import PropTypes from 'prop-types';
-import Icon from './Icon';
-import {Phone} from './Icon/Expensicons';
import styles from '../styles/styles';
-import themeColors from '../styles/themes/default';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import compose from '../libs/compose';
import Navigation from '../libs/Navigation/Navigation';
import ROUTES from '../ROUTES';
-import Text from './Text';
import Tooltip from './Tooltip';
+import Button from './Button';
+import {Phone} from './Icon/Expensicons';
const propTypes = {
...withLocalizePropTypes,
@@ -30,27 +25,14 @@ const InboxCallButton = props => (
text={props.translate('requestCallPage.needHelpTooltip')}
containerStyles={[styles.justifyContentCenter, styles.alignItemsCenter]}
>
- {
Navigation.navigate(ROUTES.getRequestCallRoute(props.taskID));
}}
- style={[styles.button, styles.buttonSmall]}
- >
-
-
-
-
-
-
- {props.translate('requestCallPage.needHelp')}
-
-
-
-
+ text={props.translate('requestCallPage.needHelp')}
+ small
+ icon={Phone}
+ />
);
diff --git a/src/languages/en.js b/src/languages/en.js
index 560e7d692f25..dfddc0518f81 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -336,7 +336,6 @@ export default {
loginForm: {
pleaseEnterEmailOrPhoneNumber: 'Please enter an email or phone number',
phoneOrEmail: 'Phone or email',
- enterYourPhoneOrEmail: 'Enter your phone or email:',
},
resendValidationForm: {
linkHasBeenResent: 'Link has been re-sent',
diff --git a/src/languages/es.js b/src/languages/es.js
index e7c6bedbe49f..e9b49d836755 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -336,7 +336,6 @@ export default {
loginForm: {
pleaseEnterEmailOrPhoneNumber: 'Por favor escribe un email o número de teléfono',
phoneOrEmail: 'Número de teléfono o email',
- enterYourPhoneOrEmail: 'Escribe tu número de teléfono o email:',
},
resendValidationForm: {
linkHasBeenResent: 'El enlace se ha reenviado',
@@ -552,17 +551,17 @@ export default {
forNextSteps: ' para conocer los próximos pasos para terminar de configurar su cuenta bancaria.',
},
beneficialOwnersStep: {
- beneficialOwners: 'Beneficial Owners',
- additionalInformation: 'Additional Information',
- checkAllThatApply: '(check all that apply, otherwise leave blank)',
- iOwnMoreThan25Percent: 'I own more than 25% of ',
- someoneOwnsMoreThan25Percent: 'Somebody else owns more than 25% of ',
- additionalOwner: 'Additional Beneficial Owner',
- removeOwner: 'Remove this beneficial owner',
- addAnotherIndividual: 'Add another individual who owns more than 25% of ',
- agreement: 'Agreement:',
- termsAndConditions: 'terms and conditions',
- certifyTrueAndAccurate: 'I certify that the information provided is true and accurate',
+ beneficialOwners: 'Beneficiario efectivo',
+ additionalInformation: 'Información adicional',
+ checkAllThatApply: '(marca todos los que apliquen, en caso de que ninguno aplique dejar en blanco)',
+ iOwnMoreThan25Percent: 'Soy dueño de mas de 25% de ',
+ someoneOwnsMoreThan25Percent: 'Otra persona es dueña de mas de 25% de ',
+ additionalOwner: 'Beneficiario efectivo adicional',
+ removeOwner: 'Eliminar este beneficiario efectivo',
+ addAnotherIndividual: 'Agregar otra persona que es dueña de mas de 25% de ',
+ agreement: 'Acuerdo:',
+ termsAndConditions: 'Términos y condiciones',
+ certifyTrueAndAccurate: 'Certifico que la información dada es correcta',
error: {
termsAndConditions: 'Debe aceptar términos y condiciones',
certify: 'Debe certificar que la información es verdadera y precisa',
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 4123ef8e0ae7..7e7c38188cd9 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -106,7 +106,7 @@ function getPersonalDetailsForLogins(logins, personalDetails) {
if (!personalDetail) {
personalDetail = {
- login: addSMSDomainIfPhoneNumber(login),
+ login,
displayName: login,
avatar: getDefaultAvatar(login),
};
@@ -239,8 +239,7 @@ function createOption(personalDetailList, report, draftComments, {
// It doesn't make sense to provide a login in the case of a report with multiple participants since
// there isn't any one single login to refer to for a report.
- // If single login is a mobile number, appending SMS domain
- login: !hasMultipleParticipants ? addSMSDomainIfPhoneNumber(personalDetail.login) : null,
+ login: !hasMultipleParticipants ? personalDetail.login : null,
reportID: report ? report.reportID : null,
isUnread: report ? report.unreadActionCount > 0 : null,
hasDraftComment: _.size(reportDraftComment) > 0,
@@ -289,7 +288,7 @@ function isCurrentUser(userDetails) {
return false;
}
- // If user login is mobile number, append sms domain if not appended already just a fail safe.
+ // If user login is mobile number, append sms domain if not appended already.
const userDetailsLogin = addSMSDomainIfPhoneNumber(userDetails.login);
// Initial check with currentUserLogin
diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js
index ef1acaf27d6c..d961aa679203 100644
--- a/src/libs/actions/BankAccounts.js
+++ b/src/libs/actions/BankAccounts.js
@@ -346,6 +346,7 @@ function fetchFreePlanVerifiedBankAccount(stepToOpen) {
// and determine which step to navigate to.
Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {
loading: true,
+ error: '',
// We temporarily keep the achData state to prevent UI changes while fetching.
achData: {state: lodashGet(reimbursementAccountInSetup, 'state', '')},
diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js
index 0a964289f5f4..6ce02391258c 100644
--- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js
+++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js
@@ -6,7 +6,7 @@ import Str from 'expensify-common/lib/str';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import ScreenWrapper from '../../components/ScreenWrapper';
-import {fetchFreePlanVerifiedBankAccount} from '../../libs/actions/BankAccounts';
+import {fetchFreePlanVerifiedBankAccount, hideBankAccountErrors} from '../../libs/actions/BankAccounts';
import ONYXKEYS from '../../ONYXKEYS';
import VBALoadingIndicator from '../../components/VBALoadingIndicator';
import Permissions from '../../libs/Permissions';
@@ -105,6 +105,7 @@ class ReimbursementAccountPage extends React.Component {
// When the step changes we will navigate to update the route params. This is mostly cosmetic as we only use
// the route params when the component first mounts to jump to a specific route instead of picking up where the
// user left off in the flow.
+ hideBankAccountErrors();
Navigation.navigate(ROUTES.getBankAccountRoute(this.getRouteForCurrentStep(currentStep)));
}
diff --git a/src/pages/ReimbursementAccount/ValidationStep.js b/src/pages/ReimbursementAccount/ValidationStep.js
index c10dd28ee004..60dcd7428ab1 100644
--- a/src/pages/ReimbursementAccount/ValidationStep.js
+++ b/src/pages/ReimbursementAccount/ValidationStep.js
@@ -142,7 +142,7 @@ class ValidationStep extends React.Component {
value={this.state.amount3}
onChangeText={amount3 => this.setState({amount3})}
/>
- {errorMessage && (
+ {!_.isEmpty(errorMessage) && (
{errorMessage}
diff --git a/src/pages/iou/IOUModal.js b/src/pages/iou/IOUModal.js
index 1fd560f46fb5..f71ce27f4d88 100755
--- a/src/pages/iou/IOUModal.js
+++ b/src/pages/iou/IOUModal.js
@@ -3,6 +3,7 @@ import {View, TouchableOpacity} from 'react-native';
import PropTypes from 'prop-types';
import lodashGet from 'lodash/get';
import {withOnyx} from 'react-native-onyx';
+import Str from 'expensify-common/lib/str';
import IOUAmountPage from './steps/IOUAmountPage';
import IOUParticipantsPage from './steps/IOUParticipantsPage';
import IOUConfirmPage from './steps/IOUConfirmPage';
@@ -17,7 +18,7 @@ import Navigation from '../../libs/Navigation/Navigation';
import ONYXKEYS from '../../ONYXKEYS';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import compose from '../../libs/compose';
-import {getPersonalDetailsForLogins} from '../../libs/OptionsListUtils';
+import {addSMSDomainIfPhoneNumber, getPersonalDetailsForLogins} from '../../libs/OptionsListUtils';
import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator';
import ScreenWrapper from '../../components/ScreenWrapper';
import Tooltip from '../../components/Tooltip';
@@ -109,7 +110,7 @@ class IOUModal extends Component {
.map(personalDetails => ({
login: personalDetails.login,
text: personalDetails.displayName,
- alternateText: personalDetails.login,
+ alternateText: Str.isSMSLogin(personalDetails.login) ? Str.removeSMSDomain(personalDetails.login) : personalDetails.login,
icons: [personalDetails.avatar],
keyForList: personalDetails.login,
}));
@@ -270,7 +271,7 @@ class IOUModal extends Component {
// should send in cents to API
amount: Math.round(this.state.amount * 100),
currency: this.props.iou.selectedCurrencyCode,
- debtorEmail: this.state.participants[0].login,
+ debtorEmail: addSMSDomainIfPhoneNumber(this.state.participants[0].login),
});
}
diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js
index 9ffe5e491fc9..e3b4bfd3f09d 100755
--- a/src/pages/signin/LoginForm.js
+++ b/src/pages/signin/LoginForm.js
@@ -4,7 +4,6 @@ import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
import _ from 'underscore';
import styles from '../../styles/styles';
-import themeColors from '../../styles/themes/default';
import Button from '../../components/Button';
import Text from '../../components/Text';
import {fetchAccountDetails} from '../../libs/actions/Session';
@@ -83,8 +82,6 @@ class LoginForm extends React.Component {
autoCapitalize="none"
autoCorrect={false}
keyboardType={getEmailKeyboardType()}
- placeholder={this.props.translate('loginForm.enterYourPhoneOrEmail')}
- placeholderTextColor={themeColors.placeholderText}
autoFocus={canFocusInputOnScreenFocus()}
translateX={-18}
/>
diff --git a/src/pages/workspace/WorkspacePeoplePage.js b/src/pages/workspace/WorkspacePeoplePage.js
index a396454083fe..f32720f7cb40 100644
--- a/src/pages/workspace/WorkspacePeoplePage.js
+++ b/src/pages/workspace/WorkspacePeoplePage.js
@@ -198,7 +198,7 @@ class WorkspacePeoplePage extends React.Component {
- Admin
+ {this.props.translate('common.admin')}
diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js
index 0a16c61e642b..0bdcea4ca963 100644
--- a/tests/unit/OptionsListUtilsTest.js
+++ b/tests/unit/OptionsListUtilsTest.js
@@ -445,7 +445,7 @@ describe('OptionsListUtils', () => {
expect(results.recentReports.length).toBe(0);
expect(results.personalDetails.length).toBe(0);
expect(results.userToInvite).not.toBe(null);
- expect(results.userToInvite.login).toBe(`+15005550006${CONST.SMS.DOMAIN}`);
+ expect(results.userToInvite.login).toBe('+15005550006');
// When we add a search term for which no options exist and the searchValue itself
// is a potential phone number with country code added
@@ -456,7 +456,7 @@ describe('OptionsListUtils', () => {
expect(results.recentReports.length).toBe(0);
expect(results.personalDetails.length).toBe(0);
expect(results.userToInvite).not.toBe(null);
- expect(results.userToInvite.login).toBe(`+15005550006${CONST.SMS.DOMAIN}`);
+ expect(results.userToInvite.login).toBe('+15005550006');
// Test Concierge's existence in new group options
results = OptionsListUtils.getNewGroupOptions(REPORTS_WITH_CONCIERGE, PERSONAL_DETAILS_WITH_CONCIERGE);