From 9fad803c6bb60e0706b35a789dafa5e0a1305321 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 8 May 2023 17:09:45 +0300 Subject: [PATCH 1/4] IOU - digit appears cutoff for a moment when entering a digit before decimal point --- src/components/TextInput/BaseTextInput.js | 19 ++++++++++++++++--- .../TextInput/baseTextInputPropTypes.js | 4 ++++ src/components/TextInput/index.js | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index 12211de67ba3..b7157e0d449e 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -39,6 +39,7 @@ class BaseTextInput extends Component { // Value should be kept in state for the autoGrow feature to work - https://github.com/Expensify/App/pull/8232#issuecomment-1077282006 value, + hiddenInputValue: value, }; this.input = null; @@ -72,13 +73,23 @@ class BaseTextInput extends Component { this.input.focus(); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps, prevState) { // Activate or deactivate the label when value is changed programmatically from outside const inputValue = _.isUndefined(this.props.value) ? this.input.value : this.props.value; if ((_.isUndefined(inputValue) || this.state.value === inputValue) && _.isEqual(prevProps.selection, this.props.selection)) { return; } + if (this.props.autoGrow) { + if (inputValue !== this.state.hiddenInputValue) { + this.setState({hiddenInputValue: inputValue, selection: this.props.selection}); + } + + if (prevState.textInputWidth === this.state.textInputWidth && this.props.shouldWaitWidthCalculation) { + return; + } + } + // eslint-disable-next-line react/no-did-update-set-state this.setState({value: inputValue, selection: this.props.selection}); @@ -148,7 +159,9 @@ class BaseTextInput extends Component { if (this.props.onInputChange) { this.props.onInputChange(value); } - this.setState({value}); + if (!this.props.autoGrow) { + this.setState({value}); + } Str.result(this.props.onChangeText, value); this.activateLabel(); } @@ -380,7 +393,7 @@ class BaseTextInput extends Component { style={[...this.props.inputStyle, this.props.autoGrowHeight ? {maxWidth: this.state.width} : {}, styles.hiddenElementOutsideOfWindow, styles.visibilityHidden]} onLayout={e => this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height})} > - {this.state.value || this.props.placeholder} + {this.props.autoGrowHeight ? this.state.value : this.state.hiddenInputValue || this.props.placeholder} )} diff --git a/src/components/TextInput/baseTextInputPropTypes.js b/src/components/TextInput/baseTextInputPropTypes.js index d7506322842a..ff23bc98c8c0 100644 --- a/src/components/TextInput/baseTextInputPropTypes.js +++ b/src/components/TextInput/baseTextInputPropTypes.js @@ -88,6 +88,9 @@ const propTypes = { /** Set the default value to the input if there is a valid saved value */ shouldUseDefaultValue: PropTypes.bool, + + /** Indicate whether input should wait until getting calculated width based on value */ + shouldWaitWidthCalculation: PropTypes.bool, }; const defaultProps = { @@ -124,6 +127,7 @@ const defaultProps = { icon: null, shouldUseDefaultValue: false, multiline: false, + shouldWaitWidthCalculation: false, }; export {propTypes, defaultProps}; diff --git a/src/components/TextInput/index.js b/src/components/TextInput/index.js index 4cbed48ce314..8f47c9f96b65 100644 --- a/src/components/TextInput/index.js +++ b/src/components/TextInput/index.js @@ -22,6 +22,7 @@ class TextInput extends React.Component { { this.textInput = el; if (!this.props.innerRef) { From 3c4a37a5a07edb2c44c0717c087d11219bf0239d Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 15 May 2023 13:19:08 +0300 Subject: [PATCH 2/4] Add expected behaviour for web browser --- src/components/TextInput/BaseTextInput.js | 10 ++++++---- src/components/TextInput/index.js | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index b7157e0d449e..f0f93d994215 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -80,12 +80,12 @@ class BaseTextInput extends Component { return; } - if (this.props.autoGrow) { + if (this.props.autoGrow && this.props.shouldWaitWidthCalculation) { if (inputValue !== this.state.hiddenInputValue) { this.setState({hiddenInputValue: inputValue, selection: this.props.selection}); } - if (prevState.textInputWidth === this.state.textInputWidth && this.props.shouldWaitWidthCalculation) { + if (prevState.textInputWidth === this.state.textInputWidth) { return; } } @@ -159,7 +159,7 @@ class BaseTextInput extends Component { if (this.props.onInputChange) { this.props.onInputChange(value); } - if (!this.props.autoGrow) { + if (!this.props.autoGrow || !this.props.shouldWaitWidthCalculation) { this.setState({value}); } Str.result(this.props.onChangeText, value); @@ -234,6 +234,8 @@ class BaseTextInput extends Component { ], (finalStyles, s) => ({...finalStyles, ...s}), {}); const maxHeight = StyleSheet.flatten(this.props.containerStyles).maxHeight; const isMultiline = this.props.multiline || this.props.autoGrowHeight; + const defaultInputValue = this.state.value || this.props.placeholder; + const defaultHiddenInputValue = this.state.hiddenInputValue || this.props.placeholder; return ( <> @@ -393,7 +395,7 @@ class BaseTextInput extends Component { style={[...this.props.inputStyle, this.props.autoGrowHeight ? {maxWidth: this.state.width} : {}, styles.hiddenElementOutsideOfWindow, styles.visibilityHidden]} onLayout={e => this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height})} > - {this.props.autoGrowHeight ? this.state.value : this.state.hiddenInputValue || this.props.placeholder} + {this.props.autoGrowHeight || !this.props.shouldWaitWidthCalculation ? defaultInputValue : defaultHiddenInputValue} )} diff --git a/src/components/TextInput/index.js b/src/components/TextInput/index.js index 8f47c9f96b65..b486d8ef6334 100644 --- a/src/components/TextInput/index.js +++ b/src/components/TextInput/index.js @@ -3,6 +3,7 @@ import _ from 'underscore'; import styles from '../../styles/styles'; import BaseTextInput from './BaseTextInput'; import * as baseTextInputPropTypes from './baseTextInputPropTypes'; +import * as BrowserUtils from '../../libs/Browser'; class TextInput extends React.Component { componentDidMount() { @@ -22,7 +23,7 @@ class TextInput extends React.Component { { this.textInput = el; if (!this.props.innerRef) { From f40d1680178ebaa9e7a3394cc6800bd2b6411b5a Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 25 May 2023 11:44:12 +0300 Subject: [PATCH 3/4] Naming and earlier set input value --- src/components/TextInput/BaseTextInput.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index 752b8b7fa943..e8093801420e 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -235,8 +235,8 @@ class BaseTextInput extends Component { {}, ); const isMultiline = this.props.multiline || this.props.autoGrowHeight; - const defaultInputValue = this.state.value || this.props.placeholder; - const defaultHiddenInputValue = this.state.hiddenInputValue || this.props.placeholder; + const inputValue = this.state.value || this.props.placeholder; + const hiddenInputValue = this.state.hiddenInputValue || this.props.placeholder; return ( <> @@ -401,9 +401,12 @@ class BaseTextInput extends Component { styles.hiddenElementOutsideOfWindow, styles.visibilityHidden, ]} - onLayout={(e) => this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height})} + onLayout={(e) => this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height}, () => { + if (!this.props.shouldWaitWidthCalculation) return; + this.setState((prevState) => ({value: prevState.hiddenInputValue, selection: this.props.selection})) + })} > - {this.props.autoGrowHeight || !this.props.shouldWaitWidthCalculation ? defaultInputValue : defaultHiddenInputValue} + {this.props.autoGrowHeight || !this.props.shouldWaitWidthCalculation ? inputValue : hiddenInputValue} )} From 710d9dabc169a918a8b42788bda3cd51fb570782 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 25 May 2023 11:55:40 +0300 Subject: [PATCH 4/4] prettier fix --- src/components/TextInput/BaseTextInput.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index e8093801420e..c17d8b173d11 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -401,10 +401,12 @@ class BaseTextInput extends Component { styles.hiddenElementOutsideOfWindow, styles.visibilityHidden, ]} - onLayout={(e) => this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height}, () => { - if (!this.props.shouldWaitWidthCalculation) return; - this.setState((prevState) => ({value: prevState.hiddenInputValue, selection: this.props.selection})) - })} + onLayout={(e) => + this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height}, () => { + if (!this.props.shouldWaitWidthCalculation) return; + this.setState((prevState) => ({value: prevState.hiddenInputValue, selection: this.props.selection})); + }) + } > {this.props.autoGrowHeight || !this.props.shouldWaitWidthCalculation ? inputValue : hiddenInputValue}