From cd9776c95bfacc3312416ed3e35e5c725962e0c0 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 21 Oct 2024 10:34:01 -0700 Subject: [PATCH] Merge pull request #51155 from Expensify/revert-49602-use-newdot-travel-page-on-olddot Revert "[HybridApp] Allow classic experience users to use NewDot travel page" (cherry picked from commit 008306791f3283b7524cbd6e1f621aed33b8edde) (CP triggered by AndrewGable) --- src/ONYXKEYS.ts | 4 -- src/components/InitialURLContextProvider.tsx | 7 ++- src/components/ScreenWrapper.tsx | 13 +---- src/hooks/useOnboardingFlow.ts | 8 ++- src/libs/TripReservationUtils.ts | 25 ++------- src/libs/actions/Link.ts | 6 +-- src/libs/actions/Session/index.ts | 53 +++++++------------- tests/perf-test/ReportScreen.perf-test.tsx | 4 +- tests/perf-test/SearchRouter.perf-test.tsx | 2 - 9 files changed, 34 insertions(+), 88 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 14c0dc4abc50..d083a46d7760 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -441,9 +441,6 @@ const ONYXKEYS = { /** Stores recently used currencies */ RECENTLY_USED_CURRENCIES: 'nvp_recentlyUsedCurrencies', - /** States whether we transitioned from OldDot to show only certain group of screens. It should be undefined on pure NewDot. */ - IS_SINGLE_NEW_DOT_ENTRY: 'isSingleNewDotEntry', - /** Company cards custom names */ NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES: 'nvp_expensify_ccCustomNames', @@ -1007,7 +1004,6 @@ type OnyxValuesMapping = { [ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflowOnyx; [ONYXKEYS.IMPORTED_SPREADSHEET]: OnyxTypes.ImportedSpreadsheet; [ONYXKEYS.LAST_ROUTE]: string; - [ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY]: boolean | undefined; [ONYXKEYS.IS_USING_IMPORTED_STATE]: boolean; [ONYXKEYS.SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP]: boolean; [ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES]: Record; diff --git a/src/components/InitialURLContextProvider.tsx b/src/components/InitialURLContextProvider.tsx index f026f2de53f9..85ad54ca6c94 100644 --- a/src/components/InitialURLContextProvider.tsx +++ b/src/components/InitialURLContextProvider.tsx @@ -31,10 +31,9 @@ function InitialURLContextProvider({children, url}: InitialURLContextProviderPro useEffect(() => { if (url) { - signInAfterTransitionFromOldDot(url).then((route) => { - setInitialURL(route); - setSplashScreenState(CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN); - }); + const route = signInAfterTransitionFromOldDot(url); + setInitialURL(route); + setSplashScreenState(CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN); return; } Linking.getInitialURL().then((initURL) => { diff --git a/src/components/ScreenWrapper.tsx b/src/components/ScreenWrapper.tsx index 46534d27b9c0..9a85e1d3af24 100644 --- a/src/components/ScreenWrapper.tsx +++ b/src/components/ScreenWrapper.tsx @@ -1,9 +1,9 @@ -import {UNSTABLE_usePreventRemove, useIsFocused, useNavigation, useRoute} from '@react-navigation/native'; +import {useIsFocused, useNavigation} from '@react-navigation/native'; import type {StackNavigationProp} from '@react-navigation/stack'; import type {ForwardedRef, ReactNode} from 'react'; import React, {createContext, forwardRef, useEffect, useMemo, useRef, useState} from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; -import {Keyboard, NativeModules, PanResponder, View} from 'react-native'; +import {Keyboard, PanResponder, View} from 'react-native'; import {PickerAvoidingView} from 'react-native-picker-select'; import type {EdgeInsets} from 'react-native-safe-area-context'; import useEnvironment from '@hooks/useEnvironment'; @@ -161,15 +161,6 @@ function ScreenWrapper( isKeyboardShownRef.current = keyboardState?.isKeyboardShown ?? false; - const route = useRoute(); - const shouldReturnToOldDot = useMemo(() => { - return !!route?.params && 'singleNewDotEntry' in route.params && route.params.singleNewDotEntry === 'true'; - }, [route]); - - UNSTABLE_usePreventRemove(shouldReturnToOldDot, () => { - NativeModules.HybridAppModule?.closeReactNativeApp(false, false); - }); - const panResponder = useRef( PanResponder.create({ onStartShouldSetPanResponderCapture: (_e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS, diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index 9e97c552a6e0..5ccd3bab9378 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -21,16 +21,14 @@ function useOnboardingFlowRouter() { selector: hasCompletedHybridAppOnboardingFlowSelector, }); - const [isSingleNewDotEntry, isSingleNewDotEntryMetadata] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY); - useEffect(() => { - if (isLoadingOnyxValue(isOnboardingCompletedMetadata, isHybridAppOnboardingCompletedMetadata, isSingleNewDotEntryMetadata)) { + if (isLoadingOnyxValue(isOnboardingCompletedMetadata, isHybridAppOnboardingCompletedMetadata)) { return; } if (NativeModules.HybridAppModule) { // When user is transitioning from OldDot to NewDot, we usually show the explanation modal - if (isHybridAppOnboardingCompleted === false && !isSingleNewDotEntry) { + if (isHybridAppOnboardingCompleted === false) { Navigation.navigate(ROUTES.EXPLANATION_MODAL_ROOT); } @@ -45,7 +43,7 @@ function useOnboardingFlowRouter() { if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) { OnboardingFlow.startOnboardingFlow(); } - }, [isOnboardingCompleted, isHybridAppOnboardingCompleted, isOnboardingCompletedMetadata, isHybridAppOnboardingCompletedMetadata, isSingleNewDotEntryMetadata, isSingleNewDotEntry]); + }, [isOnboardingCompleted, isHybridAppOnboardingCompleted, isOnboardingCompletedMetadata, isHybridAppOnboardingCompletedMetadata]); return {isOnboardingCompleted, isHybridAppOnboardingCompleted}; } diff --git a/src/libs/TripReservationUtils.ts b/src/libs/TripReservationUtils.ts index f2ce5113af81..b7f754f9cac6 100644 --- a/src/libs/TripReservationUtils.ts +++ b/src/libs/TripReservationUtils.ts @@ -1,6 +1,5 @@ import {Str} from 'expensify-common'; import type {Dispatch, SetStateAction} from 'react'; -import {NativeModules} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; @@ -14,7 +13,6 @@ import type Transaction from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import * as Link from './actions/Link'; -import Log from './Log'; import Navigation from './Navigation/Navigation'; import * as PolicyUtils from './PolicyUtils'; @@ -42,14 +40,6 @@ Onyx.connect({ }, }); -let isSingleNewDotEntry: boolean | undefined; -Onyx.connect({ - key: ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY, - callback: (val) => { - isSingleNewDotEntry = val; - }, -}); - function getTripReservationIcon(reservationType: ReservationType): IconAsset { switch (reservationType) { case CONST.RESERVATION_TYPE.FLIGHT: @@ -101,17 +91,8 @@ function bookATrip(translate: LocaleContextProps['translate'], setCtaErrorMessag if (ctaErrorMessage) { setCtaErrorMessage(''); } - Link.openTravelDotLink(activePolicyID) - ?.then(() => { - if (!NativeModules.HybridAppModule || !isSingleNewDotEntry) { - return; - } - - Log.info('[HybridApp] Returning to OldDot after opening TravelDot'); - NativeModules.HybridAppModule.closeReactNativeApp(false, false); - }) - ?.catch(() => { - setCtaErrorMessage(translate('travel.errorMessage')); - }); + Link.openTravelDotLink(activePolicyID)?.catch(() => { + setCtaErrorMessage(translate('travel.errorMessage')); + }); } export {getTripReservationIcon, getReservationsFromTripTransactions, getTripEReceiptIcon, bookATrip}; diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts index 4cda676d89e8..13fcea0df85d 100644 --- a/src/libs/actions/Link.ts +++ b/src/libs/actions/Link.ts @@ -111,7 +111,7 @@ function openTravelDotLink(policyID: OnyxEntry, postLoginPath?: string) policyID, }; - return new Promise((resolve, reject) => { + return new Promise((_, reject) => { const error = new Error('Failed to generate spotnana token.'); asyncOpenURL( @@ -122,9 +122,7 @@ function openTravelDotLink(policyID: OnyxEntry, postLoginPath?: string) reject(error); throw error; } - const travelURL = buildTravelDotURL(response.spotnanaToken, postLoginPath); - resolve(undefined); - return travelURL; + return buildTravelDotURL(response.spotnanaToken, postLoginPath); }) .catch(() => { reject(error); diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index c93a263a8f74..4d6ba6cfa774 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -482,43 +482,28 @@ function signUpUser() { function signInAfterTransitionFromOldDot(transitionURL: string) { const [route, queryParams] = transitionURL.split('?'); - const {email, authToken, encryptedAuthToken, accountID, autoGeneratedLogin, autoGeneratedPassword, clearOnyxOnStart, completedHybridAppOnboarding, isSingleNewDotEntry, primaryLogin} = - Object.fromEntries( - queryParams.split('&').map((param) => { - const [key, value] = param.split('='); - return [key, value]; - }), - ); - - const clearOnyxForNewAccount = () => { - if (clearOnyxOnStart !== 'true') { - return Promise.resolve(); - } - - return Onyx.clear(KEYS_TO_PRESERVE); + const {email, authToken, encryptedAuthToken, accountID, autoGeneratedLogin, autoGeneratedPassword, clearOnyxOnStart, completedHybridAppOnboarding} = Object.fromEntries( + queryParams.split('&').map((param) => { + const [key, value] = param.split('='); + return [key, value]; + }), + ); + + const setSessionDataAndOpenApp = () => { + 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); }; - const setSessionDataAndOpenApp = new Promise((resolve) => { - clearOnyxForNewAccount() - .then(() => - Onyx.multiSet({ - [ONYXKEYS.SESSION]: {email, authToken, encryptedAuthToken: decodeURIComponent(encryptedAuthToken), accountID: Number(accountID)}, - [ONYXKEYS.ACCOUNT]: {primaryLogin}, - [ONYXKEYS.CREDENTIALS]: {autoGeneratedLogin, autoGeneratedPassword}, - [ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY]: isSingleNewDotEntry === 'true', - [ONYXKEYS.NVP_TRYNEWDOT]: {classicRedirect: {completedHybridAppOnboarding: completedHybridAppOnboarding === 'true'}}, - }), - ) - .then(App.openApp) - .catch((error) => { - Log.hmmm('[HybridApp] Initialization of HybridApp has failed. Forcing transition', {error}); - }) - .finally(() => { - resolve(`${route}?singleNewDotEntry=${isSingleNewDotEntry}` as Route); - }); - }); + if (clearOnyxOnStart === 'true') { + Onyx.clear(KEYS_TO_PRESERVE).then(setSessionDataAndOpenApp); + } else { + setSessionDataAndOpenApp(); + } - return setSessionDataAndOpenApp; + return route as Route; } /** diff --git a/tests/perf-test/ReportScreen.perf-test.tsx b/tests/perf-test/ReportScreen.perf-test.tsx index b43004fcc82b..550b6adabc36 100644 --- a/tests/perf-test/ReportScreen.perf-test.tsx +++ b/tests/perf-test/ReportScreen.perf-test.tsx @@ -118,8 +118,6 @@ jest.mock('@react-navigation/native', () => { useFocusEffect: jest.fn(), useIsFocused: () => true, useRoute: () => jest.fn(), - // eslint-disable-next-line @typescript-eslint/naming-convention - UNSTABLE_usePreventRemove: () => jest.fn(), useNavigation: () => ({ navigate: jest.fn(), addListener: () => jest.fn(), @@ -233,6 +231,7 @@ test('[ReportScreen] should render ReportScreen', async () => { ...reportCollectionDataSet, ...reportActionsCollectionDataSet, }); + await measureRenders( { ...reportCollectionDataSet, ...reportActionsCollectionDataSet, }); + await measureRenders( { useFocusEffect: jest.fn(), useIsFocused: () => true, useRoute: () => jest.fn(), - // eslint-disable-next-line @typescript-eslint/naming-convention - UNSTABLE_usePreventRemove: () => jest.fn(), useNavigation: () => ({ navigate: jest.fn(), addListener: () => jest.fn(),