-
Notifications
You must be signed in to change notification settings - Fork 4k
feat: Refator USD flow to use useSubPage #90302
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
Changes from all commits
19880e4
b900245
ca7494a
74ff832
7a32a73
d7e09b3
be35296
9e056f4
169e0b5
e9a2719
220b7d3
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,19 @@ | ||
| let isInternal = false; | ||
|
|
||
| /** Returns true when the next `popstate` was triggered by our own `history.back()`, not a real user back navigation. */ | ||
| function isInternalPopstateInProgress(): boolean { | ||
| return isInternal; | ||
| } | ||
|
|
||
| /** Runs `action` (e.g. `history.back()`) while flagging the resulting `popstate` as internal, so listeners can ignore it. */ | ||
| function withInternalPopstate(action: () => void) { | ||
| isInternal = true; | ||
| const clear = () => { | ||
| isInternal = false; | ||
| window.removeEventListener('popstate', clear); | ||
| }; | ||
| window.addEventListener('popstate', clear); | ||
| action(); | ||
| } | ||
|
|
||
| export {isInternalPopstateInProgress, withInternalPopstate}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import {useCallback, useEffect, useRef} from 'react'; | ||
| import ONYXKEYS from '@src/ONYXKEYS'; | ||
| import useOnyx from './useOnyx'; | ||
|
|
||
| /** | ||
| * Defers navigation (onSubmit) until the reimbursement account API call completes. | ||
| * Instead of navigating to the next step immediately after firing the API call, | ||
| * this hook waits for `isLoading` to go back to `false` and checks for errors. | ||
| * | ||
| * @param onSubmit - callback that navigates to the next step | ||
| * @returns markSubmitting - call this right after firing the API action | ||
| */ | ||
| export default function useReimbursementAccountSubmitCallback(onSubmit?: () => void) { | ||
| const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); | ||
| const isSubmittingRef = useRef(false); | ||
|
|
||
| useEffect(() => { | ||
| if (!isSubmittingRef.current || reimbursementAccount?.isLoading || reimbursementAccount?.errors) { | ||
|
Contributor
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.
When the error was later cleared (for example, after the This caused issue #92726. |
||
| return; | ||
| } | ||
| isSubmittingRef.current = false; | ||
| onSubmit?.(); | ||
| }, [reimbursementAccount?.isLoading, reimbursementAccount?.errors, onSubmit]); | ||
|
|
||
| return useCallback(() => { | ||
| isSubmittingRef.current = true; | ||
| }, []); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ import React, {useCallback} from 'react'; | |||||||||||
| import {View} from 'react-native'; | ||||||||||||
| import useResponsiveLayout from '@hooks/useResponsiveLayout'; | ||||||||||||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||||||||||||
| import {isMobileChrome} from '@libs/Browser'; | ||||||||||||
| import withAgentAccessDenied from '@libs/Navigation/AppNavigator/withAgentAccessDenied'; | ||||||||||||
| import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator'; | ||||||||||||
| import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation'; | ||||||||||||
|
|
@@ -64,6 +65,16 @@ const loadAttachmentModalScreen = () => require<ReactComponentModule>('../../../ | |||||||||||
|
|
||||||||||||
| type Screens = Partial<Record<Screen, () => React.ComponentType>>; | ||||||||||||
|
|
||||||||||||
| const IS_MOBILE_CHROME = isMobileChrome(); | ||||||||||||
|
|
||||||||||||
| const REIMBURSEMENT_ACCOUNT_FLOW_SCREENS: Screen[] = [ | ||||||||||||
| SCREENS.REIMBURSEMENT_ACCOUNT, | ||||||||||||
| SCREENS.REIMBURSEMENT_ACCOUNT_USD, | ||||||||||||
| SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD, | ||||||||||||
| SCREENS.REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT, | ||||||||||||
| SCREENS.REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO, | ||||||||||||
| ]; | ||||||||||||
|
|
||||||||||||
| const OPTIONS_PER_SCREEN: Partial<Record<Screen, PlatformStackNavigationOptions>> = { | ||||||||||||
| [SCREENS.SETTINGS.MERGE_ACCOUNTS.MERGE_RESULT]: { | ||||||||||||
| animationTypeForReplace: 'push', | ||||||||||||
|
|
@@ -131,6 +142,9 @@ const OPTIONS_PER_SCREEN: Partial<Record<Screen, PlatformStackNavigationOptions> | |||||||||||
| [SCREENS.TWO_FACTOR_AUTH.SUCCESS]: { | ||||||||||||
| animationTypeForReplace: 'push', | ||||||||||||
| }, | ||||||||||||
| // Reimbursement Account flow animations glitch on low-end Android devices in Chrome mWeb so we intentionally disable them here. | ||||||||||||
| // see https://github.com/Expensify/App/issues/87658 | ||||||||||||
| ...(IS_MOBILE_CHROME ? Object.fromEntries(REIMBURSEMENT_ACCOUNT_FLOW_SCREENS.map((screen) => [screen, {animation: Animations.NONE}])) : {}), | ||||||||||||
|
Contributor
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.
Suggested change
|
||||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
|
|
@@ -740,6 +754,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP | |||||||||||
| [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_ITEMS]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage').default, | ||||||||||||
| [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: () => require<ReactComponentModule>('@pages/workspace/ConnectExistingBusinessBankAccountPage').default, | ||||||||||||
| [SCREENS.REIMBURSEMENT_ACCOUNT]: withAgentAccessDenied(() => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default), | ||||||||||||
| [SCREENS.REIMBURSEMENT_ACCOUNT_USD]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage').default, | ||||||||||||
| [SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: withAgentAccessDenied( | ||||||||||||
| () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage').default, | ||||||||||||
| ), | ||||||||||||
|
|
||||||||||||
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.
Can we add docs to both of these functions that explain what we can use this for?