From 91b17faa0ebffe35cf4d5203a61b39fa5c26dee2 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sat, 22 Jan 2022 00:48:23 +0530 Subject: [PATCH 001/361] fix: Added instance var and insertStringAt utils --- src/pages/settings/Payments/AddDebitCardPage.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index dc0f308b5526..535ee9b9667b 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -91,6 +91,7 @@ class DebitCardPage extends Component { this.submit = this.submit.bind(this); this.clearErrorAndSetValue = this.clearErrorAndSetValue.bind(this); this.getErrorText = this.getErrorText.bind(this); + this.allowExpirationDateChange = true; } /** @@ -184,6 +185,19 @@ class DebitCardPage extends Component { })); } + /** + * Insert string at index position for a given input string + * @param {String} inputString + * @param {Number} indexPosition + * @param {String} stringToAdd + * @returns {String} + */ + insertStringAt(inputString, indexPosition, stringToAdd) { + return inputString.slice(0, indexPosition) + + stringToAdd + + inputString.slice(indexPosition); + } + render() { return ( From 42b95242298d667f9e5beb0f3e17acc6f0a1b548 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sat, 22 Jan 2022 00:49:16 +0530 Subject: [PATCH 002/361] fix: Added onKeyPress and onChangeText for slash handling --- src/pages/settings/Payments/AddDebitCardPage.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 535ee9b9667b..8b5facafcc3a 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -231,11 +231,24 @@ class DebitCardPage extends Component { this.clearErrorAndSetValue('expirationDate', expirationDate)} value={this.state.expirationDate} maxLength={7} errorText={this.getErrorText('expirationDate')} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} + onKeyPress={({nativeEvent}) => { + if (nativeEvent.key === 'Backspace' && this.state.expirationDate.length === 3) { + this.allowExpirationDateChange = false; + this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, 2)})); + } else { + this.allowExpirationDateChange = true; + } + }} + onChangeText={(text) => { + if (!this.allowExpirationDateChange) { + return; + } + this.clearErrorAndSetValue('expirationDate', text.length === 3 ? `${this.insertStringAt(text, 2, '/')}` : text); + }} /> From 4ef2b51e50ae1756f3ae72537c31684bd4210e06 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Mon, 14 Feb 2022 21:13:59 -0600 Subject: [PATCH 003/361] install @storybook/addon-react-native-web --- .storybook/main.js | 1 + package-lock.json | 6 ++++++ package.json | 1 + 3 files changed, 8 insertions(+) diff --git a/.storybook/main.js b/.storybook/main.js index fcf0b3b46879..4bdb815522ae 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -6,6 +6,7 @@ module.exports = { addons: [ '@storybook/addon-essentials', '@storybook/addon-a11y', + '@storybook/addon-react-native-web', ], staticDirs: [ './public', diff --git a/package-lock.json b/package-lock.json index 4113115966f5..94074cabd4ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8454,6 +8454,12 @@ } } }, + "@storybook/addon-react-native-web": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@storybook/addon-react-native-web/-/addon-react-native-web-0.0.18.tgz", + "integrity": "sha512-tMZumiF+Dgk7sngMWFrbDdBN3h5C001traYM46CqNQvtJoZvwYe2MPGEeWy3wk+5D8vOv8TFw2i96f3wwfralg==", + "dev": true + }, "@storybook/addon-toolbars": { "version": "6.4.12", "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.12.tgz", diff --git a/package.json b/package.json index d00f22c9dcd8..709166612bb4 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "@react-native-community/eslint-config": "^2.0.0", "@storybook/addon-a11y": "^6.4.12", "@storybook/addon-essentials": "^6.4.12", + "@storybook/addon-react-native-web": "0.0.18", "@storybook/addons": "^6.4.12", "@storybook/react": "^6.4.12", "@storybook/theming": "^6.4.12", From def46e5c2b7897b1def465a2d1244b6d8ed7b921 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Mon, 14 Feb 2022 21:16:00 -0600 Subject: [PATCH 004/361] align error text to label --- src/components/InlineErrorText.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/InlineErrorText.js b/src/components/InlineErrorText.js index 90f6838e19bc..7ac4192585de 100644 --- a/src/components/InlineErrorText.js +++ b/src/components/InlineErrorText.js @@ -19,7 +19,7 @@ const InlineErrorText = (props) => { } return ( - {props.children} + {props.children} ); }; From 01fa79541b6b07b940e1edef22f07fe100935b1f Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Mon, 14 Feb 2022 21:35:27 -0600 Subject: [PATCH 005/361] Refactor BasePicker to Picker new props --- src/components/Picker/BasePicker/index.js | 57 +++++++++++++++-------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/src/components/Picker/BasePicker/index.js b/src/components/Picker/BasePicker/index.js index d283bf248398..561257a67a6c 100644 --- a/src/components/Picker/BasePicker/index.js +++ b/src/components/Picker/BasePicker/index.js @@ -1,30 +1,49 @@ import React from 'react'; import RNPickerSelect from 'react-native-picker-select'; +import _ from 'underscore'; import styles from '../../../styles/styles'; import * as basePickerPropTypes from './basePickerPropTypes'; import basePickerStyles from './basePickerStyles'; -const BasePicker = props => ( - props.icon(props.size)} - disabled={props.disabled} - fixAndroidTouchableBug - onOpen={props.onOpen} - onClose={props.onClose} - pickerProps={{ - onFocus: props.onOpen, - onBlur: props.onClose, - }} - /> -); +class BasePicker extends React.Component { + constructor(props) { + super(props); + this.state = { + selectValue: this.props.value || this.props.defaultValue || '', + }; + } + + handleChange = (value) => { + this.props.onChange(value); + this.setState({selectValue: value}); + } + + render() { + const hasError = !_.isEmpty(this.props.errorText); + return ( + this.props.icon(this.props.size)} + disabled={this.props.disabled} + fixAndroidTouchableBug + onOpen={this.props.onOpen} + onClose={this.props.onClose} + pickerProps={{ + onFocus: this.props.onOpen, + onBlur: this.props.onBlur, + ref: this.props.innerRef, + }} + /> + ); + } +} BasePicker.propTypes = basePickerPropTypes.propTypes; BasePicker.defaultProps = basePickerPropTypes.defaultProps; From a5db0dbdb35f86e15f8fcc31e120270127533a9d Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Tue, 15 Feb 2022 14:25:01 -0600 Subject: [PATCH 006/361] Create BasePicker's Web version file --- src/components/Picker/BasePicker/index.web.js | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/components/Picker/BasePicker/index.web.js diff --git a/src/components/Picker/BasePicker/index.web.js b/src/components/Picker/BasePicker/index.web.js new file mode 100644 index 000000000000..561257a67a6c --- /dev/null +++ b/src/components/Picker/BasePicker/index.web.js @@ -0,0 +1,52 @@ +import React from 'react'; +import RNPickerSelect from 'react-native-picker-select'; +import _ from 'underscore'; + +import styles from '../../../styles/styles'; +import * as basePickerPropTypes from './basePickerPropTypes'; +import basePickerStyles from './basePickerStyles'; + +class BasePicker extends React.Component { + constructor(props) { + super(props); + + this.state = { + selectValue: this.props.value || this.props.defaultValue || '', + }; + } + + handleChange = (value) => { + this.props.onChange(value); + this.setState({selectValue: value}); + } + + render() { + const hasError = !_.isEmpty(this.props.errorText); + return ( + this.props.icon(this.props.size)} + disabled={this.props.disabled} + fixAndroidTouchableBug + onOpen={this.props.onOpen} + onClose={this.props.onClose} + pickerProps={{ + onFocus: this.props.onOpen, + onBlur: this.props.onBlur, + ref: this.props.innerRef, + }} + /> + ); + } +} + +BasePicker.propTypes = basePickerPropTypes.propTypes; +BasePicker.defaultProps = basePickerPropTypes.defaultProps; +BasePicker.displayName = 'BasePicker'; + +export default BasePicker; From 68d619fcfd2a0e4094159b7cb4510b434d2ff9ad Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Tue, 15 Feb 2022 14:33:13 -0600 Subject: [PATCH 007/361] Extend focus method of View ref to scroll --- src/components/Picker/BasePicker/index.web.js | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/components/Picker/BasePicker/index.web.js b/src/components/Picker/BasePicker/index.web.js index 561257a67a6c..ee98c004eddd 100644 --- a/src/components/Picker/BasePicker/index.web.js +++ b/src/components/Picker/BasePicker/index.web.js @@ -1,5 +1,6 @@ import React from 'react'; import RNPickerSelect from 'react-native-picker-select'; +import {View} from 'react-native'; import _ from 'underscore'; import styles from '../../../styles/styles'; @@ -15,6 +16,29 @@ class BasePicker extends React.Component { }; } + componentDidMount() { + const viewRef = this.viewRef; + if (!viewRef) { + return; + } + + if (typeof this.props.innerRef !== 'function') { + return; + } + + // ! If RNPickerSelect pickerProps returns the tag's ref, the implementation of this file's Web version would be no longer neccesary, - // ! check for any update on https://github.com/lawnstarter/react-native-picker-select or https://github.com/react-native-picker/picker - // View ref will return a
, apply 'focus()' on it will not scroll to it. - // Applying 'scrollIntoView(false)' will scroll to element. + // ! Picker from https://github.com/react-native-picker/picker is being used inside RNPickerSelect. Picker 'ref' prop does not work on Web + // ! therefore it can not get '' ref that Picker renders, so a pull request https://github.com/react-native-picker/picker/pull/376 - // ! has been made with a potential fix to this issue , if Picker returns a 'ref' the implementation to this file would not be neccesary. - // An alternative is getting a View container ref. View ref will return a
, + // 'ref' is not exposed in Picker to focus on it. An alternative is getting a View container ref. View ref will return a
, // apply 'focus()' on it will not scroll to it. Applying 'scrollIntoView(false)' will scroll to element. https://developer.mozilla.org/es/docs/Web/API/Element/scrollIntoView const originalFocus = viewRef.focus; viewRef.focus = function () { From 094efbaa69f6512052c47359ce47d2b3e542461e Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Fri, 18 Feb 2022 11:23:03 -0600 Subject: [PATCH 017/361] convert index to index.native, index.web to index --- src/components/Picker/BasePicker/index.js | 59 ++++++++++----- .../Picker/BasePicker/index.native.js | 52 +++++++++++++ src/components/Picker/BasePicker/index.web.js | 75 ------------------- 3 files changed, 93 insertions(+), 93 deletions(-) create mode 100644 src/components/Picker/BasePicker/index.native.js delete mode 100644 src/components/Picker/BasePicker/index.web.js diff --git a/src/components/Picker/BasePicker/index.js b/src/components/Picker/BasePicker/index.js index cb5f264e4942..e01a885f4c37 100644 --- a/src/components/Picker/BasePicker/index.js +++ b/src/components/Picker/BasePicker/index.js @@ -1,5 +1,6 @@ import React from 'react'; import RNPickerSelect from 'react-native-picker-select'; +import {View} from 'react-native'; import _ from 'underscore'; import styles from '../../../styles/styles'; @@ -15,6 +16,27 @@ class BasePicker extends React.Component { }; } + componentDidMount() { + const viewRef = this.viewRef; + if (!viewRef) { + return; + } + + if (typeof this.props.innerRef !== 'function') { + return; + } + + // 'ref' is not exposed in Picker to focus on it. An alternative is getting a View container ref. View ref will return a
, + // apply 'focus()' on it will not scroll to it. Applying 'scrollIntoView(false)' will scroll to element. https://developer.mozilla.org/es/docs/Web/API/Element/scrollIntoView + const originalFocus = viewRef.focus; + viewRef.focus = function () { + // Execute original focus() using apply on ref context to prevent infinite focus() call stack and preserve original focus() functionality + originalFocus.apply(viewRef); + viewRef.scrollIntoView(false); + }; + this.props.innerRef(viewRef); + } + handleChange = (value) => { this.props.onChange(value); this.setState({selectValue: value}); @@ -23,24 +45,25 @@ class BasePicker extends React.Component { render() { const hasError = !_.isEmpty(this.props.errorText); return ( - this.props.icon(this.props.size)} - disabled={this.props.disabled} - fixAndroidTouchableBug - onOpen={this.props.onOpen} - onClose={this.props.onClose} - pickerProps={{ - onFocus: this.props.onOpen, - onBlur: this.props.onBlur, - ref: this.props.innerRef, - }} - /> + this.viewRef = ref}> + this.props.icon(this.props.size)} + disabled={this.props.disabled} + fixAndroidTouchableBug + onOpen={this.props.onOpen} + onClose={this.props.onClose} + pickerProps={{ + onFocus: this.props.onOpen, + onBlur: this.props.onBlur, + }} + /> + ); } } diff --git a/src/components/Picker/BasePicker/index.native.js b/src/components/Picker/BasePicker/index.native.js new file mode 100644 index 000000000000..cb5f264e4942 --- /dev/null +++ b/src/components/Picker/BasePicker/index.native.js @@ -0,0 +1,52 @@ +import React from 'react'; +import RNPickerSelect from 'react-native-picker-select'; +import _ from 'underscore'; + +import styles from '../../../styles/styles'; +import * as basePickerPropTypes from './basePickerPropTypes'; +import basePickerStyles from './basePickerStyles'; + +class BasePicker extends React.Component { + constructor(props) { + super(props); + + this.state = { + selectValue: this.props.value || this.props.defaultValue, + }; + } + + handleChange = (value) => { + this.props.onChange(value); + this.setState({selectValue: value}); + } + + render() { + const hasError = !_.isEmpty(this.props.errorText); + return ( + this.props.icon(this.props.size)} + disabled={this.props.disabled} + fixAndroidTouchableBug + onOpen={this.props.onOpen} + onClose={this.props.onClose} + pickerProps={{ + onFocus: this.props.onOpen, + onBlur: this.props.onBlur, + ref: this.props.innerRef, + }} + /> + ); + } +} + +BasePicker.propTypes = basePickerPropTypes.propTypes; +BasePicker.defaultProps = basePickerPropTypes.defaultProps; +BasePicker.displayName = 'BasePicker'; + +export default BasePicker; diff --git a/src/components/Picker/BasePicker/index.web.js b/src/components/Picker/BasePicker/index.web.js deleted file mode 100644 index e01a885f4c37..000000000000 --- a/src/components/Picker/BasePicker/index.web.js +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react'; -import RNPickerSelect from 'react-native-picker-select'; -import {View} from 'react-native'; -import _ from 'underscore'; - -import styles from '../../../styles/styles'; -import * as basePickerPropTypes from './basePickerPropTypes'; -import basePickerStyles from './basePickerStyles'; - -class BasePicker extends React.Component { - constructor(props) { - super(props); - - this.state = { - selectValue: this.props.value || this.props.defaultValue, - }; - } - - componentDidMount() { - const viewRef = this.viewRef; - if (!viewRef) { - return; - } - - if (typeof this.props.innerRef !== 'function') { - return; - } - - // 'ref' is not exposed in Picker to focus on it. An alternative is getting a View container ref. View ref will return a
, - // apply 'focus()' on it will not scroll to it. Applying 'scrollIntoView(false)' will scroll to element. https://developer.mozilla.org/es/docs/Web/API/Element/scrollIntoView - const originalFocus = viewRef.focus; - viewRef.focus = function () { - // Execute original focus() using apply on ref context to prevent infinite focus() call stack and preserve original focus() functionality - originalFocus.apply(viewRef); - viewRef.scrollIntoView(false); - }; - this.props.innerRef(viewRef); - } - - handleChange = (value) => { - this.props.onChange(value); - this.setState({selectValue: value}); - } - - render() { - const hasError = !_.isEmpty(this.props.errorText); - return ( - this.viewRef = ref}> - this.props.icon(this.props.size)} - disabled={this.props.disabled} - fixAndroidTouchableBug - onOpen={this.props.onOpen} - onClose={this.props.onClose} - pickerProps={{ - onFocus: this.props.onOpen, - onBlur: this.props.onBlur, - }} - /> - - ); - } -} - -BasePicker.propTypes = basePickerPropTypes.propTypes; -BasePicker.defaultProps = basePickerPropTypes.defaultProps; -BasePicker.displayName = 'BasePicker'; - -export default BasePicker; From 170fc7054e4eba17d9b492e4c9cef404251a2f6a Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Mon, 21 Feb 2022 10:33:19 -0600 Subject: [PATCH 018/361] update @react-native-picker/picker --- package-lock.json | 13 ++++++++++--- package.json | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 94074cabd4ff..3b40abd5f05a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6710,9 +6710,9 @@ "integrity": "sha512-2Y9OXWHRutYmdyW+bNMaFTW8uTBpaaK20xdIFoVtqahEOO9++B+ut3CAWKPZcdRtb9ikG0LUKChGqMeocg0PGA==" }, "@react-native-picker/picker": { - "version": "1.9.11", - "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-1.9.11.tgz", - "integrity": "sha512-E7whvvMIl9Ln1sxgug7OAEVWQ69n82iV0d2OWWp5VV52+RW3azKh1IFm4rxdW5/oByMfl7FFL0eHNelGgY4BMQ==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.2.1.tgz", + "integrity": "sha512-EC7yv22QLHlTfnbC1ez9IUdXTOh1W31x96Oir0PfskSGFFJMWWdLTg4VrcE2DsGLzbfjjkBk123c173vf2a5MQ==" }, "@react-native/assets": { "version": "1.0.0", @@ -37107,6 +37107,13 @@ "requires": { "@react-native-picker/picker": "^1.8.3", "lodash.isequal": "^4.5.0" + }, + "dependencies": { + "@react-native-picker/picker": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-1.16.8.tgz", + "integrity": "sha512-pacdQDX6V6EmjF+HoiIh6u++qx4mTK0WnhgUHRc01B+Qt5eoeUwseBqmqfTSXTx/aHDEd6PiIw7UGvKgFoqgFQ==" + } } }, "react-native-plaid-link-sdk": { diff --git a/package.json b/package.json index 709166612bb4..720e6f16d13f 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@react-native-firebase/crashlytics": "^12.3.0", "@react-native-firebase/perf": "^12.3.0", "@react-native-masked-view/masked-view": "^0.2.4", - "@react-native-picker/picker": "^1.9.11", + "@react-native-picker/picker": "^2.2.1", "@react-navigation/compat": "^5.3.20", "@react-navigation/drawer": "6.1.8", "@react-navigation/native": "6.0.8", From 5d29dd777cdc0f45118edf2f465f257fbc590ac5 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Tue, 22 Feb 2022 01:33:54 +0530 Subject: [PATCH 019/361] fix: Changed the auto slash logic for length --- src/pages/settings/Payments/AddDebitCardPage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 8b5facafcc3a..501e8e72e3be 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -236,9 +236,9 @@ class DebitCardPage extends Component { errorText={this.getErrorText('expirationDate')} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} onKeyPress={({nativeEvent}) => { - if (nativeEvent.key === 'Backspace' && this.state.expirationDate.length === 3) { + if (nativeEvent.key === 'Backspace' && this.state.expirationDate.length === 4) { this.allowExpirationDateChange = false; - this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, 2)})); + this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, 3)})); } else { this.allowExpirationDateChange = true; } @@ -247,7 +247,7 @@ class DebitCardPage extends Component { if (!this.allowExpirationDateChange) { return; } - this.clearErrorAndSetValue('expirationDate', text.length === 3 ? `${this.insertStringAt(text, 2, '/')}` : text); + this.clearErrorAndSetValue('expirationDate', text.length === 2 && _.indexOf(text, '/') === -1 ? `${text}/` : text); }} /> From 7fb4b0f97834bead1edaac7b0fede72e0b7868ef Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Sun, 27 Feb 2022 22:14:46 -0600 Subject: [PATCH 020/361] remove false param on scrollIntoView --- src/components/Picker/BasePicker/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Picker/BasePicker/index.js b/src/components/Picker/BasePicker/index.js index e01a885f4c37..1279afecc894 100644 --- a/src/components/Picker/BasePicker/index.js +++ b/src/components/Picker/BasePicker/index.js @@ -32,7 +32,7 @@ class BasePicker extends React.Component { viewRef.focus = function () { // Execute original focus() using apply on ref context to prevent infinite focus() call stack and preserve original focus() functionality originalFocus.apply(viewRef); - viewRef.scrollIntoView(false); + viewRef.scrollIntoView(); }; this.props.innerRef(viewRef); } From e9a33e2dab527805b8d12ada6e4a69f236a4bb16 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Tue, 1 Mar 2022 21:31:13 -0600 Subject: [PATCH 021/361] update react native picker --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5caefe057c12..9348f3f2964b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6710,9 +6710,9 @@ "integrity": "sha512-2Y9OXWHRutYmdyW+bNMaFTW8uTBpaaK20xdIFoVtqahEOO9++B+ut3CAWKPZcdRtb9ikG0LUKChGqMeocg0PGA==" }, "@react-native-picker/picker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.2.1.tgz", - "integrity": "sha512-EC7yv22QLHlTfnbC1ez9IUdXTOh1W31x96Oir0PfskSGFFJMWWdLTg4VrcE2DsGLzbfjjkBk123c173vf2a5MQ==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.3.1.tgz", + "integrity": "sha512-DAw1o3bHNRnQPImsK53xCYkgC8bH+t9uTM+0JjNIlmMwvVLFnmDxi9v5iBTIWFMWG/pUHQaw66E29wW6oJG9Tw==" }, "@react-native/assets": { "version": "1.0.0", diff --git a/package.json b/package.json index 8e10432372a8..a4b6428004e9 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@react-native-firebase/crashlytics": "^12.3.0", "@react-native-firebase/perf": "^12.3.0", "@react-native-masked-view/masked-view": "^0.2.4", - "@react-native-picker/picker": "^2.2.1", + "@react-native-picker/picker": "^2.3.1", "@react-navigation/compat": "^5.3.20", "@react-navigation/drawer": "6.1.8", "@react-navigation/native": "6.0.8", From b8158b9fe0798c0b9d378d785b6ad3aaf0515ef7 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Tue, 1 Mar 2022 21:34:20 -0600 Subject: [PATCH 022/361] correct InputIDProps name --- src/components/Picker/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index bd0d25a8fb72..7f6f1e78e93f 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -33,7 +33,7 @@ const propTypes = { * @param {Object} props - props passed to the input * @returns {Object} - returns an Error object if isFormInput is supplied but inputID is falsey or not a string */ - inputID: props => FormUtils.getInputIDPropTypes(props), + inputID: props => FormUtils.validateInputIDProps(props), /** Saves a draft of the input value when used in a form */ shouldSaveDraft: PropTypes.bool, From 2da10cf7195d8cab54e149af092c18216e6be1ab Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Tue, 1 Mar 2022 21:39:45 -0600 Subject: [PATCH 023/361] add style prop to InlineErrorText, add style Picker --- src/components/InlineErrorText.js | 4 +++- src/components/Picker/index.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/InlineErrorText.js b/src/components/InlineErrorText.js index 7ac4192585de..88345121bb55 100644 --- a/src/components/InlineErrorText.js +++ b/src/components/InlineErrorText.js @@ -7,10 +7,12 @@ import Text from './Text'; const propTypes = { /** Text to display */ children: PropTypes.string, + style: PropTypes.arrayOf(PropTypes.object), }; const defaultProps = { children: 'Error', + style: [], }; const InlineErrorText = (props) => { @@ -19,7 +21,7 @@ const InlineErrorText = (props) => { } return ( - {props.children} + {props.children} ); }; diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index 7f6f1e78e93f..b7ed7febea68 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -85,7 +85,7 @@ class Picker extends PureComponent { /> {!_.isEmpty(this.props.errorText) && ( - + {this.props.errorText} )} From a893f1a923b560e7c49824997314683046734d29 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Tue, 1 Mar 2022 21:52:15 -0600 Subject: [PATCH 024/361] remove alternative logic to Picker ref --- src/components/Picker/BasePicker/index.js | 59 ++++++------------- .../Picker/BasePicker/index.native.js | 52 ---------------- 2 files changed, 18 insertions(+), 93 deletions(-) delete mode 100644 src/components/Picker/BasePicker/index.native.js diff --git a/src/components/Picker/BasePicker/index.js b/src/components/Picker/BasePicker/index.js index 1279afecc894..cb5f264e4942 100644 --- a/src/components/Picker/BasePicker/index.js +++ b/src/components/Picker/BasePicker/index.js @@ -1,6 +1,5 @@ import React from 'react'; import RNPickerSelect from 'react-native-picker-select'; -import {View} from 'react-native'; import _ from 'underscore'; import styles from '../../../styles/styles'; @@ -16,27 +15,6 @@ class BasePicker extends React.Component { }; } - componentDidMount() { - const viewRef = this.viewRef; - if (!viewRef) { - return; - } - - if (typeof this.props.innerRef !== 'function') { - return; - } - - // 'ref' is not exposed in Picker to focus on it. An alternative is getting a View container ref. View ref will return a
, - // apply 'focus()' on it will not scroll to it. Applying 'scrollIntoView(false)' will scroll to element. https://developer.mozilla.org/es/docs/Web/API/Element/scrollIntoView - const originalFocus = viewRef.focus; - viewRef.focus = function () { - // Execute original focus() using apply on ref context to prevent infinite focus() call stack and preserve original focus() functionality - originalFocus.apply(viewRef); - viewRef.scrollIntoView(); - }; - this.props.innerRef(viewRef); - } - handleChange = (value) => { this.props.onChange(value); this.setState({selectValue: value}); @@ -45,25 +23,24 @@ class BasePicker extends React.Component { render() { const hasError = !_.isEmpty(this.props.errorText); return ( - this.viewRef = ref}> - this.props.icon(this.props.size)} - disabled={this.props.disabled} - fixAndroidTouchableBug - onOpen={this.props.onOpen} - onClose={this.props.onClose} - pickerProps={{ - onFocus: this.props.onOpen, - onBlur: this.props.onBlur, - }} - /> - + this.props.icon(this.props.size)} + disabled={this.props.disabled} + fixAndroidTouchableBug + onOpen={this.props.onOpen} + onClose={this.props.onClose} + pickerProps={{ + onFocus: this.props.onOpen, + onBlur: this.props.onBlur, + ref: this.props.innerRef, + }} + /> ); } } diff --git a/src/components/Picker/BasePicker/index.native.js b/src/components/Picker/BasePicker/index.native.js deleted file mode 100644 index cb5f264e4942..000000000000 --- a/src/components/Picker/BasePicker/index.native.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import RNPickerSelect from 'react-native-picker-select'; -import _ from 'underscore'; - -import styles from '../../../styles/styles'; -import * as basePickerPropTypes from './basePickerPropTypes'; -import basePickerStyles from './basePickerStyles'; - -class BasePicker extends React.Component { - constructor(props) { - super(props); - - this.state = { - selectValue: this.props.value || this.props.defaultValue, - }; - } - - handleChange = (value) => { - this.props.onChange(value); - this.setState({selectValue: value}); - } - - render() { - const hasError = !_.isEmpty(this.props.errorText); - return ( - this.props.icon(this.props.size)} - disabled={this.props.disabled} - fixAndroidTouchableBug - onOpen={this.props.onOpen} - onClose={this.props.onClose} - pickerProps={{ - onFocus: this.props.onOpen, - onBlur: this.props.onBlur, - ref: this.props.innerRef, - }} - /> - ); - } -} - -BasePicker.propTypes = basePickerPropTypes.propTypes; -BasePicker.defaultProps = basePickerPropTypes.defaultProps; -BasePicker.displayName = 'BasePicker'; - -export default BasePicker; From 57ab9f76f758309e1bf47daaadaf8c05f3610942 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Wed, 2 Mar 2022 13:33:52 -0600 Subject: [PATCH 025/361] fix minor naming and empty lines --- src/components/Picker/BasePicker/index.js | 6 +++--- src/components/Picker/index.js | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/Picker/BasePicker/index.js b/src/components/Picker/BasePicker/index.js index cb5f264e4942..44e4a14b8037 100644 --- a/src/components/Picker/BasePicker/index.js +++ b/src/components/Picker/BasePicker/index.js @@ -11,13 +11,13 @@ class BasePicker extends React.Component { super(props); this.state = { - selectValue: this.props.value || this.props.defaultValue, + selectedValue: this.props.value || this.props.defaultValue, }; } handleChange = (value) => { this.props.onChange(value); - this.setState({selectValue: value}); + this.setState({selectedValue: value}); } render() { @@ -29,7 +29,7 @@ class BasePicker extends React.Component { style={this.props.size === 'normal' ? basePickerStyles(this.props.disabled, hasError, this.props.focused) : styles.pickerSmall} useNativeAndroidPickerStyle={false} placeholder={this.props.placeholder} - value={this.state.selectValue} + value={this.state.selectedValue} Icon={() => this.props.icon(this.props.size)} disabled={this.props.disabled} fixAndroidTouchableBug diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index b7ed7febea68..3f1498d6c69b 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -48,7 +48,6 @@ const defaultProps = { inputID: undefined, shouldSaveDraft: false, value: undefined, - }; class Picker extends PureComponent { From 2e608ef9aeed04456476f3f80b0d3111a946a811 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Thu, 3 Mar 2022 12:23:07 -0800 Subject: [PATCH 026/361] Merge branch 'main' of /Users/tgolen/Expensidev/App with conflicts. --- ios/NewExpensify.xcodeproj/project.pbxproj | 4 ++-- package.json | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index de0bf9bf28ff..11d1b5e78da6 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -940,7 +940,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1001,7 +1001,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/package.json b/package.json index 9a8a20acb67b..ff8c50b6a0fb 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,25 @@ { "name": "new.expensify", - "version": "1.1.40-2", + "version": "1.1.39-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.", "license": "MIT", "private": true, "scripts": { - "postinstall": "scripts/react-native-web.sh && cd desktop && npm install", + "postinstall": "./build/react-native-web.sh", "clean": "react-native clean-project-auto", "android": "npm run check-metro-bundler-port && react-native run-android", "ios": "npm run check-metro-bundler-port && react-native run-ios", "ipad": "npm run check-metro-bundler-port && react-native run-ios --simulator=\"iPad Pro (12.9-inch) (4th generation)\"", "ipad-sm": "npm run check-metro-bundler-port && react-native run-ios --simulator=\"iPad Pro (9.7-inch)\"", + "desktop": "node desktop/start.js", "start": "react-native start", "web": "node web/proxy.js & webpack-dev-server --open --config config/webpack/webpack.dev.js", - "build": "webpack --config config/webpack/webpack.common.js --env.envFile=.env.production", - "build-staging": "webpack --config config/webpack/webpack.common.js --env.envFile=.env.staging", - "desktop": "node desktop/start.js", - "desktop-build": "scripts/build-desktop.sh production", - "desktop-build-staging": "scripts/build-desktop.sh staging", + "build": "webpack --config config/webpack/webpack.prod.js", + "build-staging": "webpack --config config/webpack/webpack.staging.js", + "desktop-build": "webpack --config config/webpack/webpack.prod.js --platform desktop && electron-builder --config config/electron.config.js", + "desktop-build-staging": "webpack --config config/webpack/webpack.staging.js --platform desktop && electron-builder --config config/electron.config.js", "ios-build": "fastlane ios build", "android-build": "fastlane android build", "test": "jest", @@ -61,6 +61,10 @@ "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", "dotenv": "^8.2.0", + "electron-context-menu": "^2.3.0", + "electron-log": "^4.3.5", + "electron-serve": "^1.0.0", + "electron-updater": "^4.3.4", "expensify-common": "git+https://github.com/Expensify/expensify-common.git#f77bb4710c13d01153716df7fb087b637ba3b8bd", "fbjs": "^3.0.2", "file-loader": "^6.0.0", From 61b79ee478e0fc0e90bb1a80d93ca8da252fcc23 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 7 Mar 2022 23:51:23 +0530 Subject: [PATCH 027/361] feat: moved the auto slash code to separate functions --- .../settings/Payments/AddDebitCardPage.js | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index c66301463aea..1d950cdee7e4 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -185,17 +185,26 @@ class DebitCardPage extends Component { })); } - /** - * Insert string at index position for a given input string - * @param {String} inputString - * @param {Number} indexPosition - * @param {String} stringToAdd - * @returns {String} - */ - insertStringAt(inputString, indexPosition, stringToAdd) { - return inputString.slice(0, indexPosition) - + stringToAdd - + inputString.slice(indexPosition); + addSlashToExpiryDate(text) { + if (!this.allowExpirationDateChange) { + return; + } + let expiryDate = text; + if (text.length === 2 && _.indexOf(text, '/') === -1) { + expiryDate = `${text}/`; + } if (text.length > 3 && _.indexOf(text, '/') === -1) { + expiryDate = `${text.slice(0, 2)}/${text.slice(2)}`; + } + this.clearErrorAndSetValue('expirationDate', expiryDate); + } + + removeSlashFromExpiryDate(nativeEvent) { + if (nativeEvent.key === 'Backspace' && this.state.expirationDate.length === 4) { + this.allowExpirationDateChange = false; + this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, prevState.expirationDate.length - 1)})); + } else { + this.allowExpirationDateChange = true; + } } render() { @@ -235,20 +244,8 @@ class DebitCardPage extends Component { maxLength={7} errorText={this.getErrorText('expirationDate')} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} - onKeyPress={({nativeEvent}) => { - if (nativeEvent.key === 'Backspace' && this.state.expirationDate.length === 4) { - this.allowExpirationDateChange = false; - this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, 3)})); - } else { - this.allowExpirationDateChange = true; - } - }} - onChangeText={(text) => { - if (!this.allowExpirationDateChange) { - return; - } - this.clearErrorAndSetValue('expirationDate', text.length === 2 && _.indexOf(text, '/') === -1 ? `${text}/` : text); - }} + onKeyPress={this.removeSlashFromExpiryDate} + onChangeText={this.addSlashToExpiryDate} /> From c5471514a856f62cf4d3dbd9947c363354166697 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 7 Mar 2022 23:51:59 +0530 Subject: [PATCH 028/361] fix: added funcs to this --- src/pages/settings/Payments/AddDebitCardPage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 1d950cdee7e4..1d1a1ae8d62b 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -92,6 +92,8 @@ class DebitCardPage extends Component { this.clearErrorAndSetValue = this.clearErrorAndSetValue.bind(this); this.getErrorText = this.getErrorText.bind(this); this.allowExpirationDateChange = true; + this.addSlashToExpiryDate = this.addSlashToExpiryDate.bind(this); + this.removeSlashFromExpiryDate = this.removeSlashFromExpiryDate.bind(this); } /** From a84ede9e7cc4ebe63ec122e9447b069a3a5dd69e Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 7 Mar 2022 23:55:50 +0530 Subject: [PATCH 029/361] fix: handle delete slash when its the last char --- src/pages/settings/Payments/AddDebitCardPage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 1d1a1ae8d62b..07c1a89b7c98 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import {View} from 'react-native'; import lodashGet from 'lodash/get'; +import lodashEndsWith from 'lodash/endsWith'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; @@ -201,7 +202,8 @@ class DebitCardPage extends Component { } removeSlashFromExpiryDate(nativeEvent) { - if (nativeEvent.key === 'Backspace' && this.state.expirationDate.length === 4) { + const expirationDate = this.state.expirationDate; + if (nativeEvent.key === 'Backspace' && (expirationDate.length === 4 || (expirationDate.length === 3 && lodashEndsWith(expirationDate, '/')))) { this.allowExpirationDateChange = false; this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, prevState.expirationDate.length - 1)})); } else { From 77fd124fe2290497f29586c29f9ec40c31e4613e Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Tue, 8 Mar 2022 00:07:53 +0530 Subject: [PATCH 030/361] fix: Code cleanup --- src/pages/settings/Payments/AddDebitCardPage.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 07c1a89b7c98..dc5f42f86dc4 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -188,15 +188,19 @@ class DebitCardPage extends Component { })); } - addSlashToExpiryDate(text) { + /** + * Adds slash to the expiry date + * @param {String} inputExpiryDate + */ + addSlashToExpiryDate(inputExpiryDate) { if (!this.allowExpirationDateChange) { return; } - let expiryDate = text; - if (text.length === 2 && _.indexOf(text, '/') === -1) { - expiryDate = `${text}/`; - } if (text.length > 3 && _.indexOf(text, '/') === -1) { - expiryDate = `${text.slice(0, 2)}/${text.slice(2)}`; + let expiryDate = inputExpiryDate; + if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { + expiryDate = `${inputExpiryDate}/`; + } if (inputExpiryDate.length > 3 && _.indexOf(inputExpiryDate, '/') === -1) { + expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } this.clearErrorAndSetValue('expirationDate', expiryDate); } From b1177c17ace2ce26f1a2b0bcd9b239304d9a0344 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Tue, 8 Mar 2022 00:13:44 +0530 Subject: [PATCH 031/361] fix: added comment to functions --- src/pages/settings/Payments/AddDebitCardPage.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index dc5f42f86dc4..5fcaa40ae114 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -189,7 +189,7 @@ class DebitCardPage extends Component { } /** - * Adds slash to the expiry date + * Add slash to the expiry date * @param {String} inputExpiryDate */ addSlashToExpiryDate(inputExpiryDate) { @@ -197,16 +197,25 @@ class DebitCardPage extends Component { return; } let expiryDate = inputExpiryDate; + + // Expiry Date(MM)is added so append a slash(/) if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { expiryDate = `${inputExpiryDate}/`; - } if (inputExpiryDate.length > 3 && _.indexOf(inputExpiryDate, '/') === -1) { + } else if (inputExpiryDate.length > 3 && _.indexOf(inputExpiryDate, '/') === -1) { + // Expiry Date with MM and YY without slash, hence adding slash(/) expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } this.clearErrorAndSetValue('expirationDate', expiryDate); } + /** + * Remove slash from expiry date on backspace + * @param {Object} nativeEvent + */ removeSlashFromExpiryDate(nativeEvent) { const expirationDate = this.state.expirationDate; + + // Auto remove the slash and digit when backspace is pressed and it ends with slash if (nativeEvent.key === 'Backspace' && (expirationDate.length === 4 || (expirationDate.length === 3 && lodashEndsWith(expirationDate, '/')))) { this.allowExpirationDateChange = false; this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, prevState.expirationDate.length - 1)})); From e0c7020745f84d45eee1b480d5da0671571653b8 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Tue, 8 Mar 2022 00:55:51 +0530 Subject: [PATCH 032/361] fix: change event to e.nativeEvent --- src/pages/settings/Payments/AddDebitCardPage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 5fcaa40ae114..869e4d985e61 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -210,13 +210,13 @@ class DebitCardPage extends Component { /** * Remove slash from expiry date on backspace - * @param {Object} nativeEvent + * @param {Object} e */ - removeSlashFromExpiryDate(nativeEvent) { + removeSlashFromExpiryDate(e) { const expirationDate = this.state.expirationDate; // Auto remove the slash and digit when backspace is pressed and it ends with slash - if (nativeEvent.key === 'Backspace' && (expirationDate.length === 4 || (expirationDate.length === 3 && lodashEndsWith(expirationDate, '/')))) { + if (e.nativeEvent.key === 'Backspace' && (expirationDate.length === 4 || (expirationDate.length === 3 && lodashEndsWith(expirationDate, '/')))) { this.allowExpirationDateChange = false; this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, prevState.expirationDate.length - 1)})); } else { From 578ec9e30110c786283de7b09415466c1c5f00a5 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Thu, 10 Mar 2022 22:25:20 +0530 Subject: [PATCH 033/361] fix: changed setstate to clearErrorAndSetValue, temp console added --- src/components/TextInput/BaseTextInput.js | 1 + src/pages/settings/Payments/AddDebitCardPage.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index 283bfa5a9ba2..d205ab203c25 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -65,6 +65,7 @@ class BaseTextInput extends Component { return; } + // console.log('Values to Compare in BaseTextInput', this.value, this.props.value); this.value = this.props.value; this.input.setNativeProps({text: this.value}); diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 6ef390f15d89..baef49f7fc4f 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -218,13 +218,17 @@ class DebitCardPage extends Component { // Auto remove the slash and digit when backspace is pressed and it ends with slash if (e.nativeEvent.key === 'Backspace' && (expirationDate.length === 4 || (expirationDate.length === 3 && lodashEndsWith(expirationDate, '/')))) { this.allowExpirationDateChange = false; - this.setState(prevState => ({expirationDate: prevState.expirationDate.substring(0, prevState.expirationDate.length - 1)})); + e.preventDefault(); + + // console.log('About to update state', expirationDate.substring(0, expirationDate.length - 2)); + this.clearErrorAndSetValue('expirationDate', expirationDate.substring(0, expirationDate.length - 2)); } else { this.allowExpirationDateChange = true; } } render() { + // console.log('Current State', this.state.expirationDate); return ( From bc1310dc9e040926984495071f57629cb7b80760 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Fri, 11 Mar 2022 11:41:48 -0600 Subject: [PATCH 034/361] fix coding style errors --- src/components/InlineErrorText.js | 2 ++ src/components/Picker/BasePicker/index.js | 7 ++++--- src/components/Picker/index.js | 2 +- src/stories/Picker.stories.js | 13 ++++--------- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/components/InlineErrorText.js b/src/components/InlineErrorText.js index 88345121bb55..a21af6629efb 100644 --- a/src/components/InlineErrorText.js +++ b/src/components/InlineErrorText.js @@ -7,6 +7,8 @@ import Text from './Text'; const propTypes = { /** Text to display */ children: PropTypes.string, + + /** Customized styles applied on a single InlineErrorText component */ style: PropTypes.arrayOf(PropTypes.object), }; diff --git a/src/components/Picker/BasePicker/index.js b/src/components/Picker/BasePicker/index.js index 44e4a14b8037..59cca5ea1511 100644 --- a/src/components/Picker/BasePicker/index.js +++ b/src/components/Picker/BasePicker/index.js @@ -13,9 +13,11 @@ class BasePicker extends React.Component { this.state = { selectedValue: this.props.value || this.props.defaultValue, }; + + this.updateSelectedValueAndExecuteOnChange = this.updateSelectedValueAndExecuteOnChange.bind(this); } - handleChange = (value) => { + updateSelectedValueAndExecuteOnChange(value) { this.props.onChange(value); this.setState({selectedValue: value}); } @@ -24,7 +26,7 @@ class BasePicker extends React.Component { const hasError = !_.isEmpty(this.props.errorText); return ( {!_.isEmpty(this.props.errorText) && ( - + {this.props.errorText} )} diff --git a/src/stories/Picker.stories.js b/src/stories/Picker.stories.js index 4d5a763969ea..fd230fab83ee 100644 --- a/src/stories/Picker.stories.js +++ b/src/stories/Picker.stories.js @@ -17,13 +17,11 @@ const Template = args => ; // Arguments can be passed to the component by binding // See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args - const Default = Template.bind({}); Default.args = { label: 'Default picker', name: 'Default', - onChange: () => { - }, + onChange: () => {}, items: [ { label: 'Orange', @@ -40,8 +38,7 @@ const PickerWithValue = Template.bind({}); PickerWithValue.args = { label: 'Picker with defined value', name: 'Picker with defined value', - onChange: () => { - }, + onChange: () => {}, value: 'apple', items: [ { @@ -60,8 +57,7 @@ ErrorStory.args = { label: 'Picker with error', name: 'PickerWithError', errorText: 'This field has an error.', - onChange: () => { - }, + onChange: () => {}, items: [ { label: 'Orange', @@ -79,8 +75,7 @@ Disabled.args = { label: 'Picker disabled', name: 'Disabled', isDisabled: true, - onChange: () => { - }, + onChange: () => {}, items: [ { label: 'Orange', From 189ca7c7fc6b20c475113ec244f64828c4ff8414 Mon Sep 17 00:00:00 2001 From: LucioChavezFuentes Date: Fri, 11 Mar 2022 12:49:23 -0600 Subject: [PATCH 035/361] rename onInputChange on Picker.stories --- src/stories/Picker.stories.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/stories/Picker.stories.js b/src/stories/Picker.stories.js index fd230fab83ee..dd26adebc484 100644 --- a/src/stories/Picker.stories.js +++ b/src/stories/Picker.stories.js @@ -21,7 +21,7 @@ const Default = Template.bind({}); Default.args = { label: 'Default picker', name: 'Default', - onChange: () => {}, + onInputChange: () => {}, items: [ { label: 'Orange', @@ -38,7 +38,7 @@ const PickerWithValue = Template.bind({}); PickerWithValue.args = { label: 'Picker with defined value', name: 'Picker with defined value', - onChange: () => {}, + onInputChange: () => {}, value: 'apple', items: [ { @@ -57,7 +57,7 @@ ErrorStory.args = { label: 'Picker with error', name: 'PickerWithError', errorText: 'This field has an error.', - onChange: () => {}, + onInputChange: () => {}, items: [ { label: 'Orange', @@ -75,7 +75,7 @@ Disabled.args = { label: 'Picker disabled', name: 'Disabled', isDisabled: true, - onChange: () => {}, + onInputChange: () => {}, items: [ { label: 'Orange', From 2f04f13210be3783dfc15574efdbef63b71d59a9 Mon Sep 17 00:00:00 2001 From: sobitneupane <073bct543.sobit@pcampus.edu.np> Date: Sun, 13 Mar 2022 23:29:11 +0545 Subject: [PATCH 036/361] Update isReportMessageAttachment logic --- src/libs/OptionsListUtils.js | 2 +- src/libs/actions/Report.js | 3 ++- src/libs/reportUtils.js | 7 ++++--- src/pages/home/report/ContextMenu/ContextMenuActions.js | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 23f477618d4c..0501611f9764 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -253,7 +253,7 @@ function createOption(personalDetailList, report, { : {}; const lastActorDetails = report ? _.find(personalDetailList, {login: report.lastActorEmail}) : null; - const lastMessageTextFromReport = ReportUtils.isReportMessageAttachment(lodashGet(report, 'lastMessageText', '')) + const lastMessageTextFromReport = ReportUtils.isReportMessageAttachment(lodashGet(report, 'lastMessageText', ''), lodashGet(report, 'lastMessageHtml', '')) ? `[${Localize.translateLocal('common.attachment')}]` : Str.htmlDecode(lodashGet(report, 'lastMessageText', '')); let lastMessageText = report && hasMultipleParticipants && lastActorDetails diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 4d379900e0f8..2be2c3e59d64 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -235,6 +235,7 @@ function getSimplifiedReportObject(report) { oldPolicyName, visibility, isOwnPolicyExpenseChat: lodashGet(report, ['isOwnPolicyExpenseChat'], false), + lastMessageHtml: lastActionMessage, }; } @@ -628,7 +629,7 @@ function updateReportWithNewAction( // Add the action into Onyx reportActionsToMerge[reportAction.sequenceNumber] = { ...reportAction, - isAttachment: ReportUtils.isReportMessageAttachment(messageText), + isAttachment: ReportUtils.isReportMessageAttachment(messageText, lodashGet(reportAction, ['message', 0, 'html'], '')), loading: false, }; diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 59f83ff1db9e..94f1f672bdd7 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -26,10 +26,11 @@ function getReportParticipantsTitle(logins) { * Check whether a report action is Attachment is not. * * @param {Object} reportMessageText report action's message as text + * @param {Object} reportMessageHtml report action's message as html * @returns {Boolean} */ -function isReportMessageAttachment(reportMessageText) { - return reportMessageText === '[Attachment]'; +function isReportMessageAttachment(reportMessageText, reportMessageHtml) { + return reportMessageText === '[Attachment]' && reportMessageHtml !== '[Attachment]'; } /** @@ -60,7 +61,7 @@ function canEditReportAction(reportAction) { return reportAction.actorEmail === sessionEmail && reportAction.reportActionID && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT - && !isReportMessageAttachment(lodashGet(reportAction, ['message', 0, 'text'], '')); + && !isReportMessageAttachment(lodashGet(reportAction, ['message', 0, 'text'], ''), lodashGet(reportAction, ['message', 0, 'html'], '')); } /** diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 7d23894e613d..34ddc90eadff 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -58,7 +58,7 @@ export default [ const isAttachment = _.has(reportAction, 'isAttachment') ? reportAction.isAttachment - : ReportUtils.isReportMessageAttachment(text); + : ReportUtils.isReportMessageAttachment(text, html); if (!isAttachment) { Clipboard.setString(text); } else { From 88d83b4360147051ad360e5f217d136396e80d11 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 14 Mar 2022 22:54:21 +0530 Subject: [PATCH 037/361] fix: length check to > 2 for expirationdate --- src/pages/settings/Payments/AddDebitCardPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 93f326d4802f..26f0bf962e76 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -201,7 +201,7 @@ class DebitCardPage extends Component { // Expiry Date(MM)is added so append a slash(/) if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { expiryDate = `${inputExpiryDate}/`; - } else if (inputExpiryDate.length > 3 && _.indexOf(inputExpiryDate, '/') === -1) { + } else if (inputExpiryDate.length > 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date with MM and YY without slash, hence adding slash(/) expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } From 6ac4f2d4f68c3889e67c49a6212465187c6095cc Mon Sep 17 00:00:00 2001 From: sobitneupane <073bct543.sobit@pcampus.edu.np> Date: Thu, 17 Mar 2022 20:26:01 +0545 Subject: [PATCH 038/361] Pass single param to isReportMessageAttachment --- src/libs/OptionsListUtils.js | 2 +- src/libs/actions/Report.js | 2 +- src/libs/reportUtils.js | 9 ++++----- src/pages/home/report/ContextMenu/ContextMenuActions.js | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0501611f9764..c11f490559fe 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -253,7 +253,7 @@ function createOption(personalDetailList, report, { : {}; const lastActorDetails = report ? _.find(personalDetailList, {login: report.lastActorEmail}) : null; - const lastMessageTextFromReport = ReportUtils.isReportMessageAttachment(lodashGet(report, 'lastMessageText', ''), lodashGet(report, 'lastMessageHtml', '')) + const lastMessageTextFromReport = ReportUtils.isReportMessageAttachment({text: lodashGet(report, 'lastMessageText', ''), html: lodashGet(report, 'lastMessageHtml', '')}) ? `[${Localize.translateLocal('common.attachment')}]` : Str.htmlDecode(lodashGet(report, 'lastMessageText', '')); let lastMessageText = report && hasMultipleParticipants && lastActorDetails diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 2be2c3e59d64..8eb7697cad4c 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -629,7 +629,7 @@ function updateReportWithNewAction( // Add the action into Onyx reportActionsToMerge[reportAction.sequenceNumber] = { ...reportAction, - isAttachment: ReportUtils.isReportMessageAttachment(messageText, lodashGet(reportAction, ['message', 0, 'html'], '')), + isAttachment: ReportUtils.isReportMessageAttachment({text: messageText, html: lodashGet(reportAction, ['message', 0, 'html'], '')}), loading: false, }; diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 94f1f672bdd7..7eaf5d198e41 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -25,12 +25,11 @@ function getReportParticipantsTitle(logins) { /** * Check whether a report action is Attachment is not. * - * @param {Object} reportMessageText report action's message as text - * @param {Object} reportMessageHtml report action's message as html + * @param {Object} reportMessage report action's message as text and html * @returns {Boolean} */ -function isReportMessageAttachment(reportMessageText, reportMessageHtml) { - return reportMessageText === '[Attachment]' && reportMessageHtml !== '[Attachment]'; +function isReportMessageAttachment(reportMessage) { + return lodashGet(reportMessage, 'text', '') === '[Attachment]' && lodashGet(reportMessage, 'html', '') !== '[Attachment]'; } /** @@ -61,7 +60,7 @@ function canEditReportAction(reportAction) { return reportAction.actorEmail === sessionEmail && reportAction.reportActionID && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT - && !isReportMessageAttachment(lodashGet(reportAction, ['message', 0, 'text'], ''), lodashGet(reportAction, ['message', 0, 'html'], '')); + && !isReportMessageAttachment({text: lodashGet(reportAction, ['message', 0, 'text'], ''), html: lodashGet(reportAction, ['message', 0, 'html'], '')}); } /** diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 34ddc90eadff..323266d6b4e5 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -58,7 +58,7 @@ export default [ const isAttachment = _.has(reportAction, 'isAttachment') ? reportAction.isAttachment - : ReportUtils.isReportMessageAttachment(text, html); + : ReportUtils.isReportMessageAttachment({text: lodashGet(message, 'text', ''), html}); if (!isAttachment) { Clipboard.setString(text); } else { From 375a9bbab5399fd9d1715043fc8cc9cd77548a83 Mon Sep 17 00:00:00 2001 From: sobitneupane <073bct543.sobit@pcampus.edu.np> Date: Fri, 18 Mar 2022 20:21:11 +0545 Subject: [PATCH 039/361] Change isReportMessageAttachment argument --- src/libs/actions/Report.js | 2 +- src/libs/reportUtils.js | 8 ++++---- src/pages/home/report/ContextMenu/ContextMenuActions.js | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 8eb7697cad4c..02c7251f1704 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -629,7 +629,7 @@ function updateReportWithNewAction( // Add the action into Onyx reportActionsToMerge[reportAction.sequenceNumber] = { ...reportAction, - isAttachment: ReportUtils.isReportMessageAttachment({text: messageText, html: lodashGet(reportAction, ['message', 0, 'html'], '')}), + isAttachment: ReportUtils.isReportMessageAttachment(lodashGet(reportAction, ['message', 0], {})), loading: false, }; diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 7eaf5d198e41..31be93b79253 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -25,11 +25,11 @@ function getReportParticipantsTitle(logins) { /** * Check whether a report action is Attachment is not. * - * @param {Object} reportMessage report action's message as text and html + * @param {Object} reportActionMessage report action's message as text and html * @returns {Boolean} */ -function isReportMessageAttachment(reportMessage) { - return lodashGet(reportMessage, 'text', '') === '[Attachment]' && lodashGet(reportMessage, 'html', '') !== '[Attachment]'; +function isReportMessageAttachment(reportActionMessage) { + return reportActionMessage.text === '[Attachment]' && reportActionMessage.html !== '[Attachment]'; } /** @@ -60,7 +60,7 @@ function canEditReportAction(reportAction) { return reportAction.actorEmail === sessionEmail && reportAction.reportActionID && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT - && !isReportMessageAttachment({text: lodashGet(reportAction, ['message', 0, 'text'], ''), html: lodashGet(reportAction, ['message', 0, 'html'], '')}); + && !isReportMessageAttachment(lodashGet(reportAction, ['message', 0], {})); } /** diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 323266d6b4e5..48d7abb0944d 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -58,7 +58,7 @@ export default [ const isAttachment = _.has(reportAction, 'isAttachment') ? reportAction.isAttachment - : ReportUtils.isReportMessageAttachment({text: lodashGet(message, 'text', ''), html}); + : ReportUtils.isReportMessageAttachment(message); if (!isAttachment) { Clipboard.setString(text); } else { From c8d47c992f7ab46de0bb0718e2b7114c46bf151c Mon Sep 17 00:00:00 2001 From: sobitneupane <073bct543.sobit@pcampus.edu.np> Date: Fri, 18 Mar 2022 21:56:58 +0545 Subject: [PATCH 040/361] Change defaultValue of reportAction in message --- src/pages/home/report/ContextMenu/ContextMenuActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 48d7abb0944d..e4c474bee1f8 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -48,7 +48,7 @@ export default [ // `ContextMenuItem` with `successText` and `successIcon` which will fallback to // the `text` and `icon` onPress: (closePopover, {reportAction, selection}) => { - const message = _.last(lodashGet(reportAction, 'message', null)); + const message = _.last(lodashGet(reportAction, 'message', [{}])); const html = lodashGet(message, 'html', ''); const parser = new ExpensiMark(); From eb91d95ba9bf499a08f994910ff2973dd964cb76 Mon Sep 17 00:00:00 2001 From: sobitneupane <073bct543.sobit@pcampus.edu.np> Date: Fri, 18 Mar 2022 22:54:30 +0545 Subject: [PATCH 041/361] Change comment of isReportMessageAttachment function --- src/libs/reportUtils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 31be93b79253..5ad93f313ca4 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -23,7 +23,8 @@ function getReportParticipantsTitle(logins) { } /** - * Check whether a report action is Attachment is not. + * Check whether a report action is Attachment or not. + * Ignore messages containing [Attachment] as the main content. Attachments are actions with only text as [Attachment]. * * @param {Object} reportActionMessage report action's message as text and html * @returns {Boolean} From b51bb249c255a6a906b11abdef2ea1e617135901 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 21 Mar 2022 19:29:36 +0530 Subject: [PATCH 042/361] fix: removed keyup handling and update addslash function --- .../settings/Payments/AddDebitCardPage.js | 42 ++++++------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 26f0bf962e76..f12043d52776 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -94,7 +94,6 @@ class DebitCardPage extends Component { this.getErrorText = this.getErrorText.bind(this); this.allowExpirationDateChange = true; this.addSlashToExpiryDate = this.addSlashToExpiryDate.bind(this); - this.removeSlashFromExpiryDate = this.removeSlashFromExpiryDate.bind(this); } /** @@ -189,46 +188,30 @@ class DebitCardPage extends Component { } /** - * Add slash to the expiry date * @param {String} inputExpiryDate */ - addSlashToExpiryDate(inputExpiryDate) { - if (!this.allowExpirationDateChange) { - return; - } + addOrRemoveSlashToExpiryDate(inputExpiryDate) { let expiryDate = inputExpiryDate; - - // Expiry Date(MM)is added so append a slash(/) - if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { + console.log('Expiry date', inputExpiryDate); + + // Backspace was hit/character removed + if (inputExpiryDate.length < this.state.expirationDate.length + && (((inputExpiryDate.length === 3 && lodashEndsWith(inputExpiryDate, '/')) + || (inputExpiryDate.length === 2 && lodashEndsWith(this.state.expirationDate, '/'))))) { + expiryDate = inputExpiryDate.substring(0, inputExpiryDate.length - 1); + } else if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date(MM)is added so append a slash(/) expiryDate = `${inputExpiryDate}/`; } else if (inputExpiryDate.length > 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date with MM and YY without slash, hence adding slash(/) expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } - this.clearErrorAndSetValue('expirationDate', expiryDate); - } - /** - * Remove slash from expiry date on backspace - * @param {Object} e - */ - removeSlashFromExpiryDate(e) { - const expirationDate = this.state.expirationDate; - - // Auto remove the slash and digit when backspace is pressed and it ends with slash - if (e.nativeEvent.key === 'Backspace' && (expirationDate.length === 4 || (expirationDate.length === 3 && lodashEndsWith(expirationDate, '/')))) { - this.allowExpirationDateChange = false; - e.preventDefault(); - - // console.log('About to update state', expirationDate.substring(0, expirationDate.length - 2)); - this.clearErrorAndSetValue('expirationDate', expirationDate.substring(0, expirationDate.length - 2)); - } else { - this.allowExpirationDateChange = true; - } + console.log('Updated Expiry Date', expiryDate); + this.clearErrorAndSetValue('expirationDate', expiryDate); } render() { - // console.log('Current State', this.state.expirationDate); + console.log('Current State', this.state.expirationDate); return ( @@ -265,7 +248,6 @@ class DebitCardPage extends Component { maxLength={7} errorText={this.getErrorText('expirationDate')} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} - onKeyPress={this.removeSlashFromExpiryDate} onChangeText={this.addSlashToExpiryDate} /> From 0c452886cebc9c55091d5676fbb42ca354fc5234 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 21 Mar 2022 19:30:45 +0530 Subject: [PATCH 043/361] fix: update binding and remove console log --- src/pages/settings/Payments/AddDebitCardPage.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index f12043d52776..3dc65c386e5e 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -93,7 +93,7 @@ class DebitCardPage extends Component { this.clearErrorAndSetValue = this.clearErrorAndSetValue.bind(this); this.getErrorText = this.getErrorText.bind(this); this.allowExpirationDateChange = true; - this.addSlashToExpiryDate = this.addSlashToExpiryDate.bind(this); + this.addOrRemoveSlashToExpiryDate = this.addOrRemoveSlashToExpiryDate.bind(this); } /** @@ -192,7 +192,6 @@ class DebitCardPage extends Component { */ addOrRemoveSlashToExpiryDate(inputExpiryDate) { let expiryDate = inputExpiryDate; - console.log('Expiry date', inputExpiryDate); // Backspace was hit/character removed if (inputExpiryDate.length < this.state.expirationDate.length @@ -205,8 +204,6 @@ class DebitCardPage extends Component { // Expiry Date with MM and YY without slash, hence adding slash(/) expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } - - console.log('Updated Expiry Date', expiryDate); this.clearErrorAndSetValue('expirationDate', expiryDate); } @@ -248,7 +245,7 @@ class DebitCardPage extends Component { maxLength={7} errorText={this.getErrorText('expirationDate')} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} - onChangeText={this.addSlashToExpiryDate} + onChangeText={this.addOrRemoveSlashToExpiryDate} /> From 3ca97a17c80e03167fb4858494bdab0e2fde794b Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 21 Mar 2022 19:31:40 +0530 Subject: [PATCH 044/361] fix: updated comment --- src/pages/settings/Payments/AddDebitCardPage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index 3dc65c386e5e..bfb8cc706094 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -194,11 +194,13 @@ class DebitCardPage extends Component { let expiryDate = inputExpiryDate; // Backspace was hit/character removed + // Remove extra digit when there's a / involved if (inputExpiryDate.length < this.state.expirationDate.length && (((inputExpiryDate.length === 3 && lodashEndsWith(inputExpiryDate, '/')) || (inputExpiryDate.length === 2 && lodashEndsWith(this.state.expirationDate, '/'))))) { expiryDate = inputExpiryDate.substring(0, inputExpiryDate.length - 1); - } else if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date(MM)is added so append a slash(/) + } else if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { + // Expiry Date(MM)is added so append a slash(/) expiryDate = `${inputExpiryDate}/`; } else if (inputExpiryDate.length > 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date with MM and YY without slash, hence adding slash(/) From 1bd71f3b8087168748afadf6a167873ae088e79e Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 21 Mar 2022 19:49:51 +0530 Subject: [PATCH 045/361] fix: added generic component for nested scrollview --- src/components/NestedScrollView.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/components/NestedScrollView.js diff --git a/src/components/NestedScrollView.js b/src/components/NestedScrollView.js new file mode 100644 index 000000000000..fed25ad4672d --- /dev/null +++ b/src/components/NestedScrollView.js @@ -0,0 +1,30 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {ScrollView, View} from 'react-native'; +import styles from '../styles/styles'; + +const propTypes = { + /** Any children to display */ + children: PropTypes.node, +}; + +const defaultProps = { + children: null, +}; + +const NestedScrollView = props => ( + + + {props.children} + + +); + +NestedScrollView.propTypes = propTypes; +NestedScrollView.defaultProps = defaultProps; +NestedScrollView.displayName = 'NestedScrollView'; +export default NestedScrollView; From f4120477618bf509942923a52b5d7699a8f40e66 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 21 Mar 2022 19:50:05 +0530 Subject: [PATCH 046/361] fix: wrap google places api with nestedscrollview --- src/components/AddressSearch.js | 169 ++++++++++++++++---------------- 1 file changed, 86 insertions(+), 83 deletions(-) diff --git a/src/components/AddressSearch.js b/src/components/AddressSearch.js index 9186d3659b4c..7f581bef650e 100644 --- a/src/components/AddressSearch.js +++ b/src/components/AddressSearch.js @@ -7,6 +7,7 @@ import CONFIG from '../CONFIG'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import styles from '../styles/styles'; import TextInput from './TextInput'; +import NestedScrollView from './NestedScrollView'; import Log from '../libs/Log'; import * as GooglePlacesUtils from '../libs/GooglePlacesUtils'; import * as FormUtils from '../libs/FormUtils'; @@ -117,89 +118,91 @@ const AddressSearch = (props) => { }; return ( - { - saveLocationDetails(details); - - // After we select an option, we set displayListViewBorder to false to prevent UI flickering - setDisplayListViewBorder(false); - }} - query={{ - key: 'AIzaSyC4axhhXtpiS-WozJEsmlL3Kg3kXucbZus', - language: props.preferredLocale, - types: 'address', - components: 'country:us', - }} - requestUrl={{ - useOnPlatform: 'web', - url: `${CONFIG.EXPENSIFY.EXPENSIFY_URL}api?command=Proxy_GooglePlaces&proxyUrl=`, - }} - textInputProps={{ - InputComp: TextInput, - ref: (node) => { - if (!props.innerRef) { - return; - } - - if (_.isFunction(props.innerRef)) { - props.innerRef(node); - return; - } - - // eslint-disable-next-line no-param-reassign - props.innerRef.current = node; - }, - label: props.label, - containerStyles: props.containerStyles, - errorText: props.errorText, - value: props.value, - isFormInput: props.isFormInput, - inputID: props.inputID, - shouldSaveDraft: props.shouldSaveDraft, - onBlur: props.onBlur, - autoComplete: 'off', - onChangeText: (text) => { - if (skippedFirstOnChangeTextRef.current) { - props.onChange({street: text}); - } else { - skippedFirstOnChangeTextRef.current = true; - } - - // If the text is empty, we set displayListViewBorder to false to prevent UI flickering - if (_.isEmpty(text)) { - setDisplayListViewBorder(false); - } - }, - }} - styles={{ - textInputContainer: [styles.flexColumn], - listView: [ - !displayListViewBorder && styles.googleListView, - displayListViewBorder && styles.borderTopRounded, - displayListViewBorder && styles.borderBottomRounded, - displayListViewBorder && styles.mt1, - styles.overflowAuto, - styles.borderLeft, - styles.borderRight, - ], - row: [ - styles.pv4, - styles.ph3, - styles.overflowAuto, - ], - description: [styles.googleSearchText], - separator: [styles.googleSearchSeparator], - }} - onLayout={(event) => { - // We use the height of the element to determine if we should hide the border of the listView dropdown - // to prevent a lingering border when there are no address suggestions. - // The height of the empty element is 2px (1px height for each top and bottom borders) - setDisplayListViewBorder(event.nativeEvent.layout.height > 2); - }} - /> + + { + saveLocationDetails(details); + + // After we select an option, we set displayListViewBorder to false to prevent UI flickering + setDisplayListViewBorder(false); + }} + query={{ + key: 'AIzaSyC4axhhXtpiS-WozJEsmlL3Kg3kXucbZus', + language: props.preferredLocale, + types: 'address', + components: 'country:us', + }} + requestUrl={{ + useOnPlatform: 'web', + url: `${CONFIG.EXPENSIFY.EXPENSIFY_URL}api?command=Proxy_GooglePlaces&proxyUrl=`, + }} + textInputProps={{ + InputComp: TextInput, + ref: (node) => { + if (!props.innerRef) { + return; + } + + if (_.isFunction(props.innerRef)) { + props.innerRef(node); + return; + } + + // eslint-disable-next-line no-param-reassign + props.innerRef.current = node; + }, + label: props.label, + containerStyles: props.containerStyles, + errorText: props.errorText, + value: props.value, + isFormInput: props.isFormInput, + inputID: props.inputID, + shouldSaveDraft: props.shouldSaveDraft, + onBlur: props.onBlur, + autoComplete: 'off', + onChangeText: (text) => { + if (skippedFirstOnChangeTextRef.current) { + props.onChange({street: text}); + } else { + skippedFirstOnChangeTextRef.current = true; + } + + // If the text is empty, we set displayListViewBorder to false to prevent UI flickering + if (_.isEmpty(text)) { + setDisplayListViewBorder(false); + } + }, + }} + styles={{ + textInputContainer: [styles.flexColumn], + listView: [ + !displayListViewBorder && styles.googleListView, + displayListViewBorder && styles.borderTopRounded, + displayListViewBorder && styles.borderBottomRounded, + displayListViewBorder && styles.mt1, + styles.overflowAuto, + styles.borderLeft, + styles.borderRight, + ], + row: [ + styles.pv4, + styles.ph3, + styles.overflowAuto, + ], + description: [styles.googleSearchText], + separator: [styles.googleSearchSeparator], + }} + onLayout={(event) => { + // We use the height of the element to determine if we should hide the border of the listView dropdown + // to prevent a lingering border when there are no address suggestions. + // The height of the empty element is 2px (1px height for each top and bottom borders) + setDisplayListViewBorder(event.nativeEvent.layout.height > 2); + }} + /> + ); }; From eba7a98afd4f84b5887aad49c37702313939d03a Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Thu, 24 Mar 2022 02:20:36 +0530 Subject: [PATCH 047/361] fix: updated auto-slash logic to onChangeText --- .../settings/Payments/AddDebitCardPage.js | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index bfb8cc706094..ae12c84be1ef 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -191,26 +191,34 @@ class DebitCardPage extends Component { * @param {String} inputExpiryDate */ addOrRemoveSlashToExpiryDate(inputExpiryDate) { - let expiryDate = inputExpiryDate; + this.setState((prevState) => { + let expiryDate = inputExpiryDate; + const inputKey = 'expirationDate'; - // Backspace was hit/character removed - // Remove extra digit when there's a / involved - if (inputExpiryDate.length < this.state.expirationDate.length - && (((inputExpiryDate.length === 3 && lodashEndsWith(inputExpiryDate, '/')) - || (inputExpiryDate.length === 2 && lodashEndsWith(this.state.expirationDate, '/'))))) { - expiryDate = inputExpiryDate.substring(0, inputExpiryDate.length - 1); - } else if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { + // Backspace was hit/character removed + // Remove extra digit when there's a / involved + if (inputExpiryDate.length < prevState.expirationDate.length + && (((inputExpiryDate.length === 3 && lodashEndsWith(inputExpiryDate, '/')) + || (inputExpiryDate.length === 2 && lodashEndsWith(prevState.expirationDate, '/'))))) { + expiryDate = inputExpiryDate.substring(0, inputExpiryDate.length - 1); + } else if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date(MM)is added so append a slash(/) - expiryDate = `${inputExpiryDate}/`; - } else if (inputExpiryDate.length > 2 && _.indexOf(inputExpiryDate, '/') === -1) { + expiryDate = `${inputExpiryDate}/`; + } else if (inputExpiryDate.length > 2 && _.indexOf(inputExpiryDate, '/') === -1) { // Expiry Date with MM and YY without slash, hence adding slash(/) - expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; - } - this.clearErrorAndSetValue('expirationDate', expiryDate); + expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; + } + return { + [inputKey]: expiryDate, + errors: { + ...prevState.errors, + [inputKey]: false, + }, + }; + }); } render() { - console.log('Current State', this.state.expirationDate); return ( From a5b8a5b34bc9be2521a12a023ab9932a2a123cde Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Thu, 24 Mar 2022 17:00:10 +0530 Subject: [PATCH 048/361] fix: removed unwanted var --- src/pages/settings/Payments/AddDebitCardPage.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index ae12c84be1ef..e5afc6a28233 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -193,7 +193,6 @@ class DebitCardPage extends Component { addOrRemoveSlashToExpiryDate(inputExpiryDate) { this.setState((prevState) => { let expiryDate = inputExpiryDate; - const inputKey = 'expirationDate'; // Backspace was hit/character removed // Remove extra digit when there's a / involved @@ -209,10 +208,10 @@ class DebitCardPage extends Component { expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } return { - [inputKey]: expiryDate, + expirationDate: expiryDate, errors: { ...prevState.errors, - [inputKey]: false, + expirationDate: false, }, }; }); From 80bdec7fe0894ce5981ebba09211dbf7c22b1f9e Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Thu, 24 Mar 2022 17:14:07 +0530 Subject: [PATCH 049/361] fix: comment alignment fixed --- src/pages/settings/Payments/AddDebitCardPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Payments/AddDebitCardPage.js b/src/pages/settings/Payments/AddDebitCardPage.js index e5afc6a28233..b8cc05ecee84 100644 --- a/src/pages/settings/Payments/AddDebitCardPage.js +++ b/src/pages/settings/Payments/AddDebitCardPage.js @@ -201,10 +201,10 @@ class DebitCardPage extends Component { || (inputExpiryDate.length === 2 && lodashEndsWith(prevState.expirationDate, '/'))))) { expiryDate = inputExpiryDate.substring(0, inputExpiryDate.length - 1); } else if (inputExpiryDate.length === 2 && _.indexOf(inputExpiryDate, '/') === -1) { - // Expiry Date(MM)is added so append a slash(/) + // Expiry Date(MM)is added so append a slash(/) expiryDate = `${inputExpiryDate}/`; } else if (inputExpiryDate.length > 2 && _.indexOf(inputExpiryDate, '/') === -1) { - // Expiry Date with MM and YY without slash, hence adding slash(/) + // Expiry Date with MM and YY without slash, hence adding slash(/) expiryDate = `${inputExpiryDate.slice(0, 2)}/${inputExpiryDate.slice(2)}`; } return { From e00955ae4505c6652212501f92a17ad8226edd82 Mon Sep 17 00:00:00 2001 From: Justice Arthur Date: Tue, 29 Mar 2022 11:46:17 +0000 Subject: [PATCH 050/361] fix overflown subtitle on header --- src/components/Header.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Header.js b/src/components/Header.js index 6fdcf113597f..afbdf1fa778a 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -29,7 +29,7 @@ const Header = props => ( {/* If there's no subtitle then display a fragment to avoid an empty space which moves the main title */} {_.isString(props.subtitle) - ? Boolean(props.subtitle) && {props.subtitle} + ? Boolean(props.subtitle) && {props.subtitle} : props.subtitle} {props.shouldShowEnvironmentBadge && ( From b6610ba0210088581014e56f653e1a0c6c1a36f7 Mon Sep 17 00:00:00 2001 From: mateusbra Date: Tue, 29 Mar 2022 15:18:46 -0300 Subject: [PATCH 051/361] ignore periods on search --- src/libs/OptionsListUtils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 8c600a2cb4eb..381bd91464fd 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -175,6 +175,7 @@ function getSearchText(report, personalDetailList, isChatRoomOrPolicyExpenseChat _.each(personalDetailList, (personalDetail) => { searchTerms.push(personalDetail.displayName); searchTerms.push(personalDetail.login); + searchTerms.push(personalDetail.login.replace(/\./g, '')); }); } if (report) { @@ -333,6 +334,7 @@ function createOption(personalDetailList, report, { function isSearchStringMatch(searchValue, searchText, participantNames = new Set(), isChatRoom = false) { const searchWords = _.map( searchValue + .replace(/\./g, '') .replace(/,/g, ' ') .split(' '), word => word.trim(), From ed18c4952c10ea7c8b188bbd78cbb244fa2b9dd7 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Tue, 29 Mar 2022 21:22:24 +0300 Subject: [PATCH 052/361] Add logging to fullscreen loaders to investigate infinite loading screens --- src/components/FullscreenLoadingIndicator.js | 51 +++++++++++++++----- src/components/WalletStatementModal/index.js | 4 +- src/pages/NewChatPage.js | 2 +- src/pages/SearchPage.js | 2 +- src/pages/home/ReportScreen.js | 2 +- src/pages/iou/IOUModal.js | 4 +- src/pages/workspace/WorkspaceInvitePage.js | 2 +- 7 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/components/FullscreenLoadingIndicator.js b/src/components/FullscreenLoadingIndicator.js index 41a2ef2f8436..c1e9eeff9cfc 100644 --- a/src/components/FullscreenLoadingIndicator.js +++ b/src/components/FullscreenLoadingIndicator.js @@ -5,17 +5,22 @@ import {ActivityIndicator, StyleSheet, View} from 'react-native'; import styles from '../styles/styles'; import themeColors from '../styles/themes/default'; import stylePropTypes from '../styles/stylePropTypes'; +import Log from '../libs/Log'; const propTypes = { - /** Controls whether the loader is mounted and displayed */ - visible: PropTypes.bool, + /** Name used in the logs if the loader is displayed for too long time */ + name: PropTypes.string, + + /** Optional duration (ms) after which a message would be logged if the loader is still covering the screen */ + timeout: PropTypes.number, /** Additional style props */ style: stylePropTypes, }; const defaultProps = { - visible: true, + timeout: 0, + name: '', style: [], }; @@ -25,18 +30,38 @@ const defaultProps = { * @param {Object} props * @returns {JSX.Element} */ -const FullScreenLoadingIndicator = (props) => { - if (!props.visible) { - return null; +class FullScreenLoadingIndicator extends React.Component { + componentDidMount() { + if (!this.props.name || !this.props.timeout) { + return; + } + + Log.info(`[LoadingIndicator] "${this.props.name}" became visible`); + + this.timeoutId = setTimeout( + () => Log.alert(`[LoadingIndicator] "${this.props.name}" is still visible after ${this.props.timeout} ms`), + this.props.timeout, + ); } - const additionalStyles = _.isArray(props.style) ? props.style : [props.style]; - return ( - - - - ); -}; + componentWillUnmount() { + if (!this.timeoutId) { + return; + } + + clearTimeout(this.timeoutId); + Log.info(`[LoadingIndicator] "${this.props.name}" disappeared`); + } + + render() { + const additionalStyles = _.isArray(this.props.style) ? this.props.style : [this.props.style]; + return ( + + + + ); + } +} FullScreenLoadingIndicator.propTypes = propTypes; FullScreenLoadingIndicator.defaultProps = defaultProps; diff --git a/src/components/WalletStatementModal/index.js b/src/components/WalletStatementModal/index.js index 655ef2421e29..60d57fc5c14b 100644 --- a/src/components/WalletStatementModal/index.js +++ b/src/components/WalletStatementModal/index.js @@ -41,9 +41,7 @@ class WalletStatementModal extends React.Component { const authToken = lodashGet(this.props, 'session.authToken', null); return ( <> - + {this.state.isLoading && }