From d1a7800bbbb426313d4bf791eea6f4779e6f4c6a Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 2 Oct 2023 19:37:16 +0200 Subject: [PATCH 01/17] Fix stuff --- src/components/MagicCodeInput.js | 14 +++++++++++--- .../Profile/Contacts/ContactMethodDetailsPage.js | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 1db1acddc5d7..4669ff9efef7 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -102,6 +102,11 @@ function MagicCodeInput(props) { const shouldFocusLast = useRef(false); const inputWidth = useRef(0); const lastFocusedIndex = useRef(0); + const lastValue = useRef(TEXT_INPUT_EMPTY_STATE); + + useEffect(() => { + lastValue.current = input.length; + }, [input]) const blurMagicCodeInput = () => { inputRefs.current.blur(); @@ -166,6 +171,7 @@ function MagicCodeInput(props) { */ const onFocus = (event) => { if (shouldFocusLast.current) { + lastValue.current = TEXT_INPUT_EMPTY_STATE; setInput(TEXT_INPUT_EMPTY_STATE); setFocusedIndex(lastFocusedIndex.current); setEditIndex(lastFocusedIndex.current); @@ -206,9 +212,11 @@ function MagicCodeInput(props) { return; } + const addedValue = value.slice(lastValue.current.length, value.length) || value + lastValue.current = value; // Updates the focused input taking into consideration the last input // edited and the number of digits added by the user. - const numbersArr = value + const numbersArr = addedValue .trim() .split('') .slice(0, props.maxLength - editIndex); @@ -319,10 +327,10 @@ function MagicCodeInput(props) { maxLength={props.maxLength} value={input} hideFocusedState - autoComplete={props.autoComplete} + autoComplete={input.length === 0 && props.autoComplete} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} onChangeText={(value) => { - onChangeText(value); + onChangeText(value) }} onKeyPress={onKeyPress} onFocus={onFocus} diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index b8c817350a38..ca890b8366be 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -245,6 +245,7 @@ class ContactMethodDetailsPage extends Component { title={this.props.translate('contacts.removeContactMethod')} onConfirm={this.confirmDeleteAndHideModal} onCancel={() => this.toggleDeleteModal(false)} + onModalHide={() => this.validateCodeFormRef.current.focus()} prompt={this.props.translate('contacts.removeAreYouSure')} confirmText={this.props.translate('common.yesContinue')} cancelText={this.props.translate('common.cancel')} From d50aae2196ef911cb716aeea8bb0d0c1fe82247d Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Tue, 3 Oct 2023 13:22:30 +0200 Subject: [PATCH 02/17] Prettier --- src/components/MagicCodeInput.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 4669ff9efef7..7ebfd6356eb1 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -106,7 +106,7 @@ function MagicCodeInput(props) { useEffect(() => { lastValue.current = input.length; - }, [input]) + }, [input]); const blurMagicCodeInput = () => { inputRefs.current.blur(); @@ -212,7 +212,7 @@ function MagicCodeInput(props) { return; } - const addedValue = value.slice(lastValue.current.length, value.length) || value + const addedValue = value.slice(lastValue.current.length, value.length) || value; lastValue.current = value; // Updates the focused input taking into consideration the last input // edited and the number of digits added by the user. @@ -330,7 +330,7 @@ function MagicCodeInput(props) { autoComplete={input.length === 0 && props.autoComplete} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} onChangeText={(value) => { - onChangeText(value) + onChangeText(value); }} onKeyPress={onKeyPress} onFocus={onFocus} From 261887082db7e695a8efc1b4388d6bc3d3374bbb Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Fri, 27 Oct 2023 18:32:41 +0200 Subject: [PATCH 03/17] Refocus input in basevalidatecodeform and remove wasSubmitted flag --- src/components/MagicCodeInput.js | 9 ++++----- .../Profile/Contacts/ContactMethodDetailsPage.js | 6 +++++- .../Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 6 ++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 2141b22f008a..38f5f338bc91 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -107,7 +107,6 @@ function MagicCodeInput(props) { const [input, setInput] = useState(TEXT_INPUT_EMPTY_STATE); const [focusedIndex, setFocusedIndex] = useState(0); const [editIndex, setEditIndex] = useState(0); - const [wasSubmitted, setWasSubmitted] = useState(false); const shouldFocusLast = useRef(false); const inputWidth = useRef(0); const lastFocusedIndex = useRef(0); @@ -133,6 +132,9 @@ function MagicCodeInput(props) { focus() { focusMagicCodeInput(); }, + focusLastSelected() { + inputRefs.current.focus(); + }, resetFocus() { setInput(TEXT_INPUT_EMPTY_STATE); focusMagicCodeInput(); @@ -152,12 +154,9 @@ function MagicCodeInput(props) { const validateAndSubmit = () => { const numbers = decomposeString(props.value, props.maxLength); - if (wasSubmitted || !props.shouldSubmitOnComplete || _.filter(numbers, (n) => ValidationUtils.isNumeric(n)).length !== props.maxLength || props.network.isOffline) { + if (!props.shouldSubmitOnComplete || _.filter(numbers, (n) => ValidationUtils.isNumeric(n)).length !== props.maxLength || props.network.isOffline) { return; } - if (!wasSubmitted) { - setWasSubmitted(true); - } // Blurs the input and removes focus from the last input and, if it should submit // on complete, it will call the onFulfill callback. blurMagicCodeInput(); diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 3d430d0c59b7..9cd83e425823 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -262,7 +262,11 @@ class ContactMethodDetailsPage extends Component { title={this.props.translate('contacts.removeContactMethod')} onConfirm={this.confirmDeleteAndHideModal} onCancel={() => this.toggleDeleteModal(false)} - onModalHide={() => this.validateCodeFormRef.current.focus()} + onModalHide={() => { + _.delay(() => { + this.validateCodeFormRef.current.focusLastSelected() + }, 200) + }} prompt={this.props.translate('contacts.removeAreYouSure')} confirmText={this.props.translate('common.yesContinue')} cancelText={this.props.translate('common.cancel')} diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index 73231cd315ad..4cc904f20074 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -87,6 +87,12 @@ function BaseValidateCodeForm(props) { } inputValidateCodeRef.current.focus(); }, + focusLastSelected() { + if (!inputValidateCodeRef.current) { + return; + } + inputValidateCodeRef.current.focusLastSelected(); + } })); useFocusEffect( From 4d8bc1e92246b11a1ae02cd5523a9175c75f8c67 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Fri, 27 Oct 2023 20:13:51 +0200 Subject: [PATCH 04/17] Use InteractionManager instead of delay --- .../settings/Profile/Contacts/ContactMethodDetailsPage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 9cd83e425823..1b0464ca8df4 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -2,7 +2,7 @@ import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import _ from 'underscore'; import React, {Component} from 'react'; -import {View, ScrollView, Keyboard} from 'react-native'; +import {View, ScrollView, Keyboard, InteractionManager} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import Navigation from '../../../../libs/Navigation/Navigation'; @@ -263,9 +263,9 @@ class ContactMethodDetailsPage extends Component { onConfirm={this.confirmDeleteAndHideModal} onCancel={() => this.toggleDeleteModal(false)} onModalHide={() => { - _.delay(() => { + InteractionManager.runAfterInteractions(() => { this.validateCodeFormRef.current.focusLastSelected() - }, 200) + }) }} prompt={this.props.translate('contacts.removeAreYouSure')} confirmText={this.props.translate('common.yesContinue')} From c2987ca968cb60add69b840b4f0f3256348b1024 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Fri, 27 Oct 2023 20:39:46 +0200 Subject: [PATCH 05/17] Prettier --- .../settings/Profile/Contacts/ContactMethodDetailsPage.js | 4 ++-- .../Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 1b0464ca8df4..044233a95b6a 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -264,8 +264,8 @@ class ContactMethodDetailsPage extends Component { onCancel={() => this.toggleDeleteModal(false)} onModalHide={() => { InteractionManager.runAfterInteractions(() => { - this.validateCodeFormRef.current.focusLastSelected() - }) + this.validateCodeFormRef.current.focusLastSelected(); + }); }} prompt={this.props.translate('contacts.removeAreYouSure')} confirmText={this.props.translate('common.yesContinue')} diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index 4cc904f20074..3c67631c6b0a 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -91,8 +91,8 @@ function BaseValidateCodeForm(props) { if (!inputValidateCodeRef.current) { return; } - inputValidateCodeRef.current.focusLastSelected(); - } + inputValidateCodeRef.current.focusLastSelected(); + }, })); useFocusEffect( From 008400e318a9a41dd15fa3700f4528daf4ffa52c Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 30 Oct 2023 13:03:10 +0100 Subject: [PATCH 06/17] Use @ imports --- src/components/MagicCodeInput.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 325bf8a4e539..afc59a9ffc65 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -3,16 +3,16 @@ import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} fro import {StyleSheet, View} from 'react-native'; import _ from 'underscore'; import {TapGestureHandler} from 'react-native-gesture-handler'; -import styles from '../styles/styles'; -import * as StyleUtils from '../styles/StyleUtils'; -import * as ValidationUtils from '../libs/ValidationUtils'; -import CONST from '../CONST'; +import useNetwork from '@hooks/useNetwork'; +import styles from '@styles/styles'; +import * as StyleUtils from '@styles/StyleUtils'; +import * as ValidationUtils from '@libs/ValidationUtils'; +import CONST from '@src/CONST'; import Text from './Text'; import TextInput from './TextInput'; import FormHelpMessage from './FormHelpMessage'; import {withNetwork} from './OnyxProvider'; import networkPropTypes from './networkPropTypes'; -import useNetwork from '../hooks/useNetwork'; import * as Browser from '../libs/Browser'; const TEXT_INPUT_EMPTY_STATE = ''; From 3ad8872412f56275561f991c0b84ca968c0af11c Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 30 Oct 2023 14:06:56 +0100 Subject: [PATCH 07/17] Improve import --- src/components/MagicCodeInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index afc59a9ffc65..cb798553c724 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -8,12 +8,12 @@ import styles from '@styles/styles'; import * as StyleUtils from '@styles/StyleUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; +import * as Browser from '@libs/Browser'; import Text from './Text'; import TextInput from './TextInput'; import FormHelpMessage from './FormHelpMessage'; import {withNetwork} from './OnyxProvider'; import networkPropTypes from './networkPropTypes'; -import * as Browser from '../libs/Browser'; const TEXT_INPUT_EMPTY_STATE = ''; From b757c0c7d1f2cbe4cbb82b3aa16f5bdbcfa1fd56 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 30 Oct 2023 14:18:57 +0100 Subject: [PATCH 08/17] Prettier --- src/components/MagicCodeInput.js | 12 ++++++------ .../Profile/Contacts/ContactMethodDetailsPage.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index cb798553c724..88fc1c34c4ec 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -1,19 +1,19 @@ import PropTypes from 'prop-types'; import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; import {StyleSheet, View} from 'react-native'; -import _ from 'underscore'; import {TapGestureHandler} from 'react-native-gesture-handler'; +import _ from 'underscore'; import useNetwork from '@hooks/useNetwork'; +import * as Browser from '@libs/Browser'; +import * as ValidationUtils from '@libs/ValidationUtils'; import styles from '@styles/styles'; import * as StyleUtils from '@styles/StyleUtils'; -import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; -import * as Browser from '@libs/Browser'; -import Text from './Text'; -import TextInput from './TextInput'; import FormHelpMessage from './FormHelpMessage'; -import {withNetwork} from './OnyxProvider'; import networkPropTypes from './networkPropTypes'; +import {withNetwork} from './OnyxProvider'; +import Text from './Text'; +import TextInput from './TextInput'; const TEXT_INPUT_EMPTY_STATE = ''; diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 8f31e32422d3..121527f605cf 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -2,7 +2,7 @@ import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; -import {View, ScrollView, Keyboard, InteractionManager} from 'react-native'; +import {InteractionManager, Keyboard, ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; From d1285a00642dc7a92ccc41a1e091f9b123ec33c8 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 13 Nov 2023 13:32:22 +0100 Subject: [PATCH 09/17] Use role instead of accessibilityRole --- src/components/MagicCodeInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 2b3b8827c0ec..ed6e4ded49c6 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -389,7 +389,7 @@ function MagicCodeInput(props) { }} selectionColor="transparent" inputStyle={[styles.inputTransparent]} - accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} + role={CONST.ACCESSIBILITY_ROLE.TEXT} style={[styles.inputTransparent]} textInputContainerStyles={[styles.borderNone]} /> From cc2f79770af723d9a0b68ce1da816673e65a738d Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 13 Nov 2023 13:48:40 +0100 Subject: [PATCH 10/17] Resurrect wasSubmitted flag --- src/components/MagicCodeInput.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index ed6e4ded49c6..1d8f2786f86c 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -111,6 +111,7 @@ function MagicCodeInput(props) { const [input, setInput] = useState(TEXT_INPUT_EMPTY_STATE); const [focusedIndex, setFocusedIndex] = useState(0); const [editIndex, setEditIndex] = useState(0); + const [wasSubmitted, setWasSubmitted] = useState(false); const shouldFocusLast = useRef(false); const inputWidth = useRef(0); const lastFocusedIndex = useRef(0); @@ -158,9 +159,12 @@ function MagicCodeInput(props) { const validateAndSubmit = () => { const numbers = decomposeString(props.value, props.maxLength); - if (!props.shouldSubmitOnComplete || _.filter(numbers, (n) => ValidationUtils.isNumeric(n)).length !== props.maxLength || props.network.isOffline) { + if (wasSubmitted || !props.shouldSubmitOnComplete || _.filter(numbers, (n) => ValidationUtils.isNumeric(n)).length !== props.maxLength || props.network.isOffline) { return; } + if (!wasSubmitted) { + setWasSubmitted(true); + } // Blurs the input and removes focus from the last input and, if it should submit // on complete, it will call the onFulfill callback. blurMagicCodeInput(); From 527b9e0e7b69ee91b7ff12b4f5919b5556ac8977 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Mon, 13 Nov 2023 16:47:00 +0100 Subject: [PATCH 11/17] Add additional checks for code input paste and fast typing --- src/components/MagicCodeInput.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 1d8f2786f86c..c9b9104e0e3a 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -169,6 +169,7 @@ function MagicCodeInput(props) { // on complete, it will call the onFulfill callback. blurMagicCodeInput(); props.onFulfill(props.value); + lastValue.current = ''; }; useNetwork({onReconnect: validateAndSubmit}); @@ -231,7 +232,8 @@ function MagicCodeInput(props) { return; } - const addedValue = value.slice(lastValue.current.length, value.length) || value; + const addedValue = + value.length - 1 === lastValue.current.length && value.slice(0, value.length - 1) === lastValue.current ? value.slice(lastValue.current.length, value.length) : value; lastValue.current = value; // Updates the focused input taking into consideration the last input // edited and the number of digits added by the user. From f1628fcd3dcee54437de53055c68ab32151d1736 Mon Sep 17 00:00:00 2001 From: Wojciech Stanisz Date: Tue, 14 Nov 2023 13:13:44 +0100 Subject: [PATCH 12/17] Fix lint --- src/components/MagicCodeInput.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index c9b9104e0e3a..a63d3f745d3c 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -30,9 +30,6 @@ const propTypes = { /** Should the input auto focus */ autoFocus: PropTypes.bool, - /** Whether we should wait before focusing the TextInput, useful when using transitions */ - shouldDelayFocus: PropTypes.bool, - /** Error text to display */ errorText: PropTypes.string, @@ -67,7 +64,6 @@ const defaultProps = { value: '', name: '', autoFocus: true, - shouldDelayFocus: false, errorText: '', shouldSubmitOnComplete: true, innerRef: null, From 9bd3d591cba9ff41f7c886f2a7a0c7d865416036 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 14 Nov 2023 16:42:52 +0100 Subject: [PATCH 13/17] add shouldDelayFocus --- src/components/MagicCodeInput.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index a63d3f745d3c..e554187fab47 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -30,6 +30,9 @@ const propTypes = { /** Should the input auto focus */ autoFocus: PropTypes.bool, + /** Whether we should wait before focusing the TextInput, useful when using transitions */ + shouldDelayFocus: PropTypes.bool, + /** Error text to display */ errorText: PropTypes.string, @@ -64,6 +67,7 @@ const defaultProps = { value: '', name: '', autoFocus: true, + shouldDelayFocus: false, errorText: '', shouldSubmitOnComplete: true, innerRef: null, @@ -378,6 +382,7 @@ function MagicCodeInput(props) { value={input} hideFocusedState autoComplete={input.length === 0 && props.autoComplete} + shouldDelayFocus={input.length === 0 && props.shouldDelayFocus} keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD} onChangeText={(value) => { onChangeText(value); From 92f5be143234fdbabcf5f6991d1c119f6a698e0e Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:10:00 +0100 Subject: [PATCH 14/17] fix android keyboard --- .../Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index 816ba898b34f..6f160055058b 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -91,7 +91,12 @@ function BaseValidateCodeForm(props) { if (!inputValidateCodeRef.current) { return; } - inputValidateCodeRef.current.focusLastSelected(); + if (focusTimeoutRef.current) { + clearTimeout(focusTimeoutRef.current); + } + focusTimeoutRef.current = setTimeout(() => { + inputValidateCodeRef.current.focusLastSelected(); + }, CONST.ANIMATED_TRANSITION); }, })); @@ -100,6 +105,9 @@ function BaseValidateCodeForm(props) { if (!inputValidateCodeRef.current) { return; } + if (focusTimeoutRef.current) { + clearTimeout(focusTimeoutRef.current); + } focusTimeoutRef.current = setTimeout(inputValidateCodeRef.current.focus, CONST.ANIMATED_TRANSITION); return () => { if (!focusTimeoutRef.current) { From 98c04abde0bf6868762b4e35be5f3f04d7046192 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:09:09 +0100 Subject: [PATCH 15/17] Refactor focusTimeoutRef.current in BaseValidateCodeForm.js --- .../Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index cb24bc02e6a2..3bb999261d44 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -96,9 +96,7 @@ function BaseValidateCodeForm(props) { if (focusTimeoutRef.current) { clearTimeout(focusTimeoutRef.current); } - focusTimeoutRef.current = setTimeout(() => { - inputValidateCodeRef.current.focusLastSelected(); - }, CONST.ANIMATED_TRANSITION); + focusTimeoutRef.current = setTimeout(inputValidateCodeRef.current.focusLastSelected, CONST.ANIMATED_TRANSITION); }, })); From 5c2a666eaebfffb3a76772a1599425a63b029b2d Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:08:03 +0100 Subject: [PATCH 16/17] add helper function --- src/components/MagicCodeInput.js | 34 ++++++++++++-------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 0d7ab9bbe431..4cdc89038974 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -134,6 +134,12 @@ function MagicCodeInput(props) { inputRefs.current.focus(); }; + const setInputAndIndex = (index) => { + setInput(TEXT_INPUT_EMPTY_STATE); + setFocusedIndex(index); + setEditIndex(index); + } + useImperativeHandle(props.innerRef, () => ({ focus() { focusMagicCodeInput(); @@ -146,10 +152,8 @@ function MagicCodeInput(props) { focusMagicCodeInput(); }, clear() { - setInput(TEXT_INPUT_EMPTY_STATE); - setFocusedIndex(0); lastFocusedIndex.current = 0; - setEditIndex(0); + setInputAndIndex(0); inputRefs.current.focus(); props.onChangeText(''); }, @@ -193,9 +197,7 @@ function MagicCodeInput(props) { const onFocus = (event) => { if (shouldFocusLast.current) { lastValue.current = TEXT_INPUT_EMPTY_STATE; - setInput(TEXT_INPUT_EMPTY_STATE); - setFocusedIndex(lastFocusedIndex.current); - setEditIndex(lastFocusedIndex.current); + setInputAndIndex(lastFocusedIndex.current); } event.preventDefault(); }; @@ -213,9 +215,7 @@ function MagicCodeInput(props) { if (!Browser.isMobileChrome() && !Browser.isMobileSafari()) { inputRefs.current.focus(); } - setInput(TEXT_INPUT_EMPTY_STATE); - setFocusedIndex(index); - setEditIndex(index); + setInputAndIndex(index); lastFocusedIndex.current = index; }; @@ -247,9 +247,7 @@ function MagicCodeInput(props) { let numbers = decomposeString(props.value, props.maxLength); numbers = [...numbers.slice(0, editIndex), ...numbersArr, ...numbers.slice(numbersArr.length + editIndex, props.maxLength)]; - setFocusedIndex(updatedFocusedIndex); - setEditIndex(updatedFocusedIndex); - setInput(TEXT_INPUT_EMPTY_STATE); + setInputAndIndex(updatedFocusedIndex); const finalInput = composeToString(numbers); props.onChangeText(finalInput); @@ -305,9 +303,7 @@ function MagicCodeInput(props) { // Saves the input string so that it can compare to the change text // event that will be triggered, this is a workaround for mobile that // triggers the change text on the event after the key press. - setInput(TEXT_INPUT_EMPTY_STATE); - setFocusedIndex(newFocusedIndex); - setEditIndex(newFocusedIndex); + setInputAndIndex(newFocusedIndex); props.onChangeText(composeToString(numbers)); if (!_.isUndefined(newFocusedIndex)) { @@ -316,15 +312,11 @@ function MagicCodeInput(props) { } if (keyValue === 'ArrowLeft' && !_.isUndefined(focusedIndex)) { const newFocusedIndex = Math.max(0, focusedIndex - 1); - setInput(TEXT_INPUT_EMPTY_STATE); - setFocusedIndex(newFocusedIndex); - setEditIndex(newFocusedIndex); + setInputAndIndex(newFocusedIndex); inputRefs.current.focus(); } else if (keyValue === 'ArrowRight' && !_.isUndefined(focusedIndex)) { const newFocusedIndex = Math.min(focusedIndex + 1, props.maxLength - 1); - setInput(TEXT_INPUT_EMPTY_STATE); - setFocusedIndex(newFocusedIndex); - setEditIndex(newFocusedIndex); + setInputAndIndex(newFocusedIndex); inputRefs.current.focus(); } else if (keyValue === 'Enter') { // We should prevent users from submitting when it's offline. From de8fee60ba9116dace057242b8d75ff0783513fe Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:24:54 +0100 Subject: [PATCH 17/17] add comments --- src/components/MagicCodeInput.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index 4cdc89038974..1f3dd061a4bd 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -138,7 +138,7 @@ function MagicCodeInput(props) { setInput(TEXT_INPUT_EMPTY_STATE); setFocusedIndex(index); setEditIndex(index); - } + }; useImperativeHandle(props.innerRef, () => ({ focus() { @@ -233,8 +233,12 @@ function MagicCodeInput(props) { return; } - const addedValue = - value.length - 1 === lastValue.current.length && value.slice(0, value.length - 1) === lastValue.current ? value.slice(lastValue.current.length, value.length) : value; + // Checks if one new character was added, or if the content was replaced + const hasToSlice = value.length - 1 === lastValue.current.length && value.slice(0, value.length - 1) === lastValue.current; + + // Gets the new value added by the user + const addedValue = hasToSlice ? value.slice(lastValue.current.length, value.length) : value; + lastValue.current = value; // Updates the focused input taking into consideration the last input // edited and the number of digits added by the user.