From cd73cbacc0ebbb618972acd968bd4ceb6cb84d28 Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 9 Dec 2022 17:21:53 -0800 Subject: [PATCH 01/81] Fix set-pusher-suffix after linter --- scripts/set-pusher-suffix.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/set-pusher-suffix.sh b/scripts/set-pusher-suffix.sh index e1620b149f7b..2f6f3efab5ca 100755 --- a/scripts/set-pusher-suffix.sh +++ b/scripts/set-pusher-suffix.sh @@ -4,9 +4,13 @@ # config file to be parsed for the suffix (relative to current project root) CONFIG_FILE="../Web-Expensify/_config.local.php" -if [ -f ".env" ]; then - # Export vars from the .env file to access the $EXPENSIFY_URL - export "$(grep -v '^#' .env | xargs)" +if [ -f '.env' ]; then + while read -r line; do + if [[ "$line" == \#* ]]; then + continue + fi + export "${line?}" + done < .env fi # use the suffix only when the config file can be found From 0e3c449e67a0d9d3b14ed2793a9b000279b577ac Mon Sep 17 00:00:00 2001 From: rory Date: Fri, 9 Dec 2022 17:23:46 -0800 Subject: [PATCH 02/81] Use 4 spaces --- scripts/set-pusher-suffix.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/set-pusher-suffix.sh b/scripts/set-pusher-suffix.sh index 2f6f3efab5ca..eaa51f1425c0 100755 --- a/scripts/set-pusher-suffix.sh +++ b/scripts/set-pusher-suffix.sh @@ -5,12 +5,12 @@ CONFIG_FILE="../Web-Expensify/_config.local.php" if [ -f '.env' ]; then - while read -r line; do - if [[ "$line" == \#* ]]; then - continue - fi - export "${line?}" - done < .env + while read -r line; do + if [[ "$line" == \#* ]]; then + continue + fi + export "${line?}" + done < .env fi # use the suffix only when the config file can be found From c4762c0f72350a85b398faa6502ec13a3a74a9fd Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Feb 2023 23:47:34 -0800 Subject: [PATCH 03/81] Remove dead ExpensifyCash files --- ios/ExpensifyCash-Bridging-Header.h | 2 -- .../xcshareddata/IDEWorkspaceChecks.plist | 8 -------- 2 files changed, 10 deletions(-) delete mode 100644 ios/ExpensifyCash-Bridging-Header.h delete mode 100644 ios/ExpensifyCash.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/ios/ExpensifyCash-Bridging-Header.h b/ios/ExpensifyCash-Bridging-Header.h deleted file mode 100644 index 2420459f9630..000000000000 --- a/ios/ExpensifyCash-Bridging-Header.h +++ /dev/null @@ -1,2 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. \ No newline at end of file diff --git a/ios/ExpensifyCash.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/ExpensifyCash.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/ios/ExpensifyCash.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - From 0d34efd2cadedb93141177555454af2aaebc599a Mon Sep 17 00:00:00 2001 From: Priyesh Shah Date: Thu, 16 Feb 2023 04:32:34 +1100 Subject: [PATCH 04/81] disabled timezone options if it is set to automatic --- .../settings/Profile/TimezoneSelectPage.js | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index fd91f9a2e91f..2b4e23d87622 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -34,7 +34,7 @@ class TimezoneSelectPage extends Component { this.saveSelectedTimezone = this.saveSelectedTimezone.bind(this); this.filterShownTimezones = this.filterShownTimezones.bind(this); - this.currentSelectedTimezone = lodashGet(props.currentUserPersonalDetails, 'timezone.selected', CONST.DEFAULT_TIME_ZONE.selected); + this.timezone = lodashGet(props.currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); this.allTimezones = _.chain(moment.tz.names()) .filter(timezone => !timezone.startsWith('Etc/GMT')) .map(timezone => ({ @@ -42,19 +42,40 @@ class TimezoneSelectPage extends Component { keyForList: timezone, // Include the green checkmark icon to indicate the currently selected value - customIcon: timezone === this.currentSelectedTimezone ? greenCheckmark : undefined, + customIcon: timezone === this.timezone.selected ? greenCheckmark : undefined, // This property will make the currently selected value have bold text - boldStyle: timezone === this.currentSelectedTimezone, + boldStyle: timezone === this.timezone.selected, })) .value(); this.state = { - timezoneInputText: this.currentSelectedTimezone, + timezoneInputText: this.timezone.selected, timezoneOptions: this.allTimezones, }; } + componentDidUpdate() { + // Update timezoneInputText & all timezoneOptions when the timezone object changes + const newTimezone = lodashGet(this.props.currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); + if (_.isEqual(this.timezone, newTimezone)) { return; } + this.timezone = newTimezone; + const updatedAllTimezones = _.map(this.allTimezones, timezone => ({ + ...timezone, + + // Include the green checkmark icon to indicate the currently selected value + customIcon: timezone === this.timezone.selected ? greenCheckmark : undefined, + + // This property will make the currently selected value have bold text + boldStyle: timezone === this.timezone.selected, + })); + + this.setState({ + timezoneInputText: this.timezone.selected, + timezoneOptions: updatedAllTimezones, + }); + } + /** * @param {Object} timezone * @param {String} timezone.text @@ -90,7 +111,7 @@ class TimezoneSelectPage extends Component { onChangeText={this.filterShownTimezones} onSelectRow={this.saveSelectedTimezone} optionHoveredStyle={styles.hoveredComponentBG} - sections={[{data: this.state.timezoneOptions}]} + sections={[{data: this.state.timezoneOptions, isDisabled: this.timezone.automatic}]} shouldHaveOptionSeparator safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle} /> From 073f8f75422731c219f64fb10db053adfa42d7e7 Mon Sep 17 00:00:00 2001 From: Priyesh Shah Date: Fri, 17 Feb 2023 02:40:00 +1100 Subject: [PATCH 05/81] updated the comment in componentDidUpdate --- src/pages/settings/Profile/TimezoneSelectPage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index 2b4e23d87622..97b5a23fece3 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -56,7 +56,8 @@ class TimezoneSelectPage extends Component { } componentDidUpdate() { - // Update timezoneInputText & all timezoneOptions when the timezone object changes + // componentDidUpdate is added in order to update the timezone options when automatic is toggled on/off as + // navigating back doesn't unmount the page, thus it won't update the timezone options & stay disabled without this. const newTimezone = lodashGet(this.props.currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); if (_.isEqual(this.timezone, newTimezone)) { return; } this.timezone = newTimezone; From 9e22ee5adc2e28c5c10dca2b433de097bf5216e8 Mon Sep 17 00:00:00 2001 From: Priyesh Shah Date: Fri, 17 Feb 2023 06:51:02 +1100 Subject: [PATCH 06/81] refactored componentDidUpdate to fix options not udating issue --- .../settings/Profile/TimezoneSelectPage.js | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index 97b5a23fece3..a2ec14d38131 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -39,7 +39,7 @@ class TimezoneSelectPage extends Component { .filter(timezone => !timezone.startsWith('Etc/GMT')) .map(timezone => ({ text: timezone, - keyForList: timezone, + keyForList: this.getKey(timezone), // Include the green checkmark icon to indicate the currently selected value customIcon: timezone === this.timezone.selected ? greenCheckmark : undefined, @@ -59,24 +59,38 @@ class TimezoneSelectPage extends Component { // componentDidUpdate is added in order to update the timezone options when automatic is toggled on/off as // navigating back doesn't unmount the page, thus it won't update the timezone options & stay disabled without this. const newTimezone = lodashGet(this.props.currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); - if (_.isEqual(this.timezone, newTimezone)) { return; } + if (_.isEqual(this.timezone, newTimezone)) { + return; + } this.timezone = newTimezone; - const updatedAllTimezones = _.map(this.allTimezones, timezone => ({ - ...timezone, + this.allTimezones = _.map(this.allTimezones, (timezone) => { + const text = timezone.text.split('-')[0]; + return { + text, + keyForList: this.getKey(text), - // Include the green checkmark icon to indicate the currently selected value - customIcon: timezone === this.timezone.selected ? greenCheckmark : undefined, + // Include the green checkmark icon to indicate the currently selected value + customIcon: text === this.timezone.selected ? greenCheckmark : undefined, - // This property will make the currently selected value have bold text - boldStyle: timezone === this.timezone.selected, - })); + // This property will make the currently selected value have bold text + boldStyle: text === this.timezone.selected, + }; + }); this.setState({ timezoneInputText: this.timezone.selected, - timezoneOptions: updatedAllTimezones, + timezoneOptions: this.allTimezones, }); } + /** + * @param {String} text + * @return {string} key for list item + */ + getKey(text) { + return `${text}-${(new Date()).getTime()}`; + } + /** * @param {Object} timezone * @param {String} timezone.text From 3f587b6dac1805466395136aa1726eec556cf9c7 Mon Sep 17 00:00:00 2001 From: Priyesh Shah Date: Fri, 17 Feb 2023 06:55:11 +1100 Subject: [PATCH 07/81] refactored get timezone code to follow DRY --- src/pages/settings/Profile/TimezoneSelectPage.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index a2ec14d38131..fd8af1ab4836 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -34,7 +34,7 @@ class TimezoneSelectPage extends Component { this.saveSelectedTimezone = this.saveSelectedTimezone.bind(this); this.filterShownTimezones = this.filterShownTimezones.bind(this); - this.timezone = lodashGet(props.currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); + this.timezone = this.getUserTimezone(props.currentUserPersonalDetails); this.allTimezones = _.chain(moment.tz.names()) .filter(timezone => !timezone.startsWith('Etc/GMT')) .map(timezone => ({ @@ -58,7 +58,7 @@ class TimezoneSelectPage extends Component { componentDidUpdate() { // componentDidUpdate is added in order to update the timezone options when automatic is toggled on/off as // navigating back doesn't unmount the page, thus it won't update the timezone options & stay disabled without this. - const newTimezone = lodashGet(this.props.currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); + const newTimezone = this.getUserTimezone(this.props.currentUserPersonalDetails); if (_.isEqual(this.timezone, newTimezone)) { return; } @@ -91,6 +91,14 @@ class TimezoneSelectPage extends Component { return `${text}-${(new Date()).getTime()}`; } + /** + * @param {Object} currentUserPersonalDetails + * @return {Object} user's timezone data + */ + getUserTimezone(currentUserPersonalDetails) { + return lodashGet(currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE); + } + /** * @param {Object} timezone * @param {String} timezone.text From 23eb39b4d9eef6228b99d741c462962a0487853d Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Thu, 16 Feb 2023 19:55:03 -0800 Subject: [PATCH 08/81] fix composer early line break --- src/components/Composer/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index 6a0167fe937a..e92e0603e396 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -14,6 +14,7 @@ import * as Browser from '../../libs/Browser'; import Clipboard from '../../libs/Clipboard'; import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions'; import compose from '../../libs/compose'; +import styles from '../../styles/styles'; const propTypes = { /** Maximum number of lines in the text input */ @@ -357,7 +358,13 @@ class Composer extends React.Component { onChange={this.shouldCallUpdateNumberOfLines} onSelectionChange={this.onSelectionChange} numberOfLines={this.state.numberOfLines} - style={propStyles} + style={[ + propStyles, + + // We are hiding the scrollbar to prevent it from reducing the text input width, + // so we can get the correct scroll height while calculating the number of lines. + this.state.numberOfLines < this.props.maxLines ? styles.overflowHidden : {}, + ]} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...propsWithoutStyles} disabled={this.props.isDisabled} From 3f0476448d61125de75ea9b6b1d0c6b97116fd14 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 17 Feb 2023 02:25:07 -0800 Subject: [PATCH 09/81] fix lint --- src/components/Composer/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index e92e0603e396..6eeef6d3fa1b 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -361,7 +361,7 @@ class Composer extends React.Component { style={[ propStyles, - // We are hiding the scrollbar to prevent it from reducing the text input width, + // We are hiding the scrollbar to prevent it from reducing the text input width, // so we can get the correct scroll height while calculating the number of lines. this.state.numberOfLines < this.props.maxLines ? styles.overflowHidden : {}, ]} From 953ca2ea2f3e809c190f62b3457f7aab4f5f72bb Mon Sep 17 00:00:00 2001 From: Priyesh Shah Date: Mon, 20 Feb 2023 02:10:29 +1100 Subject: [PATCH 10/81] Code refactoring to follow DRY & add comments --- .../settings/Profile/TimezoneSelectPage.js | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index fd8af1ab4836..f64714026f82 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -33,20 +33,12 @@ class TimezoneSelectPage extends Component { this.saveSelectedTimezone = this.saveSelectedTimezone.bind(this); this.filterShownTimezones = this.filterShownTimezones.bind(this); + this.getTimezoneOption = this.getTimezoneOption.bind(this); this.timezone = this.getUserTimezone(props.currentUserPersonalDetails); this.allTimezones = _.chain(moment.tz.names()) .filter(timezone => !timezone.startsWith('Etc/GMT')) - .map(timezone => ({ - text: timezone, - keyForList: this.getKey(timezone), - - // Include the green checkmark icon to indicate the currently selected value - customIcon: timezone === this.timezone.selected ? greenCheckmark : undefined, - - // This property will make the currently selected value have bold text - boldStyle: timezone === this.timezone.selected, - })) + .map(timezone => this.getTimezoneOption(timezone)) .value(); this.state = { @@ -65,16 +57,7 @@ class TimezoneSelectPage extends Component { this.timezone = newTimezone; this.allTimezones = _.map(this.allTimezones, (timezone) => { const text = timezone.text.split('-')[0]; - return { - text, - keyForList: this.getKey(text), - - // Include the green checkmark icon to indicate the currently selected value - customIcon: text === this.timezone.selected ? greenCheckmark : undefined, - - // This property will make the currently selected value have bold text - boldStyle: text === this.timezone.selected, - }; + return this.getTimezoneOption(text); }); this.setState({ @@ -84,6 +67,7 @@ class TimezoneSelectPage extends Component { } /** + * We add the current time to the key to fix a bug where the list options don't update unless the key is updated. * @param {String} text * @return {string} key for list item */ @@ -91,6 +75,24 @@ class TimezoneSelectPage extends Component { return `${text}-${(new Date()).getTime()}`; } + /** + * Get timezone option object for the list. + * @param {String} text + * @return {Object} Timezone list option + */ + getTimezoneOption(text) { + return { + text, + keyForList: this.getKey(text), + + // Include the green checkmark icon to indicate the currently selected value + customIcon: text === this.timezone.selected ? greenCheckmark : undefined, + + // This property will make the currently selected value have bold text + boldStyle: text === this.timezone.selected, + }; + } + /** * @param {Object} currentUserPersonalDetails * @return {Object} user's timezone data From 97c20b32cec80b809f0d179eb36e8d2e64c35ff9 Mon Sep 17 00:00:00 2001 From: Priyesh Shah Date: Mon, 20 Feb 2023 02:19:47 +1100 Subject: [PATCH 11/81] minor code cleanup --- src/pages/settings/Profile/TimezoneSelectPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index f64714026f82..b050a965ebfb 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -38,7 +38,7 @@ class TimezoneSelectPage extends Component { this.timezone = this.getUserTimezone(props.currentUserPersonalDetails); this.allTimezones = _.chain(moment.tz.names()) .filter(timezone => !timezone.startsWith('Etc/GMT')) - .map(timezone => this.getTimezoneOption(timezone)) + .map(this.getTimezoneOption) .value(); this.state = { From c6888fa80494ccdc2a3316d919ea24f83fa1d347 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Mon, 20 Feb 2023 12:12:14 +0100 Subject: [PATCH 12/81] migrating PronounsPage to class component --- src/pages/settings/Profile/PronounsPage.js | 110 +++++++++++++-------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index e6692a107b1f..d776ed817705 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -1,6 +1,6 @@ import _ from 'underscore'; import lodashGet from 'lodash/get'; -import React from 'react'; +import React, {Component} from 'react'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../../components/withCurrentUserPersonalDetails'; import ScreenWrapper from '../../../components/ScreenWrapper'; import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; @@ -15,6 +15,7 @@ import OptionsList from '../../../components/OptionsList'; import themeColors from '../../../styles/themes/default'; import * as Expensicons from '../../../components/Icon/Expensicons'; import CONST from '../../../CONST'; +import OptionsSelector from '../../../components/OptionsSelector'; const greenCheckmark = {src: Expensicons.Checkmark, color: themeColors.success}; @@ -27,60 +28,85 @@ const defaultProps = { ...withCurrentUserPersonalDetailsDefaultProps, }; -const PronounsPage = (props) => { - const currentPronouns = lodashGet(props.currentUserPersonalDetails, 'pronouns', ''); - const pronounsList = _.map(props.translate('pronouns'), (value, key) => { - const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${key}`; - return { - text: value, - value: fullPronounKey, - keyForList: key, +class PronounsPage extends Component { + constructor(props) { + super(props); + const currentPronouns = lodashGet(props.currentUserPersonalDetails, 'pronouns', ''); + this.pronounsList = _.map(props.translate('pronouns'), (value, key) => { + const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${key}`; + return { + text: value, + value: fullPronounKey, + keyForList: key, - // Include the green checkmark icon to indicate the currently selected value - customIcon: fullPronounKey === currentPronouns ? greenCheckmark : undefined, + // Include the green checkmark icon to indicate the currently selected value + customIcon: fullPronounKey === currentPronouns ? greenCheckmark : undefined, - // This property will make the currently selected value have bold text - boldStyle: fullPronounKey === currentPronouns, + // This property will make the currently selected value have bold text + boldStyle: fullPronounKey === currentPronouns, + }; + }); + + this.onChangeText = this.onChangeText.bind(this); + this.getFilteredPronouns = this.getFilteredPronouns.bind(this); + + this.state = { + searchValue: '', }; - }); + } + + onChangeText(searchValue = '') { + this.setState({searchValue}); + } + + getFilteredPronouns() { + if (this.state.searchValue.length === 0) { + return []; + } + return _.filter(this.pronounsList, + pronous => pronous.text.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) >= 0); + } /** * @param {String} selectedPronouns */ - const updatePronouns = (selectedPronouns) => { + updatePronouns(selectedPronouns) { + console.log('selectedPronouns', selectedPronouns); PersonalDetails.updatePronouns(selectedPronouns); - }; + } + + render() { + const filteredPronounsList = this.getFilteredPronouns(); - return ( - - {({safeAreaPaddingBottomStyle}) => ( - <> - Navigation.navigate(ROUTES.SETTINGS_PROFILE)} - onCloseButtonPress={() => Navigation.dismissModal(true)} - /> - - {props.translate('pronounsPage.isShownOnProfile')} - - updatePronouns(option.value)} - hideSectionHeaders - optionHoveredStyle={styles.hoveredComponentBG} - shouldHaveOptionSeparator - contentContainerStyles={[styles.ph5, safeAreaPaddingBottomStyle]} - /> - - )} - - ); + return ( + + {({safeAreaPaddingBottomStyle}) => ( + <> + Navigation.navigate(ROUTES.SETTINGS_PROFILE)} + onCloseButtonPress={() => Navigation.dismissModal(true)} + /> + + {this.props.translate('pronounsPage.isShownOnProfile')} + + + + )} + + ); + } }; PronounsPage.propTypes = propTypes; PronounsPage.defaultProps = defaultProps; -PronounsPage.displayName = 'PronounsPage'; export default compose( withLocalize, From 0e0e851ef0ee9e14afad0567800086412fd9d210 Mon Sep 17 00:00:00 2001 From: Cristi Paval Date: Mon, 20 Feb 2023 23:13:38 +0200 Subject: [PATCH 13/81] Show loading while authenticating from validate code link. --- src/pages/ValidateLoginPage/index.website.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/ValidateLoginPage/index.website.js b/src/pages/ValidateLoginPage/index.website.js index ee8e1f38b04c..a15e13f232a9 100644 --- a/src/pages/ValidateLoginPage/index.website.js +++ b/src/pages/ValidateLoginPage/index.website.js @@ -82,14 +82,14 @@ class ValidateLoginPage extends Component { isAuthenticated = () => Boolean(lodashGet(this.props, 'session.authToken', null)); /** - * Where SignIn was initiated on the current browser. + * Whether SignIn was initiated on the current browser. * @returns {Boolean} */ - isSignInInitiated = () => !this.isAuthenticated() && this.props.credentials && this.props.credentials.login; + isSignInInitiated = () => !this.isAuthenticated() && lodashGet(this.props, 'credentials.login', null); render() { return ( - this.isOnPasswordlessBeta() + this.isOnPasswordlessBeta() && !this.isSignInInitiated() && !lodashGet(this.props, 'account.isLoading', true) ? ( Date: Tue, 21 Feb 2023 10:49:18 +0100 Subject: [PATCH 14/81] trim the search value and send the __predefined_xxxx to update --- src/pages/settings/Profile/PronounsPage.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index d776ed817705..383b4acf1249 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -59,20 +59,26 @@ class PronounsPage extends Component { this.setState({searchValue}); } + /** + * Returns the pronouns list filtered by searchValue needed for the OptionsSelector. + * Empty array is returned if the searchValue is empty. + * + * @returns {Array} + */ getFilteredPronouns() { - if (this.state.searchValue.length === 0) { + const searchedValue = this.state.searchValue.trim(); + if (searchedValue.length === 0) { return []; } return _.filter(this.pronounsList, - pronous => pronous.text.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) >= 0); + pronous => pronous.text.toLowerCase().indexOf(searchedValue.toLowerCase()) >= 0); } /** - * @param {String} selectedPronouns + * @param {Obj} selectedPronouns */ updatePronouns(selectedPronouns) { - console.log('selectedPronouns', selectedPronouns); - PersonalDetails.updatePronouns(selectedPronouns); + PersonalDetails.updatePronouns(selectedPronouns.value); } render() { @@ -92,6 +98,7 @@ class PronounsPage extends Component { {this.props.translate('pronounsPage.isShownOnProfile')} Date: Tue, 21 Feb 2023 13:06:47 +0100 Subject: [PATCH 15/81] removed unused import --- src/pages/settings/Profile/PronounsPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index 383b4acf1249..2b6c0822443b 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -11,7 +11,6 @@ import styles from '../../../styles/styles'; import Navigation from '../../../libs/Navigation/Navigation'; import * as PersonalDetails from '../../../libs/actions/PersonalDetails'; import compose from '../../../libs/compose'; -import OptionsList from '../../../components/OptionsList'; import themeColors from '../../../styles/themes/default'; import * as Expensicons from '../../../components/Icon/Expensicons'; import CONST from '../../../CONST'; From 9b704dafc0dc9b0bf8a490a652ac3893b29da699 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Tue, 21 Feb 2023 13:07:43 +0100 Subject: [PATCH 16/81] Fixed lint errors --- src/pages/settings/Profile/PronounsPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index 2b6c0822443b..f35d0e47e966 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -59,7 +59,7 @@ class PronounsPage extends Component { } /** - * Returns the pronouns list filtered by searchValue needed for the OptionsSelector. + * Returns the pronouns list filtered by searchValue needed for the OptionsSelector. * Empty array is returned if the searchValue is empty. * * @returns {Array} @@ -109,7 +109,7 @@ class PronounsPage extends Component { ); } -}; +} PronounsPage.propTypes = propTypes; PronounsPage.defaultProps = defaultProps; From 151833d2956052a2ba6fe7e85042c31eba3b5c36 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Sat, 18 Feb 2023 01:45:56 +0500 Subject: [PATCH 17/81] passed down query and hash params when app is opened from the browser --- desktop/main.js | 2 +- src/components/DeeplinkWrapper/index.website.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop/main.js b/desktop/main.js index 9381ff0e2dfe..484398f8c363 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -246,7 +246,7 @@ const mainWindow = (() => { app.on('open-url', (event, url) => { event.preventDefault(); const urlObject = new URL(url); - deeplinkUrl = `${APP_DOMAIN}${urlObject.pathname}`; + deeplinkUrl = `${APP_DOMAIN}${urlObject.pathname}${urlObject.search}${urlObject.hash}`; if (browserWindow) { browserWindow.loadURL(deeplinkUrl); diff --git a/src/components/DeeplinkWrapper/index.website.js b/src/components/DeeplinkWrapper/index.website.js index cfcda9660ca8..5179ffa99da0 100644 --- a/src/components/DeeplinkWrapper/index.website.js +++ b/src/components/DeeplinkWrapper/index.website.js @@ -74,7 +74,7 @@ class DeeplinkWrapper extends PureComponent { openRouteInDesktopApp() { const expensifyUrl = new URL(CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL); - const expensifyDeeplinkUrl = `${CONST.DEEPLINK_BASE_URL}${expensifyUrl.host}${window.location.pathname}`; + const expensifyDeeplinkUrl = `${CONST.DEEPLINK_BASE_URL}${expensifyUrl.host}${window.location.pathname}${window.location.search}${window.location.hash}`; // This check is necessary for Safari, otherwise, if the user // does NOT have the Expensify desktop app installed, it's gonna From 1701c8c3fa28d9c7f576e68859615cfc2e276c90 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Thu, 23 Feb 2023 10:29:57 +0100 Subject: [PATCH 18/81] filled input --- src/pages/settings/Profile/PronounsPage.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index f35d0e47e966..d0cdfb6c88d3 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -31,18 +31,24 @@ class PronounsPage extends Component { constructor(props) { super(props); const currentPronouns = lodashGet(props.currentUserPersonalDetails, 'pronouns', ''); + let currentValue = ''; this.pronounsList = _.map(props.translate('pronouns'), (value, key) => { const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${key}`; + const isCurrentPronouns = fullPronounKey === currentPronouns; + if (isCurrentPronouns) { + currentValue = value; + } + return { text: value, value: fullPronounKey, keyForList: key, // Include the green checkmark icon to indicate the currently selected value - customIcon: fullPronounKey === currentPronouns ? greenCheckmark : undefined, + customIcon: isCurrentPronouns ? greenCheckmark : undefined, // This property will make the currently selected value have bold text - boldStyle: fullPronounKey === currentPronouns, + boldStyle: isCurrentPronouns, }; }); @@ -50,7 +56,7 @@ class PronounsPage extends Component { this.getFilteredPronouns = this.getFilteredPronouns.bind(this); this.state = { - searchValue: '', + searchValue: currentValue, }; } @@ -103,6 +109,7 @@ class PronounsPage extends Component { onSelectRow={this.updatePronouns} onChangeText={this.onChangeText} safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle} + shouldFocusOnSelectRow /> )} From d94ae364f9381412b446c9e73a2882d2fea788af Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 23 Feb 2023 13:34:36 +0100 Subject: [PATCH 19/81] Update expensify-common --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 42e93a21b3a7..d73306a7f778 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#a2942d035614bf4bed90ffe2114d6ee828ee96da", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#89104f0c5ff0583567a779b3712b0f13b6f8a9a1", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", From 93c6a7be0f9e1f60f4ccbb3615e0285d6552d7c2 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 23 Feb 2023 21:54:56 +0700 Subject: [PATCH 20/81] fix: remove default avatar that is used in old version --- src/pages/workspace/WorkspaceMembersPage.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index b7faf17ee803..eab52081f0d8 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -29,7 +29,6 @@ import OfflineWithFeedback from '../../components/OfflineWithFeedback'; import {withNetwork} from '../../components/OnyxProvider'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; import networkPropTypes from '../../components/networkPropTypes'; -import * as Expensicons from '../../components/Icon/Expensicons'; import * as ReportUtils from '../../libs/ReportUtils'; import FormHelpMessage from '../../components/FormHelpMessage'; import TextInput from '../../components/TextInput'; @@ -311,7 +310,7 @@ class WorkspaceMembersPage extends React.Component { if (email !== this.props.session.email && email !== this.props.policy.owner && policyMember.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { removableMembers.push(email); } - const details = lodashGet(this.props.personalDetails, email, {displayName: email, login: email, avatar: Expensicons.FallbackAvatar}); + const details = lodashGet(this.props.personalDetails, email, {displayName: email, login: email}); data.push({ ...policyMember, ...details, From 53a08178a01bfecb75808ba3fe6a35cae9d2e025 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Thu, 23 Feb 2023 18:13:24 +0100 Subject: [PATCH 21/81] removed input filled feature --- src/pages/settings/Profile/PronounsPage.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index d0cdfb6c88d3..8c5f0f88877f 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -31,13 +31,10 @@ class PronounsPage extends Component { constructor(props) { super(props); const currentPronouns = lodashGet(props.currentUserPersonalDetails, 'pronouns', ''); - let currentValue = ''; + this.pronounsList = _.map(props.translate('pronouns'), (value, key) => { const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${key}`; const isCurrentPronouns = fullPronounKey === currentPronouns; - if (isCurrentPronouns) { - currentValue = value; - } return { text: value, @@ -56,7 +53,7 @@ class PronounsPage extends Component { this.getFilteredPronouns = this.getFilteredPronouns.bind(this); this.state = { - searchValue: currentValue, + searchValue: '', }; } From 850f4991218a780fc4d5caa2dcdcf611e8f837ef Mon Sep 17 00:00:00 2001 From: Kosuke Tseng Date: Thu, 23 Feb 2023 14:31:06 -0800 Subject: [PATCH 22/81] fix proptypes --- src/components/IOUConfirmationList.js | 2 +- src/pages/iou/steps/IOUConfirmPage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js index 53baab7d64fa..ea012dd32417 100755 --- a/src/components/IOUConfirmationList.js +++ b/src/components/IOUConfirmationList.js @@ -44,7 +44,7 @@ const propTypes = { login: PropTypes.string.isRequired, alternateText: PropTypes.string, hasDraftComment: PropTypes.bool, - icons: PropTypes.arrayOf(PropTypes.string), + icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), searchText: PropTypes.string, text: PropTypes.string, keyForList: PropTypes.string, diff --git a/src/pages/iou/steps/IOUConfirmPage.js b/src/pages/iou/steps/IOUConfirmPage.js index a4f4ce866f60..9cc511990697 100644 --- a/src/pages/iou/steps/IOUConfirmPage.js +++ b/src/pages/iou/steps/IOUConfirmPage.js @@ -27,7 +27,7 @@ const propTypes = { login: PropTypes.string.isRequired, alternateText: PropTypes.string, hasDraftComment: PropTypes.bool, - icons: PropTypes.arrayOf(PropTypes.string), + icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), searchText: PropTypes.string, text: PropTypes.string, keyForList: PropTypes.string, From 7927a9583f454dc323f03912a720071ad25215e5 Mon Sep 17 00:00:00 2001 From: situchan Date: Fri, 24 Feb 2023 00:02:52 +0100 Subject: [PATCH 23/81] fix "LHN - Workspace badge is not fully visible/missing for some Room chats" --- src/styles/styles.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 9244945eabae..9869d302393e 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1222,7 +1222,7 @@ const styles = { minWidth: 'auto', flexBasis: 'auto', flexGrow: 0, - flexShrink: 0, + flexShrink: 1, }, displayNameTooltipEllipsis: { @@ -2839,7 +2839,8 @@ const styles = { borderRadius: 10, overflow: 'hidden', paddingVertical: 2, - flexShrink: 1, + flexShrink: 0, + maxWidth: 180, fontSize: variables.fontSizeSmall, ...spacing.ph2, }, From 0ea435a664a63be630117230b45cc308a07443f5 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 24 Feb 2023 13:28:16 +0000 Subject: [PATCH 24/81] Show the last closed report action --- src/libs/ReportActionsUtils.js | 53 +++++++++++++++++++-------- src/pages/home/report/ReportFooter.js | 5 ++- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 31ad10981cec..6fb694be841a 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -165,21 +165,7 @@ function getLastVisibleMessageText(reportID, actionsToMerge = {}) { * @returns {Array} */ function getSortedReportActionsForDisplay(reportActions) { - // HACK ALERT: We're temporarily filtering out any reportActions keyed by sequenceNumber - // to prevent bugs during the migration from sequenceNumber -> reportActionID - const filteredReportActions = _.filter(reportActions, (reportAction, key) => { - if (!reportAction) { - return false; - } - - if (String(reportAction.sequenceNumber) === key) { - Log.info('Front-end filtered out reportAction keyed by sequenceNumber!', false, reportAction); - return false; - } - - return true; - }); - + const filteredReportActions = filterOutDeprecatedReportActions(reportActions); const sortedReportActions = getSortedReportActions(filteredReportActions, true); return _.filter(sortedReportActions, (reportAction) => { // Filter out any unsupported reportAction types @@ -199,6 +185,42 @@ function getSortedReportActionsForDisplay(reportActions) { }); } +/** + * In some cases, there can be multiple closed report actions in a chat report. + * This method returns the last closed report action so we can always show the correct archived report reason. + * + * @param {Object} reportActions + * @returns {Object} + */ +function getLastClosedReportAction(reportActions) { + const filteredReportActions = filterOutDeprecatedReportActions(reportActions); + const sortedReportActions = getSortedReportActions(filteredReportActions, true); + return _.filter(sortedReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED)[0]; +} + +/** + * A helper method to filter out report actions keyed by sequenceNumbers. + * + * @param {Object} reportActions + * @returns {Array} + */ +function filterOutDeprecatedReportActions(reportActions) { + // HACK ALERT: We're temporarily filtering out any reportActions keyed by sequenceNumber + // to prevent bugs during the migration from sequenceNumber -> reportActionID + return _.filter(reportActions, (reportAction, key) => { + if (!reportAction) { + return false; + } + + if (String(reportAction.sequenceNumber) === key) { + Log.info('Front-end filtered out reportAction keyed by sequenceNumber!', false, reportAction); + return false; + } + + return true; + }); +} + export { getSortedReportActions, getLastVisibleAction, @@ -207,4 +229,5 @@ export { isDeletedAction, isConsecutiveActionMadeByPreviousActor, getSortedReportActionsForDisplay, + getLastClosedReportAction, }; diff --git a/src/pages/home/report/ReportFooter.js b/src/pages/home/report/ReportFooter.js index 29fea5e2ed19..736443ee98a6 100644 --- a/src/pages/home/report/ReportFooter.js +++ b/src/pages/home/report/ReportFooter.js @@ -18,6 +18,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../../../componen import styles from '../../../styles/styles'; import reportActionPropTypes from './reportActionPropTypes'; import reportPropTypes from '../../reportPropTypes'; +import * as ReportActionsUtils from '../../../libs/ReportActionsUtils'; const propTypes = { /** Report object for the current report */ @@ -70,8 +71,10 @@ class ReportFooter extends React.Component { const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); let reportClosedAction; if (isArchivedRoom) { - reportClosedAction = lodashFindLast(this.props.reportActions, action => action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED); + reportClosedAction = ReportActionsUtils.getLastClosedReportAction(this.props.reportActions); } + console.log("reportActions: ", ReportActionsUtils.getLastClosedReportAction(this.props.reportActions)); + console.log("reportClosedAction: ", reportClosedAction); const hideComposer = isArchivedRoom || !_.isEmpty(this.props.errors); return ( <> From 83eb75cf503f6dd00dedc1f9a4bb8298b95c320a Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 24 Feb 2023 13:28:46 +0000 Subject: [PATCH 25/81] Clean up --- src/pages/home/report/ReportFooter.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/home/report/ReportFooter.js b/src/pages/home/report/ReportFooter.js index 736443ee98a6..409a696107a6 100644 --- a/src/pages/home/report/ReportFooter.js +++ b/src/pages/home/report/ReportFooter.js @@ -73,8 +73,6 @@ class ReportFooter extends React.Component { if (isArchivedRoom) { reportClosedAction = ReportActionsUtils.getLastClosedReportAction(this.props.reportActions); } - console.log("reportActions: ", ReportActionsUtils.getLastClosedReportAction(this.props.reportActions)); - console.log("reportClosedAction: ", reportClosedAction); const hideComposer = isArchivedRoom || !_.isEmpty(this.props.errors); return ( <> From f77b3bad5fe269964bffbd5ca311bfa89fe9e100 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 24 Feb 2023 14:03:23 +0000 Subject: [PATCH 26/81] Fix lint --- src/libs/ReportActionsUtils.js | 48 +++++++++++++-------------- src/pages/home/report/ReportFooter.js | 1 - 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 6fb694be841a..350058ce834f 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -155,6 +155,29 @@ function getLastVisibleMessageText(reportID, actionsToMerge = {}) { .substring(0, CONST.REPORT.LAST_MESSAGE_TEXT_MAX_LENGTH); } +/** + * A helper method to filter out report actions keyed by sequenceNumbers. + * + * @param {Object} reportActions + * @returns {Array} + */ +function filterOutDeprecatedReportActions(reportActions) { + // HACK ALERT: We're temporarily filtering out any reportActions keyed by sequenceNumber + // to prevent bugs during the migration from sequenceNumber -> reportActionID + return _.filter(reportActions, (reportAction, key) => { + if (!reportAction) { + return false; + } + + if (String(reportAction.sequenceNumber) === key) { + Log.info('Front-end filtered out reportAction keyed by sequenceNumber!', false, reportAction); + return false; + } + + return true; + }); +} + /** * This method returns the report actions that are ready for display in the ReportActionsView. * The report actions need to be sorted by created timestamp first, and reportActionID second @@ -195,30 +218,7 @@ function getSortedReportActionsForDisplay(reportActions) { function getLastClosedReportAction(reportActions) { const filteredReportActions = filterOutDeprecatedReportActions(reportActions); const sortedReportActions = getSortedReportActions(filteredReportActions, true); - return _.filter(sortedReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED)[0]; -} - -/** - * A helper method to filter out report actions keyed by sequenceNumbers. - * - * @param {Object} reportActions - * @returns {Array} - */ -function filterOutDeprecatedReportActions(reportActions) { - // HACK ALERT: We're temporarily filtering out any reportActions keyed by sequenceNumber - // to prevent bugs during the migration from sequenceNumber -> reportActionID - return _.filter(reportActions, (reportAction, key) => { - if (!reportAction) { - return false; - } - - if (String(reportAction.sequenceNumber) === key) { - Log.info('Front-end filtered out reportAction keyed by sequenceNumber!', false, reportAction); - return false; - } - - return true; - }); + return _.filter(sortedReportActions, reportAction => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED)[0]; } export { diff --git a/src/pages/home/report/ReportFooter.js b/src/pages/home/report/ReportFooter.js index 409a696107a6..06f39e777c8a 100644 --- a/src/pages/home/report/ReportFooter.js +++ b/src/pages/home/report/ReportFooter.js @@ -3,7 +3,6 @@ import _ from 'underscore'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import {View, Keyboard} from 'react-native'; -import lodashFindLast from 'lodash/findLast'; import CONST from '../../../CONST'; import ReportActionCompose from './ReportActionCompose'; From 5f32a0e813e71d05b1d636424c27a781d20a7229 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 24 Feb 2023 15:37:00 +0000 Subject: [PATCH 27/81] Use lodashFindLast --- src/libs/ReportActionsUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 350058ce834f..2e394c6ddd2c 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -9,6 +9,7 @@ import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import Log from './Log'; import isReportMessageAttachment from './isReportMessageAttachment'; +import lodashFindLast from 'lodash/findLast'; const allReportActions = {}; Onyx.connect({ @@ -217,8 +218,8 @@ function getSortedReportActionsForDisplay(reportActions) { */ function getLastClosedReportAction(reportActions) { const filteredReportActions = filterOutDeprecatedReportActions(reportActions); - const sortedReportActions = getSortedReportActions(filteredReportActions, true); - return _.filter(sortedReportActions, reportAction => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED)[0]; + const sortedReportActions = getSortedReportActions(filteredReportActions); + return lodashFindLast(sortedReportActions, action => action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED); } export { From 0fc8590325ebf63bfdc9900da4ac1d93361e1bdb Mon Sep 17 00:00:00 2001 From: situchan Date: Fri, 24 Feb 2023 20:45:03 +0100 Subject: [PATCH 28/81] use variable for workspace badge max width --- src/styles/styles.js | 2 +- src/styles/variables.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 9869d302393e..ead74074d08d 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2840,7 +2840,7 @@ const styles = { overflow: 'hidden', paddingVertical: 2, flexShrink: 0, - maxWidth: 180, + maxWidth: variables.badgeMaxWidth, fontSize: variables.fontSizeSmall, ...spacing.ph2, }, diff --git a/src/styles/variables.js b/src/styles/variables.js index 0e91a707d00a..00ac9cf6ae5e 100644 --- a/src/styles/variables.js +++ b/src/styles/variables.js @@ -98,4 +98,5 @@ export default { modalTopBigIconHeight: 244, modalWordmarkWidth: 154, modalWordmarkHeight: 34, + badgeMaxWidth: 180, }; From 965122028ab83ad60f9a4bcd366424cc09da0a9c Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Fri, 24 Feb 2023 23:47:51 +0100 Subject: [PATCH 29/81] Show NotFoundPage if report does not exist in sub report views --- src/pages/home/report/withReportOrNavigateHome.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/pages/home/report/withReportOrNavigateHome.js b/src/pages/home/report/withReportOrNavigateHome.js index 5e74f65a0cb8..8306e8f5d45b 100644 --- a/src/pages/home/report/withReportOrNavigateHome.js +++ b/src/pages/home/report/withReportOrNavigateHome.js @@ -3,7 +3,7 @@ import React, {Component} from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import getComponentDisplayName from '../../../libs/getComponentDisplayName'; -import Navigation from '../../../libs/Navigation/Navigation'; +import NotFoundPage from '../../ErrorPage/NotFoundPage'; import ONYXKEYS from '../../../ONYXKEYS'; import reportPropTypes from '../../reportPropTypes'; @@ -23,14 +23,11 @@ export default function (WrappedComponent) { }; class WithReportOrNavigateHome extends Component { - componentDidMount() { - if (!_.isEmpty(this.props.report)) { - return; + render() { + if (_.isEmpty(this.props.report) || !this.props.report.reportID) { + return ; } - Navigation.dismissModal(); - } - render() { const rest = _.omit(this.props, ['forwardedRef']); return ( From 15bcf156714e59398c88786496c0a372719be7ee Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 25 Feb 2023 00:08:50 +0100 Subject: [PATCH 30/81] Renamed withReportOrNavigateHome to withReportOrNotFound --- src/pages/ReportDetailsPage.js | 4 ++-- src/pages/ReportParticipantsPage.js | 4 ++-- src/pages/ReportSettingsPage.js | 4 ++-- ...tOrNavigateHome.js => withReportOrNotFound.js} | 15 ++++++++------- 4 files changed, 14 insertions(+), 13 deletions(-) rename src/pages/home/report/{withReportOrNavigateHome.js => withReportOrNotFound.js} (76%) diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js index 688b691fb62c..02bd202c1d2c 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.js @@ -22,7 +22,7 @@ import MenuItem from '../components/MenuItem'; import Text from '../components/Text'; import CONST from '../CONST'; import reportPropTypes from './reportPropTypes'; -import withReportOrNavigateHome from './home/report/withReportOrNavigateHome'; +import withReportOrNotFound from './home/report/withReportOrNotFound'; import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; const propTypes = { @@ -181,7 +181,7 @@ ReportDetailsPage.propTypes = propTypes; export default compose( withLocalize, - withReportOrNavigateHome, + withReportOrNotFound, withOnyx({ personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS, diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index 07c4d62b448a..eb682d5026be 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -19,7 +19,7 @@ import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; import compose from '../libs/compose'; import * as ReportUtils from '../libs/ReportUtils'; import reportPropTypes from './reportPropTypes'; -import withReportOrNavigateHome from './home/report/withReportOrNavigateHome'; +import withReportOrNotFound from './home/report/withReportOrNotFound'; import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; const propTypes = { @@ -118,7 +118,7 @@ ReportParticipantsPage.displayName = 'ReportParticipantsPage'; export default compose( withLocalize, - withReportOrNavigateHome, + withReportOrNotFound, withOnyx({ personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS, diff --git a/src/pages/ReportSettingsPage.js b/src/pages/ReportSettingsPage.js index 86fa8b6cec16..fca21166d0f6 100644 --- a/src/pages/ReportSettingsPage.js +++ b/src/pages/ReportSettingsPage.js @@ -20,7 +20,7 @@ import Picker from '../components/Picker'; import * as ValidationUtils from '../libs/ValidationUtils'; import OfflineWithFeedback from '../components/OfflineWithFeedback'; import reportPropTypes from './reportPropTypes'; -import withReportOrNavigateHome from './home/report/withReportOrNavigateHome'; +import withReportOrNotFound from './home/report/withReportOrNotFound'; import Form from '../components/Form'; import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; @@ -220,7 +220,7 @@ ReportSettingsPage.propTypes = propTypes; export default compose( withLocalize, - withReportOrNavigateHome, + withReportOrNotFound, withOnyx({ policies: { key: ONYXKEYS.COLLECTION.POLICY, diff --git a/src/pages/home/report/withReportOrNavigateHome.js b/src/pages/home/report/withReportOrNotFound.js similarity index 76% rename from src/pages/home/report/withReportOrNavigateHome.js rename to src/pages/home/report/withReportOrNotFound.js index 8306e8f5d45b..e1e3b0f64ef0 100644 --- a/src/pages/home/report/withReportOrNavigateHome.js +++ b/src/pages/home/report/withReportOrNotFound.js @@ -22,7 +22,7 @@ export default function (WrappedComponent) { report: {}, }; - class WithReportOrNavigateHome extends Component { + class WithReportOrNotFound extends Component { render() { if (_.isEmpty(this.props.report) || !this.props.report.reportID) { return ; @@ -40,17 +40,18 @@ export default function (WrappedComponent) { } } - WithReportOrNavigateHome.propTypes = propTypes; - WithReportOrNavigateHome.defaultProps = defaultProps; - WithReportOrNavigateHome.displayName = `withReportOrNavigateHome(${getComponentDisplayName(WrappedComponent)})`; - const withReportOrNavigateHome = React.forwardRef((props, ref) => ( + WithReportOrNotFound.propTypes = propTypes; + WithReportOrNotFound.defaultProps = defaultProps; + WithReportOrNotFound.displayName = `withReportOrNotFound(${getComponentDisplayName(WrappedComponent)})`; + // eslint-disable-next-line rulesdir/no-negated-variables + const withReportOrNotFound = React.forwardRef((props, ref) => ( // eslint-disable-next-line react/jsx-props-no-spreading - + )); return withOnyx({ report: { key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`, }, - })(withReportOrNavigateHome); + })(withReportOrNotFound); } From 626f81f5953d9db07ba1e7fa147257031977c0dc Mon Sep 17 00:00:00 2001 From: Brayden Williams <1311325+redstar504@users.noreply.github.com> Date: Tue, 7 Feb 2023 16:18:54 -0800 Subject: [PATCH 31/81] Account for markdown using debounced comment counter --- src/CONST.js | 1 + src/components/ExceededCommentLength.js | 61 +++++++++++++++---- src/libs/ReportUtils.js | 19 ++++-- src/pages/home/report/ReportActionCompose.js | 17 +++++- .../report/ReportActionItemMessageEdit.js | 17 +++++- 5 files changed, 91 insertions(+), 24 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index accd263483f4..30f9e24ae3e7 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -402,6 +402,7 @@ const CONST = { SHOW_LOADING_SPINNER_DEBOUNCE_TIME: 250, TOOLTIP_SENSE: 1000, TRIE_INITIALIZATION: 'trie_initialization', + COMMENT_LENGTH_DEBOUNCE_TIME: 500, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/components/ExceededCommentLength.js b/src/components/ExceededCommentLength.js index 33f557c66d99..4ef6a5027e73 100644 --- a/src/components/ExceededCommentLength.js +++ b/src/components/ExceededCommentLength.js @@ -1,27 +1,62 @@ -import React from 'react'; +import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; +import {debounce} from 'lodash'; import CONST from '../CONST'; +import * as ReportUtils from '../libs/ReportUtils'; import Text from './Text'; import styles from '../styles/styles'; const propTypes = { - /** The current length of the comment */ - commentLength: PropTypes.number.isRequired, + /** Text Comment */ + comment: PropTypes.string.isRequired, + + /** Update UI on parent when comment length is exceeded */ + onExceededMaxCommentLength: PropTypes.func.isRequired, }; -const ExceededCommentLength = (props) => { - if (props.commentLength <= CONST.MAX_COMMENT_LENGTH) { - return null; +class ExceededCommentLength extends PureComponent { + constructor(props) { + super(props); + + this.state = { + commentLength: 0, + }; + + // By debouncing, we defer the calculation until there is a break in typing + this.updateCommentLength = debounce(this.updateCommentLength.bind(this), CONST.TIMING.COMMENT_LENGTH_DEBOUNCE_TIME); } - return ( - - {`${props.commentLength}/${CONST.MAX_COMMENT_LENGTH}`} - - ); -}; + componentDidMount() { + this.updateCommentLength(); + } + + componentDidUpdate(prevProps) { + if (prevProps.comment === this.props.comment) { + return; + } + + this.updateCommentLength(); + } + + updateCommentLength() { + const commentLength = ReportUtils.getCommentLength(this.props.comment); + this.setState({commentLength}); + this.props.onExceededMaxCommentLength(commentLength > CONST.MAX_COMMENT_LENGTH); + } + + render() { + if (this.state.commentLength <= CONST.MAX_COMMENT_LENGTH) { + return null; + } + + return ( + + {`${this.state.commentLength}/${CONST.MAX_COMMENT_LENGTH}`} + + ); + } +} ExceededCommentLength.propTypes = propTypes; -ExceededCommentLength.displayName = 'ExceededCommentLength'; export default ExceededCommentLength; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index c3ff12d2febf..8105482d3c02 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -774,6 +774,15 @@ function hasReportNameError(report) { return !_.isEmpty(lodashGet(report, 'errorFields.reportName', {})); } +/** + * @param {String} text + * @returns {String} + */ +function getParsedComment(text) { + const parser = new ExpensiMark(); + return text.length < CONST.MAX_MARKUP_LENGTH ? parser.replace(text) : text; +} + /** * @param {String} [text] * @param {File} [file] @@ -783,7 +792,7 @@ function buildOptimisticAddCommentReportAction(text, file) { // For comments shorter than 10k chars, convert the comment from MD into HTML because that's how it is stored in the database // For longer comments, skip parsing and display plaintext for performance reasons. It takes over 40s to parse a 100k long string!! const parser = new ExpensiMark(); - const commentText = text.length < CONST.MAX_MARKUP_LENGTH ? parser.replace(text) : text; + const commentText = getParsedComment(text); const isAttachment = _.isEmpty(text) && file !== undefined; const attachmentInfo = isAttachment ? file : {}; const htmlForNewComment = isAttachment ? 'Uploading Attachment...' : commentText; @@ -1425,13 +1434,13 @@ function getNewMarkerReportActionID(report, sortedAndFilteredReportActions) { } /** - * Replace code points > 127 with C escape sequences, and return the resulting string's overall length - * Used for compatibility with the backend auth validator for AddComment + * Performs the markdown conversion, and replaces code points > 127 with C escape sequences + * Used for compatibility with the backend auth validator for AddComment, and to account for MD in comments * @param {String} textComment - * @returns {Number} + * @returns {Number} The comment's total length as seen from the backend */ function getCommentLength(textComment) { - return textComment.replace(/[^ -~]/g, '\\u????').length; + return getParsedComment(textComment).replace(/[^ -~]/g, '\\u????').trim().length; } /** diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 0efb256e8144..dd6d208e1123 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -132,6 +132,7 @@ class ReportActionCompose extends React.Component { this.getInputPlaceholder = this.getInputPlaceholder.bind(this); this.getIOUOptions = this.getIOUOptions.bind(this); this.addAttachment = this.addAttachment.bind(this); + this.setExceededMaxCommentLength = this.setExceededMaxCommentLength.bind(this); this.comment = props.comment; // React Native will retain focus on an input for native devices but web/mWeb behave differently so we have some focus management @@ -153,6 +154,7 @@ class ReportActionCompose extends React.Component { // If we are on a small width device then don't show last 3 items from conciergePlaceholderOptions conciergePlaceholderRandomIndex: _.random(this.props.translate('reportActionCompose.conciergePlaceholderOptions').length - (this.props.isSmallScreenWidth ? 4 : 1)), + hasExceededMaxCommentLength: false, }; } @@ -302,6 +304,16 @@ class ReportActionCompose extends React.Component { this.setState({maxLines}); } + /** + * Updates the composer when the comment length is exceeded + * Shows red borders and prevents the comment from being sent + * + * @param {Boolean} hasExceededMaxCommentLength + */ + setExceededMaxCommentLength(hasExceededMaxCommentLength) { + this.setState({hasExceededMaxCommentLength}); + } + isEmptyChat() { return _.size(this.props.reportActions) === 1; } @@ -513,8 +525,7 @@ class ReportActionCompose extends React.Component { const isComposeDisabled = this.props.isDrawerOpen && this.props.isSmallScreenWidth; const isBlockedFromConcierge = ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge); const inputPlaceholder = this.getInputPlaceholder(); - const encodedCommentLength = ReportUtils.getCommentLength(this.comment); - const hasExceededMaxCommentLength = encodedCommentLength > CONST.MAX_COMMENT_LENGTH; + const hasExceededMaxCommentLength = this.state.hasExceededMaxCommentLength; return ( {!this.props.isSmallScreenWidth && } - + {this.state.isDraggingOver && } diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js index abef7beb65ca..37369611f190 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.js +++ b/src/pages/home/report/ReportActionItemMessageEdit.js @@ -69,6 +69,7 @@ class ReportActionItemMessageEdit extends React.Component { this.triggerSaveOrCancel = this.triggerSaveOrCancel.bind(this); this.onSelectionChange = this.onSelectionChange.bind(this); this.addEmojiToTextBox = this.addEmojiToTextBox.bind(this); + this.setExceededMaxCommentLength = this.setExceededMaxCommentLength.bind(this); this.saveButtonID = 'saveButton'; this.cancelButtonID = 'cancelButton'; this.emojiButtonID = 'emojiButton'; @@ -84,6 +85,7 @@ class ReportActionItemMessageEdit extends React.Component { end: draftMessage.length, }, isFocused: false, + hasExceededMaxCommentLength: false, }; } @@ -96,6 +98,16 @@ class ReportActionItemMessageEdit extends React.Component { this.setState({selection: e.nativeEvent.selection}); } + /** + * Updates the composer when the comment length is exceeded + * Shows red borders and prevents the comment from being sent + * + * @param {Boolean} hasExceededMaxCommentLength + */ + setExceededMaxCommentLength(hasExceededMaxCommentLength) { + this.setState({hasExceededMaxCommentLength}); + } + /** * Update the value of the draft in Onyx * @@ -217,8 +229,7 @@ class ReportActionItemMessageEdit extends React.Component { } render() { - const draftLength = ReportUtils.getCommentLength(this.state.draft); - const hasExceededMaxCommentLength = draftLength > CONST.MAX_COMMENT_LENGTH; + const hasExceededMaxCommentLength = this.state.hasExceededMaxCommentLength; return ( - + ); From d6da8202b2e06eba9566f989d742ddabd6c64ec3 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 27 Feb 2023 11:45:12 +0700 Subject: [PATCH 32/81] fix: update version of expensify-common repo --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51ab73ab38b2..21ddc8d7f328 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#69e32de34d28098c7316a66e28061d8df50f86c5", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#fff304449214480065bf550e562ad39e681f6f95", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", @@ -25230,8 +25230,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#69e32de34d28098c7316a66e28061d8df50f86c5", - "integrity": "sha512-dW+Lt6EO2YpsgX7ySRa9obqxI2/SO9LZlWOq6gG9MqMX2Wj6qAStgwIOWKLB6GJekmIj5nri+wVisrV5NV7hSw==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#fff304449214480065bf550e562ad39e681f6f95", + "integrity": "sha512-18tm0Y8R4vwUJNPmeA5KIv0BAUuCti6YEzwZZ3ty+0/yPFkISGSMkIyPJ2/4CVE2FXIJkIuHaDpUmtp0MUaW7Q==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -64003,9 +64003,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#69e32de34d28098c7316a66e28061d8df50f86c5", - "integrity": "sha512-dW+Lt6EO2YpsgX7ySRa9obqxI2/SO9LZlWOq6gG9MqMX2Wj6qAStgwIOWKLB6GJekmIj5nri+wVisrV5NV7hSw==", - "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#69e32de34d28098c7316a66e28061d8df50f86c5", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#fff304449214480065bf550e562ad39e681f6f95", + "integrity": "sha512-18tm0Y8R4vwUJNPmeA5KIv0BAUuCti6YEzwZZ3ty+0/yPFkISGSMkIyPJ2/4CVE2FXIJkIuHaDpUmtp0MUaW7Q==", + "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#fff304449214480065bf550e562ad39e681f6f95", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", diff --git a/package.json b/package.json index 041d83d98e37..4e5c35602047 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#69e32de34d28098c7316a66e28061d8df50f86c5", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#fff304449214480065bf550e562ad39e681f6f95", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", From 13f2e779c6b03193b1adcd5a16602fe019307a9a Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Mon, 27 Feb 2023 10:51:48 +0000 Subject: [PATCH 33/81] Fix lint --- src/libs/ReportActionsUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 2e394c6ddd2c..e3772b055bf5 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -1,6 +1,7 @@ import lodashGet from 'lodash/get'; import _ from 'underscore'; import lodashMerge from 'lodash/merge'; +import lodashFindLast from 'lodash/findLast'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import Onyx from 'react-native-onyx'; import moment from 'moment'; @@ -9,7 +10,6 @@ import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; import Log from './Log'; import isReportMessageAttachment from './isReportMessageAttachment'; -import lodashFindLast from 'lodash/findLast'; const allReportActions = {}; Onyx.connect({ From 52eb27022bb9a1a5eee621429346a5afea4a0492 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 27 Feb 2023 13:15:06 +0100 Subject: [PATCH 34/81] update both files --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 50849cbd5f53..645f2d0813c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#a2942d035614bf4bed90ffe2114d6ee828ee96da", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#ce6258b87396d3c471c9b012b9a518e2ee6283c7", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", @@ -25228,8 +25228,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#a2942d035614bf4bed90ffe2114d6ee828ee96da", - "integrity": "sha512-Mzi7TvennE7/ZgnZnCpNCbbl7l7Ee8WccF6kGzV9X97UlXTkzcZ/nprcjfOlmyc1M/KNm+MjdvIoi3xjFJ57DA==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#ce6258b87396d3c471c9b012b9a518e2ee6283c7", + "integrity": "sha512-HcFemdERXeIaltgMIgfauW516cjWUlFXWCA3hNTUcxyetUyYgVoFXa9vy55k54H2QJ1F6u9CW7v34WLLPV/7lQ==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -63924,9 +63924,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#a2942d035614bf4bed90ffe2114d6ee828ee96da", - "integrity": "sha512-Mzi7TvennE7/ZgnZnCpNCbbl7l7Ee8WccF6kGzV9X97UlXTkzcZ/nprcjfOlmyc1M/KNm+MjdvIoi3xjFJ57DA==", - "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#a2942d035614bf4bed90ffe2114d6ee828ee96da", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#ce6258b87396d3c471c9b012b9a518e2ee6283c7", + "integrity": "sha512-HcFemdERXeIaltgMIgfauW516cjWUlFXWCA3hNTUcxyetUyYgVoFXa9vy55k54H2QJ1F6u9CW7v34WLLPV/7lQ==", + "from": "expensify-common@git+https://github.com/Expensify/expensify-common.git#ce6258b87396d3c471c9b012b9a518e2ee6283c7", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", diff --git a/package.json b/package.json index d73306a7f778..dc40bbb50682 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#89104f0c5ff0583567a779b3712b0f13b6f8a9a1", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#ce6258b87396d3c471c9b012b9a518e2ee6283c7", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", From 7c2e0618996c783db842f5f02f0556fbba18e0ef Mon Sep 17 00:00:00 2001 From: Eduardo Date: Mon, 27 Feb 2023 16:05:48 +0100 Subject: [PATCH 35/81] Removed extra bottom margin and updated the UI of the items --- src/pages/settings/Profile/PronounsPage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index 8c5f0f88877f..222658494b80 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -96,7 +96,7 @@ class PronounsPage extends Component { onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_PROFILE)} onCloseButtonPress={() => Navigation.dismissModal(true)} /> - + {this.props.translate('pronounsPage.isShownOnProfile')} )} From 278c1feb03e137cd61817f249b809619a03c88a5 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Fri, 3 Feb 2023 15:16:07 +0100 Subject: [PATCH 36/81] update Onfido sdk + fix allowed documents --- ios/Podfile.lock | 10 ++++----- package-lock.json | 30 +++++++++++++------------- package.json | 6 +++--- src/components/Onfido/BaseOnfidoWeb.js | 12 ++++------- 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ed9cdc3f6850..7c7bb93b0e04 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -221,9 +221,9 @@ PODS: - nanopb/encode (= 2.30908.0) - nanopb/decode (2.30908.0) - nanopb/encode (2.30908.0) - - Onfido (27.0.0) - - onfido-react-native-sdk (7.0.1): - - Onfido (= 27.0.0) + - Onfido (27.4.0) + - onfido-react-native-sdk (7.4.0): + - Onfido (= 27.4.0) - React - OpenSSL-Universal (1.1.1100) - Permission-Camera (3.6.1): @@ -977,8 +977,8 @@ SPEC CHECKSUMS: lottie-ios: 8f97d3271e155c2d688875c29cd3c74908aef5f8 lottie-react-native: b702fab740cdb952a8e2354713d3beda63ff97b0 nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 - Onfido: bdbc3ed45598aa106ab2ea021d94e2e28c6b5be3 - onfido-react-native-sdk: 5856e76fbfc0eb7b70b0f76fa1059830932a5c88 + Onfido: e36f284b865adcf99d9c905590a64ac09d4a576b + onfido-react-native-sdk: 4ecde1a97435dcff9f00a878e3f8d1eb14fabbdc OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c Permission-Camera: bf6791b17c7f614b6826019fcfdcc286d3a107f6 Permission-LocationAccuracy: 76df17de5c6b8bc2eee34e61ee92cdd7a864c73d diff --git a/package-lock.json b/package-lock.json index 51ab73ab38b2..184004ea602e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,8 @@ "@formatjs/intl-numberformat": "^6.2.5", "@formatjs/intl-pluralrules": "^4.0.13", "@gorhom/portal": "^1.0.14", - "@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52", - "@onfido/react-native-sdk": "7.0.1", + "@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050", + "@onfido/react-native-sdk": "7.4.0", "@react-native-async-storage/async-storage": "^1.17.10", "@react-native-community/cameraroll": "git+https://github.com/react-native-cameraroll/react-native-cameraroll.git#3f0aed96db68e134f199171c7b06c1b4d6cb382b", "@react-native-community/clipboard": "^1.5.1", @@ -48,7 +48,7 @@ "metro-config": "^0.71.3", "moment": "^2.29.4", "moment-timezone": "^0.5.31", - "onfido-sdk-ui": "10.3.0", + "onfido-sdk-ui": "10.4.0", "process": "^0.11.10", "prop-types": "^15.7.2", "pusher-js": "^7.0.6", @@ -5088,9 +5088,9 @@ } }, "node_modules/@onfido/react-native-sdk": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-7.0.1.tgz", - "integrity": "sha512-nhjByw/YyTACvkDWX2QtCzYmqkrDtSBJxYYgJjPuKvPRVIJhrny3bIm0DzAi1hWyIM2ZsKW/MSQxerGhR9FQaw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-7.4.0.tgz", + "integrity": "sha512-qeeaXLxVXz+J0lrqMwQGP52fXhCnTmEAC5K8jZe8YTqst2s1FZZGKkd1bxTloHG5hBBTa39SwWVUKmgPUm+Ssw==", "peerDependencies": { "react": ">=17.0.0", "react-native": ">=0.68.2 <1.0.x" @@ -35522,9 +35522,9 @@ } }, "node_modules/onfido-sdk-ui": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-10.3.0.tgz", - "integrity": "sha512-53Yr9s9fb3heMPserJiJY8+Yf5XvRSBVXhswylhlosrZivr5ygEeweteSmdb/ICm2qpqYA8MAVNgzRKnFaImIA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-10.4.0.tgz", + "integrity": "sha512-N/GwvtRUxhV5fH9lkoz8FTb8XvwAllCdgQB/YxomJ3yaFgU8OK3XmPscQ3b0edhaRohXDKyBvsbO23lEcSSq8Q==", "dependencies": { "@onfido/active-video-capture": "^0.22.1", "@onfido/opencv": "^1.0.0", @@ -48611,9 +48611,9 @@ } }, "@onfido/react-native-sdk": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-7.0.1.tgz", - "integrity": "sha512-nhjByw/YyTACvkDWX2QtCzYmqkrDtSBJxYYgJjPuKvPRVIJhrny3bIm0DzAi1hWyIM2ZsKW/MSQxerGhR9FQaw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-7.4.0.tgz", + "integrity": "sha512-qeeaXLxVXz+J0lrqMwQGP52fXhCnTmEAC5K8jZe8YTqst2s1FZZGKkd1bxTloHG5hBBTa39SwWVUKmgPUm+Ssw==", "requires": {} }, "@pmmmwh/react-refresh-webpack-plugin": { @@ -71879,9 +71879,9 @@ } }, "onfido-sdk-ui": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-10.3.0.tgz", - "integrity": "sha512-53Yr9s9fb3heMPserJiJY8+Yf5XvRSBVXhswylhlosrZivr5ygEeweteSmdb/ICm2qpqYA8MAVNgzRKnFaImIA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-10.4.0.tgz", + "integrity": "sha512-N/GwvtRUxhV5fH9lkoz8FTb8XvwAllCdgQB/YxomJ3yaFgU8OK3XmPscQ3b0edhaRohXDKyBvsbO23lEcSSq8Q==", "requires": { "@onfido/active-video-capture": "^0.22.1", "@onfido/opencv": "^1.0.0", diff --git a/package.json b/package.json index 041d83d98e37..7bf970d62797 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ "@formatjs/intl-numberformat": "^6.2.5", "@formatjs/intl-pluralrules": "^4.0.13", "@gorhom/portal": "^1.0.14", - "@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52", - "@onfido/react-native-sdk": "7.0.1", + "@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050", + "@onfido/react-native-sdk": "7.4.0", "@react-native-async-storage/async-storage": "^1.17.10", "@react-native-community/cameraroll": "git+https://github.com/react-native-cameraroll/react-native-cameraroll.git#3f0aed96db68e134f199171c7b06c1b4d6cb382b", "@react-native-community/clipboard": "^1.5.1", @@ -79,7 +79,7 @@ "metro-config": "^0.71.3", "moment": "^2.29.4", "moment-timezone": "^0.5.31", - "onfido-sdk-ui": "10.3.0", + "onfido-sdk-ui": "10.4.0", "process": "^0.11.10", "prop-types": "^15.7.2", "pusher-js": "^7.0.6", diff --git a/src/components/Onfido/BaseOnfidoWeb.js b/src/components/Onfido/BaseOnfidoWeb.js index c3e58bc674b0..5901fa04a5cc 100644 --- a/src/components/Onfido/BaseOnfidoWeb.js +++ b/src/components/Onfido/BaseOnfidoWeb.js @@ -63,16 +63,12 @@ class Onfido extends React.Component { options: { useLiveDocumentCapture: true, forceCrossDevice: true, - showCountrySelection: false, + hideCountrySelection: true, + country: 'USA', + uploadFallback: false, documentTypes: { driving_licence: { - country: null, - }, - national_identity_card: { - country: null, - }, - residence_permit: { - country: null, + country: 'USA', }, passport: true, }, From 8cc4230b1ead02bea5bf640000ddd096c9fba319 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Mon, 27 Feb 2023 17:42:26 +0100 Subject: [PATCH 37/81] Fix androidManifest and Podfile --- android/app/src/main/AndroidManifest.xml | 4 +++- ios/Podfile.lock | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 71c3dc6c9af3..208076beeb71 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ @@ -15,7 +16,8 @@ android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:resizeableActivity="false" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" + tools:replace="android:supportsRtl"> 3.4.0) - React-Core - nanopb (2.30908.0): @@ -975,7 +975,7 @@ SPEC CHECKSUMS: libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef lottie-ios: 8f97d3271e155c2d688875c29cd3c74908aef5f8 - lottie-react-native: b702fab740cdb952a8e2354713d3beda63ff97b0 + lottie-react-native: 3e722c63015fdb9c27638b0a77969fc412067c18 nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 Onfido: e36f284b865adcf99d9c905590a64ac09d4a576b onfido-react-native-sdk: 4ecde1a97435dcff9f00a878e3f8d1eb14fabbdc From f2be136b56a8a3a7048941fe18867d0691690b6c Mon Sep 17 00:00:00 2001 From: Abdul Rahuman Date: Mon, 27 Feb 2023 22:16:19 +0530 Subject: [PATCH 38/81] Issue #14886 Fix group member order changing randomly when group members have phone numbers --- src/libs/ReportUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 4c03e35b642c..c824ea3e180a 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1380,7 +1380,7 @@ function getChatByParticipants(newParticipantList) { } // Only return the room if it has all the participants and is not a policy room - return !isUserCreatedPolicyRoom(report) && _.isEqual(newParticipantList, report.participants.sort()); + return !isUserCreatedPolicyRoom(report) && _.isEqual(newParticipantList, _.sortBy(report.participants)); }); } From 3aefddfb8d8ab150d977e7103b23a60d42ce5f40 Mon Sep 17 00:00:00 2001 From: Amy Evans Date: Mon, 27 Feb 2023 14:29:49 -0500 Subject: [PATCH 39/81] Update K2 link to publicly accessible location --- contributingGuides/KSv2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributingGuides/KSv2.md b/contributingGuides/KSv2.md index 056cb09df12c..881d191ad886 100644 --- a/contributingGuides/KSv2.md +++ b/contributingGuides/KSv2.md @@ -16,7 +16,7 @@ To help surface the issues and PRs that need the most `#urgency`, we've built a -Once you have the extension installed, you can access it by going to https://github.com/Expensify/Expensify#k2 or clicking on the K2 tab at the top of a repo (between pull requests and GH actions). You'll have to create a Personal Access Token in GitHub ([here](https://github.com/settings/tokens)) and enter that in the K2 dashboard the first time you open it, so that your K2 extension can automatically pull data about your GitHub account. +Once you have the extension installed, you can access it by going to https://github.com/Expensify/App#k2 or clicking on the K2 tab at the top of a repo (between pull requests and GH actions). You'll have to create a Personal Access Token in GitHub ([here](https://github.com/settings/tokens)) and enter that in the K2 dashboard the first time you open it, so that your K2 extension can automatically pull data about your GitHub account. ### Pull Requests for review From 3b01d3b07fed55ffda5369f799a9a3b5cd8e5b82 Mon Sep 17 00:00:00 2001 From: rory Date: Mon, 27 Feb 2023 11:50:09 -0800 Subject: [PATCH 40/81] Remove inline script tag from help site --- docs/_includes/footer.html | 4 ++-- docs/assets/js/main.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html index bbbf9fb3117d..166c1fa569d2 100644 --- a/docs/_includes/footer.html +++ b/docs/_includes/footer.html @@ -110,7 +110,7 @@

Get Started

- + @@ -118,4 +118,4 @@

Get Started

Expensify - \ No newline at end of file + diff --git a/docs/assets/js/main.js b/docs/assets/js/main.js index c335047466e1..38f495c753cf 100644 --- a/docs/assets/js/main.js +++ b/docs/assets/js/main.js @@ -58,7 +58,14 @@ function navigateBack() { setTimeout(toggleHeaderMenu, 250); } +function injectFooterCopywrite() { + const footer = document.getElementById('footer-copywrite-date'); + footer.innerHTML = `©2008-${new Date().getFullYear()} Expensify, Inc.`; +} + window.addEventListener('DOMContentLoaded', () => { + injectFooterCopywrite(); + if (window.tocbot) { window.tocbot.init({ // Where to render the table of contents. From caf5aecbd125efaa8c354813df7d66e12df1b020 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Mon, 27 Feb 2023 14:06:13 -0800 Subject: [PATCH 41/81] Add correct icon proptypes to IOU pages / reportPropTypes --- src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsPage.js | 2 +- src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsSplit.js | 2 +- src/pages/reportPropTypes.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsPage.js b/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsPage.js index 38d5c7a9d46d..185b37d85bb1 100644 --- a/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsPage.js +++ b/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsPage.js @@ -23,7 +23,7 @@ const propTypes = { login: PropTypes.string.isRequired, alternateText: PropTypes.string, hasDraftComment: PropTypes.bool, - icons: PropTypes.arrayOf(PropTypes.string), + icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), searchText: PropTypes.string, text: PropTypes.string, keyForList: PropTypes.string, diff --git a/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsSplit.js b/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsSplit.js index f43325b6bdc8..8239ded8468a 100755 --- a/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsSplit.js +++ b/src/pages/iou/steps/IOUParticipantsPage/IOUParticipantsSplit.js @@ -29,7 +29,7 @@ const propTypes = { login: PropTypes.string.isRequired, alternateText: PropTypes.string, hasDraftComment: PropTypes.bool, - icons: PropTypes.arrayOf(PropTypes.string), + icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), searchText: PropTypes.string, text: PropTypes.string, keyForList: PropTypes.string, diff --git a/src/pages/reportPropTypes.js b/src/pages/reportPropTypes.js index 95a58c26fa8a..61e283b51aab 100644 --- a/src/pages/reportPropTypes.js +++ b/src/pages/reportPropTypes.js @@ -11,7 +11,7 @@ export default PropTypes.shape({ hasOutstandingIOU: PropTypes.bool, /** List of icons for report participants */ - icons: PropTypes.arrayOf(PropTypes.string), + icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), /** Are we loading more report actions? */ isLoadingMoreReportActions: PropTypes.bool, From b337fd1663fd955764b0a8ffd42d60d22c673fcb Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 28 Feb 2023 01:37:40 +0000 Subject: [PATCH 42/81] Update version to 1.2.77-2 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 0bbafbd2dc70..b06431c65072 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001027701 - versionName "1.2.77-1" + versionCode 1001027702 + versionName "1.2.77-2" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b221144a5ae3..b9669706ad89 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.77.1 + 1.2.77.2 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 8f8bdf537df1..e55e9197755b 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.77.1 + 1.2.77.2 diff --git a/package-lock.json b/package-lock.json index e91f53094399..5e0d2a077a4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.77-1", + "version": "1.2.77-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.77-1", + "version": "1.2.77-2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 101d8c4b8bd7..ad03344cf213 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.77-1", + "version": "1.2.77-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.", From 7407ac0e299411fb64fd9ea193280d1fae131a72 Mon Sep 17 00:00:00 2001 From: rory Date: Mon, 27 Feb 2023 18:27:35 -0800 Subject: [PATCH 43/81] Make canEditReportAction return false for deleted actions --- src/libs/ReportUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 4c03e35b642c..249d103b720f 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -129,6 +129,7 @@ function canEditReportAction(reportAction) { return reportAction.actorEmail === sessionEmail && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT && !isReportMessageAttachment(lodashGet(reportAction, ['message', 0], {})) + && !ReportActionsUtils.isDeletedAction(reportAction) && reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; } From fe335c571bac2bd6eb6714d6379f066e7c47cad7 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Mon, 27 Feb 2023 18:51:09 -0800 Subject: [PATCH 44/81] use policyName sent back with public rooms for people who aren't in the workspace --- src/libs/ReportUtils.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 4c03e35b642c..f1bf49db3242 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -281,10 +281,17 @@ function isArchivedRoom(report) { * @param {Object} report * @param {String} report.policyID * @param {String} report.oldPolicyName + * @param {String} report.policyName * @param {Object} policies must have Onyxkey prefix (i.e 'policy_') for keys * @returns {String} */ function getPolicyName(report, policies) { + // Public rooms send back the policy name with the reportSummary, + // since they can also be accessed by people who aren't in the workspace + if (report.policyName) { + return report.policyName; + } + if (_.isEmpty(policies)) { return Localize.translateLocal('workspace.common.unavailable'); } From f2b118272255ff947a8f0d6b6d877f59be4504bf Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 28 Feb 2023 11:29:11 +0700 Subject: [PATCH 45/81] Fix hover effect on request or send money messages --- src/components/ReportActionItem/IOUAction.js | 1 + src/components/ReportActionItem/IOUQuote.js | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/IOUAction.js b/src/components/ReportActionItem/IOUAction.js index 5c6d207e8edd..a7fe3f17102a 100644 --- a/src/components/ReportActionItem/IOUAction.js +++ b/src/components/ReportActionItem/IOUAction.js @@ -96,6 +96,7 @@ const IOUAction = (props) => { shouldAllowViewDetails={Boolean(props.action.originalMessage.IOUReportID)} onViewDetailsPressed={launchDetailsModal} checkIfContextMenuActive={props.checkIfContextMenuActive} + isHovered={props.isHovered} /> {shouldShowIOUPreview && ( {}, checkIfContextMenuActive: () => {}, }; @@ -80,7 +86,7 @@ const IOUQuote = props => ( {Str.htmlDecode(fragment.text.substring(fragment.text.indexOf(' ')))}
- + ))} From 6b8e8f5034a656abbc12abc7f870c3982fe9ff15 Mon Sep 17 00:00:00 2001 From: Jatin Soni Date: Tue, 28 Feb 2023 12:36:42 +0530 Subject: [PATCH 46/81] Add dynamic languages and translate locale picker --- src/components/LocalePicker.js | 57 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/components/LocalePicker.js b/src/components/LocalePicker.js index 5be074168250..aff01841a65e 100644 --- a/src/components/LocalePicker.js +++ b/src/components/LocalePicker.js @@ -7,7 +7,6 @@ import * as App from '../libs/actions/App'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import ONYXKEYS from '../ONYXKEYS'; import CONST from '../CONST'; -import * as Localize from '../libs/Localize'; import Picker from './Picker'; import styles from '../styles/styles'; @@ -26,33 +25,37 @@ const defaultProps = { size: 'normal', }; -const localesToLanguages = { - default: { - value: 'en', - label: Localize.translate('en', 'languagePage.languages.en.label'), - }, - es: { - value: 'es', - label: Localize.translate('es', 'languagePage.languages.es.label'), - }, -}; - -const LocalePicker = props => ( - { - if (locale === props.preferredLocale) { - return; - } +const LocalePicker = (props) => { + const localesToLanguages = _.map( + props.translate('languagePage.languages'), + (language, key) => ({ + value: key, + label: language.label, + }), + ); + return ( + { + if (locale === props.preferredLocale) { + return; + } - App.setLocale(locale); - }} - items={_.values(localesToLanguages)} - size={props.size} - value={props.preferredLocale} - containerStyles={props.size === 'small' ? [styles.pickerContainerSmall] : []} - /> -); + App.setLocale(locale); + }} + items={localesToLanguages} + size={props.size} + value={props.preferredLocale} + containerStyles={ + props.size === 'small' ? [styles.pickerContainerSmall] : [] + } + /> + ); +}; LocalePicker.defaultProps = defaultProps; LocalePicker.propTypes = propTypes; From f7ca259300c95963e5f609dc33c4d7a623747240 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 28 Feb 2023 16:07:19 +0700 Subject: [PATCH 47/81] fix: move the onMouseDown to outside view --- src/pages/home/report/ReportActionCompose.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 0efb256e8144..61c9cd2c8767 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -680,17 +680,13 @@ class ReportActionCompose extends React.Component { onEmojiSelected={this.addEmojiToTextBox} /> )} - + e.preventDefault()}> e.preventDefault()} disabled={this.state.isCommentEmpty || isBlockedFromConcierge || this.props.disabled || hasExceededMaxCommentLength} hitSlop={{ top: 3, right: 3, bottom: 3, left: 3, From 148c83f8643be2f7c75cc6cf414eb6dca9bc11ee Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Tue, 28 Feb 2023 11:56:20 +0100 Subject: [PATCH 48/81] Fix lottie-react-native version --- ios/Podfile.lock | 28 ++++++++++++++-------------- package-lock.json | 24 ++++++++++++------------ package.json | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6346b6dbc3db..f494e566c73e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -177,29 +177,29 @@ PODS: - GoogleUtilities/Network (~> 7.4) - "GoogleUtilities/NSData+zlib (~> 7.4)" - nanopb (~> 2.30908.0) - - GoogleDataTransport (9.2.0): + - GoogleDataTransport (9.2.1): - GoogleUtilities/Environment (~> 7.7) - nanopb (< 2.30910.0, >= 2.30908.0) - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/AppDelegateSwizzler (7.10.0): + - GoogleUtilities/AppDelegateSwizzler (7.11.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (7.10.0): + - GoogleUtilities/Environment (7.11.0): - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/ISASwizzler (7.10.0) - - GoogleUtilities/Logger (7.10.0): + - GoogleUtilities/ISASwizzler (7.11.0) + - GoogleUtilities/Logger (7.11.0): - GoogleUtilities/Environment - - GoogleUtilities/MethodSwizzler (7.10.0): + - GoogleUtilities/MethodSwizzler (7.11.0): - GoogleUtilities/Logger - - GoogleUtilities/Network (7.10.0): + - GoogleUtilities/Network (7.11.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.10.0)" - - GoogleUtilities/Reachability (7.10.0): + - "GoogleUtilities/NSData+zlib (7.11.0)" + - GoogleUtilities/Reachability (7.11.0): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (7.10.0): + - GoogleUtilities/UserDefaults (7.11.0): - GoogleUtilities/Logger - hermes-engine (0.70.4) - libevent (2.1.12) @@ -235,7 +235,7 @@ PODS: - Permission-LocationWhenInUse (3.6.1): - RNPermissions - Plaid (2.5.1) - - PromisesObjC (2.1.1) + - PromisesObjC (2.2.0) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -969,8 +969,8 @@ SPEC CHECKSUMS: fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b GoogleAppMeasurement: 5ba1164e3c844ba84272555e916d0a6d3d977e91 - GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f - GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95 + GoogleDataTransport: ea169759df570f4e37bdee1623ec32a7e64e67c4 + GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f hermes-engine: 3623325e0d0676a45fbc544d72c57dd79fce7446 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef @@ -985,7 +985,7 @@ SPEC CHECKSUMS: Permission-LocationAlways: 8d99b025c9f73c696e0cdb367e42525f2e9a26f2 Permission-LocationWhenInUse: 3ba99e45c852763f730eabecec2870c2382b7bd4 Plaid: 6beadc0828cfd5396c5905931b9503493bbc139a - PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb + PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda RCTRequired: 329ead02b8edd20fb186d17745a9cadd5ce2922d RCTTypeSafety: 698418021f8b47d82c058f3115c0026d1874a3ef diff --git a/package-lock.json b/package-lock.json index 184004ea602e..0c6711d46827 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "jest-when": "^3.5.2", "localforage": "^1.10.0", "lodash": "4.17.21", - "lottie-react-native": "^5.1.4", + "lottie-react-native": "^5.1.5", "metro-config": "^0.71.3", "moment": "^2.29.4", "moment-timezone": "^0.5.31", @@ -5024,8 +5024,8 @@ }, "node_modules/@oguzhnatly/react-native-image-manipulator": { "version": "1.0.5", - "resolved": "git+ssh://git@github.com/Expensify/react-native-image-manipulator.git#5cdae3d4455b03a04c57f50be3863e2fe6c92c52", - "integrity": "sha512-C9Br1BQqm6io6lvYHptlLcOHbzlaqxp9tS35P8Qj3pdiiYRTzU3KPvZ61rQ+ZnZ4FOQ6MwPsKsmB8+6WHkAY6Q==", + "resolved": "git+ssh://git@github.com/Expensify/react-native-image-manipulator.git#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050", + "integrity": "sha512-PvrSoCq5PS1MA5ZWUpB0khfzH6sM8SI6YiVl4i2SItPr7IeRxiWfI4n45VhBCCElc1z5GhAwTZOBaIzXTX7/og==", "license": "MIT" }, "node_modules/@onfido/active-video-capture": { @@ -32733,9 +32733,9 @@ "peer": true }, "node_modules/lottie-react-native": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-5.1.4.tgz", - "integrity": "sha512-Lu6mSG92Wck+vXEX6gfj/9ciqqoz0tJQZqgX0SumGvX/oZu4MbKO/oLApyHdy2V9Rb7qvwF9whOtitADxTswPA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-5.1.5.tgz", + "integrity": "sha512-xl6uEo50joQeIqso5SvPKt1uGBqMhgNgs+36S4725Nfigf4zAY23/I9QEEkJF+1BHq7wKCeYha2KafLTm20gqA==", "dependencies": { "invariant": "^2.2.2", "react-native-safe-modules": "^1.0.3" @@ -48556,9 +48556,9 @@ } }, "@oguzhnatly/react-native-image-manipulator": { - "version": "git+ssh://git@github.com/Expensify/react-native-image-manipulator.git#5cdae3d4455b03a04c57f50be3863e2fe6c92c52", - "integrity": "sha512-C9Br1BQqm6io6lvYHptlLcOHbzlaqxp9tS35P8Qj3pdiiYRTzU3KPvZ61rQ+ZnZ4FOQ6MwPsKsmB8+6WHkAY6Q==", - "from": "@oguzhnatly/react-native-image-manipulator@github:Expensify/react-native-image-manipulator#5cdae3d4455b03a04c57f50be3863e2fe6c92c52" + "version": "git+ssh://git@github.com/Expensify/react-native-image-manipulator.git#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050", + "integrity": "sha512-PvrSoCq5PS1MA5ZWUpB0khfzH6sM8SI6YiVl4i2SItPr7IeRxiWfI4n45VhBCCElc1z5GhAwTZOBaIzXTX7/og==", + "from": "@oguzhnatly/react-native-image-manipulator@github:Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050" }, "@onfido/active-video-capture": { "version": "0.22.1", @@ -69657,9 +69657,9 @@ "peer": true }, "lottie-react-native": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-5.1.4.tgz", - "integrity": "sha512-Lu6mSG92Wck+vXEX6gfj/9ciqqoz0tJQZqgX0SumGvX/oZu4MbKO/oLApyHdy2V9Rb7qvwF9whOtitADxTswPA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-5.1.5.tgz", + "integrity": "sha512-xl6uEo50joQeIqso5SvPKt1uGBqMhgNgs+36S4725Nfigf4zAY23/I9QEEkJF+1BHq7wKCeYha2KafLTm20gqA==", "requires": { "invariant": "^2.2.2", "react-native-safe-modules": "^1.0.3" diff --git a/package.json b/package.json index 7bf970d62797..46091ac64cbe 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "jest-when": "^3.5.2", "localforage": "^1.10.0", "lodash": "4.17.21", - "lottie-react-native": "^5.1.4", + "lottie-react-native": "^5.1.5", "metro-config": "^0.71.3", "moment": "^2.29.4", "moment-timezone": "^0.5.31", From d95229827e73840552089b84eb562de2fd45fab9 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Tue, 28 Feb 2023 12:26:26 +0100 Subject: [PATCH 49/81] reset the input after component update --- src/pages/settings/Profile/PronounsPage.js | 55 +++++++++++++++------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index 222658494b80..cabd2041d32f 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -30,33 +30,26 @@ const defaultProps = { class PronounsPage extends Component { constructor(props) { super(props); - const currentPronouns = lodashGet(props.currentUserPersonalDetails, 'pronouns', ''); - - this.pronounsList = _.map(props.translate('pronouns'), (value, key) => { - const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${key}`; - const isCurrentPronouns = fullPronounKey === currentPronouns; - - return { - text: value, - value: fullPronounKey, - keyForList: key, - - // Include the green checkmark icon to indicate the currently selected value - customIcon: isCurrentPronouns ? greenCheckmark : undefined, - - // This property will make the currently selected value have bold text - boldStyle: isCurrentPronouns, - }; - }); + this.loadPronouns = this.loadPronouns.bind(this); this.onChangeText = this.onChangeText.bind(this); this.getFilteredPronouns = this.getFilteredPronouns.bind(this); + this.loadPronouns(); this.state = { searchValue: '', }; } + componentDidUpdate(prevProps) { + if (prevProps.currentUserPersonalDetails.pronouns === this.props.currentUserPersonalDetails.pronouns) { + return; + } + + this.onChangeText(); + this.loadPronouns(); + } + onChangeText(searchValue = '') { this.setState({searchValue}); } @@ -76,6 +69,32 @@ class PronounsPage extends Component { pronous => pronous.text.toLowerCase().indexOf(searchedValue.toLowerCase()) >= 0); } + /** + * Loads the pronouns list from the translations and adds the green checkmark icon to the currently selected value. + * + * @returns {void} + */ + loadPronouns() { + const currentPronouns = lodashGet(this.props.currentUserPersonalDetails, 'pronouns', ''); + + this.pronounsList = _.map(this.props.translate('pronouns'), (value, key) => { + const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${key}`; + const isCurrentPronouns = fullPronounKey === currentPronouns; + + return { + text: value, + value: fullPronounKey, + keyForList: key, + + // Include the green checkmark icon to indicate the currently selected value + customIcon: isCurrentPronouns ? greenCheckmark : undefined, + + // This property will make the currently selected value have bold text + boldStyle: isCurrentPronouns, + }; + }); + } + /** * @param {Obj} selectedPronouns */ From 5614f3cd05f5509b06f4a9d6ab1e39121eef990f Mon Sep 17 00:00:00 2001 From: Dylan Courtney <60117248+dylanexpensify@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:10:48 +0000 Subject: [PATCH 50/81] Update TestRail_Navigation_C+.md Updated process to have C+ propose the test steps --- contributingGuides/TestRail_Navigation_C+.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/contributingGuides/TestRail_Navigation_C+.md b/contributingGuides/TestRail_Navigation_C+.md index 88c4a4ed3bc3..6496664993b2 100644 --- a/contributingGuides/TestRail_Navigation_C+.md +++ b/contributingGuides/TestRail_Navigation_C+.md @@ -20,14 +20,10 @@ As a C+ member, you will have view-only access to Expensify's TestRail account i - Once determined, the C+ will post a comment in the original GH issue, mentioning which scenario the bug belongs under, why they think it belongs there, and if the new / updated test steps can fall under a current test case or if a new test case needs to be created. Please provide your reasoning for your decision in the comment and tag the BZ member to gut-check. - If the BZ member agrees with the C+'s recommendation, we can move forward. If not, a discussion will be held on where they think it might fit better and why. - There's a chance we will agree to not update/create a test case for the bug in question, depending on the bug. -- Once we know where the test will live, the C+ will tag the Contributor to propose test steps. - - If we're updating a current test case, the C+ will post what the current steps are in the GH for the Contributor to propose their test steps in relation to it. - - If we're creating a new test case, the C+ will note it for the Contributor. -- Once the Contributor has provided proposed test steps, the C+ will review to ensure: +- Once we know where the test will live, the C+ will then propose the appropriate test steps to either add to an existing case or for a new test case. +- Once the C+ has provided proposed test steps, the BZ will review to ensure: - The language style matches the language style in TestRail (e.g. action items use the term `Verify`) - The steps are clear, logical, concise, and void of any assumed knowledge - (For updating a current test case) the steps are logically placed in the test case - - If changes are needed, the C+ and Contributor will discuss what changes should be done in order to make them appropriate -- After confirming the above, the C+ will tag the BZ member and comment that the steps are ready to be reviewed + - If changes are needed, the BZ member and C+ will discuss what changes should be done in order to make them appropriate - The BZ member will then create a GH for Applause to update the TestRail steps, link it in the original bug GH, and move forward with payment. - From 9d044b1ad906804a9dcc8ac76bb290f064025e4b Mon Sep 17 00:00:00 2001 From: Eduardo Date: Tue, 28 Feb 2023 14:03:34 +0100 Subject: [PATCH 51/81] updated comments --- src/pages/settings/Profile/PronounsPage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index cabd2041d32f..aeadeb32a88a 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -42,6 +42,8 @@ class PronounsPage extends Component { } componentDidUpdate(prevProps) { + // If the pronouns have changed, we need to update the pronouns list because refreshing the page + // breaks the component lifecycle, so we need to "manually" reset the component. if (prevProps.currentUserPersonalDetails.pronouns === this.props.currentUserPersonalDetails.pronouns) { return; } @@ -96,7 +98,7 @@ class PronounsPage extends Component { } /** - * @param {Obj} selectedPronouns + * @param {Object} selectedPronouns */ updatePronouns(selectedPronouns) { PersonalDetails.updatePronouns(selectedPronouns.value); From dac6e35d5f78cf92f0b0b54756160cfbaa6851ca Mon Sep 17 00:00:00 2001 From: Cristi Paval Date: Tue, 28 Feb 2023 18:29:58 +0200 Subject: [PATCH 52/81] Revert "replace onModalHide with onDismiss for the web" --- src/components/Modal/BaseModal.js | 7 +------ src/components/Modal/index.web.js | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/Modal/BaseModal.js b/src/components/Modal/BaseModal.js index d9fccfef3312..a4b7ed90a8fe 100644 --- a/src/components/Modal/BaseModal.js +++ b/src/components/Modal/BaseModal.js @@ -16,15 +16,11 @@ const propTypes = { /** The ref to the modal container */ forwardedRef: PropTypes.func, - - /** Ensure that callback and trap deactivation are in the same loop on the web platform */ - shouldUseOnDismiss: PropTypes.bool, }; const defaultProps = { ...modalDefaultProps, forwardedRef: () => {}, - shouldUseOnDismiss: false, }; class BaseModal extends PureComponent { @@ -113,8 +109,7 @@ class BaseModal extends PureComponent { this.props.onModalShow(); }} propagateSwipe={this.props.propagateSwipe} - onDismiss={this.props.shouldUseOnDismiss ? this.hideModal : () => {}} - onModalHide={!this.props.shouldUseOnDismiss ? this.hideModal : () => {}} + onModalHide={this.hideModal} onSwipeComplete={this.props.onClose} swipeDirection={swipeDirection} isVisible={this.props.isVisible} diff --git a/src/components/Modal/index.web.js b/src/components/Modal/index.web.js index 24c83001698c..3cb6f3561b60 100644 --- a/src/components/Modal/index.web.js +++ b/src/components/Modal/index.web.js @@ -29,7 +29,6 @@ const Modal = (props) => { From 5b19c6085d0a3d4325a1e4c2bfc318ebe63c53ed Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 28 Feb 2023 17:51:59 +0000 Subject: [PATCH 53/81] Update version to 1.2.77-3 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index b06431c65072..6e6cd4e4fbfa 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001027702 - versionName "1.2.77-2" + versionCode 1001027703 + versionName "1.2.77-3" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b9669706ad89..461bf294159b 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.77.2 + 1.2.77.3 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index e55e9197755b..6293fdc8b953 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.77.2 + 1.2.77.3 diff --git a/package-lock.json b/package-lock.json index 5e0d2a077a4a..02cd1cba1f95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.77-2", + "version": "1.2.77-3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.77-2", + "version": "1.2.77-3", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index ad03344cf213..58e83436f567 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.77-2", + "version": "1.2.77-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.", From 90df45ec9e013c0d892cc80d2e93aa367ed4741e Mon Sep 17 00:00:00 2001 From: Rocio Perez-Cano Date: Tue, 28 Feb 2023 15:53:03 -0500 Subject: [PATCH 54/81] Update feedback message wen the link is sent --- .../ValidateCodeForm/BaseValidateCodeForm.js | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js index 9ae596c2fc7c..96056d68acd8 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js @@ -70,6 +70,7 @@ class BaseValidateCodeForm extends React.Component { formError: {}, validateCode: props.credentials.validateCode || '', twoFactorAuthCode: '', + linkSent: false, }; } @@ -131,6 +132,9 @@ class BaseValidateCodeForm extends React.Component { } this.setState({formError: {}}); User.resendValidateCode(this.props.credentials.login, true); + + // Give feedback to the user to let them know the email was sent so they don't spam the button. + this.setState({linkSent: true}); } /** @@ -212,15 +216,21 @@ class BaseValidateCodeForm extends React.Component { autoFocus /> - - - {this.props.translate('validateCodeForm.magicCodeNotReceived')} + {this.state.linkSent ? ( + + {this.props.account.message} - + ) : ( + + + {this.props.translate('validateCodeForm.magicCodeNotReceived')} + + + )} )} From e62b4bb65225899f7d8252358c39436f807cbebc Mon Sep 17 00:00:00 2001 From: rory Date: Tue, 28 Feb 2023 13:13:53 -0800 Subject: [PATCH 55/81] Remove references to ExpensifyCash --- ios/NewExpensify.xcodeproj/project.pbxproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index b3dab9cee754..ee77a2595272 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 00E356F31AD99517003FC87E /* ExpensifyCashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ExpensifyCashTests.m */; }; 0CDA8E34287DD650004ECBEC /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0CDA8E33287DD650004ECBEC /* AppDelegate.mm */; }; 0CDA8E35287DD650004ECBEC /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0CDA8E33287DD650004ECBEC /* AppDelegate.mm */; }; 0CDA8E37287DD6A0004ECBEC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0CDA8E36287DD6A0004ECBEC /* Images.xcassets */; }; @@ -50,7 +49,6 @@ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 00E356EE1AD99517003FC87E /* NewExpensifyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NewExpensifyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* ExpensifyCashTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExpensifyCashTests.m; sourceTree = ""; }; 01B491F27448B52C69E394BB /* Pods-NewExpensify-NewExpensifyTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release.xcconfig"; sourceTree = ""; }; 01CEE12C42AABB00D041967F /* Pods-NewExpensify.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release.xcconfig"; sourceTree = ""; }; 02BB59C8C4E7D63E4192F2FA /* Pods-NewExpensify-NewExpensifyTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; sourceTree = ""; }; @@ -111,7 +109,6 @@ 00E356EF1AD99517003FC87E /* NewExpensifyTests */ = { isa = PBXGroup; children = ( - 00E356F21AD99517003FC87E /* ExpensifyCashTests.m */, 00E356F01AD99517003FC87E /* Supporting Files */, ); path = NewExpensifyTests; @@ -558,7 +555,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 00E356F31AD99517003FC87E /* ExpensifyCashTests.m in Sources */, 0F5E5351263B73FD004CA14F /* EnvironmentChecker.m in Sources */, 0CDA8E35287DD650004ECBEC /* AppDelegate.mm in Sources */, 7041848626A8E47D00E09F4D /* RCTStartupTimer.m in Sources */, @@ -663,7 +659,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat; PRODUCT_NAME = "New Expensify"; PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; - SWIFT_OBJC_BRIDGING_HEADER = "ExpensifyCash-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -695,7 +690,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat; PRODUCT_NAME = "New Expensify"; PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; - SWIFT_OBJC_BRIDGING_HEADER = "ExpensifyCash-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; From c62574ee0d3e3d4fa8c744ad1a323c852788777c Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 28 Feb 2023 16:04:51 -0800 Subject: [PATCH 56/81] Decode transaction messages because they may have HTML Entities --- src/components/ReportTransaction.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/ReportTransaction.js b/src/components/ReportTransaction.js index be53b11c742e..5586f5e67c24 100644 --- a/src/components/ReportTransaction.js +++ b/src/components/ReportTransaction.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; +import Str from 'expensify-common/lib/str'; import styles from '../styles/styles'; import CONST from '../CONST'; import * as IOU from '../libs/actions/IOU'; @@ -76,7 +77,7 @@ class ReportTransaction extends Component { wrapperStyles={[styles.reportTransactionWrapper]} > - {this.props.action.message[0].text} + {Str.htmlDecode(this.props.action.message[0].html)} {this.props.canBeRejected && ( From 928ba7d3a0e69c68496f35e447509e4a3caa606e Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 1 Mar 2023 02:45:13 +0000 Subject: [PATCH 57/81] Update version to 1.2.77-4 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 6e6cd4e4fbfa..90919fdbf6a8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001027703 - versionName "1.2.77-3" + versionCode 1001027704 + versionName "1.2.77-4" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 461bf294159b..4a79074f3e22 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.77.3 + 1.2.77.4 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 6293fdc8b953..680745dcee4e 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.2.77.3 + 1.2.77.4 diff --git a/package-lock.json b/package-lock.json index 02cd1cba1f95..4075c68a0259 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.77-3", + "version": "1.2.77-4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.77-3", + "version": "1.2.77-4", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 58e83436f567..cd7c578edf64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.77-3", + "version": "1.2.77-4", "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.", From cbd7dc5c5564d263194accba142b7450e2045643 Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 28 Feb 2023 20:29:57 -0700 Subject: [PATCH 58/81] Modify emojiHeaderContainer style with a -1 top, only on non-native devices --- src/styles/emojiHeaderContainerPlatformStyles/index.js | 1 + src/styles/emojiHeaderContainerPlatformStyles/index.native.js | 1 + src/styles/styles.js | 2 ++ 3 files changed, 4 insertions(+) create mode 100644 src/styles/emojiHeaderContainerPlatformStyles/index.js create mode 100644 src/styles/emojiHeaderContainerPlatformStyles/index.native.js diff --git a/src/styles/emojiHeaderContainerPlatformStyles/index.js b/src/styles/emojiHeaderContainerPlatformStyles/index.js new file mode 100644 index 000000000000..f81ad6ecd883 --- /dev/null +++ b/src/styles/emojiHeaderContainerPlatformStyles/index.js @@ -0,0 +1 @@ +export default {top: -1}; diff --git a/src/styles/emojiHeaderContainerPlatformStyles/index.native.js b/src/styles/emojiHeaderContainerPlatformStyles/index.native.js new file mode 100644 index 000000000000..ff8b4c56321a --- /dev/null +++ b/src/styles/emojiHeaderContainerPlatformStyles/index.native.js @@ -0,0 +1 @@ +export default {}; diff --git a/src/styles/styles.js b/src/styles/styles.js index d52e00cf9d90..8b84e4a40c95 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -19,6 +19,7 @@ import pointerEventsNone from './pointerEventsNone'; import pointerEventsAuto from './pointerEventsAuto'; import overflowXHidden from './overflowXHidden'; import CONST from '../CONST'; +import emojiHeaderContainerPlatformStyles from './emojiHeaderContainerPlatformStyles'; const picker = { backgroundColor: themeColors.transparent, @@ -1488,6 +1489,7 @@ const styles = { height: CONST.EMOJI_PICKER_HEADER_HEIGHT, justifyContent: 'center', width: '100%', + ...emojiHeaderContainerPlatformStyles, }, emojiSkinToneTitle: { From a976c8a1980ffd16ad05914aa57230aef2b49569 Mon Sep 17 00:00:00 2001 From: Jatin Soni Date: Wed, 1 Mar 2023 09:02:46 +0530 Subject: [PATCH 59/81] Fix indentation --- src/components/LocalePicker.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/LocalePicker.js b/src/components/LocalePicker.js index aff01841a65e..e2ad0be35137 100644 --- a/src/components/LocalePicker.js +++ b/src/components/LocalePicker.js @@ -35,11 +35,7 @@ const LocalePicker = (props) => { ); return ( { if (locale === props.preferredLocale) { return; @@ -50,9 +46,7 @@ const LocalePicker = (props) => { items={localesToLanguages} size={props.size} value={props.preferredLocale} - containerStyles={ - props.size === 'small' ? [styles.pickerContainerSmall] : [] - } + containerStyles={props.size === 'small' ? [styles.pickerContainerSmall] : []} /> ); }; From f59daa3d9e6412e1f6e6630909872ae58ea3b54d Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 28 Feb 2023 20:45:49 -0700 Subject: [PATCH 60/81] Adding a clear comment of why we are making this change to the emojiHeaderContainerPlatformStyles --- src/styles/emojiHeaderContainerPlatformStyles/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/styles/emojiHeaderContainerPlatformStyles/index.js b/src/styles/emojiHeaderContainerPlatformStyles/index.js index f81ad6ecd883..c7eb2783bda5 100644 --- a/src/styles/emojiHeaderContainerPlatformStyles/index.js +++ b/src/styles/emojiHeaderContainerPlatformStyles/index.js @@ -1 +1,4 @@ +// This change is only temporary until browser have fixed the issue with position: sticky causing the header to bounce on scroll in non-native apps +// https://github.com/Expensify/App/issues/15282 +// https://bugs.chromium.org/p/chromium/issues/detail?id=734461 export default {top: -1}; From 26cc51d534790cf9a72e6f995eeb48d9d9a4f7b7 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 1 Mar 2023 20:00:02 +0700 Subject: [PATCH 61/81] fix: add comments again --- src/pages/home/report/ReportActionCompose.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 811f86fc8d0b..6af89e25dbb6 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -691,7 +691,12 @@ class ReportActionCompose extends React.Component { onEmojiSelected={this.addEmojiToTextBox} /> )} - e.preventDefault()}> + e.preventDefault()} + > Date: Wed, 1 Mar 2023 20:33:48 +0500 Subject: [PATCH 62/81] fix: added vertical styles to base pre renderer --- .../HTMLRenderers/PreRenderer/BasePreRenderer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js index e52aa318f6dd..d9ec687d59d5 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/BasePreRenderer.js @@ -6,6 +6,7 @@ import _ from 'underscore'; import htmlRendererPropTypes from '../htmlRendererPropTypes'; import withLocalize from '../../../withLocalize'; import {ShowContextMenuContext, showContextMenuForReport} from '../../../ShowContextMenuContext'; +import styles from '../../../../styles/styles'; const propTypes = { /** Press in handler for the code block */ @@ -30,6 +31,7 @@ const BasePreRenderer = forwardRef((props, ref) => { {({ From 1391e60c49e478886b28ab44e547a29458422e04 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 1 Mar 2023 10:23:37 -0700 Subject: [PATCH 63/81] Expanding for readability, and updating import order --- src/styles/emojiHeaderContainerPlatformStyles/index.js | 4 +++- src/styles/styles.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/styles/emojiHeaderContainerPlatformStyles/index.js b/src/styles/emojiHeaderContainerPlatformStyles/index.js index c7eb2783bda5..6bc0c37459ce 100644 --- a/src/styles/emojiHeaderContainerPlatformStyles/index.js +++ b/src/styles/emojiHeaderContainerPlatformStyles/index.js @@ -1,4 +1,6 @@ // This change is only temporary until browser have fixed the issue with position: sticky causing the header to bounce on scroll in non-native apps // https://github.com/Expensify/App/issues/15282 // https://bugs.chromium.org/p/chromium/issues/detail?id=734461 -export default {top: -1}; +export default { + top: -1, +}; diff --git a/src/styles/styles.js b/src/styles/styles.js index 8b84e4a40c95..50104821d8fa 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -15,11 +15,11 @@ import codeStyles from './codeStyles'; import visibility from './utilities/visibility'; import writingDirection from './utilities/writingDirection'; import optionAlternateTextPlatformStyles from './optionAlternateTextPlatformStyles'; +import emojiHeaderContainerPlatformStyles from './emojiHeaderContainerPlatformStyles'; import pointerEventsNone from './pointerEventsNone'; import pointerEventsAuto from './pointerEventsAuto'; import overflowXHidden from './overflowXHidden'; import CONST from '../CONST'; -import emojiHeaderContainerPlatformStyles from './emojiHeaderContainerPlatformStyles'; const picker = { backgroundColor: themeColors.transparent, From f63025952eeca9828daba09abb36ba7cffea2a7f Mon Sep 17 00:00:00 2001 From: Scott Deeter Date: Wed, 1 Mar 2023 12:06:05 -0800 Subject: [PATCH 64/81] Move the Small Business playbook to the right location --- docs/_data/routes.yml | 2 ++ .../Expensify-Playbook-for-US-Based-Small-Businesses.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename SmallbusinessPlaybook => docs/articles/playbooks/Expensify-Playbook-for-US-Based-Small-Businesses.md (99%) diff --git a/docs/_data/routes.yml b/docs/_data/routes.yml index c1dfea54c03d..4ab264e36791 100644 --- a/docs/_data/routes.yml +++ b/docs/_data/routes.yml @@ -38,6 +38,8 @@ hubs: title: Expensify Playbook for US-Based VC-Backed Startups - href: Expensify-Playbook-for-US-Based-Bootstrapped-Startups title: Expensify Playbook for US-Based Bootstrapped Startups + - href: Expensify-Playbook-for-US-Based-Small-Businesses + title: Expensify Playbook for US Based Small Businesses - href: other title: Other diff --git a/SmallbusinessPlaybook b/docs/articles/playbooks/Expensify-Playbook-for-US-Based-Small-Businesses.md similarity index 99% rename from SmallbusinessPlaybook rename to docs/articles/playbooks/Expensify-Playbook-for-US-Based-Small-Businesses.md index c599a466af37..17053f5b9680 100644 --- a/SmallbusinessPlaybook +++ b/docs/articles/playbooks/Expensify-Playbook-for-US-Based-Small-Businesses.md @@ -1,5 +1,5 @@ --- -title: Expensify Playbook for US Small Businesses +title: Expensify Playbook for US Based Small Businesses description: Best practices for how to deploy Expensify for your business --- This guide provides practical tips and recommendations for small businesses with under 100 employees to effectively use Expensify to improve spend visibility, facilitate employee reimbursements, and reduce the risk of fraudulent expenses. From 775610b1dae0c568688223b3e5215450d2d668c9 Mon Sep 17 00:00:00 2001 From: Scott Deeter Date: Wed, 1 Mar 2023 12:15:15 -0800 Subject: [PATCH 65/81] Add missing hyphen --- docs/_data/routes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_data/routes.yml b/docs/_data/routes.yml index 4ab264e36791..0eb26895e9ec 100644 --- a/docs/_data/routes.yml +++ b/docs/_data/routes.yml @@ -39,7 +39,7 @@ hubs: - href: Expensify-Playbook-for-US-Based-Bootstrapped-Startups title: Expensify Playbook for US-Based Bootstrapped Startups - href: Expensify-Playbook-for-US-Based-Small-Businesses - title: Expensify Playbook for US Based Small Businesses + title: Expensify Playbook for US-Based Small Businesses - href: other title: Other From 04e9d4f30c7dd384fc4b44a3b2ddc7f429dca0b7 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 1 Mar 2023 15:32:24 -0800 Subject: [PATCH 66/81] Revert "Fix miss-matched SMS email suffix on sign in page" --- src/pages/signin/ChangeExpensifyLoginLink.js | 4 +++- src/pages/signin/SignInPage.js | 6 ++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/signin/ChangeExpensifyLoginLink.js b/src/pages/signin/ChangeExpensifyLoginLink.js index a0913859f80d..fdc721317c9b 100755 --- a/src/pages/signin/ChangeExpensifyLoginLink.js +++ b/src/pages/signin/ChangeExpensifyLoginLink.js @@ -35,7 +35,9 @@ const ChangeExpensifyLoginLink = props => ( {props.translate('common.not')}   - {Str.removeSMSDomain(props.credentials.login)} + {Str.isSMSLogin(props.credentials.login || '') + ? props.toLocalPhone(Str.removeSMSDomain(props.credentials.login || '')) + : Str.removeSMSDomain(props.credentials.login || '')} {'? '} )} diff --git a/src/pages/signin/SignInPage.js b/src/pages/signin/SignInPage.js index d74119c2907e..851bdd2372d5 100644 --- a/src/pages/signin/SignInPage.js +++ b/src/pages/signin/SignInPage.js @@ -4,7 +4,6 @@ import { } from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import Str from 'expensify-common/lib/str'; import ONYXKEYS from '../../ONYXKEYS'; import styles from '../../styles/styles'; import compose from '../../libs/compose'; @@ -92,10 +91,9 @@ class SignInPage extends Component { // We will only know this after a user signs in successfully, without their 2FA code welcomeText = this.props.translate('validateCodeForm.enterAuthenticatorCode'); } else { - const userLogin = Str.removeSMSDomain(this.props.credentials.login); welcomeText = this.props.account.validated - ? this.props.translate('welcomeText.welcomeBackEnterMagicCode', {login: userLogin}) - : this.props.translate('welcomeText.welcomeEnterMagicCode', {login: userLogin}); + ? this.props.translate('welcomeText.welcomeBackEnterMagicCode', {login: this.props.credentials.login}) + : this.props.translate('welcomeText.welcomeEnterMagicCode', {login: this.props.credentials.login}); } } else if (showPasswordForm) { welcomeText = this.props.translate('welcomeText.welcomeBack'); From c1acd52d479d2ae90b3d14d60b07935fe5b5cb83 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 1 Mar 2023 16:40:03 -0800 Subject: [PATCH 67/81] Revert "Revert "Fix miss-matched SMS email suffix on sign in page"" --- src/pages/signin/ChangeExpensifyLoginLink.js | 4 +--- src/pages/signin/SignInPage.js | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/signin/ChangeExpensifyLoginLink.js b/src/pages/signin/ChangeExpensifyLoginLink.js index fdc721317c9b..a0913859f80d 100755 --- a/src/pages/signin/ChangeExpensifyLoginLink.js +++ b/src/pages/signin/ChangeExpensifyLoginLink.js @@ -35,9 +35,7 @@ const ChangeExpensifyLoginLink = props => ( {props.translate('common.not')}   - {Str.isSMSLogin(props.credentials.login || '') - ? props.toLocalPhone(Str.removeSMSDomain(props.credentials.login || '')) - : Str.removeSMSDomain(props.credentials.login || '')} + {Str.removeSMSDomain(props.credentials.login)} {'? '} )} diff --git a/src/pages/signin/SignInPage.js b/src/pages/signin/SignInPage.js index 851bdd2372d5..d74119c2907e 100644 --- a/src/pages/signin/SignInPage.js +++ b/src/pages/signin/SignInPage.js @@ -4,6 +4,7 @@ import { } from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import Str from 'expensify-common/lib/str'; import ONYXKEYS from '../../ONYXKEYS'; import styles from '../../styles/styles'; import compose from '../../libs/compose'; @@ -91,9 +92,10 @@ class SignInPage extends Component { // We will only know this after a user signs in successfully, without their 2FA code welcomeText = this.props.translate('validateCodeForm.enterAuthenticatorCode'); } else { + const userLogin = Str.removeSMSDomain(this.props.credentials.login); welcomeText = this.props.account.validated - ? this.props.translate('welcomeText.welcomeBackEnterMagicCode', {login: this.props.credentials.login}) - : this.props.translate('welcomeText.welcomeEnterMagicCode', {login: this.props.credentials.login}); + ? this.props.translate('welcomeText.welcomeBackEnterMagicCode', {login: userLogin}) + : this.props.translate('welcomeText.welcomeEnterMagicCode', {login: userLogin}); } } else if (showPasswordForm) { welcomeText = this.props.translate('welcomeText.welcomeBack'); From 221de93338a017b4cac3a69330ab7d8d97ce88e7 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 17:23:15 -0800 Subject: [PATCH 68/81] Create composite action to build test APK --- .github/actions/composite/buildAndroidAPK/action.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/actions/composite/buildAndroidAPK/action.yml diff --git a/.github/actions/composite/buildAndroidAPK/action.yml b/.github/actions/composite/buildAndroidAPK/action.yml new file mode 100644 index 000000000000..e69de29bb2d1 From 988dcfe4763a3e0976ffb3be333c643b4793ba84 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 17:24:03 -0800 Subject: [PATCH 69/81] Create composite action to build test APK --- .../composite/buildAndroidAPK/action.yml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/actions/composite/buildAndroidAPK/action.yml b/.github/actions/composite/buildAndroidAPK/action.yml index e69de29bb2d1..819234df0bc3 100644 --- a/.github/actions/composite/buildAndroidAPK/action.yml +++ b/.github/actions/composite/buildAndroidAPK/action.yml @@ -0,0 +1,29 @@ +name: Build an Android apk +description: Build an Android apk for an E2E test build and upload it as an artifact + +inputs: + ARTIFACT_NAME: + description: The name of the workflow artifact where the APK should be uploaded + required: true + +runs: + using: composite + steps: + - uses: Expensify/App/.github/actions/composite/setupNode@main + + - uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 + with: + ruby-version: '2.7' + bundler-cache: true + + - uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef + + - name: Build APK + run: npm run android-build-e2e + shell: bash + + - name: Upload APK + uses: actions/upload-artifact@65d862660abb392b8c4a3d1195a2108db131dd05 + with: + name: ${{ inputs.ARTIFACT_NAME }} + path: android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk From 8be2ec48a8b3e21870e8d0e461922ab9313a398f Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 17:24:29 -0800 Subject: [PATCH 70/81] Create callable workflow to run E2E performance tests --- .github/workflows/e2ePerformanceTests.yml | 139 ++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 .github/workflows/e2ePerformanceTests.yml diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml new file mode 100644 index 000000000000..6f651cf9950f --- /dev/null +++ b/.github/workflows/e2ePerformanceTests.yml @@ -0,0 +1,139 @@ +name: E2E Performance Tests + +on: + workflow_call: + inputs: + DELTA_REF: + description: A branch or commit ref to build the test build on + type: string + required: true + PR_NUMBER: + description: The number of a merged PR, if this workflow is being triggered by a PR merge + type: string + required: true + + workflow_dispatch: + inputs: + DELTA_REF: + description: A branch or commit ref to build the test build on + type: string + required: true + +jobs: + # TODO: Actor validation needed? + + buildBaseline: + runs-on: ubuntu-20.04-64core + name: Build apk from latest release as a baseline + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + with: + fetch-depth: 0 + + # TODO: If the baseline hasn't changed since the last time this job ran, we don't need to re-run the build and can reuse the old artifact + - name: Checkout "Baseline" commit (last release) + run: git checkout "$(gh release list --limit 1 | awk '{ print $1 }')" + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Build APK + uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main + with: + ARTIFACT_NAME: baseline-apk-${{ github.run_id }} + + buildDelta: + runs-on: ubuntu-20.04-64core + name: Build apk from delta ref + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + with: + fetch-depth: 0 + + - name: Checkout "delta ref" + run: git checkout ${{ inputs.DELTA_REF }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Build APK + uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main + with: + ARTIFACT_NAME: delta-apk-${{ inputs.DELTA_REF }} + + runTestsInAWS: + runs-on: ubuntu-20.04-64core + needs: [buildBaseline, buildDelta] + name: Run E2E tests in AWS device farm + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + with: + ref: ${{ inputs.DELTA_REF }} + + - name: Make zip directory for everything to send to AWS Device Farm + run: mkdir zip + + - name: Download baseline APK + uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b + with: + name: baseline-apk-${{ github.run_id }} + path: zip + + - name: Download delta APK + uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b + with: + name: delta-apk-${{ inputs.DELTA_REF }} + path: zip + + - name: Copy e2e code into zip folder + run: cp -r tests/e2e zip + + - name: Zip everything in the zip directory up + run: zip -qr App.zip ./zip + + - name: Configure AWS Credentials + uses: Expensify/App/.github/actions/composite/configureAwsCredentials@main + with: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: us-west-2 + + - name: Schedule AWS Device Farm test run + uses: realm/aws-devicefarm/test-application@7b9a91236c456c97e28d384c9e476035d5ea686b + with: + name: App E2E Performance Regression Tests + project_arn: ${{ secrets.AWS_PROJECT_ARN }} + device_pool_arn: ${{ secrets.AWS_DEVICE_POOL_ARN }} + app_file: zip/app-e2eRelease-baseline.apk + app_type: ANDROID_APP + test_type: APPIUM_NODE + test_package_file: App.zip + test_package_type: APPIUM_NODE_TEST_PACKAGE + test_spec_file: tests/e2e/TestSpec.yml + test_spec_type: APPIUM_NODE_TEST_SPEC + remote_src: false + file_artifacts: CustomerArtifacts.zip + cleanup: true + + - name: Unzip AWS Device Farm results + if: ${{ always() }} + run: unzip CustomerArtifacts.zip + + - name: Print AWS Device Farm run results + if: ${{ always() }} + run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/output.md" + + - name: Print AWS Device Farm verbose run results + if: ${{ always() && fromJSON(runner.debug) }} + run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log" + + - name: Check if test failed, if so post the results and add the DeployBlocker label + if: github.event_name == 'workflow_call' + run: | + if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then + gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash + gh pr comment ${{ inputs.PR_NUMBER }} -F ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md + gh pr comment ${{ inputs.PR_NUMBER }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker." + else + echo '✅ no performance regression detected' + fi + env: + GITHUB_TOKEN: ${{ github.token }} From 4078b50a7d9b8e547c5a84219ddbaa6b2630b712 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 17:27:13 -0800 Subject: [PATCH 71/81] Use callable workflow in preDeploy.yml --- .github/workflows/preDeploy.yml | 128 ++------------------------------ 1 file changed, 7 insertions(+), 121 deletions(-) diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index af42e68bdabb..dcd90b5a64c7 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -222,124 +222,10 @@ jobs: So it might take a while before you're paid for your work, but we typically post multiple new jobs every day, so there's plenty of opportunity. I hope you've had a positive experience contributing to this repo! :blush: - e2e-tests: - name: "Run e2e performance regression tests" - runs-on: ubuntu-20.04-64core - steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - with: - fetch-depth: 0 - - - uses: Expensify/App/.github/actions/composite/setupNode@main - - - uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7 - with: - ruby-version: '2.7' - bundler-cache: true - - # Cache gradle to improve Android build time - - name: Gradle cache - uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef - - - name: Make zip directory for everything to send to AWS Device Farm - run: mkdir zip - - - name: Checkout "Compare" commit - run: git checkout ${{ github.event.before }} - - - name: Install node packages - uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350 - with: - timeout_minutes: 10 - max_attempts: 5 - command: npm ci - - - name: Build "Compare" APK - run: npm run android-build-e2e - - - name: Copy "Compare" APK - run: cp android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk zip/app-e2eRelease-compare.apk - - - name: Checkout "Baseline" commit (last release) - run: git checkout "$(gh release list --limit 1 | awk '{ print $1 }')" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Install node packages - uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350 - with: - timeout_minutes: 10 - max_attempts: 5 - command: npm ci - - - name: Build "Baseline" APK - run: npm run android-build-e2e - - - name: Copy "Baseline" APK - run: cp android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk zip/app-e2eRelease-baseline.apk - - - name: Checkout previous branch for source code to run on AWS Device farm - run: git checkout - - - - name: Copy e2e code into zip folder - run: cp -r tests/e2e zip - - - name: Zip everything in the zip directory up - run: zip -qr App.zip ./zip - - - name: Configure AWS Credentials - uses: Expensify/App/.github/actions/composite/configureAwsCredentials@main - with: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: us-west-2 - - - name: Schedule AWS Device Farm test run - uses: realm/aws-devicefarm/test-application@7b9a91236c456c97e28d384c9e476035d5ea686b - with: - name: App E2E Performance Regression Tests - project_arn: ${{ secrets.AWS_PROJECT_ARN }} - device_pool_arn: ${{ secrets.AWS_DEVICE_POOL_ARN }} - app_file: zip/app-e2eRelease-baseline.apk - app_type: ANDROID_APP - test_type: APPIUM_NODE - test_package_file: App.zip - test_package_type: APPIUM_NODE_TEST_PACKAGE - test_spec_file: tests/e2e/TestSpec.yml - test_spec_type: APPIUM_NODE_TEST_SPEC - remote_src: false - file_artifacts: Customer Artifacts.zip - cleanup: true - - - name: Unzip AWS Device Farm results - if: ${{ always() }} - run: unzip Customer\ Artifacts.zip - - - name: Print AWS Device Farm run results - if: ${{ always() }} - run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log" - - - name: Set output of AWS Device Farm into GitHub ENV - run: | - { echo 'OUTPUT<> "$GITHUB_ENV" - - - name: Get merged pull request - id: getMergedPullRequest - # TODO: Point back action actions-ecosystem after https://github.com/actions-ecosystem/action-get-merged-pull-request/pull/223 is merged - uses: roryabraham/action-get-merged-pull-request@7a7a194f6ff8f3eef58c822083695a97314ebec1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - - - name: Leave output of AWS Device Farm as a PR comment - run: | - gh pr comment ${{ steps.getMergedPullRequest.outputs.number }} -F ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check if test failed, if so leave a deploy blocker label - if: ${{ contains(env.OUTPUT, '🔴') }} - run: | - gh pr edit ${{ steps.getMergedPullRequest.outputs.number }} --add-label 'DeployBlockerCash' - gh pr comment ${{ steps.getMergedPullRequest.outputs.number }} -b "@Expensify/mobile-deployers 📣 Please look into this performance regression as it's a deploy blocker." - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + e2ePerformanceTests: + needs: [chooseDeployActions] + uses: Expensify/App/.github/workflows/e2ePerformanceTests.yml + secrets: inherit + with: + DELTA_REF: main + PR_NUMBER: ${{ needs.chooseDeployActions.outputs.MERGED_PR }} From 2382a47d7ff8d8482fded1c6c034575ad1701b3d Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 17:36:51 -0800 Subject: [PATCH 72/81] Add ref for callable workflow --- .github/workflows/preDeploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index dcd90b5a64c7..ef417b8c8c31 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -224,7 +224,7 @@ jobs: e2ePerformanceTests: needs: [chooseDeployActions] - uses: Expensify/App/.github/workflows/e2ePerformanceTests.yml + uses: Expensify/App/.github/workflows/e2ePerformanceTests.yml@main secrets: inherit with: DELTA_REF: main From 7cc7b659af2e0c968d9fe4b906316f2e7ba25847 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 18:07:06 -0800 Subject: [PATCH 73/81] Don't rebuild baseline apk if it already exists --- .github/workflows/e2ePerformanceTests.yml | 34 ++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index 6f651cf9950f..39199ecc9cbb 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -21,25 +21,45 @@ on: jobs: # TODO: Actor validation needed? + getMostRecentRelease: + runs-on: ubuntu-latest + name: Get the most recent release version + outputs: + VERSION: ${{ steps.getMostRecentRelease.outputs.VERSION }} + steps: + - name: Get most recent release version + id: getMostRecentRelease + run: echo "VERSION=$(gh release list --limit 1 | awk '{ print $1 }')" >> "$GITHUB_OUTPUT" + env: + GITHUB_TOKEN: ${{ github.token }} buildBaseline: runs-on: ubuntu-20.04-64core + needs: [getMostRecentRelease] name: Build apk from latest release as a baseline steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 with: fetch-depth: 0 - # TODO: If the baseline hasn't changed since the last time this job ran, we don't need to re-run the build and can reuse the old artifact + - name: Check if there's an existing artifact for this baseline + id: checkForExistingArtifact + uses: xSAVIKx/artifact-exists-action@3c5206b1411c0d2fc0840f56b7140646933d9d6a + with: + name: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} + + - if: fromJSON(steps.checkForExistingArtifact.outputs.exists) + run: echo 'APK for baseline ${{ needs.getMostRecentRelease.outputs.VERSION }} already exists, reusing existing build' + - name: Checkout "Baseline" commit (last release) - run: git checkout "$(gh release list --limit 1 | awk '{ print $1 }')" - env: - GITHUB_TOKEN: ${{ github.token }} + if: !fromJSON(steps.checkForExistingArtifact.outputs.exists) + run: git checkout ${{ needs.getMostRecentRelease.outputs.VERSION }} - name: Build APK + if: !fromJSON(steps.checkForExistingArtifact.outputs.exists) uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main with: - ARTIFACT_NAME: baseline-apk-${{ github.run_id }} + ARTIFACT_NAME: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} buildDelta: runs-on: ubuntu-20.04-64core @@ -61,7 +81,7 @@ jobs: runTestsInAWS: runs-on: ubuntu-20.04-64core - needs: [buildBaseline, buildDelta] + needs: [getMostRecentRelease, buildBaseline, buildDelta] name: Run E2E tests in AWS device farm steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 @@ -74,7 +94,7 @@ jobs: - name: Download baseline APK uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b with: - name: baseline-apk-${{ github.run_id }} + name: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} path: zip - name: Download delta APK From 4512136a17062147ce0e38b7029d7769cd903a34 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 1 Mar 2023 18:07:36 -0800 Subject: [PATCH 74/81] Remove TODO --- .github/workflows/e2ePerformanceTests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index 39199ecc9cbb..baab6477ede2 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -20,7 +20,6 @@ on: required: true jobs: - # TODO: Actor validation needed? getMostRecentRelease: runs-on: ubuntu-latest name: Get the most recent release version From eca29105329eded90aabed23192941137d069446 Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Mar 2023 09:02:54 -0800 Subject: [PATCH 75/81] Add expression brackets around if statements --- .github/workflows/e2ePerformanceTests.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index baab6477ede2..351891e1203e 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -47,15 +47,16 @@ jobs: with: name: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} - - if: fromJSON(steps.checkForExistingArtifact.outputs.exists) + - name: Skip build if there's already an existing artifact for the baseline + if: ${{ fromJSON(steps.checkForExistingArtifact.outputs.exists) }} run: echo 'APK for baseline ${{ needs.getMostRecentRelease.outputs.VERSION }} already exists, reusing existing build' - name: Checkout "Baseline" commit (last release) - if: !fromJSON(steps.checkForExistingArtifact.outputs.exists) + if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }} run: git checkout ${{ needs.getMostRecentRelease.outputs.VERSION }} - name: Build APK - if: !fromJSON(steps.checkForExistingArtifact.outputs.exists) + if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }} uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main with: ARTIFACT_NAME: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} @@ -145,7 +146,7 @@ jobs: run: cat "./Host_Machine_Files/\$WORKING_DIRECTORY/debug.log" - name: Check if test failed, if so post the results and add the DeployBlocker label - if: github.event_name == 'workflow_call' + if: ${{ github.event_name == 'workflow_call' }} run: | if grep -q '🔴' ./Host_Machine_Files/\$WORKING_DIRECTORY/output.md; then gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash From 1a1ce51fcd29a2327e01272f7e872d172aa12e4a Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Mar 2023 09:22:30 -0800 Subject: [PATCH 76/81] Only run E2E tests if PR is triggering a deploy --- .github/workflows/preDeploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index ef417b8c8c31..d80b31496773 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -224,6 +224,7 @@ jobs: e2ePerformanceTests: needs: [chooseDeployActions] + if: ${{ needs.chooseDeployActions.outputs.SHOULD_DEPLOY }} uses: Expensify/App/.github/workflows/e2ePerformanceTests.yml@main secrets: inherit with: From 2ec65cd0ed2f4d06d343520bb4076db353da9c81 Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Mar 2023 09:50:18 -0800 Subject: [PATCH 77/81] Rely solely on PR_NUMBER and use the merge_commit_sha of the PR as the DELTA_REF --- .github/workflows/e2ePerformanceTests.yml | 52 ++++++++++++++--------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index 351891e1203e..24d8923944ff 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -3,38 +3,51 @@ name: E2E Performance Tests on: workflow_call: inputs: - DELTA_REF: - description: A branch or commit ref to build the test build on - type: string - required: true PR_NUMBER: - description: The number of a merged PR, if this workflow is being triggered by a PR merge + description: A PR to run performance tests against. If already merged, the merge commit will be used. If not, the test merge commit will be used. type: string required: true workflow_dispatch: inputs: - DELTA_REF: - description: A branch or commit ref to build the test build on + PR_NUMBER: + description: A PR to run performance tests against. If already merged, the merge commit will be used. If not, the test merge commit will be used. type: string required: true jobs: - getMostRecentRelease: + prepare: runs-on: ubuntu-latest name: Get the most recent release version outputs: VERSION: ${{ steps.getMostRecentRelease.outputs.VERSION }} + DELTA_REF: ${{ steps.getMergeCommitSha.outputs.MERGE_COMMIT_SHA }} steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - name: Get most recent release version id: getMostRecentRelease run: echo "VERSION=$(gh release list --limit 1 | awk '{ print $1 }')" >> "$GITHUB_OUTPUT" env: GITHUB_TOKEN: ${{ github.token }} + - name: Get pull request details + id: getPullRequestDetails + uses: Expensify/App/.github/actions/javascript/getPullRequestDetails@main + with: + GITHUB_TOKEN: ${{ github.token }} + PULL_REQUEST_NUMBER: ${{ inputs.PR_NUMBER }} + user: ${{ github.actor }} + + - name: Get merge commit sha for the pull request + id: getMergeCommitSha + run: echo "MERGE_COMMIT_SHA=${{ steps.getPullRequestDetails.outputs.MERGE_COMMIT_SHA }}" >> "$GITHUB_OUTPUT" + env: + GITHUB_TOKEN: ${{ github.token }} + buildBaseline: runs-on: ubuntu-20.04-64core - needs: [getMostRecentRelease] + needs: [prepare] name: Build apk from latest release as a baseline steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 @@ -45,24 +58,25 @@ jobs: id: checkForExistingArtifact uses: xSAVIKx/artifact-exists-action@3c5206b1411c0d2fc0840f56b7140646933d9d6a with: - name: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} + name: baseline-apk-${{ needs.prepare.outputs.VERSION }} - name: Skip build if there's already an existing artifact for the baseline if: ${{ fromJSON(steps.checkForExistingArtifact.outputs.exists) }} - run: echo 'APK for baseline ${{ needs.getMostRecentRelease.outputs.VERSION }} already exists, reusing existing build' + run: echo 'APK for baseline ${{ needs.prepare.outputs.VERSION }} already exists, reusing existing build' - name: Checkout "Baseline" commit (last release) if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }} - run: git checkout ${{ needs.getMostRecentRelease.outputs.VERSION }} + run: git checkout ${{ needs.prepare.outputs.VERSION }} - name: Build APK if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }} uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main with: - ARTIFACT_NAME: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} + ARTIFACT_NAME: baseline-apk-${{ needs.prepare.outputs.VERSION }} buildDelta: runs-on: ubuntu-20.04-64core + needs: [prepare] name: Build apk from delta ref steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 @@ -70,23 +84,23 @@ jobs: fetch-depth: 0 - name: Checkout "delta ref" - run: git checkout ${{ inputs.DELTA_REF }} + run: git checkout ${{ needs.prepare.outputs.DELTA_REF }} env: GITHUB_TOKEN: ${{ github.token }} - name: Build APK uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main with: - ARTIFACT_NAME: delta-apk-${{ inputs.DELTA_REF }} + ARTIFACT_NAME: delta-apk-${{ needs.prepare.outputs.DELTA_REF }} runTestsInAWS: runs-on: ubuntu-20.04-64core - needs: [getMostRecentRelease, buildBaseline, buildDelta] + needs: [prepare, buildBaseline, buildDelta] name: Run E2E tests in AWS device farm steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 with: - ref: ${{ inputs.DELTA_REF }} + ref: ${{ needs.prepare.outputs.DELTA_REF }} - name: Make zip directory for everything to send to AWS Device Farm run: mkdir zip @@ -94,13 +108,13 @@ jobs: - name: Download baseline APK uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b with: - name: baseline-apk-${{ needs.getMostRecentRelease.outputs.VERSION }} + name: baseline-apk-${{ needs.prepare.outputs.VERSION }} path: zip - name: Download delta APK uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b with: - name: delta-apk-${{ inputs.DELTA_REF }} + name: delta-apk-${{ needs.prepare.outputs.DELTA_REF }} path: zip - name: Copy e2e code into zip folder From c7a8d3aefa6e65c679da170a17e9ba7beb0d981e Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Mar 2023 09:58:14 -0800 Subject: [PATCH 78/81] Skip linting of e2e performance tests due to bug in schemastore --- .github/scripts/validateActionsAndWorkflows.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/validateActionsAndWorkflows.sh b/.github/scripts/validateActionsAndWorkflows.sh index 3785f7da3352..8d186ea51a44 100755 --- a/.github/scripts/validateActionsAndWorkflows.sh +++ b/.github/scripts/validateActionsAndWorkflows.sh @@ -43,7 +43,7 @@ for ((i=0; i < ${#WORKFLOWS[@]}; i++)); do WORKFLOW=${WORKFLOWS[$i]} # Skip linting e2e workflow due to bug here: https://github.com/SchemaStore/schemastore/issues/2579 - if [[ "$WORKFLOW" == './workflows/preDeploy.yml' ]]; then + if [[ "$WORKFLOW" == './workflows/e2ePerformanceTests.yml' ]]; then continue fi From 14f9cfd5b18efa20cdc1c4b04ec5e21e86e2dbc3 Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Mar 2023 10:41:37 -0800 Subject: [PATCH 79/81] Fix description of prepare job --- .github/workflows/e2ePerformanceTests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index 24d8923944ff..3d70d5d686c4 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -18,7 +18,7 @@ on: jobs: prepare: runs-on: ubuntu-latest - name: Get the most recent release version + name: Prepare to run builds outputs: VERSION: ${{ steps.getMostRecentRelease.outputs.VERSION }} DELTA_REF: ${{ steps.getMergeCommitSha.outputs.MERGE_COMMIT_SHA }} From fde8cd5e8fc98e1b9be3031f8468d76910f41d9b Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 2 Mar 2023 11:14:27 -0800 Subject: [PATCH 80/81] Remove DELTA_REF input from E2ETests workflow call --- .github/workflows/preDeploy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index d80b31496773..0e77dbe4704f 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -228,5 +228,4 @@ jobs: uses: Expensify/App/.github/workflows/e2ePerformanceTests.yml@main secrets: inherit with: - DELTA_REF: main PR_NUMBER: ${{ needs.chooseDeployActions.outputs.MERGED_PR }} From 2d9449aea18401978aff2411319bc0196acf5c49 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 2 Mar 2023 22:10:34 +0000 Subject: [PATCH 81/81] Update version to 1.2.78-0 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 4 ++-- ios/NewExpensifyTests/Info.plist | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 90919fdbf6a8..0f0cc258c8ea 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001027704 - versionName "1.2.77-4" + versionCode 1001027800 + versionName "1.2.78-0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 4a79074f3e22..d427cc8a061c 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.77 + 1.2.78 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.77.4 + 1.2.78.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 680745dcee4e..99534496e50d 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.77 + 1.2.78 CFBundleSignature ???? CFBundleVersion - 1.2.77.4 + 1.2.78.0 diff --git a/package-lock.json b/package-lock.json index 6a11533f12f2..b5a9673f9bdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.77-4", + "version": "1.2.78-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.77-4", + "version": "1.2.78-0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index d121b14affa2..d5ed53feb4b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.77-4", + "version": "1.2.78-0", "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.",