From 5248bc6e175d9bf72e448fd32b2b0d2d013ebaff Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 5 Oct 2023 16:36:44 +0200 Subject: [PATCH 01/18] Form validation fixes --- src/components/Form/FormProvider.js | 12 ++++++++++++ src/components/Form/FormWrapper.js | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js index 76471aeab51a..c20cc45f2fd4 100644 --- a/src/components/Form/FormProvider.js +++ b/src/components/Form/FormProvider.js @@ -186,6 +186,18 @@ function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, c propsToParse.onTouched(event); } }, + onPress: (event) => { + setTouchedInput(inputID); + if (_.isFunction(propsToParse.onPress)) { + propsToParse.onPress(event); + } + }, + onPressIn: (event) => { + setTouchedInput(inputID); + if (_.isFunction(propsToParse.onPressIn)) { + propsToParse.onPressIn(event); + } + }, onBlur: (event) => { // Only run validation when user proactively blurs the input. if (Visibility.isVisible() && Visibility.hasFocus()) { diff --git a/src/components/Form/FormWrapper.js b/src/components/Form/FormWrapper.js index 44bfee1a9e4a..d7317a673795 100644 --- a/src/components/Form/FormWrapper.js +++ b/src/components/Form/FormWrapper.js @@ -36,7 +36,7 @@ const propTypes = { isLoading: PropTypes.bool, /** Server side errors keyed by microtime */ - errors: PropTypes.objectOf(PropTypes.oneOf([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])), + errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])), /** Field-specific server side errors keyed by microtime */ errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)), @@ -59,7 +59,7 @@ const propTypes = { /** Custom content to display in the footer after submit button */ footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), - errors: PropTypes.objectOf(PropTypes.string).isRequired, + errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])), inputRefs: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object])).isRequired, }; From 5b4a41982b8edc7c38f8b2f36761279bb990d114 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Fri, 6 Oct 2023 11:10:27 +0200 Subject: [PATCH 02/18] Form docs improvements --- src/components/Form/FormProvider.js | 2 +- src/components/Form/FormWrapper.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js index c20cc45f2fd4..2a5c5c5a5ff1 100644 --- a/src/components/Form/FormProvider.js +++ b/src/components/Form/FormProvider.js @@ -240,7 +240,7 @@ function FormProvider({validate, shouldValidateOnBlur, shouldValidateOnChange, c }, }; }, - [errors, formState, inputValues, onValidate, setTouchedInput, shouldValidateOnBlur, shouldValidateOnChange], + [errors, formState, hasServerError, inputValues, onValidate, setTouchedInput, shouldValidateOnBlur, shouldValidateOnChange], ); const value = useMemo(() => ({registerInput}), [registerInput]); diff --git a/src/components/Form/FormWrapper.js b/src/components/Form/FormWrapper.js index d7317a673795..7b8cda333507 100644 --- a/src/components/Form/FormWrapper.js +++ b/src/components/Form/FormWrapper.js @@ -59,7 +59,7 @@ const propTypes = { /** Custom content to display in the footer after submit button */ footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), - errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])), + errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])).isRequired, inputRefs: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object])).isRequired, }; From bd873794098eb82cde1649312b695398ba70e3a5 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Fri, 6 Oct 2023 15:00:02 +0200 Subject: [PATCH 03/18] Fix prop types --- src/components/Form/FormWrapper.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormWrapper.js b/src/components/Form/FormWrapper.js index 7b8cda333507..4358078f5229 100644 --- a/src/components/Form/FormWrapper.js +++ b/src/components/Form/FormWrapper.js @@ -36,7 +36,7 @@ const propTypes = { isLoading: PropTypes.bool, /** Server side errors keyed by microtime */ - errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])), + errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]))])), /** Field-specific server side errors keyed by microtime */ errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)), @@ -59,7 +59,7 @@ const propTypes = { /** Custom content to display in the footer after submit button */ footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), - errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])).isRequired, + errors: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]))])).isRequired, inputRefs: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object])).isRequired, }; @@ -84,6 +84,7 @@ function FormWrapper(props) { const latestErrorMessage = ErrorUtils.getLatestErrorMessage(formState); return typeof latestErrorMessage === 'string' ? latestErrorMessage : ''; }, [formState]); + console.log({errors}) const scrollViewContent = useCallback( (safeAreaPaddingBottomStyle) => ( From 10ea700bb9f2d363a43127eeb7859ac1fbf5df70 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Fri, 6 Oct 2023 15:00:28 +0200 Subject: [PATCH 04/18] Remove console log --- src/components/Form/FormWrapper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Form/FormWrapper.js b/src/components/Form/FormWrapper.js index 4358078f5229..c00c0458d81d 100644 --- a/src/components/Form/FormWrapper.js +++ b/src/components/Form/FormWrapper.js @@ -84,7 +84,6 @@ function FormWrapper(props) { const latestErrorMessage = ErrorUtils.getLatestErrorMessage(formState); return typeof latestErrorMessage === 'string' ? latestErrorMessage : ''; }, [formState]); - console.log({errors}) const scrollViewContent = useCallback( (safeAreaPaddingBottomStyle) => ( From eab18e6e62e0ef4944e164b53a1f6706633fe1d1 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 12 Oct 2023 15:36:48 +0200 Subject: [PATCH 05/18] Refactor roomNameInput --- src/components/RoomNameInput/index.js | 7 +++++-- src/components/RoomNameInput/index.native.js | 7 +++++-- src/components/RoomNameInput/roomNameInputPropTypes.js | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/components/RoomNameInput/index.js b/src/components/RoomNameInput/index.js index 37d131108e9e..32f162d1cf24 100644 --- a/src/components/RoomNameInput/index.js +++ b/src/components/RoomNameInput/index.js @@ -5,8 +5,9 @@ import TextInput from '../TextInput'; import useLocalize from '../../hooks/useLocalize'; import * as roomNameInputPropTypes from './roomNameInputPropTypes'; import * as RoomNameInputUtils from '../../libs/RoomNameInputUtils'; +import InputWrapper from "../Form/InputWrapper"; -function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, value, onBlur, onChangeText, onInputChange, shouldDelayFocus}) { +function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, value, onBlur, onChangeText, onInputChange, shouldDelayFocus, inputID}) { const {translate} = useLocalize(); const [selection, setSelection] = useState(); @@ -43,7 +44,9 @@ function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, }; return ( - {}, - inputID: undefined, onBlur: () => {}, autoFocus: false, shouldDelayFocus: false, From 40a6da22e47632e56b2c9cedd7f387f8cbc4af50 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 12 Oct 2023 15:37:09 +0200 Subject: [PATCH 06/18] Refactor RoomNamePage --- src/pages/settings/Report/RoomNamePage.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Report/RoomNamePage.js b/src/pages/settings/Report/RoomNamePage.js index 985d83e7fd95..cb14ca336d57 100644 --- a/src/pages/settings/Report/RoomNamePage.js +++ b/src/pages/settings/Report/RoomNamePage.js @@ -21,6 +21,7 @@ import * as Report from '../../../libs/actions/Report'; import RoomNameInput from '../../../components/RoomNameInput'; import * as ReportUtils from '../../../libs/ReportUtils'; import FullPageNotFoundView from '../../../components/BlockingViews/FullPageNotFoundView'; +import FormProvider from "../../../components/Form/FormProvider"; const propTypes = { ...withLocalizePropTypes, @@ -90,7 +91,7 @@ function RoomNamePage(props) { title={translate('newRoomPage.roomName')} onBackButtonPress={() => Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(report.reportID))} /> -
Report.updatePolicyRoomNameAndNavigate(report, values.roomName)} @@ -106,7 +107,7 @@ function RoomNamePage(props) { isFocused={isFocused} /> -
+ ); From e35bddca007bd7445d5a1323aba3c6b099d95066 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 12 Oct 2023 15:37:28 +0200 Subject: [PATCH 07/18] Refactor WorkspaceNewRoomPage --- src/pages/workspace/WorkspaceNewRoomPage.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index e1fbab65486b..8c6d5c60db16 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -26,6 +26,8 @@ import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoun import compose from '../../libs/compose'; import variables from '../../styles/variables'; import useDelayedInputFocus from '../../hooks/useDelayedInputFocus'; +import FormProvider from "../../components/Form/FormProvider"; +import InputWrapper from "../../components/Form/InputWrapper"; const propTypes = { /** All reports shared with the user */ @@ -172,7 +174,7 @@ function WorkspaceNewRoomPage(props) { // This is because when wrapping whole screen the screen was freezing when changing Tabs. keyboardVerticalOffset={variables.contentHeaderHeight + variables.tabSelectorButtonHeight + variables.tabSelectorButtonPadding + insets.top} > -
- {isPolicyAdmin && ( - )} - {visibilityDescription} - + )} From 1fd92cc621c5e49406f1edf5dee3aaac1122796f Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Mon, 16 Oct 2023 15:07:33 +0200 Subject: [PATCH 08/18] Post-merge fixes --- src/pages/settings/Report/RoomNamePage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/settings/Report/RoomNamePage.js b/src/pages/settings/Report/RoomNamePage.js index cb14ca336d57..342ba9b41dd6 100644 --- a/src/pages/settings/Report/RoomNamePage.js +++ b/src/pages/settings/Report/RoomNamePage.js @@ -7,7 +7,6 @@ import CONST from '../../../CONST'; import ScreenWrapper from '../../../components/ScreenWrapper'; import HeaderWithBackButton from '../../../components/HeaderWithBackButton'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; -import Form from '../../../components/Form'; import ONYXKEYS from '../../../ONYXKEYS'; import styles from '../../../styles/styles'; import Navigation from '../../../libs/Navigation/Navigation'; From ba1a78d9e5bfe31c4e7afff6091237eca6c1a4f8 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Mon, 16 Oct 2023 15:08:44 +0200 Subject: [PATCH 09/18] Prettier fixes --- src/components/RoomNameInput/index.js | 2 +- src/components/RoomNameInput/index.native.js | 2 +- src/components/RoomNameInput/roomNameInputPropTypes.js | 1 - src/pages/settings/Report/RoomNamePage.js | 2 +- src/pages/workspace/WorkspaceNewRoomPage.js | 4 ++-- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/RoomNameInput/index.js b/src/components/RoomNameInput/index.js index 32f162d1cf24..173b906c8867 100644 --- a/src/components/RoomNameInput/index.js +++ b/src/components/RoomNameInput/index.js @@ -5,7 +5,7 @@ import TextInput from '../TextInput'; import useLocalize from '../../hooks/useLocalize'; import * as roomNameInputPropTypes from './roomNameInputPropTypes'; import * as RoomNameInputUtils from '../../libs/RoomNameInputUtils'; -import InputWrapper from "../Form/InputWrapper"; +import InputWrapper from '../Form/InputWrapper'; function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, value, onBlur, onChangeText, onInputChange, shouldDelayFocus, inputID}) { const {translate} = useLocalize(); diff --git a/src/components/RoomNameInput/index.native.js b/src/components/RoomNameInput/index.native.js index 1b1a26746ea0..d46a9db9ec40 100644 --- a/src/components/RoomNameInput/index.native.js +++ b/src/components/RoomNameInput/index.native.js @@ -6,7 +6,7 @@ import TextInput from '../TextInput'; import * as roomNameInputPropTypes from './roomNameInputPropTypes'; import * as RoomNameInputUtils from '../../libs/RoomNameInputUtils'; import getOperatingSystem from '../../libs/getOperatingSystem'; -import InputWrapper from "../Form/InputWrapper"; +import InputWrapper from '../Form/InputWrapper'; function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, value, onBlur, onChangeText, onInputChange, shouldDelayFocus, inputID}) { const {translate} = useLocalize(); diff --git a/src/components/RoomNameInput/roomNameInputPropTypes.js b/src/components/RoomNameInput/roomNameInputPropTypes.js index 17afe833ea81..098d3fc1be68 100644 --- a/src/components/RoomNameInput/roomNameInputPropTypes.js +++ b/src/components/RoomNameInput/roomNameInputPropTypes.js @@ -29,7 +29,6 @@ const propTypes = { /** Whether we should wait before focusing the TextInput, useful when using transitions on Android */ shouldDelayFocus: PropTypes.bool, - ...withNavigationFocusPropTypes, }; diff --git a/src/pages/settings/Report/RoomNamePage.js b/src/pages/settings/Report/RoomNamePage.js index 342ba9b41dd6..3abf50d3e7db 100644 --- a/src/pages/settings/Report/RoomNamePage.js +++ b/src/pages/settings/Report/RoomNamePage.js @@ -20,7 +20,7 @@ import * as Report from '../../../libs/actions/Report'; import RoomNameInput from '../../../components/RoomNameInput'; import * as ReportUtils from '../../../libs/ReportUtils'; import FullPageNotFoundView from '../../../components/BlockingViews/FullPageNotFoundView'; -import FormProvider from "../../../components/Form/FormProvider"; +import FormProvider from '../../../components/Form/FormProvider'; const propTypes = { ...withLocalizePropTypes, diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index dd0aba2bafe8..9ce3a3f45b2d 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -26,8 +26,8 @@ import compose from '../../libs/compose'; import variables from '../../styles/variables'; import useDelayedInputFocus from '../../hooks/useDelayedInputFocus'; import ValuePicker from '../../components/ValuePicker'; -import FormProvider from "../../components/Form/FormProvider"; -import InputWrapper from "../../components/Form/InputWrapper"; +import FormProvider from '../../components/Form/FormProvider'; +import InputWrapper from '../../components/Form/InputWrapper'; const propTypes = { /** All reports shared with the user */ From fefdb2b3bcf3076daf99e446e6837356d697a4a6 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Tue, 17 Oct 2023 15:08:19 +0200 Subject: [PATCH 10/18] Add value parser to the new form --- src/components/Form/FormProvider.js | 8 ++++++-- src/components/Form/InputWrapper.js | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js index ada40c24ed89..863e3b707bd1 100644 --- a/src/components/Form/FormProvider.js +++ b/src/components/Form/FormProvider.js @@ -233,7 +233,7 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC inputID, key: propsToParse.key || inputID, errorText: errors[inputID] || fieldErrorMessage, - value: inputValues[inputID], + value: propsToParse.valueParser && !_.isUndefined(inputValues[`${inputID}ToDisplay`]) ? inputValues[`${inputID}ToDisplay`] : inputValues[inputID], // As the text input is controlled, we never set the defaultValue prop // as this is already happening by the value prop. defaultValue: undefined, @@ -276,7 +276,11 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC onInputChange: (value, key) => { const inputKey = key || inputID; setInputValues((prevState) => { - const newState = { + const newState = _.isFunction(propsToParse.valueParser) ? { + ...prevState, + [inputKey]: propsToParse.valueParser(value), + [`${inputKey}ToDisplay`]: value, + } : { ...prevState, [inputKey]: value, }; diff --git a/src/components/Form/InputWrapper.js b/src/components/Form/InputWrapper.js index 43064b5a6690..584740f925a3 100644 --- a/src/components/Form/InputWrapper.js +++ b/src/components/Form/InputWrapper.js @@ -7,11 +7,13 @@ const propTypes = { inputID: PropTypes.string.isRequired, valueType: PropTypes.string, forwardedRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({current: PropTypes.instanceOf(React.Component)})]), + valueParser: PropTypes.func }; const defaultProps = { forwardedRef: undefined, valueType: 'string', + valueParser: undefined, }; function InputWrapper(props) { From e05b537a1588d62f66342c391edd5a8792462135 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Tue, 17 Oct 2023 15:08:46 +0200 Subject: [PATCH 11/18] Remove native room name input --- src/components/RoomNameInput/index.native.js | 65 -------------------- 1 file changed, 65 deletions(-) delete mode 100644 src/components/RoomNameInput/index.native.js diff --git a/src/components/RoomNameInput/index.native.js b/src/components/RoomNameInput/index.native.js deleted file mode 100644 index d46a9db9ec40..000000000000 --- a/src/components/RoomNameInput/index.native.js +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react'; -import _ from 'underscore'; -import CONST from '../../CONST'; -import useLocalize from '../../hooks/useLocalize'; -import TextInput from '../TextInput'; -import * as roomNameInputPropTypes from './roomNameInputPropTypes'; -import * as RoomNameInputUtils from '../../libs/RoomNameInputUtils'; -import getOperatingSystem from '../../libs/getOperatingSystem'; -import InputWrapper from '../Form/InputWrapper'; - -function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, value, onBlur, onChangeText, onInputChange, shouldDelayFocus, inputID}) { - const {translate} = useLocalize(); - - /** - * Calls the onChangeText callback with a modified room name - * @param {Event} event - */ - const setModifiedRoomName = (event) => { - const roomName = event.nativeEvent.text; - const modifiedRoomName = RoomNameInputUtils.modifyRoomName(roomName); - onChangeText(modifiedRoomName); - - // if custom component has onInputChange, use it to trigger changes (Form input) - if (_.isFunction(onInputChange)) { - onInputChange(modifiedRoomName); - } - }; - - const keyboardType = getOperatingSystem() === CONST.OS.IOS ? CONST.KEYBOARD_TYPE.ASCII_CAPABLE : CONST.KEYBOARD_TYPE.VISIBLE_PASSWORD; - - return ( - isFocused && onBlur()} - autoFocus={isFocused && autoFocus} - autoCapitalize="none" - shouldDelayFocus={shouldDelayFocus} - /> - ); -} - -RoomNameInput.propTypes = roomNameInputPropTypes.propTypes; -RoomNameInput.defaultProps = roomNameInputPropTypes.defaultProps; -RoomNameInput.displayName = 'RoomNameInput'; - -export default React.forwardRef((props, ref) => ( - -)); From eff3e88fcd590acc9d62099571bc0488e6500670 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Tue, 17 Oct 2023 15:09:02 +0200 Subject: [PATCH 12/18] Update room name input --- src/components/RoomNameInput/index.js | 47 +++++---------------------- 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/src/components/RoomNameInput/index.js b/src/components/RoomNameInput/index.js index 173b906c8867..8bc86e5b730b 100644 --- a/src/components/RoomNameInput/index.js +++ b/src/components/RoomNameInput/index.js @@ -1,47 +1,18 @@ -import React, {useState} from 'react'; -import _ from 'underscore'; +import React from 'react'; import CONST from '../../CONST'; import TextInput from '../TextInput'; import useLocalize from '../../hooks/useLocalize'; import * as roomNameInputPropTypes from './roomNameInputPropTypes'; -import * as RoomNameInputUtils from '../../libs/RoomNameInputUtils'; import InputWrapper from '../Form/InputWrapper'; +import getOperatingSystem from "../../libs/getOperatingSystem"; +import * as RoomNameInputUtils from "../../libs/RoomNameInputUtils"; -function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, value, onBlur, onChangeText, onInputChange, shouldDelayFocus, inputID}) { +function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, onBlur, shouldDelayFocus, inputID}) { const {translate} = useLocalize(); - const [selection, setSelection] = useState(); + const keyboardType = getOperatingSystem() === CONST.OS.IOS ? CONST.KEYBOARD_TYPE.ASCII_CAPABLE : CONST.KEYBOARD_TYPE.VISIBLE_PASSWORD; - /** - * Calls the onChangeText callback with a modified room name - * @param {Event} event - */ - const setModifiedRoomName = (event) => { - const roomName = event.nativeEvent.text; - const modifiedRoomName = RoomNameInputUtils.modifyRoomName(roomName); - onChangeText(modifiedRoomName); - - // if custom component has onInputChange, use it to trigger changes (Form input) - if (_.isFunction(onInputChange)) { - onInputChange(modifiedRoomName); - } - - // Prevent cursor jump behaviour: - // Check if newRoomNameWithHash is the same as modifiedRoomName - // If it is then the room name is valid (does not contain unallowed characters); no action required - // If not then the room name contains unvalid characters and we must adjust the cursor position manually - // Read more: https://github.com/Expensify/App/issues/12741 - const oldRoomNameWithHash = value || ''; - const newRoomNameWithHash = `${CONST.POLICY.ROOM_PREFIX}${roomName}`; - if (modifiedRoomName !== newRoomNameWithHash) { - const offset = modifiedRoomName.length - oldRoomNameWithHash.length; - const newSelection = { - start: selection.start + offset, - end: selection.end + offset, - }; - setSelection(newSelection); - } - }; + const valueParser = (roomName) => RoomNameInputUtils.modifyRoomName(roomName) return ( setSelection(event.nativeEvent.selection)} errorText={errorText} + valueParser={valueParser} autoCapitalize="none" onBlur={() => isFocused && onBlur()} shouldDelayFocus={shouldDelayFocus} @@ -66,6 +34,7 @@ function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, maxLength={CONST.REPORT.MAX_ROOM_NAME_LENGTH} spellCheck={false} shouldInterceptSwipe + keyboardType={keyboardType} // this is a bit hacky solution to a RN issue https://github.com/facebook/react-native/issues/27449 /> ); } From 398b8427f1742f516ffcee81643f6bfe71337e34 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Tue, 17 Oct 2023 16:04:22 +0200 Subject: [PATCH 13/18] Prettier --- src/components/Form/FormProvider.js | 18 ++++++++++-------- src/components/Form/InputWrapper.js | 2 +- src/components/RoomNameInput/index.js | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js index 863e3b707bd1..becdbf99e136 100644 --- a/src/components/Form/FormProvider.js +++ b/src/components/Form/FormProvider.js @@ -276,14 +276,16 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC onInputChange: (value, key) => { const inputKey = key || inputID; setInputValues((prevState) => { - const newState = _.isFunction(propsToParse.valueParser) ? { - ...prevState, - [inputKey]: propsToParse.valueParser(value), - [`${inputKey}ToDisplay`]: value, - } : { - ...prevState, - [inputKey]: value, - }; + const newState = _.isFunction(propsToParse.valueParser) + ? { + ...prevState, + [inputKey]: propsToParse.valueParser(value), + [`${inputKey}ToDisplay`]: value, + } + : { + ...prevState, + [inputKey]: value, + }; if (shouldValidateOnChange) { onValidate(newState); diff --git a/src/components/Form/InputWrapper.js b/src/components/Form/InputWrapper.js index 584740f925a3..b7a73239d11e 100644 --- a/src/components/Form/InputWrapper.js +++ b/src/components/Form/InputWrapper.js @@ -7,7 +7,7 @@ const propTypes = { inputID: PropTypes.string.isRequired, valueType: PropTypes.string, forwardedRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({current: PropTypes.instanceOf(React.Component)})]), - valueParser: PropTypes.func + valueParser: PropTypes.func, }; const defaultProps = { diff --git a/src/components/RoomNameInput/index.js b/src/components/RoomNameInput/index.js index 8bc86e5b730b..b76fd39bbcbf 100644 --- a/src/components/RoomNameInput/index.js +++ b/src/components/RoomNameInput/index.js @@ -4,15 +4,15 @@ import TextInput from '../TextInput'; import useLocalize from '../../hooks/useLocalize'; import * as roomNameInputPropTypes from './roomNameInputPropTypes'; import InputWrapper from '../Form/InputWrapper'; -import getOperatingSystem from "../../libs/getOperatingSystem"; -import * as RoomNameInputUtils from "../../libs/RoomNameInputUtils"; +import getOperatingSystem from '../../libs/getOperatingSystem'; +import * as RoomNameInputUtils from '../../libs/RoomNameInputUtils'; function RoomNameInput({isFocused, autoFocus, disabled, errorText, forwardedRef, onBlur, shouldDelayFocus, inputID}) { const {translate} = useLocalize(); const keyboardType = getOperatingSystem() === CONST.OS.IOS ? CONST.KEYBOARD_TYPE.ASCII_CAPABLE : CONST.KEYBOARD_TYPE.VISIBLE_PASSWORD; - const valueParser = (roomName) => RoomNameInputUtils.modifyRoomName(roomName) + const valueParser = (roomName) => RoomNameInputUtils.modifyRoomName(roomName); return ( Date: Wed, 18 Oct 2023 11:48:57 +0200 Subject: [PATCH 14/18] Code review changes --- src/components/Form/FormProvider.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js index becdbf99e136..35abee3d3776 100644 --- a/src/components/Form/FormProvider.js +++ b/src/components/Form/FormProvider.js @@ -227,13 +227,15 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC .first() .value() || ''; + const value = !_.isUndefined(inputValues[`${inputID}ToDisplay`]) ? inputValues[`${inputID}ToDisplay`] : inputValues[inputID]; + return { ...propsToParse, ref: newRef, inputID, key: propsToParse.key || inputID, errorText: errors[inputID] || fieldErrorMessage, - value: propsToParse.valueParser && !_.isUndefined(inputValues[`${inputID}ToDisplay`]) ? inputValues[`${inputID}ToDisplay`] : inputValues[inputID], + value, // As the text input is controlled, we never set the defaultValue prop // as this is already happening by the value prop. defaultValue: undefined, @@ -273,18 +275,18 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC propsToParse.onBlur(event); } }, - onInputChange: (value, key) => { + onInputChange: (inputValue, key) => { const inputKey = key || inputID; setInputValues((prevState) => { const newState = _.isFunction(propsToParse.valueParser) ? { ...prevState, - [inputKey]: propsToParse.valueParser(value), - [`${inputKey}ToDisplay`]: value, + [inputKey]: propsToParse.valueParser(inputValue), + [`${inputKey}ToDisplay`]: inputValue, } : { ...prevState, - [inputKey]: value, + [inputKey]: inputValue, }; if (shouldValidateOnChange) { @@ -294,11 +296,11 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC }); if (propsToParse.shouldSaveDraft) { - FormActions.setDraftValues(propsToParse.formID, {[inputKey]: value}); + FormActions.setDraftValues(propsToParse.formID, {[inputKey]: inputValue}); } if (_.isFunction(propsToParse.onValueChange)) { - propsToParse.onValueChange(value, inputKey); + propsToParse.onValueChange(inputValue, inputKey); } }, }; From 6edeecf7f1bccb6c7f47612149987baab8b73a1c Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Wed, 25 Oct 2023 14:31:57 +0200 Subject: [PATCH 15/18] Remove empty file --- src/components/RoomNameInput/index.native.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/components/RoomNameInput/index.native.js diff --git a/src/components/RoomNameInput/index.native.js b/src/components/RoomNameInput/index.native.js deleted file mode 100644 index e69de29bb2d1..000000000000 From f0b7aeaa8d21835450574a1204231477b70e2671 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 26 Oct 2023 13:05:53 +0200 Subject: [PATCH 16/18] Fix wrong ref --- src/pages/settings/Report/RoomNamePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Report/RoomNamePage.js b/src/pages/settings/Report/RoomNamePage.js index 2b4b36b28e3b..5e21fc062ebf 100644 --- a/src/pages/settings/Report/RoomNamePage.js +++ b/src/pages/settings/Report/RoomNamePage.js @@ -100,7 +100,7 @@ function RoomNamePage(props) { > (roomNameInputRef.current = ref)} + ref={ref} inputID="roomName" defaultValue={report.reportName} isFocused={isFocused} From 19077c16f104325c93c4cc12be8a08b2dd707b39 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 26 Oct 2023 15:36:21 +0200 Subject: [PATCH 17/18] Fix wrong ref passing --- src/pages/settings/Report/RoomNamePage.js | 2 +- src/pages/workspace/WorkspaceNewRoomPage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Report/RoomNamePage.js b/src/pages/settings/Report/RoomNamePage.js index 5e21fc062ebf..8163b09ca943 100644 --- a/src/pages/settings/Report/RoomNamePage.js +++ b/src/pages/settings/Report/RoomNamePage.js @@ -100,7 +100,7 @@ function RoomNamePage(props) { > (roomNameInputRef.current = el)} + ref={roomNameInputRef} inputID="roomName" isFocused={props.isFocused} shouldDelayFocus From ccf0b9f6acbc22d2d769be7d46b2b48ef57b779b Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 26 Oct 2023 19:47:20 +0200 Subject: [PATCH 18/18] Fix propType --- src/components/RoomNameInput/roomNameInputPropTypes.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/RoomNameInput/roomNameInputPropTypes.js b/src/components/RoomNameInput/roomNameInputPropTypes.js index 1284653076d2..3d1ad18d27b3 100644 --- a/src/components/RoomNameInput/roomNameInputPropTypes.js +++ b/src/components/RoomNameInput/roomNameInputPropTypes.js @@ -1,4 +1,5 @@ import PropTypes from 'prop-types'; +import refPropTypes from '../refPropTypes'; const propTypes = { /** Callback to execute when the text input is modified correctly */ @@ -14,7 +15,7 @@ const propTypes = { errorText: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object]))]), /** A ref forwarded to the TextInput */ - forwardedRef: PropTypes.func, + forwardedRef: refPropTypes, /** The ID used to uniquely identify the input in a Form */ inputID: PropTypes.string.isRequired,