diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index a551e5e21b6ad..b2df1bbc6ae4d 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -2395,27 +2395,6 @@ PODS:
- React-logger (= 0.76.3)
- React-perflogger (= 0.76.3)
- React-utils (= 0.76.3)
- - ReactNativeHybridApp (0.0.0):
- - DoubleConversion
- - glog
- - hermes-engine
- - RCT-Folly (= 2024.01.01.00)
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-NativeModulesApple
- - React-RCTFabric
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/bridging
- - ReactCommon/turbomodule/core
- - Yoga
- RNAppleAuthentication (2.2.2):
- React-Core
- RNCClipboard (1.15.0):
@@ -2984,7 +2963,6 @@ DEPENDENCIES:
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- ReactCodegen (from `build/generated/ios`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- - "ReactNativeHybridApp (from `../node_modules/@expensify/react-native-hybrid-app`)"
- "RNAppleAuthentication (from `../node_modules/@invertase/react-native-apple-authentication`)"
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
- "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
@@ -3255,8 +3233,6 @@ EXTERNAL SOURCES:
:path: build/generated/ios
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
- ReactNativeHybridApp:
- :path: "../node_modules/@expensify/react-native-hybrid-app"
RNAppleAuthentication:
:path: "../node_modules/@invertase/react-native-apple-authentication"
RNCClipboard:
@@ -3445,7 +3421,6 @@ SPEC CHECKSUMS:
React-utils: 2bcaf4f4dfe361344bce2fae428603d518488630
ReactCodegen: ae99a130606068ed40d1d9c0d5f25fda142a0647
ReactCommon: 89c87b343deacc8610b099ac764848f0ce937e3e
- ReactNativeHybridApp: 18cab0d029f08d51391a07c5c2c7872287544485
RNAppleAuthentication: 0571c08da8c327ae2afc0261b48b4a515b0286a6
RNCClipboard: 8212ca9e8370d0e23bfb7f5a591380da5a63456d
RNCPicker: b978067931744f5a7316b48b8dcf145d4d722672
diff --git a/jest/setup.ts b/jest/setup.ts
index bb1b14f1e7264..2fc4d289471cb 100644
--- a/jest/setup.ts
+++ b/jest/setup.ts
@@ -94,13 +94,6 @@ jest.mock('../modules/background-task/src/NativeReactNativeBackgroundTask', () =
onBackgroundTaskExecution: jest.fn(),
}));
-jest.mock('../modules/hybrid-app/src/NativeReactNativeHybridApp', () => ({
- isHybridApp: jest.fn(),
- closeReactNativeApp: jest.fn(),
- completeOnboarding: jest.fn(),
- switchAccount: jest.fn(),
-}));
-
// This makes FlatList render synchronously for easier testing.
jest.mock(
'@react-native/virtualized-lists/Interaction/Batchinator',
diff --git a/modules/hybrid-app/ReactNativeHybridApp.podspec b/modules/hybrid-app/ReactNativeHybridApp.podspec
deleted file mode 100644
index b52b89de7d070..0000000000000
--- a/modules/hybrid-app/ReactNativeHybridApp.podspec
+++ /dev/null
@@ -1,22 +0,0 @@
-require "json"
-
-package = JSON.parse(File.read(File.join(__dir__, "package.json")))
-
-Pod::Spec.new do |s|
- s.name = "ReactNativeHybridApp"
- s.version = package["version"]
- s.summary = package["description"]
- s.homepage = package["homepage"]
- s.license = package["license"]
- s.authors = package["author"]
-
- s.platforms = { :ios => min_ios_version_supported }
- s.source = { :git => ".git", :tag => "#{s.version}" }
-
- s.source_files = "ios/**/*.{h,m,mm,cpp}"
- s.pod_target_xcconfig = {
- "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
- }
-
- install_modules_dependencies(s)
-end
diff --git a/modules/hybrid-app/android/build.gradle b/modules/hybrid-app/android/build.gradle
deleted file mode 100644
index 2baa6772f697f..0000000000000
--- a/modules/hybrid-app/android/build.gradle
+++ /dev/null
@@ -1,82 +0,0 @@
-buildscript {
- ext.getExtOrDefault = { name ->
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeHybridApp_' + name]
- }
-
- repositories {
- google()
- mavenCentral()
- }
-
- dependencies {
- classpath "com.android.tools.build:gradle:8.7.2"
- // noinspection DifferentKotlinGradleVersion
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
- }
-}
-
-apply plugin: "com.android.library"
-apply plugin: "kotlin-android"
-apply plugin: "com.facebook.react"
-
-def getExtOrIntegerDefault(name) {
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeHybridApp_" + name]).toInteger()
-}
-
-android {
- namespace "com.expensify.reactnativehybridapp"
-
- compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
-
- defaultConfig {
- minSdkVersion getExtOrIntegerDefault("minSdkVersion")
- targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
- buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", "true"
- }
-
- buildFeatures {
- buildConfig true
- }
-
- buildTypes {
- release {
- minifyEnabled false
- }
- }
-
- lintOptions {
- disable "GradleCompatible"
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- sourceSets {
- main {
- java.srcDirs += [
- "generated/java",
- "generated/jni"
- ]
- }
- }
-}
-
-repositories {
- mavenCentral()
- google()
-}
-
-def kotlin_version = getExtOrDefault("kotlinVersion")
-
-dependencies {
- implementation "com.facebook.react:react-android"
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-}
-
-react {
- jsRootDir = file("../src/")
- libraryName = "ReactNativeHybridApp"
- codegenJavaPackageName = "com.expensify.reactnativehybridapp"
-}
diff --git a/modules/hybrid-app/android/gradle.properties b/modules/hybrid-app/android/gradle.properties
deleted file mode 100644
index 97f8d26853633..0000000000000
--- a/modules/hybrid-app/android/gradle.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-ReactNativeHybridApp_kotlinVersion=2.0.21
-ReactNativeHybridApp_minSdkVersion=24
-ReactNativeHybridApp_targetSdkVersion=34
-ReactNativeHybridApp_compileSdkVersion=35
-ReactNativeHybridApp_ndkVersion=27.1.12297006
diff --git a/modules/hybrid-app/android/src/main/AndroidManifest.xml b/modules/hybrid-app/android/src/main/AndroidManifest.xml
deleted file mode 100644
index f6c04eda07d6d..0000000000000
--- a/modules/hybrid-app/android/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
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
deleted file mode 100644
index da3f745f4564d..0000000000000
--- a/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridApp.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.expensify.reactnativehybridapp
-
-import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.module.annotations.ReactModule
-import android.util.Log
-
-@ReactModule(name = NativeReactNativeHybridAppSpec.NAME)
-class ReactNativeHybridApp(reactContext: ReactApplicationContext) :
- NativeReactNativeHybridAppSpec(reactContext) {
-
- override fun isHybridApp(): Boolean {
- return false
- }
-
- override fun closeReactNativeApp(shouldSignOut: Boolean, shouldSetNVP: Boolean) {
- Log.d(NAME, "`closeReactNativeApp` should never be called in standalone `New Expensify` app")
- }
-
- override fun completeOnboarding(status: Boolean) {
- Log.d(NAME, "`completeOnboarding` should never be called in standalone `New Expensify` app")
- }
-
- override fun switchAccount(
- newDotCurrentAccountEmail: String?,
- authToken: String?,
- policyID: String?,
- accountID: String?
- ) {
- Log.d(NAME, "`switchAccount` should never be called in standalone `New Expensify` app")
- }
-}
diff --git a/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridAppPackage.kt b/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridAppPackage.kt
deleted file mode 100644
index ab05f997efce8..0000000000000
--- a/modules/hybrid-app/android/src/main/java/com/expensify/reactnativehybridapp/ReactNativeHybridAppPackage.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.expensify.reactnativehybridapp
-
-import com.facebook.react.BaseReactPackage
-import com.facebook.react.bridge.NativeModule
-import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.module.model.ReactModuleInfo
-import com.facebook.react.module.model.ReactModuleInfoProvider
-import java.util.HashMap
-
-class ReactNativeHybridAppPackage : BaseReactPackage() {
- override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
- return if (name == NativeReactNativeHybridAppSpec.NAME) {
- ReactNativeHybridApp(reactContext)
- } else {
- null
- }
- }
-
- override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
- return ReactModuleInfoProvider {
- val moduleInfos: MutableMap = HashMap()
- moduleInfos[NativeReactNativeHybridAppSpec.NAME] = ReactModuleInfo(
- NativeReactNativeHybridAppSpec.NAME,
- NativeReactNativeHybridAppSpec.NAME,
- false, // canOverrideExistingModule
- false, // needsEagerInit
- false, // isCxxModule
- true // isTurboModule
- )
- moduleInfos
- }
- }
-}
diff --git a/modules/hybrid-app/ios/ReactNativeHybridApp.h b/modules/hybrid-app/ios/ReactNativeHybridApp.h
deleted file mode 100644
index 828964f33f84d..0000000000000
--- a/modules/hybrid-app/ios/ReactNativeHybridApp.h
+++ /dev/null
@@ -1,6 +0,0 @@
-
-#import "RNReactNativeHybridAppSpec/RNReactNativeHybridAppSpec.h"
-
-@interface ReactNativeHybridApp : NSObject
-
-@end
diff --git a/modules/hybrid-app/ios/ReactNativeHybridApp.mm b/modules/hybrid-app/ios/ReactNativeHybridApp.mm
deleted file mode 100644
index 8b55a73be5a3a..0000000000000
--- a/modules/hybrid-app/ios/ReactNativeHybridApp.mm
+++ /dev/null
@@ -1,29 +0,0 @@
-#import "ReactNativeHybridApp.h"
-
-@implementation ReactNativeHybridApp
-RCT_EXPORT_MODULE()
-
-- (NSNumber *)isHybridApp {
- return @false;
-}
-
-- (void)closeReactNativeApp:(BOOL)shouldSignOut shouldSetNVP:(BOOL)shouldSetNVP {
- NSLog(@"[ReactNativeHybridApp] `closeReactNativeApp` should never be called in standalone `New Expensify` app");
-}
-
-- (void)completeOnboarding:(BOOL)status {
- NSLog(@"[ReactNativeHybridApp] `completeOnboarding` should never be called in standalone `New Expensify` app");
-
-}
-
-- (void)switchAccount:(NSString *)newDotCurrentAccountEmail authToken:(NSString *)authToken policyID:(NSString *)policyID accountID:(NSString *)accountID {
- NSLog(@"[ReactNativeHybridApp] `switchAccount` should never be called in standalone `New Expensify` app");
-}
-
-- (std::shared_ptr)getTurboModule:
- (const facebook::react::ObjCTurboModule::InitParams &)params
-{
- return std::make_shared(params);
-}
-
-@end
diff --git a/modules/hybrid-app/package.json b/modules/hybrid-app/package.json
deleted file mode 100644
index 60880f31bfa49..0000000000000
--- a/modules/hybrid-app/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "@expensify/react-native-hybrid-app",
- "version": "0.0.0",
- "description": "HybridApp",
- "main": "src/index",
- "codegenConfig": {
- "name": "RNReactNativeHybridAppSpec",
- "type": "modules",
- "jsSrcsDir": "src"
- },
- "author": " <> ()",
- "license": "UNLICENSED",
- "homepage": "#readme",
- "create-react-native-library": {
- "type": "turbo-module",
- "languages": "kotlin-objc",
- "version": "0.48.1"
- }
-}
diff --git a/modules/hybrid-app/react-native.config.js b/modules/hybrid-app/react-native.config.js
deleted file mode 100644
index 5bad2c0ec4088..0000000000000
--- a/modules/hybrid-app/react-native.config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * @type {import('@react-native-community/cli-types').UserDependencyConfig}
- */
-module.exports = {
- dependency: {
- platforms: {
- android: {
- cmakeListsPath: 'build/generated/source/codegen/jni/CMakeLists.txt',
- },
- },
- },
-};
diff --git a/modules/hybrid-app/src/NativeReactNativeHybridApp.ts b/modules/hybrid-app/src/NativeReactNativeHybridApp.ts
deleted file mode 100644
index f9041c5577172..0000000000000
--- a/modules/hybrid-app/src/NativeReactNativeHybridApp.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type {TurboModule} from 'react-native';
-import {TurboModuleRegistry} from 'react-native';
-
-// eslint-disable-next-line rulesdir/no-inline-named-export, @typescript-eslint/consistent-type-definitions
-export interface Spec extends TurboModule {
- isHybridApp: () => boolean;
- closeReactNativeApp: (shouldSignOut: boolean, shouldSetNVP: boolean) => void;
- completeOnboarding: (status: boolean) => void;
- switchAccount: (newDotCurrentAccountEmail: string, authToken: string, policyID: string, accountID: string) => void;
-}
-
-export default TurboModuleRegistry.getEnforcing('ReactNativeHybridApp');
diff --git a/modules/hybrid-app/src/index.native.ts b/modules/hybrid-app/src/index.native.ts
deleted file mode 100644
index 956cb5784dfc4..0000000000000
--- a/modules/hybrid-app/src/index.native.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import ReactNativeHybridApp from './NativeReactNativeHybridApp';
-import type HybridAppModuleType from './types';
-
-const HybridAppModule: HybridAppModuleType = {
- isHybridApp() {
- return ReactNativeHybridApp.isHybridApp();
- },
- closeReactNativeApp({shouldSignOut, shouldSetNVP}) {
- ReactNativeHybridApp.closeReactNativeApp(shouldSignOut, shouldSetNVP);
- },
- completeOnboarding({status}) {
- ReactNativeHybridApp.completeOnboarding(status);
- },
- switchAccount({newDotCurrentAccountEmail, authToken, policyID, accountID}) {
- ReactNativeHybridApp.switchAccount(newDotCurrentAccountEmail, authToken, policyID, accountID);
- },
-};
-
-export default HybridAppModule;
diff --git a/modules/hybrid-app/src/index.ts b/modules/hybrid-app/src/index.ts
deleted file mode 100644
index 08a37c4799e22..0000000000000
--- a/modules/hybrid-app/src/index.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import Log from '@libs/Log';
-import type HybridAppModuleType from './types';
-
-const HybridAppModule: HybridAppModuleType = {
- isHybridApp() {
- return false;
- },
- closeReactNativeApp() {
- Log.warn('HybridAppModule: `closeReactNativeApp` should never be called on web');
- },
- completeOnboarding() {
- Log.warn('HybridAppModule: `completeOnboarding` should never be called on web');
- },
- switchAccount() {
- Log.warn('HybridAppModule: `switchAccount` should never be called on web');
- },
-};
-
-export default HybridAppModule;
diff --git a/modules/hybrid-app/src/types.ts b/modules/hybrid-app/src/types.ts
deleted file mode 100644
index 5fef691d3a48a..0000000000000
--- a/modules/hybrid-app/src/types.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-type HybridAppModuleType = {
- isHybridApp: () => boolean;
- closeReactNativeApp: (args: {shouldSignOut: boolean; shouldSetNVP: boolean}) => void;
- completeOnboarding: (args: {status: boolean}) => void;
- switchAccount: (args: {newDotCurrentAccountEmail: string; authToken: string; policyID: string; accountID: string}) => void;
-};
-
-export default HybridAppModuleType;
diff --git a/package-lock.json b/package-lock.json
index 89a2581ce4414..10a4c199ea6ba 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,6 @@
"dependencies": {
"@dotlottie/react-player": "^1.6.3",
"@expensify/react-native-background-task": "file:./modules/background-task",
- "@expensify/react-native-hybrid-app": "file:./modules/hybrid-app",
"@expensify/react-native-live-markdown": "0.1.238",
"@expo/metro-runtime": "^4.0.0",
"@firebase/app": "^0.10.10",
@@ -295,11 +294,6 @@
"version": "0.0.0",
"license": "UNLICENSED"
},
- "modules/hybrid-app": {
- "name": "@expensify/react-native-hybrid-app",
- "version": "0.0.0",
- "license": "UNLICENSED"
- },
"node_modules/@0no-co/graphql.web": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.0.11.tgz",
@@ -3649,10 +3643,6 @@
"resolved": "modules/background-task",
"link": true
},
- "node_modules/@expensify/react-native-hybrid-app": {
- "resolved": "modules/hybrid-app",
- "link": true
- },
"node_modules/@expensify/react-native-live-markdown": {
"version": "0.1.238",
"resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.238.tgz",
diff --git a/package.json b/package.json
index 0c62b5c096eaa..02e21969fe90e 100644
--- a/package.json
+++ b/package.json
@@ -195,8 +195,7 @@
"react-plaid-link": "3.3.2",
"react-web-config": "^1.0.0",
"react-webcam": "^7.1.1",
- "react-window": "^1.8.9",
- "@expensify/react-native-hybrid-app": "file:./modules/hybrid-app"
+ "react-window": "^1.8.9"
},
"devDependencies": {
"@actions/core": "1.10.0",
diff --git a/src/CONFIG.ts b/src/CONFIG.ts
index a2c07f691959b..72f98c0ee1064 100644
--- a/src/CONFIG.ts
+++ b/src/CONFIG.ts
@@ -1,4 +1,3 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
import {Platform} from 'react-native';
import type {NativeConfig} from 'react-native-config';
import Config from 'react-native-config';
@@ -106,5 +105,4 @@ export default {
USE_REACT_STRICT_MODE_IN_DEV: false,
ELECTRON_DISABLE_SECURITY_WARNINGS: 'true',
IS_TEST_ENV: process.env.NODE_ENV === 'test',
- IS_HYBRID_APP: HybridAppModule.isHybridApp(),
} as const;
diff --git a/src/Expensify.tsx b/src/Expensify.tsx
index 0db7270dc8abd..0f3138bbfb755 100644
--- a/src/Expensify.tsx
+++ b/src/Expensify.tsx
@@ -1,7 +1,7 @@
import {Audio} from 'expo-av';
import React, {useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
import type {NativeEventSubscription} from 'react-native';
-import {AppState, Linking, Platform} from 'react-native';
+import {AppState, Linking, NativeModules, Platform} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import Onyx, {useOnyx} from 'react-native-onyx';
import ConfirmModal from './components/ConfirmModal';
@@ -14,7 +14,7 @@ import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper';
import SplashScreenHider from './components/SplashScreenHider';
import TestToolsModal from './components/TestToolsModal';
import UpdateAppModal from './components/UpdateAppModal';
-import CONFIG from './CONFIG';
+import * as CONFIG from './CONFIG';
import CONST from './CONST';
import useDebugShortcut from './hooks/useDebugShortcut';
import useIsAuthenticated from './hooks/useIsAuthenticated';
@@ -122,9 +122,9 @@ function Expensify() {
const autoAuthState = useMemo(() => session?.autoAuthState ?? '', [session]);
const shouldInit = isNavigationReady && hasAttemptedToOpenPublicRoom;
- const isSplashVisible = splashScreenState === CONST.BOOT_SPLASH_STATE.VISIBLE;
- const isHybridAppReady = splashScreenState === CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN && isAuthenticated;
- const shouldHideSplash = shouldInit && (CONFIG.IS_HYBRID_APP ? isHybridAppReady : isSplashVisible);
+ const shouldHideSplash =
+ shouldInit &&
+ (NativeModules.HybridAppModule ? splashScreenState === CONST.BOOT_SPLASH_STATE.READY_TO_BE_HIDDEN && isAuthenticated : splashScreenState === CONST.BOOT_SPLASH_STATE.VISIBLE);
const initializeClient = () => {
if (!Visibility.isVisible()) {
diff --git a/src/components/BookTravelButton.tsx b/src/components/BookTravelButton.tsx
index 98f5806add45d..01d512e9b2be8 100644
--- a/src/components/BookTravelButton.tsx
+++ b/src/components/BookTravelButton.tsx
@@ -1,6 +1,6 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
import {Str} from 'expensify-common';
import React, {useCallback, useContext, useState} from 'react';
+import {NativeModules} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
@@ -13,7 +13,6 @@ import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import {getAdminsPrivateEmailDomains, isPaidGroupPolicy} from '@libs/PolicyUtils';
import colors from '@styles/theme/colors';
-import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -80,13 +79,13 @@ function BookTravelButton({text}: BookTravelButtonProps) {
?.then(() => {
// When a user selects "Trips" in the Expensify Classic menu, the HybridApp opens the ManageTrips page in NewDot.
// The wasNewDotLaunchedJustForTravel flag indicates if NewDot was launched solely for this purpose.
- if (!CONFIG.IS_HYBRID_APP || !wasNewDotLaunchedJustForTravel) {
+ if (!NativeModules.HybridAppModule || !wasNewDotLaunchedJustForTravel) {
return;
}
// Close NewDot if it was opened only for Travel, as its purpose is now fulfilled.
Log.info('[HybridApp] Returning to OldDot after opening TravelDot');
- HybridAppModule.closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
+ NativeModules.HybridAppModule.closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
setRootStatusBarEnabled(false);
})
?.catch(() => {
diff --git a/src/components/ScreenWrapper.tsx b/src/components/ScreenWrapper.tsx
index 021b0e240aea1..73d0bf96db405 100644
--- a/src/components/ScreenWrapper.tsx
+++ b/src/components/ScreenWrapper.tsx
@@ -1,9 +1,8 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
import {UNSTABLE_usePreventRemove, useIsFocused, useNavigation} from '@react-navigation/native';
import type {ForwardedRef, ReactNode} from 'react';
import React, {createContext, forwardRef, useContext, useEffect, useMemo, useRef, useState} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
-import {Keyboard, PanResponder, View} from 'react-native';
+import {Keyboard, NativeModules, PanResponder, View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import {PickerAvoidingView} from 'react-native-picker-select';
import type {EdgeInsets} from 'react-native-safe-area-context';
@@ -20,7 +19,6 @@ import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNa
import type {ReportsSplitNavigatorParamList, RootNavigatorParamList} from '@libs/Navigation/types';
import addViewportResizeListener from '@libs/VisualViewport';
import toggleTestToolsModal from '@userActions/TestTool';
-import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import CustomDevMenu from './CustomDevMenu';
@@ -181,10 +179,7 @@ function ScreenWrapper(
const {isBlurred, setIsBlurred} = useInputBlurContext();
UNSTABLE_usePreventRemove((isSingleNewDotEntry ?? false) && initialURL === Navigation.getActiveRouteWithoutParams(), () => {
- if (!CONFIG.IS_HYBRID_APP) {
- return;
- }
- HybridAppModule.closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
+ NativeModules.HybridAppModule?.closeReactNativeApp({shouldSignOut: false, shouldSetNVP: false});
setRootStatusBarEnabled(false);
});
diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts
index 0aaa8ddad9d0a..d09658cdcfdaa 100644
--- a/src/hooks/useOnboardingFlow.ts
+++ b/src/hooks/useOnboardingFlow.ts
@@ -1,12 +1,11 @@
import {useEffect} from 'react';
-import {InteractionManager} from 'react-native';
+import {InteractionManager, NativeModules} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import {isUserOnPrivateDomain} from '@libs/actions/Session';
import {startOnboardingFlow} from '@libs/actions/Welcome/OnboardingFlow';
import Navigation from '@libs/Navigation/Navigation';
import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors';
import {buildCannedSearchQuery} from '@libs/SearchQueryUtils';
-import CONFIG from '@src/CONFIG';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
@@ -42,7 +41,7 @@ function useOnboardingFlowRouter() {
return;
}
- if (CONFIG.IS_HYBRID_APP && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) {
+ if (NativeModules.HybridAppModule && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) {
return;
}
@@ -58,7 +57,7 @@ function useOnboardingFlowRouter() {
return;
}
- if (CONFIG.IS_HYBRID_APP) {
+ if (NativeModules.HybridAppModule) {
// For single entries, such as using the Travel feature from OldDot, we don't want to show onboarding
if (isSingleNewDotEntry) {
return;
@@ -77,7 +76,7 @@ function useOnboardingFlowRouter() {
}
// If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet
- if (!CONFIG.IS_HYBRID_APP && isOnboardingCompleted === false) {
+ if (!NativeModules.HybridAppModule && isOnboardingCompleted === false) {
startOnboardingFlow(isPrivateDomain);
}
});
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
index 837c9aa15650f..7b52887f3905d 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
@@ -1,6 +1,7 @@
import type {RouteProp} from '@react-navigation/native';
import {findFocusedRoute, useNavigation} from '@react-navigation/native';
import React, {memo, useEffect, useMemo, useRef} from 'react';
+import {NativeModules} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import Onyx, {withOnyx} from 'react-native-onyx';
import ActiveGuidesEventListener from '@components/ActiveGuidesEventListener';
@@ -231,7 +232,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
// On HybridApp we need to prevent flickering during transition to OldDot
const shouldRenderOnboardingExclusivelyOnHybridApp = useMemo(() => {
- return CONFIG.IS_HYBRID_APP && Navigation.getActiveRoute().includes(ROUTES.ONBOARDING_EMPLOYEES.route) && isOnboardingCompleted === true;
+ return NativeModules.HybridAppModule && Navigation.getActiveRoute().includes(ROUTES.ONBOARDING_EMPLOYEES.route) && isOnboardingCompleted === true;
}, [isOnboardingCompleted]);
useEffect(() => {
@@ -263,7 +264,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
initializePusher();
// In Hybrid App we decide to call one of those method when booting ND and we don't want to duplicate calls
- if (!CONFIG.IS_HYBRID_APP) {
+ if (!NativeModules.HybridAppModule) {
// If we are on this screen then we are "logged in", but the user might not have "just logged in". They could be reopening the app
// or returning from background. If so, we'll assume they have some app data already and we can call reconnectApp() instead of openApp().
if (SessionUtils.didUserLogInDuringSession()) {
diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.tsx b/src/libs/Navigation/AppNavigator/PublicScreens.tsx
index 095fffae96dcd..1fc3a30e6c76b 100644
--- a/src/libs/Navigation/AppNavigator/PublicScreens.tsx
+++ b/src/libs/Navigation/AppNavigator/PublicScreens.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import {NativeModules} from 'react-native';
import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
import type {PublicScreensParamList} from '@navigation/types';
import ConnectionCompletePage from '@pages/ConnectionCompletePage';
@@ -10,7 +11,6 @@ import SAMLSignInPage from '@pages/signin/SAMLSignInPage';
import SignInPage from '@pages/signin/SignInPage';
import UnlinkLoginPage from '@pages/UnlinkLoginPage';
import ValidateLoginPage from '@pages/ValidateLoginPage';
-import CONFIG from '@src/CONFIG';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
import defaultScreenOptions from './defaultScreenOptions';
@@ -27,7 +27,7 @@ function PublicScreens() {
{
- if (!CONFIG.IS_HYBRID_APP || !initialURL) {
+ if (!NativeModules.HybridAppModule || !initialURL) {
return;
}
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 3168a3aaab23a..e5a878031c8ab 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -1,6 +1,7 @@
import type {NavigationState} from '@react-navigation/native';
import {DarkTheme, DefaultTheme, findFocusedRoute, NavigationContainer} from '@react-navigation/native';
import React, {useContext, useEffect, useMemo, useRef} from 'react';
+import {NativeModules} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
import {usePlaybackContext} from '@components/VideoPlayerContexts/PlaybackContext';
@@ -18,7 +19,6 @@ import {updateLastVisitedPath} from '@userActions/App';
import * as Session from '@userActions/Session';
import {updateOnboardingLastVisitedPath} from '@userActions/Welcome';
import {getOnboardingInitialPath} from '@userActions/Welcome/OnboardingFlow';
-import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -115,13 +115,13 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady, sh
// If the user haven't completed the flow, we want to always redirect them to the onboarding flow.
// We also make sure that the user is authenticated, isn't part of a group workspace, isn't in the transition flow & wasn't invited to NewDot.
- if (!CONFIG.IS_HYBRID_APP && !hasNonPersonalPolicy && !isOnboardingCompleted && !wasInvitedToNewDot && authenticated && !isTransitioning && !shouldShowRequire2FAModal) {
+ if (!NativeModules.HybridAppModule && !hasNonPersonalPolicy && !isOnboardingCompleted && !wasInvitedToNewDot && authenticated && !isTransitioning && !shouldShowRequire2FAModal) {
return getAdaptedStateFromPath(getOnboardingInitialPath(isPrivateDomain), linkingConfig.config);
}
// If there is no lastVisitedPath, we can do early return. We won't modify the default behavior.
// The same applies to HybridApp, as we always define the route to which we want to transition.
- if (!lastVisitedPath || CONFIG.IS_HYBRID_APP) {
+ if (!lastVisitedPath || NativeModules.HybridAppModule) {
return undefined;
}
diff --git a/src/libs/Notification/PushNotification/subscribePushNotification/index.ts b/src/libs/Notification/PushNotification/subscribePushNotification/index.ts
index 2b6110d265485..66c51eb2a8075 100644
--- a/src/libs/Notification/PushNotification/subscribePushNotification/index.ts
+++ b/src/libs/Notification/PushNotification/subscribePushNotification/index.ts
@@ -1,3 +1,4 @@
+import {NativeModules} from 'react-native';
import Onyx from 'react-native-onyx';
import applyOnyxUpdatesReliably from '@libs/actions/applyOnyxUpdatesReliably';
import * as ActiveClientManager from '@libs/ActiveClientManager';
@@ -8,7 +9,6 @@ import {extractPolicyIDFromPath} from '@libs/PolicyUtils';
import Visibility from '@libs/Visibility';
import {updateLastVisitedPath} from '@userActions/App';
import * as Modal from '@userActions/Modal';
-import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -123,7 +123,7 @@ function navigateToReport({reportID, reportActionID}: ReportActionPushNotificati
}
// Get rid of the transition screen, if it is on the top of the stack
- if (CONFIG.IS_HYBRID_APP && Navigation.getActiveRoute().includes(ROUTES.TRANSITION_BETWEEN_APPS)) {
+ if (NativeModules.HybridAppModule && Navigation.getActiveRoute().includes(ROUTES.TRANSITION_BETWEEN_APPS)) {
Navigation.goBack();
}
// If a chat is visible other than the one we are trying to navigate to, then we need to navigate back
diff --git a/src/libs/actions/AppUpdate/updateApp/index.android.ts b/src/libs/actions/AppUpdate/updateApp/index.android.ts
index 17f30c813d17c..aac98a1928aad 100644
--- a/src/libs/actions/AppUpdate/updateApp/index.android.ts
+++ b/src/libs/actions/AppUpdate/updateApp/index.android.ts
@@ -1,5 +1,4 @@
-import {Linking} from 'react-native';
-import CONFIG from '@src/CONFIG';
+import {Linking, NativeModules} from 'react-native';
import CONST from '@src/CONST';
export default function updateApp(isProduction: boolean) {
@@ -7,5 +6,5 @@ export default function updateApp(isProduction: boolean) {
Linking.openURL(CONST.APP_DOWNLOAD_LINKS.OLD_DOT_ANDROID);
return;
}
- Linking.openURL(CONFIG.IS_HYBRID_APP ? CONST.APP_DOWNLOAD_LINKS.OLD_DOT_ANDROID : CONST.APP_DOWNLOAD_LINKS.ANDROID);
+ Linking.openURL(NativeModules.HybridAppModule ? CONST.APP_DOWNLOAD_LINKS.OLD_DOT_ANDROID : CONST.APP_DOWNLOAD_LINKS.ANDROID);
}
diff --git a/src/libs/actions/AppUpdate/updateApp/index.ios.ts b/src/libs/actions/AppUpdate/updateApp/index.ios.ts
index 6d6d582a67aeb..608c7ab028ca0 100644
--- a/src/libs/actions/AppUpdate/updateApp/index.ios.ts
+++ b/src/libs/actions/AppUpdate/updateApp/index.ios.ts
@@ -1,5 +1,4 @@
-import {Linking} from 'react-native';
-import CONFIG from '@src/CONFIG';
+import {Linking, NativeModules} from 'react-native';
import CONST from '@src/CONST';
export default function updateApp(isProduction: boolean) {
@@ -7,5 +6,5 @@ export default function updateApp(isProduction: boolean) {
Linking.openURL(CONST.APP_DOWNLOAD_LINKS.OLD_DOT_IOS);
return;
}
- Linking.openURL(CONFIG.IS_HYBRID_APP ? CONST.APP_DOWNLOAD_LINKS.OLD_DOT_IOS : CONST.APP_DOWNLOAD_LINKS.IOS);
+ Linking.openURL(NativeModules.HybridAppModule ? CONST.APP_DOWNLOAD_LINKS.OLD_DOT_IOS : CONST.APP_DOWNLOAD_LINKS.IOS);
}
diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts
index da6e60717c4af..a4053855d813c 100644
--- a/src/libs/actions/Delegate.ts
+++ b/src/libs/actions/Delegate.ts
@@ -1,4 +1,4 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
+import {NativeModules} from 'react-native';
import Onyx from 'react-native-onyx';
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import * as API from '@libs/API';
@@ -8,7 +8,6 @@ import * as ErrorUtils from '@libs/ErrorUtils';
import Log from '@libs/Log';
import * as NetworkStore from '@libs/Network/NetworkStore';
import * as SequentialQueue from '@libs/Network/SequentialQueue';
-import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Delegate, DelegatedAccess, DelegateRole} from '@src/types/onyx/Account';
@@ -158,17 +157,14 @@ function connect(email: string) {
NetworkStore.setAuthToken(response?.restrictedToken ?? null);
confirmReadyToOpenApp();
- openApp().then(() => {
- if (!CONFIG.IS_HYBRID_APP) {
- return;
- }
- HybridAppModule.switchAccount({
+ openApp().then(() =>
+ NativeModules.HybridAppModule?.switchAccount({
newDotCurrentAccountEmail: email,
authToken: restrictedToken,
policyID,
accountID: String(previousAccountID),
- });
- });
+ }),
+ );
});
})
.catch((error) => {
@@ -252,17 +248,14 @@ function disconnect() {
NetworkStore.setAuthToken(response?.authToken ?? null);
confirmReadyToOpenApp();
- openApp().then(() => {
- if (!CONFIG.IS_HYBRID_APP) {
- return;
- }
- HybridAppModule.switchAccount({
+ openApp().then(() =>
+ NativeModules.HybridAppModule?.switchAccount({
newDotCurrentAccountEmail: requesterEmail,
authToken,
policyID: '',
accountID: '',
- });
- });
+ }),
+ );
});
})
.catch((error) => {
diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts
index 13a5876b381f2..bcee7646ff704 100644
--- a/src/libs/actions/Session/index.ts
+++ b/src/libs/actions/Session/index.ts
@@ -1,8 +1,7 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
import throttle from 'lodash/throttle';
import type {ChannelAuthorizationData} from 'pusher-js/types/src/core/auth/options';
import type {ChannelAuthorizationCallback} from 'pusher-js/with-encryption';
-import {InteractionManager, Linking} from 'react-native';
+import {InteractionManager, Linking, NativeModules} from 'react-native';
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
@@ -244,8 +243,8 @@ function signOutAndRedirectToSignIn(shouldResetToHome?: boolean, shouldStashSess
}
// In the HybridApp, we want the Old Dot to handle the sign out process
- if (CONFIG.IS_HYBRID_APP && killHybridApp) {
- HybridAppModule.closeReactNativeApp({shouldSignOut: true, shouldSetNVP: false});
+ if (NativeModules.HybridAppModule && killHybridApp) {
+ NativeModules.HybridAppModule.closeReactNativeApp({shouldSignOut: true, shouldSetNVP: false});
return;
}
// We'll only call signOut if we're not stashing the session and this is not a supportal session,
@@ -1184,7 +1183,7 @@ function handleExitToNavigation(exitTo: Route | HybridAppRoute) {
InteractionManager.runAfterInteractions(() => {
waitForUserSignIn().then(() => {
Navigation.waitForProtectedRoutes().then(() => {
- const url = CONFIG.IS_HYBRID_APP ? Navigation.parseHybridAppUrl(exitTo) : (exitTo as Route);
+ const url = NativeModules.HybridAppModule ? Navigation.parseHybridAppUrl(exitTo) : (exitTo as Route);
Navigation.goBack();
Navigation.navigate(url);
});
diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts
index a98b600e5baf1..e64d7690833bd 100644
--- a/src/libs/actions/Welcome/index.ts
+++ b/src/libs/actions/Welcome/index.ts
@@ -1,11 +1,10 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
+import {NativeModules} from 'react-native';
import type {OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import DateUtils from '@libs/DateUtils';
import Log from '@libs/Log';
-import CONFIG from '@src/CONFIG';
import type {OnboardingCompanySize} from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {OnboardingPurpose} from '@src/types/onyx';
@@ -123,7 +122,7 @@ function updateOnboardingLastVisitedPath(path: string) {
}
function completeHybridAppOnboarding() {
- if (!CONFIG.IS_HYBRID_APP) {
+ if (!NativeModules.HybridAppModule) {
return;
}
@@ -147,7 +146,7 @@ function completeHybridAppOnboarding() {
// No matter what the response is, we want to mark the onboarding as completed (user saw the explanation modal)
Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true);
- HybridAppModule.completeOnboarding({status: true});
+ NativeModules.HybridAppModule.completeOnboarding({status: true});
});
}
diff --git a/src/pages/ErrorPage/SessionExpiredPage.tsx b/src/pages/ErrorPage/SessionExpiredPage.tsx
index 85dd6724a3bdd..2849dcd624ac8 100644
--- a/src/pages/ErrorPage/SessionExpiredPage.tsx
+++ b/src/pages/ErrorPage/SessionExpiredPage.tsx
@@ -1,6 +1,5 @@
-import HybridAppModule from '@expensify/react-native-hybrid-app';
import React from 'react';
-import {View} from 'react-native';
+import {NativeModules, View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
@@ -11,7 +10,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import {clearSignInData} from '@userActions/Session';
-import CONFIG from '@src/CONFIG';
function SessionExpiredPage() {
const styles = useThemeStyles();
@@ -34,12 +32,12 @@ function SessionExpiredPage() {
{translate('deeplinkWrapper.expired')}{' '}
{
- if (!CONFIG.IS_HYBRID_APP) {
+ if (!NativeModules.HybridAppModule) {
clearSignInData();
Navigation.goBack();
return;
}
- HybridAppModule.closeReactNativeApp({shouldSignOut: true, shouldSetNVP: false});
+ NativeModules.HybridAppModule.closeReactNativeApp({shouldSignOut: true, shouldSetNVP: false});
}}
>
{translate('deeplinkWrapper.signIn')}
diff --git a/src/pages/ErrorPage/UpdateRequiredView.tsx b/src/pages/ErrorPage/UpdateRequiredView.tsx
index c2d447da63e76..750a3c891b0fd 100644
--- a/src/pages/ErrorPage/UpdateRequiredView.tsx
+++ b/src/pages/ErrorPage/UpdateRequiredView.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import {View} from 'react-native';
+import {NativeModules, View} from 'react-native';
import Button from '@components/Button';
import Header from '@components/Header';
import HeaderGap from '@components/HeaderGap';
@@ -12,8 +12,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
-import {updateApp} from '@userActions/AppUpdate';
-import CONFIG from '@src/CONFIG';
+import * as AppUpdate from '@libs/actions/AppUpdate';
function UpdateRequiredView() {
const insets = useSafeAreaInsets();
@@ -23,7 +22,7 @@ function UpdateRequiredView() {
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {isProduction} = useEnvironment();
- const isStandaloneNewAppProduction = isProduction && !CONFIG.IS_HYBRID_APP;
+ const isStandaloneNewAppProduction = isProduction && !NativeModules.HybridAppModule;
return (
@@ -57,7 +56,7 @@ function UpdateRequiredView() {