From 00f6568288cced5173b55235212571f68a92a0ce Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 23 Sep 2024 10:34:21 +0200 Subject: [PATCH 01/21] Refactor completeOnboarding function to update onboarding status --- src/libs/actions/Report.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index b038f16d003d..7583a5766fca 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3582,6 +3582,11 @@ function completeOnboarding( key: ONYXKEYS.NVP_INTRO_SELECTED, value: {choice: engagementChoice}, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.NVP_ONBOARDING, + value: {hasCompletedGuidedSetupFlow: true}, + }, ); const successData: OnyxUpdate[] = [...tasksForSuccessData]; @@ -3637,6 +3642,11 @@ function completeOnboarding( key: ONYXKEYS.NVP_INTRO_SELECTED, value: {choice: null}, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.NVP_ONBOARDING, + value: {hasCompletedGuidedSetupFlow: null}, + }, ); const guidedSetupData: GuidedSetupData = [ From 67ef4d21b175dfae30fcc9cd2564b3a3f9f63e0a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 23 Sep 2024 10:56:02 +0200 Subject: [PATCH 02/21] Set hasCompletedGuidedSetupFlow to false --- src/libs/actions/Report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 7583a5766fca..e2b4e3c80fc0 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3645,7 +3645,7 @@ function completeOnboarding( { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.NVP_ONBOARDING, - value: {hasCompletedGuidedSetupFlow: null}, + value: {hasCompletedGuidedSetupFlow: false}, }, ); From 4ae48e50d8cafe2febedbdfb5cfd2654e7181e19 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 23 Sep 2024 18:25:14 +0200 Subject: [PATCH 03/21] Clean navigation to onboarding logic --- .../Navigation/AppNavigator/AuthScreens.tsx | 39 +++++++++++++------ .../Navigators/OnboardingModalNavigator.tsx | 32 +-------------- .../BottomTabBar.tsx | 7 ---- 3 files changed, 29 insertions(+), 49 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index dee84a4f201f..997131d6ea8c 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -41,6 +41,8 @@ import * as Session from '@userActions/Session'; import toggleTestToolsModal from '@userActions/TestTool'; import Timing from '@userActions/Timing'; import * as User from '@userActions/User'; +import * as Welcome from '@userActions/Welcome'; +import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; @@ -235,6 +237,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie () => getOnboardingModalScreenOptions(shouldUseNarrowLayout, styles, StyleUtils, onboardingIsMediumOrLargerScreenWidth), [StyleUtils, shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, styles], ); + const [shouldShowOnboardingNavigator, setShouldShowOnboardingNavigator] = useState(false); const modal = useRef({}); const [didPusherInit, setDidPusherInit] = useState(false); @@ -253,9 +256,21 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie initialReportID = initialReport?.reportID ?? ''; } + Welcome.isOnboardingFlowCompleted({ + onNotCompleted: () => setShouldShowOnboardingNavigator(true), + onCompleted: () => setShouldShowOnboardingNavigator(false), + }); + isInitialRender.current = false; } + useEffect(() => { + if (!shouldShowOnboardingNavigator) { + return; + } + OnboardingFlow.startOnboardingFlow(); + }, [shouldShowOnboardingNavigator]); + useEffect(() => { const shortcutsOverviewShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SHORTCUTS; const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH; @@ -526,17 +541,19 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie options={onboardingModalScreenOptions} component={WelcomeVideoModalNavigator} /> - { - Modal.setDisableDismissOnEscape(true); - }, - beforeRemove: () => Modal.setDisableDismissOnEscape(false), - }} - /> + {shouldShowOnboardingNavigator && ( + { + Modal.setDisableDismissOnEscape(true); + }, + beforeRemove: () => Modal.setDisableDismissOnEscape(false), + }} + /> + )} (); function OnboardingModalNavigator() { const styles = useThemeStyles(); const {onboardingIsMediumOrLargerScreenWidth} = useResponsiveLayout(); - const [hasCompletedGuidedSetupFlow] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { - selector: hasCompletedGuidedSetupFlowSelector, - }); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - - useEffect(() => { - if (!hasCompletedGuidedSetupFlow) { - return; - } - Navigation.isNavigationReady().then(() => { - // On small screens, pop all navigation states and go back to HOME. - // On large screens, need to go back to previous route and then redirect to Concierge, - // otherwise going back on Concierge will go to onboarding and then redirected to Concierge again - if (shouldUseNarrowLayout) { - Navigation.setShouldPopAllStateOnUP(true); - Navigation.goBack(ROUTES.HOME, true, true); - } else { - Navigation.goBack(); - Report.navigateToConciergeChat(); - } - }); - }, [hasCompletedGuidedSetupFlow, shouldUseNarrowLayout]); - const outerViewRef = React.useRef(null); const handleOuterClick = useCallback(() => { @@ -58,9 +31,6 @@ function OnboardingModalNavigator() { useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ESCAPE, handleOuterClick, {shouldBubble: true}); - if (hasCompletedGuidedSetupFlow) { - return null; - } return ( diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index d06be872c70a..e571957200ad 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -23,8 +23,6 @@ import {getChatTabBrickRoad} from '@libs/WorkspacesSettingsUtils'; import BottomTabAvatar from '@pages/home/sidebar/BottomTabAvatar'; import BottomTabBarFloatingActionButton from '@pages/home/sidebar/BottomTabBarFloatingActionButton'; import variables from '@styles/variables'; -import * as Welcome from '@userActions/Welcome'; -import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -92,11 +90,6 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) { if (NativeModules.HybridAppModule) { return; } - - Welcome.isOnboardingFlowCompleted({ - onNotCompleted: () => OnboardingFlow.startOnboardingFlow(), - }); - // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, [isLoadingApp]); From eda9b65350e01a459a8d1441ddeb776ef4ea8d27 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 23 Sep 2024 18:28:37 +0200 Subject: [PATCH 04/21] Remove unused imports --- .../AppNavigator/Navigators/OnboardingModalNavigator.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index eed40afabd1b..e564af8103cc 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -1,7 +1,6 @@ import {createStackNavigator} from '@react-navigation/stack'; -import React, {useCallback, useEffect, useRef} from 'react'; +import React, {useCallback} from 'react'; import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; import NoDropZone from '@components/DragAndDrop/NoDropZone'; import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; @@ -14,7 +13,6 @@ import OnboardingPersonalDetails from '@pages/OnboardingPersonalDetails'; import OnboardingPurpose from '@pages/OnboardingPurpose'; import OnboardingWork from '@pages/OnboardingWork'; import CONST from '@src/CONST'; -import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import Overlay from './Overlay'; From f07f55e7ba4ee79618eeb63bd46989912cd7b5a7 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 11:37:36 +0200 Subject: [PATCH 05/21] Add useful comments --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 997131d6ea8c..bbc2ccdac3c9 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -257,13 +257,14 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie } Welcome.isOnboardingFlowCompleted({ + // When onboarding is not completed, we want to display the onboarding navigator onNotCompleted: () => setShouldShowOnboardingNavigator(true), - onCompleted: () => setShouldShowOnboardingNavigator(false), }); isInitialRender.current = false; } + // Start the onboarding flow after onboarding navigator is mounted useEffect(() => { if (!shouldShowOnboardingNavigator) { return; From 647622b17a3233b48190fa5b0240959a9bcb0845 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 12:10:59 +0200 Subject: [PATCH 06/21] Remove onboarding logic from bottom tabs --- .../BottomTabBar.tsx | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index e571957200ad..e15ff45b5dc5 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -1,6 +1,6 @@ import {useNavigation} from '@react-navigation/native'; import React, {memo, useCallback, useEffect, useState} from 'react'; -import {NativeModules, View} from 'react-native'; +import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -11,11 +11,8 @@ import useActiveWorkspace from '@hooks/useActiveWorkspace'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Session from '@libs/actions/Session'; import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import Navigation from '@libs/Navigation/Navigation'; -import type {RootStackParamList, State} from '@libs/Navigation/types'; -import {isCentralPaneName} from '@libs/NavigationUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as SearchUtils from '@libs/SearchUtils'; import type {BrickRoad} from '@libs/WorkspacesSettingsUtils'; @@ -24,7 +21,6 @@ import BottomTabAvatar from '@pages/home/sidebar/BottomTabAvatar'; import BottomTabBarFloatingActionButton from '@pages/home/sidebar/BottomTabBarFloatingActionButton'; import variables from '@styles/variables'; import CONST from '@src/CONST'; -import NAVIGATORS from '@src/NAVIGATORS'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; @@ -66,9 +62,7 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); - const navigation = useNavigation(); const {activeWorkspaceID} = useActiveWorkspace(); - const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP); const transactionViolations = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); const [chatTabBrickRoad, setChatTabBrickRoad] = useState(getChatTabBrickRoad(activeWorkspaceID)); @@ -76,23 +70,6 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) { setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID)); }, [activeWorkspaceID, transactionViolations]); - useEffect(() => { - const navigationState = navigation.getState() as State | undefined; - const routes = navigationState?.routes; - const currentRoute = routes?.[navigationState?.index ?? 0]; - // When we are redirected to the Settings tab from the OldDot, we don't want to call the Welcome.show() method. - // To prevent this, the value of the bottomTabRoute?.name is checked here - if (!!(currentRoute && currentRoute.name !== NAVIGATORS.BOTTOM_TAB_NAVIGATOR && !isCentralPaneName(currentRoute.name)) || Session.isAnonymousUser()) { - return; - } - - // HybridApp has own entry point when we decide whether to display onboarding and explanation modal. - if (NativeModules.HybridAppModule) { - return; - } - // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - }, [isLoadingApp]); - const navigateToChats = useCallback(() => { if (selectedTab === SCREENS.HOME) { return; From a94e8b5aa10e64a805d7790c1ff971516fe58fe7 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 15:48:53 +0200 Subject: [PATCH 07/21] Adjust onboardinf flow with hybrid app considerations --- src/Expensify.tsx | 9 --- src/components/ExplanationModal.tsx | 17 +---- .../LHNOptionsList/OptionRowLHN.tsx | 4 +- src/hooks/useOnboardingFlow.ts | 42 +++++++++++++ .../Navigation/AppNavigator/AuthScreens.tsx | 21 +------ src/libs/Navigation/NavigationRoot.tsx | 5 +- src/libs/actions/Welcome/index.ts | 63 +------------------ .../hasCompletedGuidedSetupFlowSelector.ts | 13 ---- src/libs/onboardingSelectors.ts | 23 +++++++ 9 files changed, 76 insertions(+), 121 deletions(-) create mode 100644 src/hooks/useOnboardingFlow.ts delete mode 100644 src/libs/hasCompletedGuidedSetupFlowSelector.ts create mode 100644 src/libs/onboardingSelectors.ts diff --git a/src/Expensify.tsx b/src/Expensify.tsx index 62e7839b21f0..d4e12282ee13 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -20,7 +20,6 @@ import {updateLastRoute} from './libs/actions/App'; import * as EmojiPickerAction from './libs/actions/EmojiPickerAction'; import * as Report from './libs/actions/Report'; import * as User from './libs/actions/User'; -import {handleHybridAppOnboarding} from './libs/actions/Welcome'; import * as ActiveClientManager from './libs/ActiveClientManager'; import FS from './libs/Fullstory'; import * as Growl from './libs/Growl'; @@ -118,14 +117,6 @@ function Expensify({ setAttemptedToOpenPublicRoom(true); }, [isCheckingPublicRoom]); - useEffect(() => { - if (splashScreenState !== CONST.BOOT_SPLASH_STATE.HIDDEN || tryNewDotData === undefined) { - return; - } - - handleHybridAppOnboarding(); - }, [splashScreenState, tryNewDotData]); - const isAuthenticated = useMemo(() => !!(session?.authToken ?? null), [session]); const autoAuthState = useMemo(() => session?.autoAuthState ?? '', [session]); diff --git a/src/components/ExplanationModal.tsx b/src/components/ExplanationModal.tsx index 73290c43d39a..902b510832d1 100644 --- a/src/components/ExplanationModal.tsx +++ b/src/components/ExplanationModal.tsx @@ -10,21 +10,6 @@ import FeatureTrainingModal from './FeatureTrainingModal'; function ExplanationModal() { const {translate} = useLocalize(); - const onClose = useCallback(() => { - Welcome.completeHybridAppOnboarding(); - - // We need to check if standard NewDot onboarding is completed. - Welcome.isOnboardingFlowCompleted({ - onNotCompleted: () => { - setTimeout(() => { - Navigation.isNavigationReady().then(() => { - OnboardingFlow.startOnboardingFlow(); - }); - }, variables.welcomeVideoDelay); - }, - }); - }, []); - return ( ); } diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index 353bacdc0a25..172488a07712 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -21,7 +21,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; import DomUtils from '@libs/DomUtils'; -import hasCompletedGuidedSetupFlowSelector from '@libs/hasCompletedGuidedSetupFlowSelector'; +import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; import Performance from '@libs/Performance'; @@ -47,7 +47,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${optionItem?.reportID || -1}`); const [isFirstTimeNewExpensifyUser] = useOnyx(ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER); - const [hasCompletedGuidedSetupFlow] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { + const [hasCompletedGuidedSetupFlow = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, }); const [shouldHideGBRTooltip] = useOnyx(ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP, {initialValue: true}); diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts new file mode 100644 index 000000000000..e70e17cd5e33 --- /dev/null +++ b/src/hooks/useOnboardingFlow.ts @@ -0,0 +1,42 @@ +import {useEffect} from 'react'; +import {NativeModules} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import Navigation from '@libs/Navigation/Navigation'; +import {hasCompletedGuidedSetupFlowSelector, hasCompletedHybridAppSetupFlowSelector} from '@libs/onboardingSelectors'; +import variables from '@styles/variables'; +import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function useOnboardingFlow() { + const [isOnboardingCompleted] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { + selector: hasCompletedGuidedSetupFlowSelector, + }); + const [isHybridAppOnboardingCompleted] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, { + selector: hasCompletedHybridAppSetupFlowSelector, + }); + + useEffect(() => { + if (NativeModules.HybridAppModule) { + if (isHybridAppOnboardingCompleted === false) { + Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); + return; + } + + if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { + setTimeout(() => { + OnboardingFlow.startOnboardingFlow(); + }, variables.explanationModalDelay); + return; + } + } + + if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { + OnboardingFlow.startOnboardingFlow(); + } + }, [isOnboardingCompleted, isHybridAppOnboardingCompleted]); + + return {isOnboardingCompleted, isHybridAppOnboardingCompleted}; +} + +export default useOnboardingFlow; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index bbc2ccdac3c9..d7510736bf26 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -9,6 +9,7 @@ import OptionsListContextProvider from '@components/OptionListContextProvider'; import {SearchContextProvider} from '@components/Search/SearchContext'; import SearchRouter from '@components/Search/SearchRouter/SearchRouter'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; +import useOnboardingFlow from '@hooks/useOnboardingFlow'; import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -41,8 +42,6 @@ import * as Session from '@userActions/Session'; import toggleTestToolsModal from '@userActions/TestTool'; import Timing from '@userActions/Timing'; import * as User from '@userActions/User'; -import * as Welcome from '@userActions/Welcome'; -import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; @@ -237,10 +236,9 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie () => getOnboardingModalScreenOptions(shouldUseNarrowLayout, styles, StyleUtils, onboardingIsMediumOrLargerScreenWidth), [StyleUtils, shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, styles], ); - const [shouldShowOnboardingNavigator, setShouldShowOnboardingNavigator] = useState(false); const modal = useRef({}); const [didPusherInit, setDidPusherInit] = useState(false); - + const {isOnboardingCompleted} = useOnboardingFlow(); let initialReportID: string | undefined; const isInitialRender = useRef(true); if (isInitialRender.current) { @@ -256,22 +254,9 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie initialReportID = initialReport?.reportID ?? ''; } - Welcome.isOnboardingFlowCompleted({ - // When onboarding is not completed, we want to display the onboarding navigator - onNotCompleted: () => setShouldShowOnboardingNavigator(true), - }); - isInitialRender.current = false; } - // Start the onboarding flow after onboarding navigator is mounted - useEffect(() => { - if (!shouldShowOnboardingNavigator) { - return; - } - OnboardingFlow.startOnboardingFlow(); - }, [shouldShowOnboardingNavigator]); - useEffect(() => { const shortcutsOverviewShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SHORTCUTS; const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH; @@ -542,7 +527,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie options={onboardingModalScreenOptions} component={WelcomeVideoModalNavigator} /> - {shouldShowOnboardingNavigator && ( + {!isOnboardingCompleted && ( { - let completedHybridAppOnboarding = tryNewDotData?.classicRedirect?.completedHybridAppOnboarding; - // Backend might return strings instead of booleans - if (typeof completedHybridAppOnboarding === 'string') { - completedHybridAppOnboarding = completedHybridAppOnboarding === 'true'; - } - - if (NativeModules.HybridAppModule && !completedHybridAppOnboarding) { - onFirstTimeInHybridApp?.(); - return; - } - - onSubsequentRuns?.(); - }); -} - -/** - * Handles HybridApp onboarding flow if it's possible and necessary. - */ -function handleHybridAppOnboarding() { - if (!NativeModules.HybridAppModule) { - return; - } - - isFirstTimeHybridAppUser({ - // When user opens New Expensify for the first time from HybridApp we always want to show explanation modal first. - onFirstTimeInHybridApp: () => Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT), - // In other scenarios we need to check if onboarding was completed. - onSubsequentRuns: () => - isOnboardingFlowCompleted({ - onNotCompleted: () => - setTimeout(() => { - OnboardingFlow.startOnboardingFlow(); - }, variables.explanationModalDelay), - }), - }); -} - /** * Check if report data are loaded */ @@ -175,27 +129,15 @@ function completeHybridAppOnboarding() { }, ]; - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.NVP_TRYNEWDOT, - value: { - classicRedirect: { - completedHybridAppOnboarding: false, - }, - }, - }, - ]; - // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING, {}, {optimisticData, failureData}).then((response) => { + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING, {}, {optimisticData}).then((response) => { if (!response) { return; } // if the call succeeded HybridApp onboarding is finished, otherwise it's not Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding: response?.jsonCode === CONST.JSON_CODE.SUCCESS}); - NativeModules.HybridAppModule.completeOnboarding(response?.jsonCode === CONST.JSON_CODE.SUCCESS); + NativeModules.HybridAppModule.completeOnboarding(true); }); } @@ -245,6 +187,5 @@ export { setOnboardingAdminsChatReportID, setOnboardingPolicyID, completeHybridAppOnboarding, - handleHybridAppOnboarding, setOnboardingErrorMessage, }; diff --git a/src/libs/hasCompletedGuidedSetupFlowSelector.ts b/src/libs/hasCompletedGuidedSetupFlowSelector.ts deleted file mode 100644 index 4934c83d7773..000000000000 --- a/src/libs/hasCompletedGuidedSetupFlowSelector.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type {OnyxValue} from 'react-native-onyx'; -import type ONYXKEYS from '@src/ONYXKEYS'; - -function hasCompletedGuidedSetupFlowSelector(onboarding: OnyxValue): boolean { - // onboarding is an array for old accounts and accounts created from olddot - if (Array.isArray(onboarding)) { - return true; - } - - return onboarding?.hasCompletedGuidedSetupFlow ?? true; -} - -export default hasCompletedGuidedSetupFlowSelector; diff --git a/src/libs/onboardingSelectors.ts b/src/libs/onboardingSelectors.ts new file mode 100644 index 000000000000..287ec3b70ae1 --- /dev/null +++ b/src/libs/onboardingSelectors.ts @@ -0,0 +1,23 @@ +import {type OnyxValue} from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; + +function hasCompletedGuidedSetupFlowSelector(onboarding: OnyxValue): boolean | undefined { + // onboarding is an array for old accounts and accounts created from olddot + if (Array.isArray(onboarding)) { + return true; + } + + return onboarding?.hasCompletedGuidedSetupFlow; +} + +function hasCompletedHybridAppSetupFlowSelector(tryNewDotData: OnyxValue): boolean | undefined { + let completedHybridAppOnboarding = tryNewDotData?.classicRedirect?.completedHybridAppOnboarding; + // Backend might return strings instead of booleans + if (typeof completedHybridAppOnboarding === 'string') { + completedHybridAppOnboarding = completedHybridAppOnboarding === 'true'; + } + + return completedHybridAppOnboarding; +} + +export {hasCompletedGuidedSetupFlowSelector, hasCompletedHybridAppSetupFlowSelector}; From bb1cd88be217fbf3a9228155c1b56ed593cc02ed Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 17:32:36 +0200 Subject: [PATCH 08/21] Fix the logic and remove console.log --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 2 +- src/libs/Navigation/NavigationRoot.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index d7510736bf26..39f268c43b67 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -527,7 +527,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie options={onboardingModalScreenOptions} component={WelcomeVideoModalNavigator} /> - {!isOnboardingCompleted && ( + {isOnboardingCompleted === false && ( Date: Tue, 24 Sep 2024 18:00:53 +0200 Subject: [PATCH 09/21] Add comments for selectors --- src/libs/onboardingSelectors.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/libs/onboardingSelectors.ts b/src/libs/onboardingSelectors.ts index 287ec3b70ae1..aa77b822c9e9 100644 --- a/src/libs/onboardingSelectors.ts +++ b/src/libs/onboardingSelectors.ts @@ -1,8 +1,15 @@ import {type OnyxValue} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; +/** + * Selector to get the value of hasCompletedGuidedSetupFlow from the Onyx store + * + * `undefined` means the value is not loaded yet + * `true` means the user has completed the NewDot onboarding flow + * `false` means the user has not completed the NewDot onboarding flow + */ function hasCompletedGuidedSetupFlowSelector(onboarding: OnyxValue): boolean | undefined { - // onboarding is an array for old accounts and accounts created from olddot + // Onboarding is an array for old accounts and accounts created from OldDot if (Array.isArray(onboarding)) { return true; } @@ -10,8 +17,16 @@ function hasCompletedGuidedSetupFlowSelector(onboarding: OnyxValue): boolean | undefined { +/** + * Selector to get the value of completedHybridAppOnboarding from the Onyx store + * + * `undefined` means the value is not loaded yet + * `true` means the user has completed the hybrid app onboarding flow + * `false` means the user has not completed the hybrid app onboarding flow + */ +function hasCompletedHybridAppOnboardingFlowSelector(tryNewDotData: OnyxValue): boolean | undefined { let completedHybridAppOnboarding = tryNewDotData?.classicRedirect?.completedHybridAppOnboarding; + // Backend might return strings instead of booleans if (typeof completedHybridAppOnboarding === 'string') { completedHybridAppOnboarding = completedHybridAppOnboarding === 'true'; @@ -20,4 +35,4 @@ function hasCompletedHybridAppSetupFlowSelector(tryNewDotData: OnyxValue Date: Tue, 24 Sep 2024 18:03:38 +0200 Subject: [PATCH 10/21] Refactor onboarding logic and improve logging --- src/libs/actions/Welcome/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts index c921b6a099db..b77f608f44ac 100644 --- a/src/libs/actions/Welcome/index.ts +++ b/src/libs/actions/Welcome/index.ts @@ -135,8 +135,8 @@ function completeHybridAppOnboarding() { return; } - // if the call succeeded HybridApp onboarding is finished, otherwise it's not - Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding: response?.jsonCode === CONST.JSON_CODE.SUCCESS}); + // No matter what the response is, we want to mark the onboarding as completed (user saw the explanation modal) + Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true); NativeModules.HybridAppModule.completeOnboarding(true); }); } From c1aecb0adb1941ee2cc192b57a5c2fd48c29e7d1 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 18:03:59 +0200 Subject: [PATCH 11/21] Remove unused import --- src/libs/actions/Welcome/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts index b77f608f44ac..5337b44b8d2d 100644 --- a/src/libs/actions/Welcome/index.ts +++ b/src/libs/actions/Welcome/index.ts @@ -5,7 +5,6 @@ import * as API from '@libs/API'; import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; import Log from '@libs/Log'; import type {OnboardingPurposeType} from '@src/CONST'; -import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type Onboarding from '@src/types/onyx/Onboarding'; import type TryNewDot from '@src/types/onyx/TryNewDot'; From e4dd28052df83a37d413c70336e6a78b003d0be4 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 18:09:56 +0200 Subject: [PATCH 12/21] Add comments to useOnboardingFlow hook --- src/hooks/useOnboardingFlow.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index e70e17cd5e33..5ea8dd87021f 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -2,28 +2,37 @@ import {useEffect} from 'react'; import {NativeModules} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import Navigation from '@libs/Navigation/Navigation'; -import {hasCompletedGuidedSetupFlowSelector, hasCompletedHybridAppSetupFlowSelector} from '@libs/onboardingSelectors'; +import {hasCompletedGuidedSetupFlowSelector, hasCompletedHybridAppOnboardingFlowSelector} from '@libs/onboardingSelectors'; import variables from '@styles/variables'; import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +/** + * Hook to handle redirection to the onboarding flow based on the user's onboarding status + * + * Warning: This hook should be used only once in the app + */ function useOnboardingFlow() { const [isOnboardingCompleted] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, }); const [isHybridAppOnboardingCompleted] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, { - selector: hasCompletedHybridAppSetupFlowSelector, + selector: hasCompletedHybridAppOnboardingFlowSelector, }); useEffect(() => { if (NativeModules.HybridAppModule) { + // When user is transitioning from OldDot to NewDot, we should show the explanation modal + // Only if the hybrid app onboarding is not completed, we should show the explanation modal if (isHybridAppOnboardingCompleted === false) { Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); return; } + // If the hybrid app onboarding is completed, but the onboarding is not completed, we should start NewDot onboarding flow if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { + // Delay NewDot onboarding flow to hide the explanation modal in time setTimeout(() => { OnboardingFlow.startOnboardingFlow(); }, variables.explanationModalDelay); @@ -31,6 +40,7 @@ function useOnboardingFlow() { } } + // If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { OnboardingFlow.startOnboardingFlow(); } From 4ce64797a1c2dc36e68b64f0ba2f6a050345a1ce Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 18:13:47 +0200 Subject: [PATCH 13/21] Send the completeHybridAppOnboarding request only if HybridApp module is available --- src/libs/actions/Welcome/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts index 5337b44b8d2d..89737acc74ac 100644 --- a/src/libs/actions/Welcome/index.ts +++ b/src/libs/actions/Welcome/index.ts @@ -116,6 +116,10 @@ function updateOnboardingLastVisitedPath(path: string) { } function completeHybridAppOnboarding() { + if (!NativeModules.HybridAppModule) { + return; + } + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, From baf8497263b2cdd2e095ac290372f8f5934940cc Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 18:21:38 +0200 Subject: [PATCH 14/21] Remove unused useOnyx --- src/Expensify.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Expensify.tsx b/src/Expensify.tsx index d4e12282ee13..f5d4655c4861 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -98,7 +98,6 @@ function Expensify({ const [account] = useOnyx(ONYXKEYS.ACCOUNT); const [session] = useOnyx(ONYXKEYS.SESSION); const [lastRoute] = useOnyx(ONYXKEYS.LAST_ROUTE); - const [tryNewDotData] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT); const [shouldShowRequire2FAModal, setShouldShowRequire2FAModal] = useState(false); useEffect(() => { From e2a855cb282a373fc947f7a266aed4df56084dd6 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 24 Sep 2024 18:57:35 +0200 Subject: [PATCH 15/21] Fix imports --- src/components/ExplanationModal.tsx | 5 +---- src/libs/actions/Welcome/index.ts | 8 -------- src/libs/onboardingSelectors.ts | 4 ++-- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/components/ExplanationModal.tsx b/src/components/ExplanationModal.tsx index 902b510832d1..d846dd4d28ba 100644 --- a/src/components/ExplanationModal.tsx +++ b/src/components/ExplanationModal.tsx @@ -1,9 +1,6 @@ -import React, {useCallback} from 'react'; +import React from 'react'; import useLocalize from '@hooks/useLocalize'; -import Navigation from '@libs/Navigation/Navigation'; -import variables from '@styles/variables'; import * as Welcome from '@userActions/Welcome'; -import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; import CONST from '@src/CONST'; import FeatureTrainingModal from './FeatureTrainingModal'; diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts index 89737acc74ac..53db834c1024 100644 --- a/src/libs/actions/Welcome/index.ts +++ b/src/libs/actions/Welcome/index.ts @@ -21,11 +21,6 @@ type HasCompletedOnboardingFlowProps = { onNotCompleted?: () => void; }; -type HasOpenedForTheFirstTimeFromHybridAppProps = { - onFirstTimeInHybridApp?: () => void; - onSubsequentRuns?: () => void; -}; - let resolveIsReadyPromise: (value?: Promise) => void | undefined; let isServerDataReadyPromise = new Promise((resolve) => { resolveIsReadyPromise = resolve; @@ -37,9 +32,6 @@ let isOnboardingFlowStatusKnownPromise = new Promise((resolve) => { }); let resolveTryNewDotStatus: (value?: Promise) => void | undefined; -const tryNewDotStatusPromise = new Promise((resolve) => { - resolveTryNewDotStatus = resolve; -}); function onServerDataReady(): Promise { return isServerDataReadyPromise; diff --git a/src/libs/onboardingSelectors.ts b/src/libs/onboardingSelectors.ts index aa77b822c9e9..efa67d2aed48 100644 --- a/src/libs/onboardingSelectors.ts +++ b/src/libs/onboardingSelectors.ts @@ -1,5 +1,5 @@ -import {type OnyxValue} from 'react-native-onyx'; -import ONYXKEYS from '@src/ONYXKEYS'; +import type {OnyxValue} from 'react-native-onyx'; +import type ONYXKEYS from '@src/ONYXKEYS'; /** * Selector to get the value of hasCompletedGuidedSetupFlow from the Onyx store From ab69af2bb95bd61274cd7a4a06586fa8975abc61 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Wed, 25 Sep 2024 10:21:36 +0200 Subject: [PATCH 16/21] Init HybridApp with information about HybridApp onboarding --- src/libs/actions/Session/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index ab209e9bf928..4d6ba6cfa774 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -482,7 +482,7 @@ function signUpUser() { function signInAfterTransitionFromOldDot(transitionURL: string) { const [route, queryParams] = transitionURL.split('?'); - const {email, authToken, encryptedAuthToken, accountID, autoGeneratedLogin, autoGeneratedPassword, clearOnyxOnStart} = Object.fromEntries( + const {email, authToken, encryptedAuthToken, accountID, autoGeneratedLogin, autoGeneratedPassword, clearOnyxOnStart, completedHybridAppOnboarding} = Object.fromEntries( queryParams.split('&').map((param) => { const [key, value] = param.split('='); return [key, value]; @@ -493,6 +493,7 @@ function signInAfterTransitionFromOldDot(transitionURL: string) { Onyx.multiSet({ [ONYXKEYS.SESSION]: {email, authToken, encryptedAuthToken: decodeURIComponent(encryptedAuthToken), accountID: Number(accountID)}, [ONYXKEYS.CREDENTIALS]: {autoGeneratedLogin, autoGeneratedPassword}, + [ONYXKEYS.NVP_TRYNEWDOT]: {classicRedirect: {completedHybridAppOnboarding: completedHybridAppOnboarding === 'true'}}, }).then(App.openApp); }; From cdfe1c7cba976010a946248baf9d5adc01d9ddcc Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 26 Sep 2024 14:37:33 +0200 Subject: [PATCH 17/21] Make the hybrid app flow weven easier --- src/hooks/useOnboardingFlow.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index 5ea8dd87021f..f6467b2df28c 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -3,7 +3,6 @@ import {NativeModules} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import Navigation from '@libs/Navigation/Navigation'; import {hasCompletedGuidedSetupFlowSelector, hasCompletedHybridAppOnboardingFlowSelector} from '@libs/onboardingSelectors'; -import variables from '@styles/variables'; import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -23,20 +22,15 @@ function useOnboardingFlow() { useEffect(() => { if (NativeModules.HybridAppModule) { - // When user is transitioning from OldDot to NewDot, we should show the explanation modal - // Only if the hybrid app onboarding is not completed, we should show the explanation modal + // When user is transitioning from OldDot to NewDot, we usually show the explanation modal if (isHybridAppOnboardingCompleted === false) { Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); - return; } - // If the hybrid app onboarding is completed, but the onboarding is not completed, we should start NewDot onboarding flow + // But if the hybrid app onboarding is completed, but NewDot onboarding is not completed, we start NewDot onboarding flow + // This is a special case when user created an account from NewDot without finishing the onboarding flow and then logged in from OldDot if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { - // Delay NewDot onboarding flow to hide the explanation modal in time - setTimeout(() => { - OnboardingFlow.startOnboardingFlow(); - }, variables.explanationModalDelay); - return; + OnboardingFlow.startOnboardingFlow(); } } From 15a0eda0898595af4cf9ab76e6458e4f976065e9 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 26 Sep 2024 14:37:41 +0200 Subject: [PATCH 18/21] Remove unsued variables --- src/styles/variables.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 300574514e59..4352eb6270a2 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -213,8 +213,6 @@ export default { restrictedActionIllustrationHeight: 136, photoUploadPopoverWidth: 335, onboardingModalWidth: 500, - welcomeVideoDelay: 1000, - explanationModalDelay: 2000, // The height of the empty list is 14px (2px for borders and 12px for vertical padding) // This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility From 993839270ede091e790f72decebf508561494028 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 26 Sep 2024 16:33:53 +0200 Subject: [PATCH 19/21] Refactor useOnboardingFlow to use useOnboardingFlowRouter --- src/hooks/useOnboardingFlow.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index f6467b2df28c..4b797d05115c 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -12,7 +12,7 @@ import ROUTES from '@src/ROUTES'; * * Warning: This hook should be used only once in the app */ -function useOnboardingFlow() { +function useOnboardingFlowRouter() { const [isOnboardingCompleted] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, }); @@ -43,4 +43,4 @@ function useOnboardingFlow() { return {isOnboardingCompleted, isHybridAppOnboardingCompleted}; } -export default useOnboardingFlow; +export default useOnboardingFlowRouter; From 12b4a392e3b138815799466a025848a789e6257a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 26 Sep 2024 16:34:23 +0200 Subject: [PATCH 20/21] Change names to be more consistent --- src/components/LHNOptionsList/OptionRowLHN.tsx | 4 ++-- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 4 ++-- src/libs/Navigation/NavigationRoot.tsx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index a106dd113779..3c4d57717b3b 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -47,7 +47,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${optionItem?.reportID || -1}`); const [isFirstTimeNewExpensifyUser] = useOnyx(ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER); - const [hasCompletedGuidedSetupFlow = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { + const [isOnboardingCompleted = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, }); const [shouldHideGBRTooltip] = useOnyx(ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP, {initialValue: true}); @@ -173,7 +173,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti shouldRender={ isFirstTimeNewExpensifyUser && !shouldHideGBRTooltip && - hasCompletedGuidedSetupFlow && + isOnboardingCompleted && isScreenFocused && shouldUseNarrowLayout && ReportUtils.isConciergeChatReport(report) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index d6ca53caabfd..a73ea4b694c9 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -9,7 +9,7 @@ import OptionsListContextProvider from '@components/OptionListContextProvider'; import {SearchContextProvider} from '@components/Search/SearchContext'; import SearchRouter from '@components/Search/SearchRouter/SearchRouter'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; -import useOnboardingFlow from '@hooks/useOnboardingFlow'; +import useOnboardingFlowRouter from '@hooks/useOnboardingFlow'; import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -231,7 +231,7 @@ function AuthScreens() { ); const modal = useRef({}); const [didPusherInit, setDidPusherInit] = useState(false); - const {isOnboardingCompleted} = useOnboardingFlow(); + const {isOnboardingCompleted} = useOnboardingFlowRouter(); let initialReportID: string | undefined; const isInitialRender = useRef(true); if (isInitialRender.current) { diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx index ff2ea1283ac8..39e3dfa697f1 100644 --- a/src/libs/Navigation/NavigationRoot.tsx +++ b/src/libs/Navigation/NavigationRoot.tsx @@ -92,7 +92,7 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady, sh const {setActiveWorkspaceID} = useActiveWorkspace(); const [user] = useOnyx(ONYXKEYS.USER); - const [hasCompletedGuidedSetupFlow = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { + const [isOnboardingCompleted = true] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, }); @@ -103,7 +103,7 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady, sh // If the user haven't completed the flow, we want to always redirect them to the onboarding flow. // We also make sure that the user is authenticated. - if (!NativeModules.HybridAppModule && !hasCompletedGuidedSetupFlow && authenticated && !shouldShowRequire2FAModal) { + if (!NativeModules.HybridAppModule && !isOnboardingCompleted && authenticated && !shouldShowRequire2FAModal) { const {adaptedState} = getAdaptedStateFromPath(getOnboardingInitialPath(), linkingConfig.config); return adaptedState; } From d45243517e54be842d14306dfdce9ee609d4b7ed Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 26 Sep 2024 16:43:51 +0200 Subject: [PATCH 21/21] Fix prettier --- src/components/LHNOptionsList/OptionRowLHN.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index 3c4d57717b3b..b2068bfe1b1b 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -171,12 +171,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti >