Skip to content

Commit c07874f

Browse files
committed
Revert "Revert "Bring back new sign-in page""
This reverts commit def8188.
1 parent faeece6 commit c07874f

43 files changed

Lines changed: 620 additions & 294 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

__mocks__/@ua/react-native-airship.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ enum EventType {
66
PushReceived = 'com.airship.push_received',
77
}
88

9+
// eslint-disable-next-line no-restricted-syntax
10+
enum PermissionStatus {
11+
Granted = 'granted',
12+
Denied = 'denied',
13+
NotDetermined = 'not_determined',
14+
}
15+
916
// eslint-disable-next-line @typescript-eslint/no-namespace
1017
namespace iOS {
1118
/**
@@ -71,4 +78,4 @@ const Airship: Partial<AirshipRoot> = {
7178

7279
export default Airship;
7380

74-
export {EventType, iOS};
81+
export {EventType, iOS, PermissionStatus};

src/App.tsx

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {CurrentReportIDContextProvider} from './hooks/useCurrentReportID';
4141
import useDefaultDragAndDrop from './hooks/useDefaultDragAndDrop';
4242
import HybridAppHandler from './HybridAppHandler';
4343
import OnyxUpdateManager from './libs/actions/OnyxUpdateManager';
44+
import './libs/HybridApp';
4445
import {AttachmentModalContextProvider} from './pages/media/AttachmentModalScreen/AttachmentModalContext';
4546
import type {Route} from './ROUTES';
4647
import './setup/backgroundTask';
@@ -79,47 +80,53 @@ function App({url}: AppProps) {
7980
<InitialURLContextProvider url={url}>
8081
<HybridAppHandler />
8182
<GestureHandlerRootView style={fill}>
82-
<ComposeProviders
83-
components={[
84-
OnyxProvider,
85-
ThemeProvider,
86-
ThemeStylesProvider,
87-
ThemeIllustrationsProvider,
88-
SafeAreaProvider,
89-
PortalProvider,
90-
SafeArea,
91-
LocaleContextProvider,
92-
HTMLEngineProvider,
93-
PopoverContextProvider,
94-
CurrentReportIDContextProvider,
95-
ScrollOffsetContextProvider,
96-
AttachmentModalContextProvider,
97-
PickerStateProvider,
98-
EnvironmentProvider,
99-
CustomStatusBarAndBackgroundContextProvider,
100-
ActiveElementRoleProvider,
101-
ActionSheetAwareScrollViewProvider,
102-
PlaybackContextProvider,
103-
FullScreenContextProvider,
104-
VolumeContextProvider,
105-
VideoPopoverMenuContextProvider,
106-
KeyboardProvider,
107-
KeyboardStateProvider,
108-
SearchRouterContextProvider,
109-
ProductTrainingContextProvider,
110-
InputBlurContextProvider,
111-
FullScreenBlockingViewContextProvider,
112-
FullScreenLoaderContextProvider,
113-
]}
83+
<SafeAreaProvider
84+
initialMetrics={{
85+
insets: {top: 0, right: 0, bottom: 0, left: 0},
86+
frame: {x: 0, y: 0, width: 0, height: 0},
87+
}}
11488
>
115-
<CustomStatusBarAndBackground />
116-
<ErrorBoundary errorMessage="NewExpensify crash caught by error boundary">
117-
<ColorSchemeWrapper>
118-
<Expensify />
119-
</ColorSchemeWrapper>
120-
</ErrorBoundary>
121-
<NavigationBar />
122-
</ComposeProviders>
89+
<ComposeProviders
90+
components={[
91+
OnyxProvider,
92+
ThemeProvider,
93+
ThemeStylesProvider,
94+
ThemeIllustrationsProvider,
95+
PortalProvider,
96+
SafeArea,
97+
LocaleContextProvider,
98+
HTMLEngineProvider,
99+
PopoverContextProvider,
100+
CurrentReportIDContextProvider,
101+
ScrollOffsetContextProvider,
102+
AttachmentModalContextProvider,
103+
PickerStateProvider,
104+
EnvironmentProvider,
105+
CustomStatusBarAndBackgroundContextProvider,
106+
ActiveElementRoleProvider,
107+
ActionSheetAwareScrollViewProvider,
108+
PlaybackContextProvider,
109+
FullScreenContextProvider,
110+
VolumeContextProvider,
111+
VideoPopoverMenuContextProvider,
112+
KeyboardProvider,
113+
KeyboardStateProvider,
114+
SearchRouterContextProvider,
115+
ProductTrainingContextProvider,
116+
InputBlurContextProvider,
117+
FullScreenBlockingViewContextProvider,
118+
FullScreenLoaderContextProvider,
119+
]}
120+
>
121+
<CustomStatusBarAndBackground />
122+
<ErrorBoundary errorMessage="NewExpensify crash caught by error boundary">
123+
<ColorSchemeWrapper>
124+
<Expensify />
125+
</ColorSchemeWrapper>
126+
</ErrorBoundary>
127+
<NavigationBar />
128+
</ComposeProviders>
129+
</SafeAreaProvider>
123130
</GestureHandlerRootView>
124131
</InitialURLContextProvider>
125132
</SplashScreenStateContextProvider>

src/CONFIG.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ export default {
9595
GOOGLE_SIGN_IN: {
9696
// cspell:disable-next-line
9797
WEB_CLIENT_ID: '921154746561-gpsoaqgqfuqrfsjdf8l7vohfkfj7b9up.apps.googleusercontent.com',
98+
// cspell:disable-next-line
9899
IOS_CLIENT_ID: '921154746561-s3uqn2oe4m85tufi6mqflbfbuajrm2i3.apps.googleusercontent.com',
100+
// cspell:disable-next-line
101+
HYBRID_APP_WEB_CLIENT_ID: '1008697809946-5e095eqem3o6ugtpc2rjf7v880tcp28p.apps.googleusercontent.com',
102+
// cspell:disable-next-line
103+
HYBRID_APP_IOS_CLIENT_ID: '1008697809946-sh04nqq0hea396s1qdqqbj6ia649odb2.apps.googleusercontent.com',
99104
},
100105
GCP_GEOLOCATION_API_KEY: googleGeolocationAPIKey,
101106
FIREBASE_WEB_CONFIG: {

src/CONST/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6718,6 +6718,12 @@ const CONST = {
67186718
HIDDEN: `hidden`,
67196719
},
67206720

6721+
HYBRID_APP_SIGN_IN_STATE: {
6722+
NOT_STARTED: 'notStarted',
6723+
STARTED: 'started',
6724+
FINISHED: 'finished',
6725+
},
6726+
67216727
CSV_IMPORT_COLUMNS: {
67226728
EMAIL: 'email',
67236729
NAME: 'name',

src/Expensify.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ function Expensify() {
9999
const [isSidebarLoaded] = useOnyx(ONYXKEYS.IS_SIDEBAR_LOADED, {canBeMissing: true});
100100
const [screenShareRequest] = useOnyx(ONYXKEYS.SCREEN_SHARE_REQUEST, {canBeMissing: true});
101101
const [lastVisitedPath] = useOnyx(ONYXKEYS.LAST_VISITED_PATH, {canBeMissing: true});
102+
const [hybridApp] = useOnyx(ONYXKEYS.HYBRID_APP, {canBeMissing: true});
102103

103104
useDebugShortcut();
104105

@@ -114,10 +115,12 @@ function Expensify() {
114115
const isAuthenticated = useIsAuthenticated();
115116
const autoAuthState = useMemo(() => session?.autoAuthState ?? '', [session]);
116117

117-
const shouldInit = isNavigationReady && hasAttemptedToOpenPublicRoom && !!preferredLocale;
118-
const isSplashVisible = splashScreenState === CONST.BOOT_SPLASH_STATE.VISIBLE;
119-
const isHybridAppReady = splashScreenState === CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN && isAuthenticated;
120-
const shouldHideSplash = shouldInit && (CONFIG.IS_HYBRID_APP ? isHybridAppReady : isSplashVisible);
118+
const shouldInit = isNavigationReady && hasAttemptedToOpenPublicRoom && !!preferredLocale && (CONFIG.IS_HYBRID_APP ? !hybridApp?.loggedOutFromOldDot : true);
119+
const shouldHideSplash =
120+
shouldInit &&
121+
(CONFIG.IS_HYBRID_APP
122+
? splashScreenState === CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN && (isAuthenticated || !!hybridApp?.useNewDotSignInPage)
123+
: splashScreenState === CONST.BOOT_SPLASH_STATE.VISIBLE);
121124

122125
const initializeClient = () => {
123126
if (!Visibility.isVisible()) {

src/HybridAppHandler.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {setupNewDotAfterTransitionFromOldDot} from './libs/actions/Session';
88
import Log from './libs/Log';
99
import ONYXKEYS from './ONYXKEYS';
1010
import SplashScreenStateContext from './SplashScreenStateContext';
11+
import isLoadingOnyxValue from './types/utils/isLoadingOnyxValue';
1112

1213
function HybridAppHandler() {
1314
const {splashScreenState, setSplashScreenState} = useContext(SplashScreenStateContext);

src/ONYXKEYS.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,9 +476,6 @@ const ONYXKEYS = {
476476
/** Stores recently used currencies */
477477
RECENTLY_USED_CURRENCIES: 'nvp_recentlyUsedCurrencies',
478478

479-
/** States whether we transitioned from OldDot to show only certain group of screens. It should be undefined on pure NewDot. */
480-
IS_SINGLE_NEW_DOT_ENTRY: 'isSingleNewDotEntry',
481-
482479
/** Company cards custom names */
483480
NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES: 'nvp_expensify_ccCustomNames',
484481

@@ -535,6 +532,9 @@ const ONYXKEYS = {
535532
/** Set this gets redirected from global reimbursements flow */
536533
IS_COMING_FROM_GLOBAL_REIMBURSEMENTS_FLOW: 'isComingFromGlobalReimbursementsFlow',
537534

535+
/** Stores HybridApp specific state required to interoperate with OldDot */
536+
HYBRID_APP: 'hybridApp',
537+
538538
/** Stores information for OpenUnreportedExpensesPage API call pagination */
539539
HAS_MORE_UNREPORTED_TRANSACTIONS_RESULTS: 'hasMoreUnreportedTransactionsResults',
540540

@@ -1172,7 +1172,6 @@ type OnyxValuesMapping = {
11721172
[ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflowOnyx;
11731173
[ONYXKEYS.IMPORTED_SPREADSHEET]: OnyxTypes.ImportedSpreadsheet;
11741174
[ONYXKEYS.LAST_ROUTE]: string;
1175-
[ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY]: boolean | undefined;
11761175
[ONYXKEYS.IS_USING_IMPORTED_STATE]: boolean;
11771176
[ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES]: Record<string, string>;
11781177
[ONYXKEYS.CONCIERGE_REPORT_ID]: string;
@@ -1191,6 +1190,7 @@ type OnyxValuesMapping = {
11911190
[ONYXKEYS.SCHEDULE_CALL_DRAFT]: OnyxTypes.ScheduleCallDraft;
11921191
[ONYXKEYS.IS_FORCED_TO_CHANGE_CURRENCY]: boolean | undefined;
11931192
[ONYXKEYS.IS_COMING_FROM_GLOBAL_REIMBURSEMENTS_FLOW]: boolean | undefined;
1193+
[ONYXKEYS.HYBRID_APP]: OnyxTypes.HybridApp;
11941194
[ONYXKEYS.HAS_MORE_UNREPORTED_TRANSACTIONS_RESULTS]: boolean | undefined;
11951195
[ONYXKEYS.IS_LOADING_UNREPORTED_TRANSACTIONS]: boolean | undefined;
11961196
[ONYXKEYS.NVP_LAST_ECASH_IOS_LOGIN]: string;

src/components/BookTravelButton.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import HybridAppModule from '@expensify/react-native-hybrid-app';
21
import {Str} from 'expensify-common';
32
import type {ReactElement} from 'react';
4-
import React, {useCallback, useContext, useEffect, useState} from 'react';
3+
import React, {useCallback, useEffect, useState} from 'react';
54
import {useOnyx} from 'react-native-onyx';
65
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
76
import useLocalize from '@hooks/useLocalize';
@@ -22,7 +21,6 @@ import ROUTES from '@src/ROUTES';
2221
import {isEmptyObject} from '@src/types/utils/EmptyObject';
2322
import Button from './Button';
2423
import ConfirmModal from './ConfirmModal';
25-
import CustomStatusBarAndBackgroundContext from './CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContext';
2624
import DotIndicatorMessage from './DotIndicatorMessage';
2725
import {RocketDude} from './Icon/Illustrations';
2826
import Text from './Text';
@@ -62,7 +60,6 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false, se
6260
const [travelSettings] = useOnyx(ONYXKEYS.NVP_TRAVEL_SETTINGS, {canBeMissing: false});
6361
const [sessionEmail] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email, canBeMissing: false});
6462
const primaryContactMethod = primaryLogin ?? sessionEmail ?? '';
65-
const {setRootStatusBarEnabled} = useContext(CustomStatusBarAndBackgroundContext);
6663
const {isBlockedFromSpotnanaTravel, isBetaEnabled} = usePermissions();
6764
const [isPreventionModalVisible, setPreventionModalVisibility] = useState(false);
6865
const [isVerificationModalVisible, setVerificationModalVisibility] = useState(false);
@@ -72,7 +69,7 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false, se
7269
const groupPaidPolicies = activePolicies.filter((activePolicy) => activePolicy.type !== CONST.POLICY.TYPE.PERSONAL && isPaidGroupPolicy(activePolicy));
7370
// Flag indicating whether NewDot was launched exclusively for Travel,
7471
// e.g., when the user selects "Trips" from the Expensify Classic menu in HybridApp.
75-
const [wasNewDotLaunchedJustForTravel] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY, {canBeMissing: false});
72+
const [hybridApp] = useOnyx(ONYXKEYS.HYBRID_APP, {canBeMissing: true});
7673

7774
const hidePreventionModal = () => setPreventionModalVisibility(false);
7875
const hideVerificationModal = () => setVerificationModalVisibility(false);
@@ -130,15 +127,14 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false, se
130127
openTravelDotLink(policy?.id)
131128
?.then(() => {
132129
// When a user selects "Trips" in the Expensify Classic menu, the HybridApp opens the ManageTrips page in NewDot.
133-
// The wasNewDotLaunchedJustForTravel flag indicates if NewDot was launched solely for this purpose.
134-
if (!CONFIG.IS_HYBRID_APP || !wasNewDotLaunchedJustForTravel) {
130+
// The isSingleNewDotEntry flag indicates if NewDot was launched solely for this purpose.
131+
if (!CONFIG.IS_HYBRID_APP || !hybridApp?.isSingleNewDotEntry) {
135132
return;
136133
}
137134

138135
// Close NewDot if it was opened only for Travel, as its purpose is now fulfilled.
139136
Log.info('[HybridApp] Returning to OldDot after opening TravelDot');
140-
HybridAppModule.closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
141-
setRootStatusBarEnabled(false);
137+
closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
142138
})
143139
?.catch(() => {
144140
setErrorMessage(translate('travel.errorMessage'));
@@ -175,8 +171,7 @@ function BookTravelButton({text, shouldRenderErrorMessageBelowButton = false, se
175171
styles.link,
176172
StyleUtils,
177173
translate,
178-
wasNewDotLaunchedJustForTravel,
179-
setRootStatusBarEnabled,
174+
hybridApp?.isSingleNewDotEntry,
180175
isUserValidated,
181176
groupPaidPolicies.length,
182177
isBetaEnabled,

src/components/CustomStatusBarAndBackground/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import useTheme from '@hooks/useTheme';
55
import {navigationRef} from '@libs/Navigation/Navigation';
66
import StatusBar from '@libs/StatusBar';
77
import type {StatusBarStyle} from '@styles/index';
8+
import ONYXKEYS from '@src/ONYXKEYS';
9+
import {useOnyx} from '../../../__mocks__/react-native-onyx';
810
import CustomStatusBarAndBackgroundContext from './CustomStatusBarAndBackgroundContext';
911
import updateGlobalBackgroundColor from './updateGlobalBackgroundColor';
1012
import updateStatusBarAppearance from './updateStatusBarAppearance';
@@ -19,8 +21,9 @@ function CustomStatusBarAndBackground({isNested = false}: CustomStatusBarAndBack
1921
const {isRootStatusBarEnabled, setRootStatusBarEnabled} = useContext(CustomStatusBarAndBackgroundContext);
2022
const theme = useTheme();
2123
const [statusBarStyle, setStatusBarStyle] = useState<StatusBarStyle>();
24+
const [hybridApp] = useOnyx(ONYXKEYS.HYBRID_APP, {canBeMissing: true});
2225

23-
const isDisabled = !isNested && !isRootStatusBarEnabled;
26+
const isDisabled = (!isNested && !isRootStatusBarEnabled) || (hybridApp?.closingReactNativeApp ?? false);
2427

2528
// Disable the root status bar when a nested status bar is rendered
2629
useEffect(() => {

src/components/ScreenWrapper/index.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import HybridAppModule from '@expensify/react-native-hybrid-app';
21
import {useIsFocused, useNavigation, usePreventRemove} from '@react-navigation/native';
32
import type {ForwardedRef, ReactNode} from 'react';
43
import React, {forwardRef, useContext, useEffect, useMemo, useState} from 'react';
@@ -7,7 +6,6 @@ import {Keyboard} from 'react-native';
76
import {useOnyx} from 'react-native-onyx';
87
import type {EdgeInsets} from 'react-native-safe-area-context';
98
import CustomDevMenu from '@components/CustomDevMenu';
10-
import CustomStatusBarAndBackgroundContext from '@components/CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContext';
119
import FocusTrapForScreen from '@components/FocusTrap/FocusTrapForScreen';
1210
import type FocusTrapForScreenProps from '@components/FocusTrap/FocusTrapForScreen/FocusTrapProps';
1311
import HeaderGap from '@components/HeaderGap';
@@ -18,6 +16,7 @@ import useNetwork from '@hooks/useNetwork';
1816
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1917
import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings';
2018
import useThemeStyles from '@hooks/useThemeStyles';
19+
import {closeReactNativeApp} from '@libs/actions/Session';
2120
import NarrowPaneContext from '@libs/Navigation/AppNavigator/Navigators/NarrowPaneContext';
2221
import Navigation from '@libs/Navigation/Navigation';
2322
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -170,15 +169,13 @@ function ScreenWrapper(
170169
const shouldOffsetMobileOfflineIndicator = displaySmallScreenOfflineIndicator && addSmallScreenOfflineIndicatorBottomSafeAreaPadding && isOffline;
171170

172171
const {initialURL} = useContext(InitialURLContext);
173-
const [isSingleNewDotEntry] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY, {canBeMissing: true});
174-
const {setRootStatusBarEnabled} = useContext(CustomStatusBarAndBackgroundContext);
172+
const [hybridApp] = useOnyx(ONYXKEYS.HYBRID_APP, {canBeMissing: true});
175173

176-
usePreventRemove((isSingleNewDotEntry ?? false) && initialURL === Navigation.getActiveRouteWithoutParams(), () => {
174+
usePreventRemove((hybridApp?.isSingleNewDotEntry ?? false) && initialURL === Navigation.getActiveRouteWithoutParams(), () => {
177175
if (!CONFIG.IS_HYBRID_APP) {
178176
return;
179177
}
180-
HybridAppModule.closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
181-
setRootStatusBarEnabled(false);
178+
closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
182179
});
183180

184181
useEffect(() => {

0 commit comments

Comments
 (0)