diff --git a/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridApp.kt b/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridApp.kt index 9a743490ffa3..02216f889603 100644 --- a/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridApp.kt +++ b/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridApp.kt @@ -3,6 +3,7 @@ package com.expensify.reactnativehybridapp import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.annotations.ReactModule import android.util.Log +import com.facebook.react.bridge.Promise @ReactModule(name = NativeReactNativeHybridAppSpec.NAME) class ReactNativeHybridApp(reactContext: ReactApplicationContext) : @@ -36,4 +37,9 @@ class ReactNativeHybridApp(reactContext: ReactApplicationContext) : override fun sendAuthToken(authToken: String?) { Log.d(NAME, "`sendAuthToken` should never be called in standalone `New Expensify` app") } + + override fun getHybridAppSettings(promise: Promise) { + Log.d(NAME, "`getHybridAppSettings` should never be called in standalone `New Expensify` app") + promise.reject("NOT_IMPLEMENTED", "getHybridAppSettings is not implemented in standalone New Expensify app") + } } diff --git a/modules/hybrid-app/ios/ReactNativeHybridApp.mm b/modules/hybrid-app/ios/ReactNativeHybridApp.mm index 6b093b3f26b5..287d8be1164a 100644 --- a/modules/hybrid-app/ios/ReactNativeHybridApp.mm +++ b/modules/hybrid-app/ios/ReactNativeHybridApp.mm @@ -27,6 +27,12 @@ - (void)sendAuthToken:(NSString *)authToken { NSLog(@"[ReactNativeHybridApp] `sendAuthToken` should never be called in standalone `New Expensify` app"); } +- (void)getHybridAppSettings:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject { + NSLog(@"[ReactNativeHybridApp] `getHybridAppSettings` should never be called in standalone `New Expensify` app"); + reject(@"NOT_IMPLEMENTED", @"This method is not available in standalone New Expensify app", nil); +} + - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { diff --git a/modules/hybrid-app/src/NativeReactNativeHybridApp.ts b/modules/hybrid-app/src/NativeReactNativeHybridApp.ts index a18f44f87d50..a0bf73e1f942 100644 --- a/modules/hybrid-app/src/NativeReactNativeHybridApp.ts +++ b/modules/hybrid-app/src/NativeReactNativeHybridApp.ts @@ -9,6 +9,7 @@ export interface Spec extends TurboModule { completeOnboarding: (status: boolean) => void; switchAccount: (newDotCurrentAccountEmail: string, authToken: string, policyID: string, accountID: string) => void; sendAuthToken: (authToken: string) => void; + getHybridAppSettings: () => Promise; } export default TurboModuleRegistry.getEnforcing('ReactNativeHybridApp'); diff --git a/modules/hybrid-app/src/index.native.ts b/modules/hybrid-app/src/index.native.ts index 50dfd719449a..229589cb255d 100644 --- a/modules/hybrid-app/src/index.native.ts +++ b/modules/hybrid-app/src/index.native.ts @@ -20,6 +20,9 @@ const HybridAppModule: HybridAppModuleType = { sendAuthToken({authToken}) { ReactNativeHybridApp.sendAuthToken(authToken); }, + getHybridAppSettings() { + return ReactNativeHybridApp.getHybridAppSettings(); + }, }; export default HybridAppModule; diff --git a/modules/hybrid-app/src/index.ts b/modules/hybrid-app/src/index.ts index ca45aeeb2075..18c248ec7639 100644 --- a/modules/hybrid-app/src/index.ts +++ b/modules/hybrid-app/src/index.ts @@ -24,6 +24,11 @@ const HybridAppModule: HybridAppModuleType = { // eslint-disable-next-line no-console console.warn('HybridAppModule: `sendAuthToken` should never be called on web'); }, + getHybridAppSettings() { + // eslint-disable-next-line no-console + console.warn('HybridAppModule: `getHybridAppSettings` should never be called on web'); + return Promise.resolve(null); + }, }; export default HybridAppModule; diff --git a/modules/hybrid-app/src/types.ts b/modules/hybrid-app/src/types.ts index 8a40a1fc5767..90a44ab380de 100644 --- a/modules/hybrid-app/src/types.ts +++ b/modules/hybrid-app/src/types.ts @@ -5,6 +5,7 @@ type HybridAppModuleType = { completeOnboarding: (args: {status: boolean}) => void; switchAccount: (args: {newDotCurrentAccountEmail: string; authToken: string; policyID: string; accountID: string}) => void; sendAuthToken: (args: {authToken: string}) => void; + getHybridAppSettings: () => Promise; }; export default HybridAppModuleType; diff --git a/src/App.tsx b/src/App.tsx index dc17fe242a55..6eac37c6f2db 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -54,8 +54,6 @@ import {SplashScreenStateContextProvider} from './SplashScreenStateContext'; type AppProps = { /** The URL specifying the initial navigation destination when the app opens */ url?: Route; - /** Serialized configuration data required to initialize the React Native app (e.g. authentication details) */ - hybridAppSettings?: string; }; LogBox.ignoreLogs([ @@ -71,7 +69,7 @@ const fill = {flex: 1}; const StrictModeWrapper = CONFIG.USE_REACT_STRICT_MODE_IN_DEV ? React.StrictMode : ({children}: {children: React.ReactElement}) => children; -function App({url, hybridAppSettings}: AppProps) { +function App({url}: AppProps) { useDefaultDragAndDrop(); OnyxUpdateManager(); @@ -79,7 +77,7 @@ function App({url, hybridAppSettings}: AppProps) { - + { + if (!CONFIG.IS_HYBRID_APP) { + return; + } - signInAfterTransitionFromOldDot(hybridAppSettings).then(() => { - setSplashScreenState(CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN); - setSignInHandled(true); - }); + HybridAppModule.getHybridAppSettings().then((hybridAppSettings: string | null) => { + if (!hybridAppSettings) { + // Native method can send non-null value only once per NewDot lifecycle. It prevents issues with multiple initializations during reloads on debug builds. + Log.info('[HybridApp] `getHybridAppSettings` called more than once during single NewDot lifecycle. Skipping initialization.'); + return; + } + + signInAfterTransitionFromOldDot(hybridAppSettings).then(() => { + setSplashScreenState(CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN); + }); + }); + }, [setSplashScreenState]); return null; }