Skip to content

Commit 53883d3

Browse files
authored
Merge pull request Expensify#65178 from software-mansion-labs/fix-reload-on-new-sign-in-page
Bring back new `SignInPage`
2 parents a3c24e1 + 18baf7e commit 53883d3

35 files changed

Lines changed: 553 additions & 208 deletions

File tree

__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};

modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridApp.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,22 @@ class ReactNativeHybridApp(reactContext: ReactApplicationContext) :
5151
override fun onURLListenerAdded() {
5252
Log.d(NAME, "`onURLListenerAdded` should never be called in standalone `New Expensify` app")
5353
}
54+
55+
override fun signInToOldDot(
56+
autoGeneratedLogin: String,
57+
autoGeneratedPassword: String,
58+
authToken: String,
59+
email: String,
60+
policyID: String
61+
) {
62+
Log.d(NAME, "`signInToOldDot` should never be called in standalone `New Expensify` app")
63+
}
64+
65+
override fun signOutFromOldDot() {
66+
Log.d(NAME, "`signOutFromOldDot` should never be called in standalone `New Expensify` app")
67+
}
68+
69+
override fun clearOldDotAfterSignOut() {
70+
Log.d(NAME, "`clearOldDotAfterSignOut` should never be called in standalone `New Expensify` app")
71+
}
5472
}

modules/hybrid-app/ios/ReactNativeHybridApp.mm

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ - (void)onURLListenerAdded {
4343
NSLog(@"[ReactNativeHybridApp] `onURLListenerAdded` should never be called in standalone `New Expensify` app");
4444
}
4545

46+
- (void)signInToOldDot:(NSString *)autoGeneratedLogin autoGeneratedPassword:(NSString *)autoGeneratedPassword authToken:(NSString *)authToken email:(NSString *)email policyID:(NSString *)policyID {
47+
NSLog(@"[ReactNativeHybridApp] `signInToOldDot` should never be called in standalone `New Expensify` app");
48+
}
49+
50+
- (void)signOutFromOldDot {
51+
NSLog(@"[ReactNativeHybridApp] `signOutFromOldDot` should never be called in standalone `New Expensify` app");
52+
}
53+
54+
- (void)clearOldDotAfterSignOut {
55+
NSLog(@"[ReactNativeHybridApp] `clearOldDotAfterSignOut` should never be called in standalone `New Expensify` app");
56+
}
57+
4658
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
4759
(const facebook::react::ObjCTurboModule::InitParams &)params
4860
{

modules/hybrid-app/src/NativeReactNativeHybridApp.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export interface Spec extends TurboModule {
1212
getHybridAppSettings: () => Promise<string | null>;
1313
getInitialURL(): Promise<string | null>;
1414
onURLListenerAdded: () => void;
15+
signInToOldDot: (autoGeneratedLogin: string, autoGeneratedPassword: string, authToken: string, email: string, policyID: string) => void;
16+
signOutFromOldDot: () => void;
17+
clearOldDotAfterSignOut: () => void;
1518
}
1619

1720
export default TurboModuleRegistry.getEnforcing<Spec>('ReactNativeHybridApp');

modules/hybrid-app/src/index.native.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ const HybridAppModule: HybridAppModuleType = {
2929
onURLListenerAdded() {
3030
ReactNativeHybridApp.onURLListenerAdded();
3131
},
32+
signInToOldDot({autoGeneratedLogin, autoGeneratedPassword, authToken, email, policyID}) {
33+
ReactNativeHybridApp.signInToOldDot(autoGeneratedLogin, autoGeneratedPassword, authToken, email, policyID);
34+
},
35+
signOutFromOldDot() {
36+
ReactNativeHybridApp.signOutFromOldDot();
37+
},
38+
clearOldDotAfterSignOut() {
39+
ReactNativeHybridApp.clearOldDotAfterSignOut();
40+
},
3241
};
3342

3443
export default HybridAppModule;

modules/hybrid-app/src/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ const HybridAppModule: HybridAppModuleType = {
3838
// eslint-disable-next-line no-console
3939
console.warn('HybridAppModule: `onURLListenerAdded` should never be called on web');
4040
},
41+
signInToOldDot() {
42+
// eslint-disable-next-line no-console
43+
console.warn('HybridAppModule: `signInToOldDot` should never be called on web');
44+
},
45+
signOutFromOldDot() {
46+
// eslint-disable-next-line no-console
47+
console.warn('HybridAppModule: `signOutFromOldDot` should never be called on web');
48+
},
49+
clearOldDotAfterSignOut() {
50+
// eslint-disable-next-line no-console
51+
console.warn('HybridAppModule: `clearOldDotAfterSignOut` should never be called on web');
52+
},
4153
};
4254

4355
export default HybridAppModule;

modules/hybrid-app/src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ type HybridAppModuleType = {
88
getHybridAppSettings: () => Promise<string | null>;
99
getInitialURL(): Promise<string | null>;
1010
onURLListenerAdded: () => void;
11+
signInToOldDot: (args: {autoGeneratedLogin: string; autoGeneratedPassword: string; authToken: string; email: string; policyID: string}) => void;
12+
signOutFromOldDot: () => void;
13+
clearOldDotAfterSignOut: () => void;
1114
};
1215

1316
export default HybridAppModuleType;

src/App.tsx

Lines changed: 51 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 './setup/backgroundTask';
4647
import './setup/hybridApp';
@@ -69,47 +70,57 @@ function App() {
6970
<InitialURLContextProvider>
7071
<HybridAppHandler />
7172
<GestureHandlerRootView style={fill}>
72-
<ComposeProviders
73-
components={[
74-
OnyxListItemProvider,
75-
ThemeProvider,
76-
ThemeStylesProvider,
77-
ThemeIllustrationsProvider,
78-
SafeAreaProvider,
79-
HTMLEngineProvider,
80-
PortalProvider,
81-
SafeArea,
82-
LocaleContextProvider,
83-
PopoverContextProvider,
84-
CurrentReportIDContextProvider,
85-
ScrollOffsetContextProvider,
86-
AttachmentModalContextProvider,
87-
PickerStateProvider,
88-
EnvironmentProvider,
89-
CustomStatusBarAndBackgroundContextProvider,
90-
ActiveElementRoleProvider,
91-
ActionSheetAwareScrollViewProvider,
92-
PlaybackContextProvider,
93-
FullScreenContextProvider,
94-
VolumeContextProvider,
95-
VideoPopoverMenuContextProvider,
96-
KeyboardProvider,
97-
KeyboardStateProvider,
98-
SearchRouterContextProvider,
99-
ProductTrainingContextProvider,
100-
InputBlurContextProvider,
101-
FullScreenBlockingViewContextProvider,
102-
FullScreenLoaderContextProvider,
103-
]}
73+
{/* Initialize metrics early to ensure the UI renders even when NewDot is hidden.
74+
This is necessary for iOS HybridApp's SignInPage to appear correctly without the bootsplash.
75+
See: https://github.com/Expensify/App/pull/65178#issuecomment-3139026551
76+
*/}
77+
<SafeAreaProvider
78+
initialMetrics={{
79+
insets: {top: 0, right: 0, bottom: 0, left: 0},
80+
frame: {x: 0, y: 0, width: 0, height: 0},
81+
}}
10482
>
105-
<CustomStatusBarAndBackground />
106-
<ErrorBoundary errorMessage="NewExpensify crash caught by error boundary">
107-
<ColorSchemeWrapper>
108-
<Expensify />
109-
</ColorSchemeWrapper>
110-
</ErrorBoundary>
111-
<NavigationBar />
112-
</ComposeProviders>
83+
<ComposeProviders
84+
components={[
85+
OnyxListItemProvider,
86+
ThemeProvider,
87+
ThemeStylesProvider,
88+
ThemeIllustrationsProvider,
89+
HTMLEngineProvider,
90+
PortalProvider,
91+
SafeArea,
92+
LocaleContextProvider,
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+
]}
114+
>
115+
<CustomStatusBarAndBackground />
116+
<ErrorBoundary errorMessage="NewExpensify crash caught by error boundary">
117+
<ColorSchemeWrapper>
118+
<Expensify />
119+
</ColorSchemeWrapper>
120+
</ErrorBoundary>
121+
<NavigationBar />
122+
</ComposeProviders>
123+
</SafeAreaProvider>
113124
</GestureHandlerRootView>
114125
</InitialURLContextProvider>
115126
</SplashScreenStateContextProvider>

src/CONFIG.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,18 @@ 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+
HYBRID_APP: {
101+
// cspell:disable-next-line
102+
IOS_CLIENT_ID: '1008697809946-sh04nqq0hea396s1qdqqbj6ia649odb2.apps.googleusercontent.com',
103+
WEB_CLIENT_ID: {
104+
// cspell:disable-next-line
105+
IOS: '1008697809946-5e095eqem3o6ugtpc2rjf7v880tcp28p.apps.googleusercontent.com',
106+
// cspell:disable-next-line
107+
ANDROID: '240677659774-86pov3adub93cv4b8uj13g7varolmk2l.apps.googleusercontent.com',
108+
},
109+
},
99110
},
100111
GCP_GEOLOCATION_API_KEY: googleGeolocationAPIKey,
101112
FIREBASE_WEB_CONFIG: {

src/Expensify.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ function Expensify() {
105105
const [currentOnboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, {canBeMissing: true});
106106
const [currentOnboardingCompanySize] = useOnyx(ONYXKEYS.ONBOARDING_COMPANY_SIZE, {canBeMissing: true});
107107
const [onboardingInitialPath] = useOnyx(ONYXKEYS.ONBOARDING_LAST_VISITED_PATH, {canBeMissing: true});
108+
const [hybridApp] = useOnyx(ONYXKEYS.HYBRID_APP, {canBeMissing: true});
108109

109110
useDebugShortcut();
110111
usePriorityMode();
@@ -121,10 +122,22 @@ function Expensify() {
121122
const isAuthenticated = useIsAuthenticated();
122123
const autoAuthState = useMemo(() => session?.autoAuthState ?? '', [session]);
123124

124-
const shouldInit = isNavigationReady && hasAttemptedToOpenPublicRoom && !!preferredLocale;
125+
const isSplashReadyToBeHidden = splashScreenState === CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN;
125126
const isSplashVisible = splashScreenState === CONST.BOOT_SPLASH_STATE.VISIBLE;
126-
const isHybridAppReady = splashScreenState === CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN && isAuthenticated;
127-
const shouldHideSplash = shouldInit && (CONFIG.IS_HYBRID_APP ? isHybridAppReady : isSplashVisible);
127+
128+
const shouldInit = isNavigationReady && hasAttemptedToOpenPublicRoom && !!preferredLocale;
129+
const shouldHideSplash = (isSplashReadyToBeHidden || isSplashVisible) && shouldInit && !hybridApp?.loggedOutFromOldDot;
130+
131+
// This effect is closing OldDot sign out modal based on splash screen state
132+
useEffect(() => {
133+
if (!isSplashReadyToBeHidden || !shouldInit || !hybridApp?.loggedOutFromOldDot) {
134+
return;
135+
}
136+
137+
setSplashScreenState(CONST.BOOT_SPLASH_STATE.HIDDEN);
138+
HybridAppModule.clearOldDotAfterSignOut();
139+
}, [hybridApp?.loggedOutFromOldDot, isSplashReadyToBeHidden, setSplashScreenState, shouldInit, splashScreenState]);
140+
128141
const initializeClient = () => {
129142
if (!Visibility.isVisible()) {
130143
return;

0 commit comments

Comments
 (0)