From c5d61ae285f53e06028a2ab76d8aedf711aba02d Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Sat, 20 Apr 2024 21:54:45 +0200 Subject: [PATCH] Adjust onboarding to BE changes --- src/ONYXKEYS.ts | 5 +++ src/libs/actions/Session/index.ts | 2 + src/libs/actions/Welcome.ts | 71 ++++++++++++------------------- src/types/onyx/Onboarding.ts | 6 +++ 4 files changed, 41 insertions(+), 43 deletions(-) create mode 100644 src/types/onyx/Onboarding.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 819680db0e8a..5a6efd8a7571 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -2,6 +2,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from './CONST'; import type * as FormTypes from './types/form'; import type * as OnyxTypes from './types/onyx'; +import type Onboarding from './types/onyx/Onboarding'; import type AssertTypesEqual from './types/utils/AssertTypesEqual'; import type DeepValueOf from './types/utils/DeepValueOf'; @@ -114,6 +115,9 @@ const ONYXKEYS = { /** Boolean flag only true when first set */ NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER: 'nvp_isFirstTimeNewExpensifyUser', + /** This NVP contains the choice that the user made on the engagement modal */ + NVP_ONBOARDING: 'nvp_onboarding', + /** Contains the user preference for the LHN priority mode */ NVP_PRIORITY_MODE: 'nvp_priorityMode', @@ -562,6 +566,7 @@ type OnyxValuesMapping = { [ONYXKEYS.ACCOUNT]: OnyxTypes.Account; [ONYXKEYS.ACCOUNT_MANAGER_REPORT_ID]: string; [ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER]: boolean; + [ONYXKEYS.NVP_ONBOARDING]: Onboarding | []; [ONYXKEYS.ACTIVE_CLIENTS]: string[]; [ONYXKEYS.DEVICE_ID]: string; [ONYXKEYS.IS_SIDEBAR_LOADED]: boolean; diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 7f7531a094fa..9fc1485cd6e5 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -39,6 +39,7 @@ import * as Device from '@userActions/Device'; import * as PriorityMode from '@userActions/PriorityMode'; import redirectToSignIn from '@userActions/SignInRedirect'; import Timing from '@userActions/Timing'; +import * as Welcome from '@userActions/Welcome'; import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -642,6 +643,7 @@ function resetHomeRouteParams() { function cleanupSession() { Pusher.disconnect(); Timers.clearAll(); + Welcome.resetAllChecks(); PriorityMode.resetHasReadRequiredDataFromStorage(); MainQueue.clear(); HttpUtils.cancelPendingRequests(); diff --git a/src/libs/actions/Welcome.ts b/src/libs/actions/Welcome.ts index e6eff28e1f6f..7264f98d3939 100644 --- a/src/libs/actions/Welcome.ts +++ b/src/libs/actions/Welcome.ts @@ -2,32 +2,28 @@ import type {OnyxCollection} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {SelectedPurposeType} from '@pages/OnboardingPurpose/BaseOnboardingPurpose'; import ONYXKEYS from '@src/ONYXKEYS'; +import type Onboarding from '@src/types/onyx/Onboarding'; import type OnyxPolicy from '@src/types/onyx/Policy'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; let hasSelectedPurpose: boolean | undefined; let hasProvidedPersonalDetails: boolean | undefined; -let isFirstTimeNewExpensifyUser: boolean | undefined; +let onboarding: Onboarding | [] | undefined; let hasDismissedModal: boolean | undefined; let isLoadingReportData = true; -type DetermineOnboardingStatusProps = { - onAble?: () => void; - onNotAble?: () => void; -}; - type HasCompletedOnboardingFlowProps = { onCompleted?: () => void; onNotCompleted?: () => void; }; let resolveIsReadyPromise: (value?: Promise) => void | undefined; -const isServerDataReadyPromise = new Promise((resolve) => { +let isServerDataReadyPromise = new Promise((resolve) => { resolveIsReadyPromise = resolve; }); let resolveOnboardingFlowStatus: (value?: Promise) => void | undefined; -const isOnboardingFlowStatusKnownPromise = new Promise((resolve) => { +let isOnboardingFlowStatusKnownPromise = new Promise((resolve) => { resolveOnboardingFlowStatus = resolve; }); @@ -35,40 +31,15 @@ function onServerDataReady(): Promise { return isServerDataReadyPromise; } -/** - * Checks if Onyx keys required to determine the - * onboarding flow status have been loaded (namely, - * are not undefined). - */ -function isAbleToDetermineOnboardingStatus({onAble, onNotAble}: DetermineOnboardingStatusProps) { - const hasRequiredOnyxKeysBeenLoaded = [hasProvidedPersonalDetails, hasSelectedPurpose].every((value) => value !== undefined); - - if (hasRequiredOnyxKeysBeenLoaded) { - onAble?.(); - } else { - onNotAble?.(); - } -} - -/** - * A promise returning the onboarding flow status. - * Returns true if user has completed the onboarding - * flow, false otherwise. - */ function isOnboardingFlowCompleted({onCompleted, onNotCompleted}: HasCompletedOnboardingFlowProps) { isOnboardingFlowStatusKnownPromise.then(() => { - if (!isFirstTimeNewExpensifyUser) { + if (Array.isArray(onboarding) || onboarding?.hasCompletedGuidedSetupFlow === undefined) { return; } - const onboardingFlowCompleted = hasProvidedPersonalDetails && hasSelectedPurpose; - - if (onboardingFlowCompleted) { + if (onboarding?.hasCompletedGuidedSetupFlow) { onCompleted?.(); } else { - // This key is only updated when we call ReconnectApp, setting it to false now allows the user to navigate normally instead of always redirecting to the workspace chat - Onyx.set(ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, false); - onNotCompleted?.(); } }); @@ -82,12 +53,13 @@ function isOnboardingFlowCompleted({onCompleted, onNotCompleted}: HasCompletedOn * - Whether we have loaded all reports the server knows about */ function checkOnReady() { - const hasRequiredOnyxKeysBeenLoaded = [isFirstTimeNewExpensifyUser, hasDismissedModal].every((value) => value !== undefined); + const hasRequiredOnyxKeysBeenLoaded = [onboarding, hasSelectedPurpose, hasDismissedModal, hasProvidedPersonalDetails].every((value) => value !== undefined); if (isLoadingReportData || !hasRequiredOnyxKeysBeenLoaded) { return; } + resolveOnboardingFlowStatus?.(); resolveIsReadyPromise?.(); } @@ -101,7 +73,7 @@ function getPersonalDetails(accountID: number | undefined) { } hasProvidedPersonalDetails = !!value[accountID]?.firstName && !!value[accountID]?.lastName; - isAbleToDetermineOnboardingStatus({onAble: resolveOnboardingFlowStatus}); + checkOnReady(); }, }); } @@ -111,13 +83,14 @@ function setOnboardingPurposeSelected(value: SelectedPurposeType) { } Onyx.connect({ - key: ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, + key: ONYXKEYS.NVP_ONBOARDING, initWithStoredValues: false, callback: (value) => { - // If isFirstTimeNewExpensifyUser was true do not update it to false. We update it to false inside the Welcome.isOnboardingFlowCompleted logic - // More context here https://github.com/Expensify/App/pull/16962#discussion_r1167351359 + if (value === null) { + return; + } - isFirstTimeNewExpensifyUser = value ?? undefined; + onboarding = value; checkOnReady(); }, @@ -128,7 +101,8 @@ Onyx.connect({ initWithStoredValues: true, callback: (value) => { hasSelectedPurpose = !!value; - isAbleToDetermineOnboardingStatus({onAble: resolveOnboardingFlowStatus}); + + checkOnReady(); }, }); @@ -179,4 +153,15 @@ Onyx.connect({ }, }); -export {onServerDataReady, isOnboardingFlowCompleted, setOnboardingPurposeSelected}; +function resetAllChecks() { + isServerDataReadyPromise = new Promise((resolve) => { + resolveIsReadyPromise = resolve; + }); + isOnboardingFlowStatusKnownPromise = new Promise((resolve) => { + resolveOnboardingFlowStatus = resolve; + }); + onboarding = undefined; + isLoadingReportData = true; +} + +export {onServerDataReady, isOnboardingFlowCompleted, setOnboardingPurposeSelected, resetAllChecks}; diff --git a/src/types/onyx/Onboarding.ts b/src/types/onyx/Onboarding.ts new file mode 100644 index 000000000000..3e069c63b062 --- /dev/null +++ b/src/types/onyx/Onboarding.ts @@ -0,0 +1,6 @@ +type Onboarding = { + /** A Boolean that informs whether the user has completed onboarding. */ + hasCompletedGuidedSetupFlow: boolean; +}; + +export default Onboarding;