mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
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:
committed by
Facebook GitHub Bot
parent
ee02152fee
commit
faef2b1252
@@ -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 {
|
||||
|
||||
-461
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user