diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 3a2d9a0fd7b9..b6e59643e499 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -4,14 +4,18 @@ import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import AccountUtils from '@libs/AccountUtils'; import * as App from '@userActions/App'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Locale} from '@src/types/onyx'; +import type {Account, Locale} from '@src/types/onyx'; import Picker from './Picker'; import type {PickerSize} from './Picker/types'; type LocalePickerOnyxProps = { + /** The details about the account that the user is signing in with */ + account: OnyxEntry; + /** Indicates which locale the user currently has selected */ preferredLocale: OnyxEntry; }; @@ -21,7 +25,7 @@ type LocalePickerProps = LocalePickerOnyxProps & { size?: PickerSize; }; -function LocalePicker({preferredLocale = CONST.LOCALES.DEFAULT, size = 'normal'}: LocalePickerProps) { +function LocalePicker({account, preferredLocale = CONST.LOCALES.DEFAULT, size = 'normal'}: LocalePickerProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -31,6 +35,7 @@ function LocalePicker({preferredLocale = CONST.LOCALES.DEFAULT, size = 'normal'} keyForList: language, isSelected: preferredLocale === language, })); + const shouldDisablePicker = AccountUtils.isValidateCodeFormSubmitting(account); return ( ({ + account: { + key: ONYXKEYS.ACCOUNT, + }, preferredLocale: { key: ONYXKEYS.NVP_PREFERRED_LOCALE, }, diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index c86d3b71c1d9..03f1e0f496a8 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -33,7 +33,9 @@ function BasePicker( containerStyles, placeholder = {}, size = 'normal', + shouldAllowDisabledStyle = true, shouldFocusPicker = false, + shouldShowOnlyTextWhenDisabled = true, onBlur = () => {}, additionalPickerEvents = () => {}, }: BasePickerProps, @@ -155,7 +157,7 @@ function BasePicker( const hasError = !!errorText; - if (isDisabled) { + if (isDisabled && shouldShowOnlyTextWhenDisabled) { return ( {!!label && ( @@ -176,14 +178,20 @@ function BasePicker( <> {label && {label}} ({...item, color: itemColor}))} - style={size === 'normal' ? styles.picker(isDisabled, backgroundColor) : styles.pickerSmall(backgroundColor)} + style={size === 'normal' ? styles.picker(isDisabled, backgroundColor) : styles.pickerSmall(isDisabled, backgroundColor)} useNativeAndroidPickerStyle={false} placeholder={pickerPlaceholder} value={value} diff --git a/src/components/Picker/types.ts b/src/components/Picker/types.ts index a12f4cbe683a..3f7c0282d35a 100644 --- a/src/components/Picker/types.ts +++ b/src/components/Picker/types.ts @@ -70,9 +70,15 @@ type BasePickerProps = { /** The ID used to uniquely identify the input in a Form */ inputID?: string; + /** Show disabled style when disabled */ + shouldAllowDisabledStyle?: boolean; + /** Saves a draft of the input value when used in a form */ shouldSaveDraft?: boolean; + /** Show only picker's label and value when disabled */ + shouldShowOnlyTextWhenDisabled?: boolean; + /** A callback method that is called when the value changes and it receives the selected value as an argument */ onInputChange: (value: TPickerValue, index?: number) => void; diff --git a/src/libs/AccountUtils.ts b/src/libs/AccountUtils.ts new file mode 100644 index 000000000000..d903584e15b4 --- /dev/null +++ b/src/libs/AccountUtils.ts @@ -0,0 +1,8 @@ +import type {OnyxEntry} from 'react-native-onyx'; +import CONST from '@src/CONST'; +import type {Account} from '@src/types/onyx'; + +const isValidateCodeFormSubmitting = (account: OnyxEntry) => + !!account?.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); + +export default {isValidateCodeFormSubmitting}; diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index 428df32bf032..8111e8d39afa 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -17,6 +17,7 @@ import useNetwork from '@hooks/useNetwork'; import usePrevious from '@hooks/usePrevious'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; +import AccountUtils from '@libs/AccountUtils'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; @@ -76,8 +77,7 @@ function BaseValidateCodeForm({account, credentials, session, autoComplete, isUs const hasError = !!account && !isEmptyObject(account?.errors) && !needToClearError; const isLoadingResendValidationForm = account?.loadingForm === CONST.FORMS.RESEND_VALIDATE_CODE_FORM; const shouldDisableResendValidateCode = isOffline ?? account?.isLoading; - const isValidateCodeFormSubmitting = - account?.isLoading && account?.loadingForm === (account?.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); + const isValidateCodeFormSubmitting = AccountUtils.isValidateCodeFormSubmitting(account); useEffect(() => { if (!(inputValidateCodeRef.current && hasError && (session?.autoAuthState === CONST.AUTO_AUTH_STATE.FAILED || account?.isLoading))) { diff --git a/src/styles/index.ts b/src/styles/index.ts index 405a05cfce78..3ec9e727a251 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -750,7 +750,7 @@ const styles = (theme: ThemeColors) => height: 140, }, - pickerSmall: (backgroundColor = theme.highlightBG) => + pickerSmall: (disabled = false, backgroundColor = theme.highlightBG) => ({ inputIOS: { fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, @@ -792,7 +792,7 @@ const styles = (theme: ThemeColors) => height: 26, opacity: 1, backgroundColor, - ...cursor.cursorPointer, + ...(disabled ? cursor.cursorDisabled : cursor.cursorPointer), }, inputAndroid: { fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, diff --git a/tests/perf-test/SignInPage.perf-test.tsx b/tests/perf-test/SignInPage.perf-test.tsx index 3ff62fd60701..e3e2c20ae72a 100644 --- a/tests/perf-test/SignInPage.perf-test.tsx +++ b/tests/perf-test/SignInPage.perf-test.tsx @@ -18,6 +18,14 @@ import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; +jest.mock('../../src/libs/Log'); + +jest.mock('../../src/libs/API', () => ({ + write: jest.fn(), + makeRequestWithSideEffects: jest.fn(), + read: jest.fn(), +})); + const mockedNavigate = jest.fn(); jest.mock('@react-navigation/native', () => { const actualNav = jest.requireActual('@react-navigation/native');