diff --git a/src/components/HybridAppMiddleware/index.ios.tsx b/src/components/HybridAppMiddleware/index.ios.tsx index 5b06e5626c6e..c348cc86c974 100644 --- a/src/components/HybridAppMiddleware/index.ios.tsx +++ b/src/components/HybridAppMiddleware/index.ios.tsx @@ -3,6 +3,7 @@ import {useContext, useEffect, useState} from 'react'; import {NativeEventEmitter, NativeModules} from 'react-native'; import type {NativeModule} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import {InitialURLContext} from '@components/InitialURLContextProvider'; import useExitTo from '@hooks/useExitTo'; import useSplashScreen from '@hooks/useSplashScreen'; @@ -14,12 +15,23 @@ import * as Welcome from '@userActions/Welcome'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {HybridAppRoute, Route} from '@src/ROUTES'; +import type {TryNewDot} from '@src/types/onyx'; type HybridAppMiddlewareProps = { authenticated: boolean; children: React.ReactNode; }; +const onboardingStatusSelector = (tryNewDot: OnyxEntry) => { + let completedHybridAppOnboarding = tryNewDot?.classicRedirect?.completedHybridAppOnboarding; + + if (typeof completedHybridAppOnboarding === 'string') { + completedHybridAppOnboarding = completedHybridAppOnboarding === 'true'; + } + + return completedHybridAppOnboarding; +}; + /* * HybridAppMiddleware is responsible for handling BootSplash visibility correctly. * It is crucial to make transitions between OldDot and NewDot look smooth. @@ -36,6 +48,20 @@ function HybridAppMiddleware({children, authenticated}: HybridAppMiddlewareProps const [isAccountLoading] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.isLoading ?? false}); const [sessionEmail] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email}); + const [completedHybridAppOnboarding] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, {selector: onboardingStatusSelector}); + + /** + * This useEffect tracks changes of `nvp_tryNewDot` value. + * We propagate it from OldDot to NewDot with native method due to limitations of old app. + */ + useEffect(() => { + if (completedHybridAppOnboarding === undefined) { + return; + } + + Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding}); + NativeModules.HybridAppModule.completeOnboarding(completedHybridAppOnboarding); + }, [completedHybridAppOnboarding]); // In iOS, the HybridApp defines the `onReturnToOldDot` event. // If we frequently transition from OldDot to NewDot during a single app lifecycle, diff --git a/src/components/HybridAppMiddleware/index.tsx b/src/components/HybridAppMiddleware/index.tsx index b8c72d9200ac..b3d346a1b65c 100644 --- a/src/components/HybridAppMiddleware/index.tsx +++ b/src/components/HybridAppMiddleware/index.tsx @@ -2,6 +2,7 @@ import type React from 'react'; import {useContext, useEffect, useState} from 'react'; import {NativeModules} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import {InitialURLContext} from '@components/InitialURLContextProvider'; import useExitTo from '@hooks/useExitTo'; import useSplashScreen from '@hooks/useSplashScreen'; @@ -13,12 +14,23 @@ import * as Welcome from '@userActions/Welcome'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {HybridAppRoute, Route} from '@src/ROUTES'; +import type {TryNewDot} from '@src/types/onyx'; type HybridAppMiddlewareProps = { authenticated: boolean; children: React.ReactNode; }; +const onboardingStatusSelector = (tryNewDot: OnyxEntry) => { + let completedHybridAppOnboarding = tryNewDot?.classicRedirect?.completedHybridAppOnboarding; + + if (typeof completedHybridAppOnboarding === 'string') { + completedHybridAppOnboarding = completedHybridAppOnboarding === 'true'; + } + + return completedHybridAppOnboarding; +}; + /* * HybridAppMiddleware is responsible for handling BootSplash visibility correctly. * It is crucial to make transitions between OldDot and NewDot look smooth. @@ -35,6 +47,20 @@ function HybridAppMiddleware({children, authenticated}: HybridAppMiddlewareProps const [isAccountLoading] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.isLoading ?? false}); const [sessionEmail] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email}); + const [completedHybridAppOnboarding] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, {selector: onboardingStatusSelector}); + + /** + * This useEffect tracks changes of `nvp_tryNewDot` value. + * We propagate it from OldDot to NewDot with native method due to limitations of old app. + */ + useEffect(() => { + if (completedHybridAppOnboarding === undefined) { + return; + } + + Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding}); + NativeModules.HybridAppModule.completeOnboarding(completedHybridAppOnboarding); + }, [completedHybridAppOnboarding]); // Save `exitTo` when we reach /transition route. // `exitTo` should always exist during OldDot -> NewDot transitions. diff --git a/src/libs/actions/Welcome.ts b/src/libs/actions/Welcome.ts index b592424cfcdf..19797caee1a8 100644 --- a/src/libs/actions/Welcome.ts +++ b/src/libs/actions/Welcome.ts @@ -96,7 +96,7 @@ function handleHybridAppOnboarding() { isOnboardingFlowCompleted({ onNotCompleted: () => setTimeout(() => { - Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); + Navigation.navigate(ROUTES.ONBOARDING_ROOT); }, variables.explanationModalDelay), }), }); diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts index a2e271a3839d..2efab8e90cfc 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -12,6 +12,7 @@ import type StartupTimer from '@libs/StartupTimer/types'; type HybridAppModule = { closeReactNativeApp: () => void; + completeOnboarding: (status: boolean) => void; exitApp: () => void; };