Back out "Back out "[react-native][PR] Migrate ReactDelegate to Kotlin"" (#52322)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52322

Original commit changeset: 4a366205ea9c

Original Phabricator Diff: D77388940

Reverting the revert since it did not fix our javascript crash problem for v270 https://fburl.com/scuba/errorreporting_system_vros_javascripterrors/mtexik9e

Original diff stack: D76908041
Revert diff stack: D77388940

Changelog[Internal]:
Puting back the Kotlin Migration for ReactDelegate file

Reviewed By: cortinico

Differential Revision: D77448238

fbshipit-source-id: f41faa19f6761b7ed644e804019f5ec4738326a7
This commit is contained in:
Soe Lynn
2025-06-27 11:55:44 -07:00
committed by Facebook GitHub Bot
parent ee02152fee
commit faef2b1252
4 changed files with 433 additions and 485 deletions
@@ -148,29 +148,29 @@ public class com/facebook/react/ReactDelegate {
public fun <init> (Landroid/app/Activity;Lcom/facebook/react/ReactNativeHost;Ljava/lang/String;Landroid/os/Bundle;)V
public fun <init> (Landroid/app/Activity;Lcom/facebook/react/ReactNativeHost;Ljava/lang/String;Landroid/os/Bundle;Z)V
protected fun createRootView ()Lcom/facebook/react/ReactRootView;
public fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;
public fun getReactHost ()Lcom/facebook/react/ReactHost;
public fun getReactInstanceManager ()Lcom/facebook/react/ReactInstanceManager;
public fun getReactRootView ()Lcom/facebook/react/ReactRootView;
protected fun isFabricEnabled ()Z
public fun loadApp ()V
public fun loadApp (Ljava/lang/String;)V
public fun onActivityResult (IILandroid/content/Intent;Z)V
public fun onBackPressed ()Z
public fun onConfigurationChanged (Landroid/content/res/Configuration;)V
public fun onHostDestroy ()V
public fun onHostPause ()V
public fun onHostResume ()V
public fun onKeyDown (ILandroid/view/KeyEvent;)Z
public fun onKeyLongPress (I)Z
public fun onNewIntent (Landroid/content/Intent;)Z
public fun onUserLeaveHint ()V
public fun onWindowFocusChanged (Z)V
public fun reload ()V
public fun setReactRootView (Lcom/facebook/react/ReactRootView;)V
public fun setReactSurface (Lcom/facebook/react/interfaces/fabric/ReactSurface;)V
public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z
public fun unloadApp ()V
public final fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;
public final fun getReactHost ()Lcom/facebook/react/ReactHost;
public final fun getReactInstanceManager ()Lcom/facebook/react/ReactInstanceManager;
public final fun getReactRootView ()Lcom/facebook/react/ReactRootView;
protected final fun isFabricEnabled ()Z
public final fun loadApp ()V
public final fun loadApp (Ljava/lang/String;)V
public final fun onActivityResult (IILandroid/content/Intent;Z)V
public final fun onBackPressed ()Z
public final fun onConfigurationChanged (Landroid/content/res/Configuration;)V
public final fun onHostDestroy ()V
public final fun onHostPause ()V
public final fun onHostResume ()V
public final fun onKeyDown (ILandroid/view/KeyEvent;)Z
public final fun onKeyLongPress (I)Z
public final fun onNewIntent (Landroid/content/Intent;)Z
public final fun onUserLeaveHint ()V
public final fun onWindowFocusChanged (Z)V
public final fun reload ()V
public final fun setReactRootView (Lcom/facebook/react/ReactRootView;)V
public final fun setReactSurface (Lcom/facebook/react/interfaces/fabric/ReactSurface;)V
public final fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z
public final fun unloadApp ()V
}
public class com/facebook/react/ReactFragment : androidx/fragment/app/Fragment, com/facebook/react/modules/core/PermissionAwareActivity {
@@ -1,461 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.KeyEvent;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.common.annotations.DeprecatedInNewArchitecture;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.devsupport.ReleaseDevSupportManager;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.interfaces.fabric.ReactSurface;
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import java.util.Objects;
/**
* A delegate for handling React Application support. This delegate is unaware whether it is used in
* an {@link Activity} or a {@link android.app.Fragment}.
*/
@Nullsafe(Nullsafe.Mode.LOCAL)
public class ReactDelegate {
private final Activity mActivity;
@Nullable private ReactRootView mReactRootView;
@Nullable private final String mMainComponentName;
@Nullable private Bundle mLaunchOptions;
@Nullable private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
@Nullable private ReactNativeHost mReactNativeHost;
@Nullable private ReactHost mReactHost;
@Nullable private ReactSurface mReactSurface;
private boolean mFabricEnabled = ReactNativeNewArchitectureFeatureFlags.enableFabricRenderer();
/**
* Do not use this constructor as it's not accounting for New Architecture at all. You should use
* {@link ReactDelegate#ReactDelegate(Activity, ReactNativeHost, String, Bundle, boolean)} as it's
* the constructor used for New Architecture.
*
* @deprecated Use one of the other constructors instead to account for New Architecture.
*/
@Deprecated(since = "0.75.0")
public ReactDelegate(
Activity activity,
@Nullable ReactNativeHost reactNativeHost,
@Nullable String appKey,
@Nullable Bundle launchOptions) {
mActivity = activity;
mMainComponentName = appKey;
mLaunchOptions = launchOptions;
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
mReactNativeHost = reactNativeHost;
}
public ReactDelegate(
Activity activity,
@Nullable ReactHost reactHost,
@Nullable String appKey,
@Nullable Bundle launchOptions) {
mActivity = activity;
mMainComponentName = appKey;
mLaunchOptions = launchOptions;
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
mReactHost = reactHost;
}
@Deprecated(since = "0.81.0")
public ReactDelegate(
Activity activity,
@Nullable ReactNativeHost reactNativeHost,
@Nullable String appKey,
@Nullable Bundle launchOptions,
boolean fabricEnabled) {
mFabricEnabled = fabricEnabled;
mActivity = activity;
mMainComponentName = appKey;
mLaunchOptions = launchOptions;
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
mReactNativeHost = reactNativeHost;
}
@Nullable
private DevSupportManager getDevSupportManager() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null
&& mReactHost.getDevSupportManager() != null) {
return mReactHost.getDevSupportManager();
} else if (getReactNativeHost() != null
&& getReactNativeHost().hasInstance()
&& getReactNativeHost().getReactInstanceManager() != null) {
return getReactNativeHost().getReactInstanceManager().getDevSupportManager();
} else {
return null;
}
}
public void onHostResume() {
if (!(mActivity instanceof DefaultHardwareBackBtnHandler)) {
throw new ClassCastException(
"Host Activity `${activity.javaClass.simpleName}` does not implement"
+ " DefaultHardwareBackBtnHandler");
}
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null && reactNativeHost.hasInstance()) {
reactNativeHost
.getReactInstanceManager()
.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
}
}
}
public void onUserLeaveHint() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onHostLeaveHint(mActivity);
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null && reactNativeHost.hasInstance()) {
reactNativeHost.getReactInstanceManager().onUserLeaveHint(mActivity);
}
}
}
public void onHostPause() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onHostPause(mActivity);
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null && reactNativeHost.hasInstance()) {
reactNativeHost.getReactInstanceManager().onHostPause(mActivity);
}
}
}
public void onHostDestroy() {
unloadApp();
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onHostDestroy(mActivity);
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null && reactNativeHost.hasInstance()) {
reactNativeHost.getReactInstanceManager().onHostDestroy(mActivity);
}
}
}
public boolean onBackPressed() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onBackPressed();
return true;
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null && reactNativeHost.hasInstance()) {
reactNativeHost.getReactInstanceManager().onBackPressed();
return true;
}
}
return false;
}
public boolean onNewIntent(Intent intent) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onNewIntent(intent);
return true;
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null && reactNativeHost.hasInstance()) {
reactNativeHost.getReactInstanceManager().onNewIntent(intent);
return true;
}
}
return false;
}
public void onActivityResult(
int requestCode,
int resultCode,
@Nullable Intent data,
boolean shouldForwardToReactInstance) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onActivityResult(mActivity, requestCode, resultCode, data);
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null
&& reactNativeHost.hasInstance()
&& shouldForwardToReactInstance) {
reactNativeHost
.getReactInstanceManager()
.onActivityResult(mActivity, requestCode, resultCode, data);
}
}
}
public void onWindowFocusChanged(boolean hasFocus) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onWindowFocusChange(hasFocus);
} else {
if (getReactNativeHost() != null && getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager().onWindowFocusChange(hasFocus);
}
}
}
public void onConfigurationChanged(Configuration newConfig) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
mReactHost.onConfigurationChanged(Assertions.assertNotNull(mActivity));
} else {
if (getReactNativeHost() != null && getReactNativeHost().hasInstance()) {
getReactInstanceManager()
.onConfigurationChanged(Assertions.assertNotNull(mActivity), newConfig);
}
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
&& ((ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null
&& mReactHost.getDevSupportManager() != null)
|| (getReactNativeHost() != null
&& getReactNativeHost().hasInstance()
&& getReactNativeHost().getUseDeveloperSupport()))) {
event.startTracking();
return true;
}
return false;
}
public boolean onKeyLongPress(int keyCode) {
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()
&& mReactHost != null) {
DevSupportManager devSupportManager = mReactHost.getDevSupportManager();
// onKeyLongPress is a Dev API and not supported in RELEASE mode.
if (devSupportManager != null && !(devSupportManager instanceof ReleaseDevSupportManager)) {
devSupportManager.showDevOptionsDialog();
return true;
}
} else {
ReactNativeHost reactNativeHost = getReactNativeHost();
if (reactNativeHost != null
&& reactNativeHost.hasInstance()
&& reactNativeHost.getUseDeveloperSupport()) {
reactNativeHost.getReactInstanceManager().showDevOptionsDialog();
return true;
}
}
}
return false;
}
public void reload() {
DevSupportManager devSupportManager = getDevSupportManager();
if (devSupportManager == null) {
return;
}
// Reload in RELEASE mode
if (devSupportManager instanceof ReleaseDevSupportManager) {
// Do not reload the bundle from JS as there is no bundler running in release mode.
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (mReactHost != null) {
mReactHost.reload("ReactDelegate.reload()");
}
} else {
UiThreadUtil.runOnUiThread(
() -> {
if (mReactNativeHost != null
&& mReactNativeHost.hasInstance()
&& mReactNativeHost.getReactInstanceManager() != null) {
mReactNativeHost.getReactInstanceManager().recreateReactContextInBackground();
}
});
}
return;
}
// Reload in DEBUG mode
devSupportManager.handleReloadJS();
}
/** Start the React surface with the app key supplied in the {@link ReactDelegate} constructor. */
public void loadApp() {
if (mMainComponentName == null) {
throw new IllegalStateException("Cannot loadApp without a main component name.");
} else {
loadApp(mMainComponentName);
}
}
/**
* Start the React surface for the given app key.
*
* @param appKey The ID of the app to load into the surface.
*/
public void loadApp(String appKey) {
// With Bridgeless enabled, create and start the surface
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (mReactSurface == null && mReactHost != null) {
mReactSurface = mReactHost.createSurface(mActivity, appKey, mLaunchOptions);
}
Objects.requireNonNull(mReactSurface).start();
} else {
if (mReactRootView != null) {
throw new IllegalStateException("Cannot loadApp while app is already running.");
}
mReactRootView = createRootView();
if (getReactNativeHost() != null) {
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
}
}
}
/** Stop the React surface started with {@link ReactDelegate#loadApp()}. */
public void unloadApp() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (mReactSurface != null) {
mReactSurface.stop();
mReactSurface = null;
}
} else {
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
mReactRootView = null;
}
}
}
public void setReactSurface(ReactSurface reactSurface) {
mReactSurface = reactSurface;
}
public void setReactRootView(ReactRootView reactRootView) {
mReactRootView = reactRootView;
}
@Nullable
public ReactRootView getReactRootView() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (mReactSurface != null) {
return (ReactRootView) mReactSurface.getView();
} else {
return null;
}
} else {
return mReactRootView;
}
}
// Not used in bridgeless
protected ReactRootView createRootView() {
ReactRootView reactRootView = new ReactRootView(mActivity);
reactRootView.setIsFabric(isFabricEnabled());
return reactRootView;
}
/**
* Handles delegating the {@link Activity#onKeyUp(int, KeyEvent)} method to determine whether the
* application should show the developer menu or should reload the React Application.
*
* @return true if we consume the event and either shoed the develop menu or reloaded the
* application.
*/
public boolean shouldShowDevMenuOrReload(int keyCode, KeyEvent event) {
DevSupportManager devSupportManager = getDevSupportManager();
// shouldShowDevMenuOrReload is a Dev API and not supported in RELEASE mode.
if (devSupportManager == null || devSupportManager instanceof ReleaseDevSupportManager) {
return false;
}
if (keyCode == KeyEvent.KEYCODE_MENU) {
devSupportManager.showDevOptionsDialog();
return true;
}
boolean didDoubleTapR =
Objects.requireNonNull(mDoubleTapReloadRecognizer)
.didDoubleTapR(keyCode, mActivity.getCurrentFocus());
if (didDoubleTapR) {
devSupportManager.handleReloadJS();
return true;
}
return false;
}
/** Get the {@link ReactNativeHost} used by this app. */
@DeprecatedInNewArchitecture(message = "Use getReactHost()")
private @Nullable ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@DeprecatedInNewArchitecture(message = "Use getReactHost()")
public ReactInstanceManager getReactInstanceManager() {
if (getReactNativeHost() == null) {
throw new IllegalStateException("Cannot get ReactInstanceManager without a ReactNativeHost.");
}
return getReactNativeHost().getReactInstanceManager();
}
public @Nullable ReactHost getReactHost() {
return mReactHost;
}
/**
* Get the current {@link ReactContext} from ReactHost or ReactInstanceManager
*
* <p>Do not store a reference to this, if the React instance is reloaded or destroyed, this
* context will no longer be valid.
*/
public @Nullable ReactContext getCurrentReactContext() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (mReactHost != null) {
return mReactHost.getCurrentReactContext();
} else {
return null;
}
} else {
return getReactInstanceManager().getCurrentReactContext();
}
}
/**
* Override this method if you wish to selectively toggle Fabric for a specific surface. This will
* also control if Concurrent Root (React 18) should be enabled or not.
*
* @return true if Fabric is enabled for this Activity, false otherwise.
*/
protected boolean isFabricEnabled() {
return mFabricEnabled;
}
}
@@ -0,0 +1,409 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react
import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import android.view.KeyEvent
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.UiThreadUtil.runOnUiThread
import com.facebook.react.common.annotations.DeprecatedInNewArchitecture
import com.facebook.react.devsupport.DoubleTapReloadRecognizer
import com.facebook.react.devsupport.ReleaseDevSupportManager
import com.facebook.react.devsupport.interfaces.DevSupportManager
import com.facebook.react.interfaces.fabric.ReactSurface
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler
/**
* A delegate for handling React Application support. This delegate is unaware whether it is used in
* an [Activity] or a [android.app.Fragment].
*/
public open class ReactDelegate {
private val activity: Activity
private var internalReactRootView: ReactRootView? = null
private val mainComponentName: String?
private var launchOptions: Bundle?
private var doubleTapReloadRecognizer: DoubleTapReloadRecognizer?
private var reactNativeHost: ReactNativeHost? = null
public var reactHost: ReactHost? = null
private set
private var reactSurface: ReactSurface? = null
/**
* Override this method if you wish to selectively toggle Fabric for a specific surface. This will
* also control if Concurrent Root (React 18) should be enabled or not.
*
* @return true if Fabric is enabled for this Activity, false otherwise.
*/
protected var isFabricEnabled: Boolean =
ReactNativeNewArchitectureFeatureFlags.enableFabricRenderer()
private set
/**
* Do not use this constructor as it's not accounting for New Architecture at all. You should use
* [ReactDelegate(Activity, ReactNativeHost, String, Bundle, boolean)] as it's the constructor
* used for New Architecture.
*/
@Deprecated(
"Use one of the other constructors instead to account for New Architecture. Deprecated since 0.75.0")
public constructor(
activity: Activity,
reactNativeHost: ReactNativeHost?,
appKey: String?,
launchOptions: Bundle?
) {
this.activity = activity
mainComponentName = appKey
this.launchOptions = launchOptions
doubleTapReloadRecognizer = DoubleTapReloadRecognizer()
this.reactNativeHost = reactNativeHost
}
public constructor(
activity: Activity,
reactHost: ReactHost?,
appKey: String?,
launchOptions: Bundle?
) {
this.activity = activity
mainComponentName = appKey
this.launchOptions = launchOptions
doubleTapReloadRecognizer = DoubleTapReloadRecognizer()
this.reactHost = reactHost
}
@Deprecated("Deprecated since 0.81.0, use one of the other constructors instead.")
public constructor(
activity: Activity,
reactNativeHost: ReactNativeHost?,
appKey: String?,
launchOptions: Bundle?,
fabricEnabled: Boolean
) {
isFabricEnabled = fabricEnabled
this.activity = activity
mainComponentName = appKey
this.launchOptions = launchOptions
doubleTapReloadRecognizer = DoubleTapReloadRecognizer()
this.reactNativeHost = reactNativeHost
}
private val devSupportManager: DevSupportManager?
get() =
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost?.devSupportManager != null) {
reactHost?.devSupportManager
} else if (reactNativeHost?.hasInstance() == true &&
reactNativeHost?.reactInstanceManager != null) {
reactNativeHost?.reactInstanceManager?.devSupportManager
} else {
null
}
public fun onHostResume() {
if (activity !is DefaultHardwareBackBtnHandler) {
throw ClassCastException(
"Host Activity `${activity.javaClass.simpleName}` does not implement DefaultHardwareBackBtnHandler")
}
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onHostResume(activity, activity as DefaultHardwareBackBtnHandler)
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost
?.reactInstanceManager
?.onHostResume(activity, activity as DefaultHardwareBackBtnHandler)
}
}
}
public fun onUserLeaveHint() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onHostLeaveHint(activity)
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost?.reactInstanceManager?.onUserLeaveHint(activity)
}
}
}
public fun onHostPause() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onHostPause(activity)
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost?.reactInstanceManager?.onHostPause(activity)
}
}
}
public fun onHostDestroy() {
unloadApp()
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onHostDestroy(activity)
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost?.reactInstanceManager?.onHostDestroy(activity)
}
}
}
public fun onBackPressed(): Boolean {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onBackPressed()
return true
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost?.reactInstanceManager?.onBackPressed()
return true
}
}
return false
}
public fun onNewIntent(intent: Intent): Boolean {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onNewIntent(intent)
return true
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost?.reactInstanceManager?.onNewIntent(intent)
return true
}
}
return false
}
public fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?,
shouldForwardToReactInstance: Boolean
) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onActivityResult(activity, requestCode, resultCode, data)
} else {
if (reactNativeHost?.hasInstance() == true && shouldForwardToReactInstance) {
reactNativeHost
?.reactInstanceManager
?.onActivityResult(activity, requestCode, resultCode, data)
}
}
}
public fun onWindowFocusChanged(hasFocus: Boolean) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onWindowFocusChange(hasFocus)
} else {
if (reactNativeHost?.hasInstance() == true) {
reactNativeHost?.reactInstanceManager?.onWindowFocusChange(hasFocus)
}
}
}
public fun onConfigurationChanged(newConfig: Configuration?) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
reactHost?.onConfigurationChanged(checkNotNull(activity))
} else {
if (reactNativeHost?.hasInstance() == true) {
getReactInstanceManager().onConfigurationChanged(checkNotNull(activity), newConfig)
}
}
}
public fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD &&
((ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost?.devSupportManager != null) ||
(reactNativeHost?.hasInstance() == true &&
reactNativeHost?.useDeveloperSupport == true))) {
event.startTracking()
return true
}
return false
}
public fun onKeyLongPress(keyCode: Int): Boolean {
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture() &&
reactHost != null) {
val devSupportManager = reactHost?.devSupportManager
// onKeyLongPress is a Dev API and not supported in RELEASE mode.
if (devSupportManager != null && devSupportManager !is ReleaseDevSupportManager) {
devSupportManager.showDevOptionsDialog()
return true
}
} else {
if (reactNativeHost?.hasInstance() == true &&
reactNativeHost?.useDeveloperSupport == true) {
reactNativeHost?.reactInstanceManager?.showDevOptionsDialog()
return true
}
}
}
return false
}
public fun reload() {
val devSupportManager = devSupportManager ?: return
// Reload in RELEASE mode
if (devSupportManager is ReleaseDevSupportManager) {
// Do not reload the bundle from JS as there is no bundler running in release mode.
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
reactHost?.reload("ReactDelegate.reload()")
} else {
runOnUiThread {
if (reactNativeHost?.hasInstance() == true &&
reactNativeHost?.reactInstanceManager != null) {
reactNativeHost?.reactInstanceManager?.recreateReactContextInBackground()
}
}
}
return
}
// Reload in DEBUG mode
devSupportManager.handleReloadJS()
}
/** Start the React surface with the app key supplied in the [ReactDelegate] constructor. */
public fun loadApp() {
val name = requireNotNull(mainComponentName) { "Cannot loadApp without a main component name." }
loadApp(name)
}
/**
* Start the React surface for the given app key.
*
* @param appKey The ID of the app to load into the surface.
*/
public fun loadApp(appKey: String) {
// With Bridgeless enabled, create and start the surface
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
val reactHost = reactHost
if (reactSurface == null && reactHost != null) {
reactSurface = reactHost.createSurface(activity, appKey, launchOptions)
}
reactSurface?.start()
} else {
check(internalReactRootView == null) { "Cannot loadApp while app is already running." }
internalReactRootView = createRootView()
if (reactNativeHost != null) {
internalReactRootView?.startReactApplication(
reactNativeHost?.reactInstanceManager, appKey, launchOptions)
}
}
}
/** Stop the React surface started with [ReactDelegate.loadApp]. */
public fun unloadApp() {
if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
reactSurface?.stop()
reactSurface = null
} else {
if (internalReactRootView != null) {
internalReactRootView?.unmountReactApplication()
internalReactRootView = null
}
}
}
public fun setReactSurface(reactSurface: ReactSurface?) {
this.reactSurface = reactSurface
}
public var reactRootView: ReactRootView?
get() {
return if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (reactSurface != null) {
reactSurface?.view as ReactRootView?
} else {
null
}
} else {
internalReactRootView
}
}
set(reactRootView) {
internalReactRootView = reactRootView
}
// Not used in bridgeless
protected open fun createRootView(): ReactRootView? {
val reactRootView = ReactRootView(activity)
reactRootView.setIsFabric(isFabricEnabled)
return reactRootView
}
/**
* Handles delegating the [Activity.onKeyUp] method to determine whether the application should
* show the developer menu or should reload the React Application.
*
* @return true if we consume the event and either show the develop menu or reloaded the
* application.
*/
public fun shouldShowDevMenuOrReload(keyCode: Int, event: KeyEvent?): Boolean {
val devSupportManager = devSupportManager
// shouldShowDevMenuOrReload is a Dev API and not supported in RELEASE mode.
if (devSupportManager == null || devSupportManager is ReleaseDevSupportManager) {
return false
}
if (keyCode == KeyEvent.KEYCODE_MENU) {
devSupportManager.showDevOptionsDialog()
return true
}
val didDoubleTapR = doubleTapReloadRecognizer?.didDoubleTapR(keyCode, activity.currentFocus)
if (didDoubleTapR == true) {
devSupportManager.handleReloadJS()
return true
}
return false
}
@DeprecatedInNewArchitecture(message = "Use reactHost")
public fun getReactInstanceManager(): ReactInstanceManager {
val nonNullReactNativeHost =
checkNotNull(reactNativeHost) {
"Cannot get ReactInstanceManager without a ReactNativeHost."
}
return nonNullReactNativeHost.reactInstanceManager
}
/**
* Get the current [ReactContext] from [ReactHost] or [ReactInstanceManager]
*
* Do not store a reference to this, if the React instance is reloaded or destroyed, this context
* will no longer be valid.
*/
public val currentReactContext: ReactContext?
get() {
return if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
if (reactHost != null) {
reactHost?.currentReactContext
} else {
null
}
} else {
getReactInstanceManager().currentReactContext
}
}
}
@@ -68,7 +68,7 @@ internal class RNTesterActivity : ReactActivity() {
// register insets listener to update margins on the ReactRootView to avoid overlap w/ system
// bars
getReactDelegate()?.getReactRootView()?.let { rootView ->
getReactDelegate()?.reactRootView?.let { rootView ->
val insetsType: Int =
WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()