-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix:blank page appears in validate code form page #55588
base: main
Are you sure you want to change the base?
Changes from 17 commits
6373c37
172c7b0
c4e944f
6232476
d216e60
217ac60
622df4f
9f1f207
5493c6b
dd436e9
a404826
6640264
6a12518
3f12bb5
433778f
c001758
72e88b7
0afd14a
9b7b20d
c19c2af
0c12b86
b6e0138
5cce05c
426d8be
00d7c51
8d37911
23498e9
0d1f9fe
a317155
5b3af3c
e37d564
589f444
0e4b20f
bc83a7b
1c0cced
91e940d
943ce63
a2c3878
600d0d5
3fc7ee4
c715494
ef17df1
9b73217
08b8d76
aac99d3
bc398e4
3a7ebdf
35ab2c8
f415985
09e4bc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import React, {forwardRef, useEffect, useRef} from 'react'; | ||
import type {ForwardedRef} from 'react'; | ||
import {View} from 'react-native'; | ||
import {useOnyx} from 'react-native-onyx'; | ||
import useThemeStyles from '@hooks/useThemeStyles'; | ||
import ONYXKEYS from '@src/ONYXKEYS'; | ||
import Text from './Text'; | ||
import type {ValidateCodeActionModalProps} from './ValidateCodeActionModal/type'; | ||
import ValidateCodeForm from './ValidateCodeActionModal/ValidateCodeForm'; | ||
import type {ValidateCodeFormHandle} from './ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm'; | ||
|
||
type ValidateCodeActionWithoutModalProps = { | ||
/** Ref for validate code form */ | ||
forwardedRef: ForwardedRef<ValidateCodeFormHandle>; | ||
}; | ||
|
||
type ValidateCodeActionProps = ValidateCodeActionModalProps & ValidateCodeActionWithoutModalProps; | ||
|
||
function ValidateCodeActionWithoutModal({ | ||
isVisible, | ||
descriptionPrimary, | ||
descriptionSecondary, | ||
validatePendingAction, | ||
validateError, | ||
handleSubmitForm, | ||
clearError, | ||
sendValidateCode, | ||
hasMagicCodeBeenSent, | ||
isLoading, | ||
forwardedRef, | ||
}: ValidateCodeActionProps) { | ||
const themeStyles = useThemeStyles(); | ||
const firstRenderRef = useRef(true); | ||
|
||
const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE); | ||
|
||
useEffect( | ||
() => () => { | ||
firstRenderRef.current = true; | ||
}, | ||
[], | ||
); | ||
|
||
useEffect(() => { | ||
if (!firstRenderRef.current || !isVisible || hasMagicCodeBeenSent) { | ||
return () => { | ||
clearError(); | ||
}; | ||
} | ||
firstRenderRef.current = false; | ||
sendValidateCode(); | ||
}, [isVisible, sendValidateCode, hasMagicCodeBeenSent, clearError]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's not a modal. Do we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. W/o it, it will send validate code in validated contact method or default method. It only sends validate code in validate code page only. |
||
|
||
return ( | ||
<View style={[themeStyles.ph5, themeStyles.mt3, themeStyles.mb5, themeStyles.flex1]}> | ||
<Text style={[themeStyles.mb3]}>{descriptionPrimary}</Text> | ||
{!!descriptionSecondary && <Text style={[themeStyles.mb3]}>{descriptionSecondary}</Text>} | ||
<ValidateCodeForm | ||
isLoading={isLoading} | ||
validateCodeAction={validateCodeAction} | ||
validatePendingAction={validatePendingAction} | ||
validateError={validateError} | ||
handleSubmitForm={handleSubmitForm} | ||
sendValidateCode={sendValidateCode} | ||
clearError={clearError} | ||
buttonStyles={[themeStyles.justifyContentEnd, themeStyles.flex1]} | ||
ref={forwardedRef} | ||
hasMagicCodeBeenSent={hasMagicCodeBeenSent} | ||
/> | ||
</View> | ||
); | ||
} | ||
|
||
ValidateCodeActionWithoutModal.displayName = 'ValidateCodeActionWithoutModal'; | ||
|
||
export default forwardRef<ValidateCodeFormHandle, ValidateCodeActionProps>((props, ref) => ( | ||
<ValidateCodeActionWithoutModal | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...props} | ||
forwardedRef={ref} | ||
/> | ||
)); |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -13,12 +13,13 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; | |||
import ScreenWrapper from '@components/ScreenWrapper'; | ||||
import ScrollView from '@components/ScrollView'; | ||||
import Text from '@components/Text'; | ||||
import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; | ||||
import ValidateCodeActionWithoutModal from '@components/ValidateCodeActionWithoutModal'; | ||||
import useBeforeRemove from '@hooks/useBeforeRemove'; | ||||
import useLocalize from '@hooks/useLocalize'; | ||||
import usePrevious from '@hooks/usePrevious'; | ||||
import useTheme from '@hooks/useTheme'; | ||||
import useThemeStyles from '@hooks/useThemeStyles'; | ||||
import useWindowDimensions from '@hooks/useWindowDimensions'; | ||||
import blurActiveElement from '@libs/Accessibility/blurActiveElement'; | ||||
import { | ||||
clearContactMethod, | ||||
|
@@ -61,6 +62,7 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) { | |||
const {formatPhoneNumber, translate} = useLocalize(); | ||||
const theme = useTheme(); | ||||
const themeStyles = useThemeStyles(); | ||||
const {windowWidth} = useWindowDimensions(); | ||||
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||||
const validateCodeFormRef = useRef<ValidateCodeFormHandle>(null); | ||||
|
@@ -270,12 +272,41 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) { | |||
<ScreenWrapper | ||||
onEntryTransitionEnd={() => validateCodeFormRef.current?.focus?.()} | ||||
testID={ContactMethodDetailsPage.displayName} | ||||
focusTrapSettings={{ | ||||
focusTrapOptions: { | ||||
// It is added because input form's focusing bothers transition animation: | ||||
// https://github.com/Expensify/App/issues/53884#issuecomment-2594568960 | ||||
checkCanFocusTrap: (trapContainers: Array<HTMLElement | SVGElement>) => { | ||||
return new Promise((resolve) => { | ||||
const interval = setInterval(() => { | ||||
const trapContainer = trapContainers.at(0); | ||||
if (!trapContainer || (trapContainer && getComputedStyle(trapContainer).visibility !== 'hidden')) { | ||||
resolve(); | ||||
clearInterval(interval); | ||||
} | ||||
}, 5); | ||||
}); | ||||
}, | ||||
}, | ||||
}} | ||||
> | ||||
<HeaderWithBackButton | ||||
title={formattedContactMethod} | ||||
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS.getRoute(backTo))} | ||||
threeDotsMenuItems={getThreeDotsMenuItems()} | ||||
shouldShowThreeDotsButton={getThreeDotsMenuItems().length > 0} | ||||
shouldOverlayDots | ||||
threeDotsAnchorPosition={themeStyles.threeDotsPopoverOffset(windowWidth)} | ||||
onThreeDotsButtonPress={() => { | ||||
// Hide the keyboard when the user clicks the three-dot menu. | ||||
// Use blurActiveElement() for mWeb and KeyboardUtils.dismiss() for native apps. | ||||
blurActiveElement(); | ||||
KeyboardUtils.dismiss(); | ||||
}} | ||||
/> | ||||
<ScrollView keyboardShouldPersistTaps="handled"> | ||||
<ScrollView | ||||
keyboardShouldPersistTaps="handled" | ||||
contentContainerStyle={themeStyles.flex1} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you elaborate why do we need this style? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This style makes put "Verify" button to bottom. W/o the style the button will be placed beneath validate code form. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping @jacobkim9881 again ^ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The elements can fit the necessary space. The explain, form and button elements are placed in its position with this style. |
||||
> | ||||
{isFailedAddContactMethod && ( | ||||
<ErrorMessageRow | ||||
errors={getLatestErrorField(loginData, 'addedLogin')} | ||||
|
@@ -289,32 +320,21 @@ function ContactMethodDetailsPage({route}: ContactMethodDetailsPageProps) { | |||
/> | ||||
)} | ||||
|
||||
<ValidateCodeActionModal | ||||
title={formattedContactMethod} | ||||
onModalHide={() => {}} | ||||
hasMagicCodeBeenSent={hasMagicCodeBeenSent} | ||||
isVisible={isValidateCodeActionModalVisible && !loginData.validatedDate && !!loginData} | ||||
validatePendingAction={loginData.pendingFields?.validateCodeSent} | ||||
handleSubmitForm={(validateCode) => validateSecondaryLogin(loginList, contactMethod, validateCode)} | ||||
validateError={!isEmptyObject(validateLoginError) ? validateLoginError : getLatestErrorField(loginData, 'validateCodeSent')} | ||||
clearError={() => clearContactMethodErrors(contactMethod, !isEmptyObject(validateLoginError) ? 'validateLogin' : 'validateCodeSent')} | ||||
onClose={() => { | ||||
Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS.getRoute(backTo)); | ||||
setIsValidateCodeActionModalVisible(false); | ||||
}} | ||||
sendValidateCode={() => requestContactMethodValidateCode(contactMethod)} | ||||
descriptionPrimary={translate('contacts.enterMagicCode', {contactMethod: formattedContactMethod})} | ||||
onThreeDotsButtonPress={() => { | ||||
// Hide the keyboard when the user clicks the three-dot menu. | ||||
// Use blurActiveElement() for mWeb and KeyboardUtils.dismiss() for native apps. | ||||
blurActiveElement(); | ||||
KeyboardUtils.dismiss(); | ||||
}} | ||||
threeDotsMenuItems={getThreeDotsMenuItems()} | ||||
footer={getDeleteConfirmationModal} | ||||
/> | ||||
{!loginData?.validatedDate && ( | ||||
<ValidateCodeActionWithoutModal | ||||
hasMagicCodeBeenSent={hasMagicCodeBeenSent} | ||||
isVisible={isValidateCodeActionModalVisible && !loginData.validatedDate && !!loginData} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should control the visibility of this component in line 323 instead of a prop. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before it is controled with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||
validatePendingAction={loginData.pendingFields?.validateCodeSent} | ||||
handleSubmitForm={(validateCode) => validateSecondaryLogin(loginList, contactMethod, validateCode)} | ||||
validateError={!isEmptyObject(validateLoginError) ? validateLoginError : getLatestErrorField(loginData, 'validateCodeSent')} | ||||
clearError={() => clearContactMethodErrors(contactMethod, !isEmptyObject(validateLoginError) ? 'validateLogin' : 'validateCodeSent')} | ||||
sendValidateCode={() => requestContactMethodValidateCode(contactMethod)} | ||||
descriptionPrimary={translate('contacts.enterMagicCode', {contactMethod: formattedContactMethod})} | ||||
forwardedRef={validateCodeFormRef} | ||||
/> | ||||
)} | ||||
|
||||
{!isValidateCodeActionModalVisible && getMenuItems()} | ||||
{!isValidateCodeActionModalVisible && !!loginData?.validatedDate && getMenuItems()} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate why do we need add an extra condition here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. W/o it, trash can will show when navigating out on Android mWeb. expensify-test19-2025-02-02_12.45.08.mp4 |
||||
</ScrollView> | ||||
</ScreenWrapper> | ||||
); | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any other names for this component? It seems is not a good name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated it to
ValidateCodeActionForm
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it shares
ValidateCodeActionModalProps
, I thinkValidateCodeAction
should be included. It has the form element and has props to run actions. I thinkValidateCodeActionForm
can be properly used. Please to tell me if you have any idea though.