diff --git a/FORMS.md b/FORMS.md
index 65e9cfaeae0c..d80b2dff3310 100644
--- a/FORMS.md
+++ b/FORMS.md
@@ -210,4 +210,4 @@ Form.js will automatically provide the following props to any input with the inp
- defaultValue: The input default value.
- errorText: The translated error text that is returned by validate for that specific input.
- onBlur: An onBlur handler that calls validate.
-- onChange: An onChange handler that saves draft values and calls validate.
+- onInputChange: An onChange handler that saves draft values and calls validate for that input (inputA). Passing an inputID as a second param allows inputA to manipulate the input value of the provided inputID (inputB).
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 443f02db466b..47c964dc1874 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -152,8 +152,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001017001
- versionName "1.1.70-1"
+ versionCode 1001017002
+ versionName "1.1.70-2"
}
splits {
abi {
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 03b85a8b6e04..35bb5c0abe92 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -30,7 +30,7 @@
CFBundleVersion
- 1.1.70.1
+ 1.1.70.2
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index 03f71a81554c..fe19515cd8f5 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.1.70.1
+ 1.1.70.2
diff --git a/package-lock.json b/package-lock.json
index 6e34320b54e1..2ac942b3c2d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.1.70-1",
+ "version": "1.1.70-2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 28c258a37659..196d773e4ae5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.1.70-1",
+ "version": "1.1.70-2",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
diff --git a/src/components/AddressSearch.js b/src/components/AddressSearch.js
index 9458a85361f4..7ad5474ae06b 100644
--- a/src/components/AddressSearch.js
+++ b/src/components/AddressSearch.js
@@ -106,7 +106,11 @@ const AddressSearch = (props) => {
if (_.size(values) === 0) {
return;
}
- props.onInputChange(values);
+ if (props.inputID) {
+ _.each(values, (value, key) => props.onInputChange(value, key));
+ } else {
+ props.onInputChange(values);
+ }
};
return (
@@ -161,7 +165,7 @@ const AddressSearch = (props) => {
label: props.label,
containerStyles: props.containerStyles,
errorText: props.errorText,
- hint: props.hint,
+ hint: displayListViewBorder ? undefined : props.hint,
value: props.value,
defaultValue: props.defaultValue,
inputID: props.inputID,
diff --git a/src/components/Banner.js b/src/components/Banner.js
index a7ac463646f1..a4ea17eec2c8 100644
--- a/src/components/Banner.js
+++ b/src/components/Banner.js
@@ -23,6 +23,7 @@ const Banner = props => (
styles.p5,
styles.borderRadiusNormal,
isHovered ? styles.activeComponentBG : styles.hoveredComponentBG,
+ styles.breakAll,
]}
>
diff --git a/src/components/Button.js b/src/components/Button.js
index a315abc160fc..4fcc046e0f7c 100644
--- a/src/components/Button.js
+++ b/src/components/Button.js
@@ -173,14 +173,11 @@ class Button extends Component {
return ;
}
- if (this.props.isLoading) {
- return ;
- }
-
const textComponent = (
{this.renderContent()}
+ {this.props.isLoading && (
+
+ )}
)}
diff --git a/src/components/Form.js b/src/components/Form.js
index 41fe3bc1b480..e33d3a959274 100644
--- a/src/components/Form.js
+++ b/src/components/Form.js
@@ -158,10 +158,16 @@ class Form extends React.Component {
this.setTouchedInput(inputID);
this.validate(this.inputValues);
},
- onInputChange: (value) => {
- this.inputValues[inputID] = value;
+ onInputChange: (value, key) => {
+ const inputKey = key || inputID;
+ this.inputValues[inputKey] = value;
+ const inputRef = this.inputRefs[inputKey];
+
+ if (key && inputRef && _.isFunction(inputRef.setNativeProps)) {
+ inputRef.setNativeProps({value});
+ }
if (child.props.shouldSaveDraft) {
- FormActions.setDraftValues(this.props.formID, {[inputID]: value});
+ FormActions.setDraftValues(this.props.formID, {[inputKey]: value});
}
this.validate(this.inputValues);
},
diff --git a/src/components/Modal/BaseModal.js b/src/components/Modal/BaseModal.js
index 3779304830f0..105d4cef3230 100644
--- a/src/components/Modal/BaseModal.js
+++ b/src/components/Modal/BaseModal.js
@@ -77,6 +77,7 @@ class BaseModal extends PureComponent {
);
return (
{
if (e && e.type === 'keydown' && e.key === 'Enter') {
return;
diff --git a/src/components/ReportTransaction.js b/src/components/ReportTransaction.js
index 599fa482c4b0..c201434d9569 100644
--- a/src/components/ReportTransaction.js
+++ b/src/components/ReportTransaction.js
@@ -1,18 +1,16 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import lodashGet from 'lodash/get';
-import {
- View, Pressable, ActivityIndicator,
-} from 'react-native';
+import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import ONYXKEYS from '../ONYXKEYS';
import styles from '../styles/styles';
-import themeColors from '../styles/themes/default';
import * as IOU from '../libs/actions/IOU';
import reportActionPropTypes from '../pages/home/report/reportActionPropTypes';
import ReportActionItemSingle from '../pages/home/report/ReportActionItemSingle';
import Text from './Text';
+import Button from './Button';
const propTypes = {
/** The chatReport which the transaction is associated with */
@@ -88,30 +86,13 @@ class ReportTransaction extends Component {
{this.props.canBeRejected && (
-
- {
- this.isBeingRejected()
- ? (
-
- )
- : (
-
- {this.props.rejectButtonLabelText}
-
- )
- }
-
+ isLoading={this.isBeingRejected()}
+ />
)}
diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js
index 84e8b6fe70db..600d428f0be8 100644
--- a/src/libs/Pusher/pusher.js
+++ b/src/libs/Pusher/pusher.js
@@ -102,11 +102,10 @@ function getChannel(channelName) {
* @param {Pusher.Channel} channel
* @param {String} eventName
* @param {Function} [eventCallback]
- * @param {Boolean} [isChunked] Do we expect this channel to send chunked/separate blocks of data that need recombining?
*
* @private
*/
-function bindEventToChannel(channel, eventName, eventCallback = () => {}, isChunked = false) {
+function bindEventToChannel(channel, eventName, eventCallback = () => {}) {
if (!eventName) {
return;
}
@@ -120,7 +119,7 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}, isChun
Log.alert('[Pusher] Unable to parse JSON response from Pusher', {error: err, eventData});
return;
}
- if (!isChunked) {
+ if (data.id === undefined || data.chunk === undefined || data.final === undefined) {
eventCallback(data);
return;
}
@@ -169,9 +168,6 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}, isChun
* @param {String} channelName
* @param {String} eventName
* @param {Function} [eventCallback]
- * @param {Boolean} [isChunked] This parameters tells us whether or not we expect the result to come in individual
- * pieces/chunks (because it exceeds
- * the 10kB limit that pusher has).
* @param {Function} [onResubscribe] Callback to be called when reconnection happen
*
* @return {Promise}
@@ -182,7 +178,6 @@ function subscribe(
channelName,
eventName,
eventCallback = () => {},
- isChunked = false,
onResubscribe = () => {},
) {
return new Promise((resolve, reject) => {
@@ -201,7 +196,7 @@ function subscribe(
channel.bind('pusher:subscription_succeeded', () => {
// Check so that we do not bind another event with each reconnect attempt
if (!isBound) {
- bindEventToChannel(channel, eventName, eventCallback, isChunked);
+ bindEventToChannel(channel, eventName, eventCallback);
resolve();
isBound = true;
return;
@@ -225,7 +220,7 @@ function subscribe(
reject(error);
});
} else {
- bindEventToChannel(channel, eventName, eventCallback, isChunked);
+ bindEventToChannel(channel, eventName, eventCallback);
resolve();
}
});
diff --git a/src/libs/actions/Inbox.js b/src/libs/actions/Inbox.js
index 84662dba8a2b..4bd92abdf0bf 100644
--- a/src/libs/actions/Inbox.js
+++ b/src/libs/actions/Inbox.js
@@ -1,5 +1,6 @@
import Onyx from 'react-native-onyx';
import ONYXKEYS from '../../ONYXKEYS';
+import * as API from '../API';
import * as DeprecatedAPI from '../deprecatedAPI';
import Growl from '../Growl';
import * as Localize from '../Localize';
@@ -46,14 +47,11 @@ function requestInboxCall({
});
}
-function getInboxCallWaitTime() {
- DeprecatedAPI.Inbox_CallUser_WaitTime()
- .then((data) => {
- Onyx.set(ONYXKEYS.INBOX_CALL_USER_WAIT_TIME, data.waitTime);
- });
+function openRequestCallPage() {
+ API.read('OpenRequestCallPage');
}
export {
requestInboxCall,
- getInboxCallWaitTime,
+ openRequestCallPage,
};
diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js
index cb0bea164d01..76f52becc26f 100644
--- a/src/libs/actions/Policy.js
+++ b/src/libs/actions/Policy.js
@@ -526,9 +526,12 @@ function subscribeToPolicyEvents() {
// Remove the members from the policy
Onyx.set(key, policyWithoutEmployee);
- // Refetch the policy expense chats to update their state
+ // Refetch the policy expense chats to update their state and their actions to get the archive reason
if (!_.isEmpty(policyExpenseChatIDs)) {
Report.fetchChatReportsByIDs(policyExpenseChatIDs);
+ _.each(policyExpenseChatIDs, (reportID) => {
+ Report.fetchActions(reportID);
+ });
}
// Remove the default chats if we are one of the users getting removed
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index c64d9a630cbf..79438cb60f8a 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -728,9 +728,8 @@ function getReportChannelName(reportID) {
*
* @param {String} eventName
* @param {Function} onEvent
- * @param {Boolean} isChunked
*/
-function subscribeToPrivateUserChannelEvent(eventName, onEvent, isChunked = false) {
+function subscribeToPrivateUserChannelEvent(eventName, onEvent) {
const pusherChannelName = `private-encrypted-user-accountID-${currentUserAccountID}${CONFIG.PUSHER.SUFFIX}`;
/**
@@ -759,7 +758,7 @@ function subscribeToPrivateUserChannelEvent(eventName, onEvent, isChunked = fals
Log.hmmm('[Report] Failed to subscribe to Pusher channel', false, {error, pusherChannelName, eventName});
}
- Pusher.subscribe(pusherChannelName, eventName, onEventPush, isChunked, onPusherResubscribeToPrivateUserChannel)
+ Pusher.subscribe(pusherChannelName, eventName, onEventPush, onPusherResubscribeToPrivateUserChannel)
.catch(onSubscriptionFailed);
}
@@ -781,17 +780,13 @@ function subscribeToUserEvents() {
subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_COMMENT, pushJSON => updateReportWithNewAction(pushJSON.reportID, pushJSON.reportAction, pushJSON.notificationPreference));
// Live-update a report's actions when a 'chunked report comment' event is received.
- subscribeToPrivateUserChannelEvent(
- Pusher.TYPE.REPORT_COMMENT_CHUNK,
- pushJSON => updateReportWithNewAction(pushJSON.reportID, pushJSON.reportAction, pushJSON.notificationPreference),
- true,
- );
+ subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_COMMENT_CHUNK, pushJSON => updateReportWithNewAction(pushJSON.reportID, pushJSON.reportAction, pushJSON.notificationPreference));
// Live-update a report's actions when an 'edit comment' event is received.
subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_COMMENT_EDIT, pushJSON => updateReportActionMessage(pushJSON.reportID, pushJSON.sequenceNumber, pushJSON.message));
// Live-update a report's actions when an 'edit comment chunk' event is received.
- subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_COMMENT_EDIT_CHUNK, pushJSON => updateReportActionMessage(pushJSON.reportID, pushJSON.sequenceNumber, pushJSON.message), true);
+ subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_COMMENT_EDIT_CHUNK, pushJSON => updateReportActionMessage(pushJSON.reportID, pushJSON.sequenceNumber, pushJSON.message));
// Live-update a report's pinned state when a 'report toggle pinned' event is received.
subscribeToPrivateUserChannelEvent(Pusher.TYPE.REPORT_TOGGLE_PINNED, pushJSON => updateReportPinnedState(pushJSON.reportID, pushJSON.isPinned));
diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js
index 5727c0b880a1..16220acb7c80 100644
--- a/src/libs/actions/User.js
+++ b/src/libs/actions/User.js
@@ -305,7 +305,7 @@ function subscribeToUserEvents() {
// Live-update an user's preferred locale
Pusher.subscribe(pusherChannelName, Pusher.TYPE.PREFERRED_LOCALE, (pushJSON) => {
Onyx.merge(ONYXKEYS.NVP_PREFERRED_LOCALE, pushJSON.preferredLocale);
- }, false,
+ },
() => {
NetworkConnection.triggerReconnectionCallbacks('pusher re-subscribed to private user channel');
})
@@ -320,7 +320,7 @@ function subscribeToUserEvents() {
// Subscribe to screen share requests sent by GuidesPlus agents
Pusher.subscribe(pusherChannelName, Pusher.TYPE.SCREEN_SHARE_REQUEST, (pushJSON) => {
Onyx.merge(ONYXKEYS.SCREEN_SHARE_REQUEST, pushJSON);
- }, false,
+ },
() => {
NetworkConnection.triggerReconnectionCallbacks('pusher re-subscribed to private user channel');
})
@@ -351,7 +351,7 @@ function subscribeToExpensifyCardUpdates() {
} else {
Onyx.merge(ONYXKEYS.USER, {isCheckingDomain: pushJSON.isCheckingDomain});
}
- }, false,
+ },
() => {
NetworkConnection.triggerReconnectionCallbacks('pusher re-subscribed to private user channel');
})
diff --git a/src/libs/deprecatedAPI.js b/src/libs/deprecatedAPI.js
index d154ee6c0472..67333741f0a7 100644
--- a/src/libs/deprecatedAPI.js
+++ b/src/libs/deprecatedAPI.js
@@ -843,15 +843,6 @@ function Inbox_CallUser(parameters) {
return Network.post(commandName, parameters);
}
-/**
- * Get the current wait time in minutes for an inbox call
- * @returns {Promise}
- */
-function Inbox_CallUser_WaitTime() {
- const commandName = 'Inbox_CallUser_WaitTime';
- return Network.post(commandName);
-}
-
/**
* @param {Object} parameters
* @param {String} parameters.reportIDList
@@ -952,7 +943,6 @@ export {
GetRequestCountryCode,
Graphite_Timer,
Inbox_CallUser,
- Inbox_CallUser_WaitTime,
PayIOU,
PayWithWallet,
PersonalDetails_GetForEmails,
diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js
index b42ecfc57332..84617412d833 100644
--- a/src/pages/RequestCallPage.js
+++ b/src/pages/RequestCallPage.js
@@ -234,7 +234,7 @@ class RequestCallPage extends Component {
return;
}
- Inbox.getInboxCallWaitTime();
+ Inbox.openRequestCallPage();
}
validatePhoneInput() {
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js
index 7196a4ce1b2e..c06d0fea408b 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.js
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js
@@ -51,6 +51,9 @@ export default [
let {sourceURL} = attachmentDetails;
sourceURL = addEncryptedAuthTokenToURL(sourceURL);
fileDownload(sourceURL, originalFileName);
+ if (closePopover) {
+ hideContextMenu(true, ReportActionComposeFocusManager.focus);
+ }
},
getDescription: () => {},
},
diff --git a/src/pages/signin/ResendValidationForm.js b/src/pages/signin/ResendValidationForm.js
index 3a19e901cc15..701cc41d8561 100755
--- a/src/pages/signin/ResendValidationForm.js
+++ b/src/pages/signin/ResendValidationForm.js
@@ -143,7 +143,6 @@ class ResendValidationForm extends React.Component {
text={this.props.translate('resendValidationForm.resendLink')}
isLoading={this.props.account.loading}
onPress={this.validateAndSubmitForm}
- style={styles.resendLinkButton}
/>
>
diff --git a/src/stories/Form.stories.js b/src/stories/Form.stories.js
index 6473750dac6d..926aa40fddc2 100644
--- a/src/stories/Form.stories.js
+++ b/src/stories/Form.stories.js
@@ -104,7 +104,7 @@ const Template = (args) => {
/>
@@ -179,8 +179,8 @@ const defaultArgs = {
if (!values.pickAnotherFruit) {
errors.pickAnotherFruit = 'Please select a fruit';
}
- if (!values.pickState) {
- errors.pickState = 'Please select a state';
+ if (!values.state) {
+ errors.state = 'Please select a state';
}
if (!values.checkbox) {
errors.checkbox = 'You must accept the Terms of Service to continue';
@@ -204,7 +204,7 @@ const defaultArgs = {
dob: '1990-01-01',
pickFruit: 'orange',
pickAnotherFruit: 'apple',
- pickState: 'AL',
+ state: 'AL',
checkbox: false,
},
};
@@ -221,7 +221,7 @@ InputError.args = {
pickFruit: '',
dob: '',
pickAnotherFruit: '',
- pickState: '',
+ state: '',
checkbox: false,
},
};
diff --git a/src/styles/styles.js b/src/styles/styles.js
index 60159bba44fa..d46612af0886 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -320,6 +320,10 @@ const styles = {
backgroundColor: 'transparent',
},
+ opacity0: {
+ opacity: 0,
+ },
+
opacity1: {
opacity: 1,
},
@@ -952,10 +956,6 @@ const styles = {
height: '100%',
},
- resendLinkButton: {
- minWidth: 124,
- },
-
sidebarFooter: {
alignItems: 'center',
display: 'flex',
diff --git a/src/styles/utilities/positioning.js b/src/styles/utilities/positioning.js
index 455566b4655d..f25c757fbfc3 100644
--- a/src/styles/utilities/positioning.js
+++ b/src/styles/utilities/positioning.js
@@ -15,6 +15,12 @@ export default {
tn8: {
top: -32,
},
+ l0: {
+ left: 0,
+ },
+ r0: {
+ right: 0,
+ },
r4: {
right: 16,
},