From d577410e047757568cc4691fa4cfc7dc66bd9521 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Thu, 10 Sep 2020 15:43:20 -0700 Subject: [PATCH 01/12] test code --- src/components/TextInputFocusable/index.js | 4 ---- src/page/home/report/ReportActionCompose.js | 10 +++++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index b60fa72a4d404..72839d0a1b7b2 100644 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -76,10 +76,6 @@ class TextInputFocusable extends React.Component { focusInput() { this.textInput.focus(); - if (this.props.value) { - this.textInput.selectionStart = this.props.value.length; - this.textInput.selectionEnd = this.props.value.length; - } } render() { diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index a92e454e80794..29355f7bb1b9f 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -35,6 +35,10 @@ class ReportActionCompose extends React.Component { this.submitForm = this.submitForm.bind(this); this.triggerSubmitShortcut = this.triggerSubmitShortcut.bind(this); this.submitForm = this.submitForm.bind(this); + + this.state = { + comment: this.props.comment || '' + }; } /** @@ -43,6 +47,8 @@ class ReportActionCompose extends React.Component { * @param {string} newComment */ updateComment(newComment) { + this.moveCursorToEnd = false; + this.setState({comment: newComment}); saveReportComment(this.props.reportID, newComment || ''); } @@ -83,6 +89,8 @@ class ReportActionCompose extends React.Component { render() { const href = `${CONFIG.PUSHER.AUTH_URL}/report?reportID=${this.props.reportID}&shouldScrollToLastUnread=true`; + const check = this.state.comment; + const comment = this.props.comment; return ( @@ -105,7 +113,7 @@ class ReportActionCompose extends React.Component { onChangeText={this.updateComment} onKeyPress={this.triggerSubmitShortcut} style={[styles.textInput, styles.textInputCompose, styles.flex4]} - value={this.props.comment || ''} + value={comment} maxLines={16} // This is the same that slack has /> Date: Thu, 10 Sep 2020 16:27:28 -0700 Subject: [PATCH 02/12] Updates to fix cursor --- src/components/TextInputFocusable/index.js | 11 ++++++++--- src/page/home/report/ReportActionCompose.js | 13 +++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index 72839d0a1b7b2..88780cb6ed192 100644 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -6,8 +6,8 @@ const propTypes = { // Maximum number of lines in the text input maxLines: PropTypes.number, - // The value of the comment box - value: PropTypes.string.isRequired, + // The default value of the comment box + defaultValue: PropTypes.string.isRequired, }; const defaultProps = { @@ -33,8 +33,13 @@ class TextInputFocusable extends React.Component { componentDidUpdate(prevProps) { this.focusInput(); - if (prevProps.value !== this.props.value) { + if (prevProps.defaultValue !== this.props.defaultValue) { this.updateNumberOfLines(); + + if (this.props.defaultValue) { + this.textInput.selectionStart = this.props.defaultValue.length; + this.textInput.selectionEnd = this.props.defaultValue.length; + } } } diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index 29355f7bb1b9f..a0ab79a0547f3 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import _ from 'underscore'; import {View, Image, TouchableOpacity} from 'react-native'; import styles, {colors} from '../../../style/StyleSheet'; import TextInputFocusable from '../../../components/TextInputFocusable'; @@ -35,10 +36,6 @@ class ReportActionCompose extends React.Component { this.submitForm = this.submitForm.bind(this); this.triggerSubmitShortcut = this.triggerSubmitShortcut.bind(this); this.submitForm = this.submitForm.bind(this); - - this.state = { - comment: this.props.comment || '' - }; } /** @@ -47,8 +44,6 @@ class ReportActionCompose extends React.Component { * @param {string} newComment */ updateComment(newComment) { - this.moveCursorToEnd = false; - this.setState({comment: newComment}); saveReportComment(this.props.reportID, newComment || ''); } @@ -89,8 +84,6 @@ class ReportActionCompose extends React.Component { render() { const href = `${CONFIG.PUSHER.AUTH_URL}/report?reportID=${this.props.reportID}&shouldScrollToLastUnread=true`; - const check = this.state.comment; - const comment = this.props.comment; return ( @@ -110,10 +103,10 @@ class ReportActionCompose extends React.Component { textAlignVertical="top" placeholder="Write something..." placeholderTextColor={colors.textSupporting} - onChangeText={this.updateComment} + onChangeText={_.debounce(this.updateComment, 1000)} onKeyPress={this.triggerSubmitShortcut} style={[styles.textInput, styles.textInputCompose, styles.flex4]} - value={comment} + defaultValue={this.props.comment || ''} maxLines={16} // This is the same that slack has /> Date: Thu, 10 Sep 2020 16:52:27 -0700 Subject: [PATCH 03/12] Fixes --- src/components/TextInputFocusable/index.js | 12 +++++++----- src/page/home/report/ReportActionCompose.js | 8 +++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index 88780cb6ed192..58997b7ff07c7 100644 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -35,11 +35,6 @@ class TextInputFocusable extends React.Component { if (prevProps.defaultValue !== this.props.defaultValue) { this.updateNumberOfLines(); - - if (this.props.defaultValue) { - this.textInput.selectionStart = this.props.defaultValue.length; - this.textInput.selectionEnd = this.props.defaultValue.length; - } } } @@ -83,6 +78,13 @@ class TextInputFocusable extends React.Component { this.textInput.focus(); } + /** + * Clears the input + */ + clear() { + this.textInput.clear(); + } + render() { return ( this.textInput = el} placeholderTextColor={colors.textSupporting} - onChangeText={_.debounce(this.updateComment, 1000)} + onChangeText={this.updateComment} onKeyPress={this.triggerSubmitShortcut} style={[styles.textInput, styles.textInputCompose, styles.flex4]} defaultValue={this.props.comment || ''} From bbc4822e3edefb5b9507ecf5daef49efa8a99c62 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Thu, 10 Sep 2020 17:34:36 -0700 Subject: [PATCH 04/12] removing unneeded import --- src/page/home/report/ReportActionCompose.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index 6b879333130bf..7968c71a609c0 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import _ from 'underscore'; import {View, Image, TouchableOpacity} from 'react-native'; import styles, {colors} from '../../../style/StyleSheet'; import TextInputFocusable from '../../../components/TextInputFocusable'; From 5063dabc02da7e9238b1df735d48857a0b918b67 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 11:51:46 -0700 Subject: [PATCH 05/12] trying out forward ref --- src/components/TextInputFocusable/index.js | 15 +++++++-------- src/page/home/report/ReportActionCompose.js | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index 58997b7ff07c7..808548b442ec6 100644 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -3,6 +3,9 @@ import {TextInput} from 'react-native'; import PropTypes from 'prop-types'; const propTypes = { + // A ref to forward to the text input + forwardedRef: PropTypes.func.isRequired, + // Maximum number of lines in the text input maxLines: PropTypes.number, @@ -78,13 +81,6 @@ class TextInputFocusable extends React.Component { this.textInput.focus(); } - /** - * Clears the input - */ - clear() { - this.textInput.clear(); - } - render() { return ( ( + /* eslint-disable-next-line react/jsx-props-no-spreading */ + +)); diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index 7968c71a609c0..e7ff2977bdde6 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import {View, Image, TouchableOpacity} from 'react-native'; +import _ from 'underscore'; import styles, {colors} from '../../../style/StyleSheet'; import TextInputFocusable from '../../../components/TextInputFocusable'; import sendIcon from '../../../../assets/images/icon-send.png'; From 84740e3d2338e6e3904754c699d800d1fb6321ec Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 12:29:40 -0700 Subject: [PATCH 06/12] forwardRef and debounce --- src/components/TextInputFocusable/index.js | 9 +++++++++ src/page/home/report/ReportActionCompose.js | 10 ++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js index 808548b442ec6..4d6b53df4d9c3 100644 --- a/src/components/TextInputFocusable/index.js +++ b/src/components/TextInputFocusable/index.js @@ -1,6 +1,7 @@ import React from 'react'; import {TextInput} from 'react-native'; import PropTypes from 'prop-types'; +import _ from 'underscore'; const propTypes = { // A ref to forward to the text input @@ -31,6 +32,14 @@ class TextInputFocusable extends React.Component { componentDidMount() { this.focusInput(); + + // This callback prop is used by the parent component using the constructor to + // get a ref to the inner textInput element e.g. if we do + // this.textInput = el} /> this will not + // return a ref to the component, but rather the HTML element by default + if (this.props.forwardedRef && _.isFunction(this.props.forwardedRef)) { + this.props.forwardedRef(this.textInput); + } } componentDidUpdate(prevProps) { diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index e7ff2977bdde6..5237122bf0c2d 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -32,7 +32,7 @@ class ReportActionCompose extends React.Component { constructor(props) { super(props); - this.updateComment = this.updateComment.bind(this); + this.updateComment = _.debounce(this.updateComment.bind(this), 1000, false); this.submitForm = this.submitForm.bind(this); this.triggerSubmitShortcut = this.triggerSubmitShortcut.bind(this); this.submitForm = this.submitForm.bind(this); @@ -70,11 +70,9 @@ class ReportActionCompose extends React.Component { e.preventDefault(); } - if (!this.props.comment) { - return; - } - - const trimmedComment = this.props.comment.trim(); + // Let's get the data directly from textInput because saving the data in Ion report comment is asynchronous + // so if we refer this.props.comment here we won't get the most recent value if the user types fast. + const trimmedComment = this.textInput.value.trim(); // Don't submit empty comments // @TODO show an error in the UI From f9e85e61156d2d54b5bee2fbfbbc3423446c34a2 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 14:53:31 -0700 Subject: [PATCH 07/12] converting index native to class component --- .../TextInputFocusable/index.native.js | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/components/TextInputFocusable/index.native.js b/src/components/TextInputFocusable/index.native.js index c609e023b5e61..149118fad7423 100644 --- a/src/components/TextInputFocusable/index.native.js +++ b/src/components/TextInputFocusable/index.native.js @@ -1,13 +1,50 @@ import React from 'react'; import {TextInput} from 'react-native'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; + +const propTypes = { + // A ref to forward to the text input + forwardedRef: PropTypes.func.isRequired, +}; /** * On native layers we like to have the Text Input not focused so the user can read new chats without they keyboard in * the way of the view */ -// eslint-disable-next-line react/jsx-props-no-spreading -const TextInputFocusable = props => (); +class TextInputFocusable extends React.Component { + componentDidMount() { + // This callback prop is used by the parent component using the constructor to + // get a ref to the inner textInput element e.g. if we do + // this.textInput = el} /> this will not + // return a ref to the component, but rather the HTML element by default + if (this.props.forwardedRef && _.isFunction(this.props.forwardedRef)) { + this.props.forwardedRef(this.textInput); + } + } + + render() { + console.debug('test1'); + if (this.textInput) { + console.debug(`test2 ${this.textInput.value}`); + } + + return ( + this.textInput = el} + maxHeight={116} + /* eslint-disable-next-line react/jsx-props-no-spreading */ + {...this.props} + /> + ); + } +} TextInputFocusable.displayName = 'TextInputFocusable'; +TextInputFocusable.propTypes = propTypes; -export default TextInputFocusable; +// export default TextInputFocusable; +export default React.forwardRef((props, ref) => ( + /* eslint-disable-next-line react/jsx-props-no-spreading */ + +)); From 1929b64c00df0dbf10108afd2d0c90e9098a492f Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 15:55:01 -0700 Subject: [PATCH 08/12] Using a local comment variable since getting value directly from textInput doesn't work well --- src/page/home/report/ReportActionCompose.js | 25 ++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index 5237122bf0c2d..df3beb3c42828 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -32,10 +32,28 @@ class ReportActionCompose extends React.Component { constructor(props) { super(props); - this.updateComment = _.debounce(this.updateComment.bind(this), 1000, false); + this.updateComment = this.updateComment.bind(this); + this.debouncedSaveReportComment = _.debounce(this.debouncedSaveReportComment.bind(this), 1000, false); this.submitForm = this.submitForm.bind(this); this.triggerSubmitShortcut = this.triggerSubmitShortcut.bind(this); this.submitForm = this.submitForm.bind(this); + this.comment = ''; + } + + componentDidUpdate(prevProps) { + if (this.props.comment && prevProps.comment === '' && prevProps.comment !== this.props.comment) { + this.comment = this.props.comment; + } + } + + /** + * Save our report comment in Ion. We debounce this method in the constructor so that it's not called too often + * to update Ion and re-render this component. + * + * @param {string} comment + */ + debouncedSaveReportComment(comment) { + saveReportComment(this.props.reportID, comment || ''); } /** @@ -44,7 +62,8 @@ class ReportActionCompose extends React.Component { * @param {string} newComment */ updateComment(newComment) { - saveReportComment(this.props.reportID, newComment || ''); + this.comment = newComment; + this.debouncedSaveReportComment(newComment); } /** @@ -72,7 +91,7 @@ class ReportActionCompose extends React.Component { // Let's get the data directly from textInput because saving the data in Ion report comment is asynchronous // so if we refer this.props.comment here we won't get the most recent value if the user types fast. - const trimmedComment = this.textInput.value.trim(); + const trimmedComment = this.comment.trim(); // Don't submit empty comments // @TODO show an error in the UI From 319f640d70b2f25d90ff437c74cc9ed111e04337 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 15:56:15 -0700 Subject: [PATCH 09/12] remove debugs --- src/components/TextInputFocusable/index.native.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/TextInputFocusable/index.native.js b/src/components/TextInputFocusable/index.native.js index 149118fad7423..338445874c732 100644 --- a/src/components/TextInputFocusable/index.native.js +++ b/src/components/TextInputFocusable/index.native.js @@ -24,11 +24,6 @@ class TextInputFocusable extends React.Component { } render() { - console.debug('test1'); - if (this.textInput) { - console.debug(`test2 ${this.textInput.value}`); - } - return ( this.textInput = el} From 7d07a2baae7669646205a38da9a7ccf5d004b66e Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 15:58:25 -0700 Subject: [PATCH 10/12] remove incorrect comment --- src/page/home/report/ReportActionCompose.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index df3beb3c42828..d625907a06c43 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -89,8 +89,6 @@ class ReportActionCompose extends React.Component { e.preventDefault(); } - // Let's get the data directly from textInput because saving the data in Ion report comment is asynchronous - // so if we refer this.props.comment here we won't get the most recent value if the user types fast. const trimmedComment = this.comment.trim(); // Don't submit empty comments From aa8a233fabf7ab92f40bd7d6e162de5406cc0e00 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 16:00:51 -0700 Subject: [PATCH 11/12] Adding comment --- src/page/home/report/ReportActionCompose.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index d625907a06c43..b655921aa30ef 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -41,6 +41,8 @@ class ReportActionCompose extends React.Component { } componentDidUpdate(prevProps) { + // The first time the component loads the props is emptry and the next time it may contain value. + // If it does let's update this.comment so that it matches the defaultValue that we show in textInput. if (this.props.comment && prevProps.comment === '' && prevProps.comment !== this.props.comment) { this.comment = this.props.comment; } From ed8551f16a195c82dda7f518394037c637ac55c6 Mon Sep 17 00:00:00 2001 From: chiragsalian Date: Fri, 11 Sep 2020 17:18:40 -0700 Subject: [PATCH 12/12] comment correction --- src/page/home/report/ReportActionCompose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page/home/report/ReportActionCompose.js b/src/page/home/report/ReportActionCompose.js index b655921aa30ef..934c6a6a90e56 100644 --- a/src/page/home/report/ReportActionCompose.js +++ b/src/page/home/report/ReportActionCompose.js @@ -41,7 +41,7 @@ class ReportActionCompose extends React.Component { } componentDidUpdate(prevProps) { - // The first time the component loads the props is emptry and the next time it may contain value. + // The first time the component loads the props is empty and the next time it may contain value. // If it does let's update this.comment so that it matches the defaultValue that we show in textInput. if (this.props.comment && prevProps.comment === '' && prevProps.comment !== this.props.comment) { this.comment = this.props.comment;