mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Adding interface to wrap surface interactions for LogBox
Summary: This diff introduces a new interface named `SurfaceDelegate`. The interface abstracts the API for interacting with a surface, which is required for platforms other than mobile to implement how it wants to show and hide a surface. For existing Mobile use cases, the `LogBoxDialogSurfaceDelegate` is provided as a fallback solution so everything still works. Changelog: [Android][Added] - Add SurfaceDelegate abstraction to support interaction in multiple platforms and provide default implementation in LogBoxModule Reviewed By: mdvacca Differential Revision: D31132285 fbshipit-source-id: 13315a8bc5b7bcaee9b5e53ef5c6f6cc8cb01f31
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f2eecae63d
commit
652cb541a5
@@ -76,6 +76,7 @@ import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.devsupport.DevSupportManagerFactory;
|
||||
@@ -232,7 +233,8 @@ public class ReactInstanceManager {
|
||||
int minTimeLeftInFrameForNonBatchedOperationMs,
|
||||
@Nullable JSIModulePackage jsiModulePackage,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
|
||||
@Nullable ReactPackageTurboModuleManagerDelegate.Builder tmmDelegateBuilder) {
|
||||
@Nullable ReactPackageTurboModuleManagerDelegate.Builder tmmDelegateBuilder,
|
||||
@Nullable SurfaceDelegateFactory surfaceDelegateFactory) {
|
||||
FLog.d(TAG, "ReactInstanceManager.ctor()");
|
||||
initializeSoLoaderIfNecessary(applicationContext);
|
||||
|
||||
@@ -259,7 +261,8 @@ public class ReactInstanceManager {
|
||||
redBoxHandler,
|
||||
devBundleDownloadListener,
|
||||
minNumShakes,
|
||||
customPackagerCommandHandlers);
|
||||
customPackagerCommandHandlers,
|
||||
surfaceDelegateFactory);
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
mBridgeIdleDebugListener = bridgeIdleDebugListener;
|
||||
mLifecycleState = initialLifecycleState;
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.facebook.react.bridge.JavaScriptExecutorFactory;
|
||||
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
|
||||
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.devsupport.DefaultDevSupportManagerFactory;
|
||||
import com.facebook.react.devsupport.DevSupportManagerFactory;
|
||||
import com.facebook.react.devsupport.RedBoxHandler;
|
||||
@@ -63,6 +64,7 @@ public class ReactInstanceManagerBuilder {
|
||||
private @Nullable JSIModulePackage mJSIModulesPackage;
|
||||
private @Nullable Map<String, RequestHandler> mCustomPackagerCommandHandlers;
|
||||
private @Nullable ReactPackageTurboModuleManagerDelegate.Builder mTMMDelegateBuilder;
|
||||
private @Nullable SurfaceDelegateFactory mSurfaceDelegateFactory;
|
||||
|
||||
/* package protected */ ReactInstanceManagerBuilder() {}
|
||||
|
||||
@@ -195,6 +197,20 @@ public class ReactInstanceManagerBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the {@link SurfaceDelegateFactory} is provided, it will be used for native modules to get
|
||||
* a {@link SurfaceDelegate} to interact with the platform specific surface that they that needs
|
||||
* to be rendered in. For mobile platform this is default to be null so that these modules will
|
||||
* need to provide a default surface delegate. One example of such native module is LogBoxModule,
|
||||
* which is rendered in mobile platform with LogBoxDialog, while in VR platform with custom layer
|
||||
* provided by runtime.
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setSurfaceDelegateFactory(
|
||||
@Nullable final SurfaceDelegateFactory surfaceDelegateFactory) {
|
||||
mSurfaceDelegateFactory = surfaceDelegateFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initial lifecycle state of the host. For example, if the host is already resumed at
|
||||
* creation time, we wouldn't expect an onResume call until we get an onPause call.
|
||||
@@ -322,7 +338,8 @@ public class ReactInstanceManagerBuilder {
|
||||
mMinTimeLeftInFrameForNonBatchedOperationMs,
|
||||
mJSIModulesPackage,
|
||||
mCustomPackagerCommandHandlers,
|
||||
mTMMDelegateBuilder);
|
||||
mTMMDelegateBuilder,
|
||||
mSurfaceDelegateFactory);
|
||||
}
|
||||
|
||||
private JavaScriptExecutorFactory getDefaultJSExecutorFactory(
|
||||
|
||||
@@ -15,6 +15,8 @@ import com.facebook.react.bridge.JavaScriptExecutorFactory;
|
||||
import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.bridge.ReactMarkerConstants;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.common.SurfaceDelegate;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.devsupport.DevSupportManagerFactory;
|
||||
import com.facebook.react.devsupport.RedBoxHandler;
|
||||
import com.facebook.react.uimanager.UIImplementationProvider;
|
||||
@@ -71,6 +73,7 @@ public abstract class ReactNativeHost {
|
||||
.setUseDeveloperSupport(getUseDeveloperSupport())
|
||||
.setDevSupportManagerFactory(getDevSupportManagerFactory())
|
||||
.setRequireActivity(getShouldRequireActivity())
|
||||
.setSurfaceDelegateFactory(getSurfaceDelegateFactory())
|
||||
.setRedBoxHandler(getRedBoxHandler())
|
||||
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
|
||||
.setUIImplementationProvider(getUIImplementationProvider())
|
||||
@@ -132,6 +135,21 @@ public abstract class ReactNativeHost {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link SurfaceDelegateFactory} used by NativeModules to get access to a {@link
|
||||
* SurfaceDelegate} to interact with a surface. By default in the mobile platform the {@link
|
||||
* SurfaceDelegate} it returns is null, and the NativeModule needs to implement its own {@link
|
||||
* SurfaceDelegate} to decide how it would interact with its own container surface.
|
||||
*/
|
||||
public SurfaceDelegateFactory getSurfaceDelegateFactory() {
|
||||
return new SurfaceDelegateFactory() {
|
||||
@Override
|
||||
public @Nullable SurfaceDelegate createSurfaceDelegate(String moduleName) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main module. Determines the URL used to fetch the JS bundle from Metro.
|
||||
* It is only used when dev support is enabled. This is the first file to be executed once the
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.common;
|
||||
|
||||
/**
|
||||
* Interface for handling a surface in React Native. In mobile platform a surface can be any
|
||||
* container that holds some {@link View}. For example, a Dialog can be a surface to wrap content
|
||||
* view object as needed. In VR platform, a surface is provided by Shell panel app sdk, which
|
||||
* requires custom logic to show/hide. NativeModules requires a surface will delegate interactions
|
||||
* with the surface to a SurfaceDelegate.
|
||||
*/
|
||||
public interface SurfaceDelegate {
|
||||
/**
|
||||
* Create the React content view that uses the appKey as the React application name
|
||||
*
|
||||
* @param appKey
|
||||
*/
|
||||
void createContentView(String appKey);
|
||||
|
||||
/**
|
||||
* Check if the content view is created and ready to be shown
|
||||
*
|
||||
* @return true if the content view is ready to be shown
|
||||
*/
|
||||
boolean isContentViewReady();
|
||||
|
||||
/** Destroy the React content view to avoid memory leak */
|
||||
void destroyContentView();
|
||||
|
||||
/** Show the surface containing the React content view */
|
||||
void show();
|
||||
|
||||
/** Hide the surface containing the React content view */
|
||||
void hide();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.common;
|
||||
|
||||
/**
|
||||
* Factory to create a {@link SurfaceDelegate}. The moduleName is needed to help the factory decide
|
||||
* which surface to return {@link SurfaceDelegate} that the given module should use to interact
|
||||
* with.
|
||||
*/
|
||||
public interface SurfaceDelegateFactory {
|
||||
/**
|
||||
* Create a {@link SurfaceDelegate} instance which is used to interact with a surface of platform
|
||||
* the app is running in.
|
||||
*
|
||||
* @param moduleName the module name that will be using the surface
|
||||
* @return {@link SurfaceDelegate} instance
|
||||
*/
|
||||
SurfaceDelegate createSurfaceDelegate(String moduleName);
|
||||
}
|
||||
@@ -57,6 +57,7 @@ rn_android_library(
|
||||
react_native_dep("third-party/android/androidx:annotation"),
|
||||
react_native_dep("third-party/java/jsr-305:jsr-305"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/common:common"),
|
||||
react_native_target("java/com/facebook/react/modules/debug:interfaces"),
|
||||
],
|
||||
)
|
||||
|
||||
+5
-2
@@ -22,6 +22,7 @@ import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.bridge.ReactMarkerConstants;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.common.futures.SimpleSettableFuture;
|
||||
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
|
||||
import com.facebook.react.devsupport.interfaces.DevOptionHandler;
|
||||
@@ -71,7 +72,8 @@ public final class BridgeDevSupportManager extends DevSupportManagerBase {
|
||||
@Nullable RedBoxHandler redBoxHandler,
|
||||
@Nullable DevBundleDownloadListener devBundleDownloadListener,
|
||||
int minNumShakes,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
|
||||
@Nullable SurfaceDelegateFactory surfaceDelegateFactory) {
|
||||
super(
|
||||
applicationContext,
|
||||
reactInstanceManagerHelper,
|
||||
@@ -80,7 +82,8 @@ public final class BridgeDevSupportManager extends DevSupportManagerBase {
|
||||
redBoxHandler,
|
||||
devBundleDownloadListener,
|
||||
minNumShakes,
|
||||
customPackagerCommandHandlers);
|
||||
customPackagerCommandHandlers,
|
||||
surfaceDelegateFactory);
|
||||
|
||||
if (getDevSettings().isStartSamplingProfilerOnInit()) {
|
||||
// Only start the profiler. If its already running, there is an error
|
||||
|
||||
+8
-3
@@ -9,6 +9,7 @@ package com.facebook.react.devsupport;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.packagerconnection.RequestHandler;
|
||||
@@ -41,6 +42,7 @@ public class DefaultDevSupportManagerFactory implements DevSupportManagerFactory
|
||||
null,
|
||||
null,
|
||||
minNumShakes,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
@@ -53,7 +55,8 @@ public class DefaultDevSupportManagerFactory implements DevSupportManagerFactory
|
||||
@Nullable RedBoxHandler redBoxHandler,
|
||||
@Nullable DevBundleDownloadListener devBundleDownloadListener,
|
||||
int minNumShakes,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
|
||||
@Nullable SurfaceDelegateFactory surfaceDelegateFactory) {
|
||||
if (!enableOnCreate) {
|
||||
return new DisabledDevSupportManager();
|
||||
}
|
||||
@@ -76,7 +79,8 @@ public class DefaultDevSupportManagerFactory implements DevSupportManagerFactory
|
||||
RedBoxHandler.class,
|
||||
DevBundleDownloadListener.class,
|
||||
int.class,
|
||||
Map.class);
|
||||
Map.class,
|
||||
SurfaceDelegateFactory.class);
|
||||
return (DevSupportManager)
|
||||
constructor.newInstance(
|
||||
applicationContext,
|
||||
@@ -86,7 +90,8 @@ public class DefaultDevSupportManagerFactory implements DevSupportManagerFactory
|
||||
redBoxHandler,
|
||||
devBundleDownloadListener,
|
||||
minNumShakes,
|
||||
customPackagerCommandHandlers);
|
||||
customPackagerCommandHandlers,
|
||||
surfaceDelegateFactory);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Requested enabled DevSupportManager, but BridgeDevSupportManager class was not found"
|
||||
|
||||
+21
-2
@@ -41,6 +41,8 @@ import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.DebugServerException;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.ShakeDetector;
|
||||
import com.facebook.react.common.SurfaceDelegate;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.devsupport.DevServerHelper.PackagerCommandListener;
|
||||
import com.facebook.react.devsupport.interfaces.BundleLoadCallback;
|
||||
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
|
||||
@@ -118,6 +120,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
private @Nullable Map<String, RequestHandler> mCustomPackagerCommandHandlers;
|
||||
|
||||
private @Nullable Activity currentActivity;
|
||||
private @Nullable final SurfaceDelegateFactory mSurfaceDelegateFactory;
|
||||
|
||||
public DevSupportManagerBase(
|
||||
Context applicationContext,
|
||||
@@ -127,7 +130,8 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
@Nullable RedBoxHandler redBoxHandler,
|
||||
@Nullable DevBundleDownloadListener devBundleDownloadListener,
|
||||
int minNumShakes,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
|
||||
@Nullable SurfaceDelegateFactory surfaceDelegateFactory) {
|
||||
mReactInstanceDevHelper = reactInstanceDevHelper;
|
||||
mApplicationContext = applicationContext;
|
||||
mJSAppBundleName = packagerPathForJSBundleName;
|
||||
@@ -202,7 +206,8 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
|
||||
mRedBoxHandler = redBoxHandler;
|
||||
mDevLoadingViewController = new DevLoadingViewController(reactInstanceDevHelper);
|
||||
}
|
||||
mSurfaceDelegateFactory = surfaceDelegateFactory;
|
||||
};
|
||||
|
||||
protected abstract String getUniqueTag();
|
||||
|
||||
@@ -1204,4 +1209,18 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
||||
DevSupportManager.PackagerLocationCustomizer packagerLocationCustomizer) {
|
||||
mPackagerLocationCustomizer = packagerLocationCustomizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Activity getCurrentActivity() {
|
||||
return mReactInstanceDevHelper.getCurrentActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SurfaceDelegate createSurfaceDelegate(String moduleName) {
|
||||
if (mSurfaceDelegateFactory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mSurfaceDelegateFactory.createSurfaceDelegate(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -9,6 +9,7 @@ package com.facebook.react.devsupport;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.common.SurfaceDelegateFactory;
|
||||
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.packagerconnection.RequestHandler;
|
||||
@@ -23,5 +24,6 @@ public interface DevSupportManagerFactory {
|
||||
@Nullable RedBoxHandler redBoxHandler,
|
||||
@Nullable DevBundleDownloadListener devBundleDownloadListener,
|
||||
int minNumShakes,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers);
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
|
||||
@Nullable SurfaceDelegateFactory surfaceDelegateFactory);
|
||||
}
|
||||
|
||||
+12
@@ -7,11 +7,13 @@
|
||||
|
||||
package com.facebook.react.devsupport;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.common.SurfaceDelegate;
|
||||
import com.facebook.react.devsupport.interfaces.BundleLoadCallback;
|
||||
import com.facebook.react.devsupport.interfaces.DevOptionHandler;
|
||||
import com.facebook.react.devsupport.interfaces.DevSplitBundleCallback;
|
||||
@@ -175,4 +177,14 @@ public class DisabledDevSupportManager implements DevSupportManager {
|
||||
public void handleException(Exception e) {
|
||||
mDefaultNativeModuleCallExceptionHandler.handleException(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Activity getCurrentActivity() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SurfaceDelegate createSurfaceDelegate(String moduleName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.devsupport;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.common.SurfaceDelegate;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.util.RNLog;
|
||||
|
||||
/**
|
||||
* The implementation of SurfaceDelegate with {@link Activity}. This is the default SurfaceDelegate
|
||||
* for Mobile.
|
||||
*/
|
||||
public class LogBoxDialogSurfaceDelegate implements SurfaceDelegate {
|
||||
|
||||
private @Nullable View mReactRootView;
|
||||
private @Nullable LogBoxDialog mDialog;
|
||||
private final DevSupportManager mDevSupportManager;
|
||||
|
||||
LogBoxDialogSurfaceDelegate(DevSupportManager devSupportManager) {
|
||||
mDevSupportManager = devSupportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createContentView(String appKey) {
|
||||
Assertions.assertCondition(
|
||||
appKey.equals("LogBox"), "This surface manager can only create LogBox React application");
|
||||
mReactRootView = mDevSupportManager.createRootView("LogBox");
|
||||
if (mReactRootView == null) {
|
||||
RNLog.e("Unable to launch logbox because react was unable to create the root view");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContentViewReady() {
|
||||
return mReactRootView != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyContentView() {
|
||||
if (mReactRootView != null) {
|
||||
mDevSupportManager.destroyRootView(mReactRootView);
|
||||
mReactRootView = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (isSurfaceVisible() || !isContentViewReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final @Nullable Activity context = mDevSupportManager.getCurrentActivity();
|
||||
if (context == null || context.isFinishing()) {
|
||||
RNLog.e(
|
||||
"Unable to launch logbox because react activity "
|
||||
+ "is not available, here is the error that logbox would've displayed: ");
|
||||
return;
|
||||
}
|
||||
|
||||
mDialog = new LogBoxDialog(context, mReactRootView);
|
||||
mDialog.setCancelable(false);
|
||||
mDialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if (!isSurfaceVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mReactRootView != null && mReactRootView.getParent() != null) {
|
||||
((ViewGroup) mReactRootView.getParent()).removeView(mReactRootView);
|
||||
}
|
||||
|
||||
mDialog.dismiss();
|
||||
mDialog = null;
|
||||
}
|
||||
|
||||
private boolean isSurfaceVisible() {
|
||||
return mDialog != null;
|
||||
}
|
||||
}
|
||||
@@ -7,16 +7,13 @@
|
||||
|
||||
package com.facebook.react.devsupport;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.fbreact.specs.NativeLogBoxSpec;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.SurfaceDelegate;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.util.RNLog;
|
||||
|
||||
@ReactModule(name = LogBoxModule.NAME)
|
||||
public class LogBoxModule extends NativeLogBoxSpec {
|
||||
@@ -24,24 +21,30 @@ public class LogBoxModule extends NativeLogBoxSpec {
|
||||
public static final String NAME = "LogBox";
|
||||
|
||||
private final DevSupportManager mDevSupportManager;
|
||||
private @Nullable View mReactRootView;
|
||||
private @Nullable LogBoxDialog mLogBoxDialog;
|
||||
private final SurfaceDelegate mSurfaceDelegate;
|
||||
|
||||
/**
|
||||
* LogBoxModule can be rendered in different surface. By default, it will use LogBoxDialog to wrap
|
||||
* the content of logs. In other platform (for example VR), a surfaceDelegate can be provided so
|
||||
* that the content can be wrapped in custom surface.
|
||||
*/
|
||||
public LogBoxModule(ReactApplicationContext reactContext, DevSupportManager devSupportManager) {
|
||||
super(reactContext);
|
||||
|
||||
mDevSupportManager = devSupportManager;
|
||||
|
||||
@Nullable SurfaceDelegate surfaceDelegate = devSupportManager.createSurfaceDelegate(NAME);
|
||||
if (surfaceDelegate != null) {
|
||||
mSurfaceDelegate = surfaceDelegate;
|
||||
} else {
|
||||
mSurfaceDelegate = new LogBoxDialogSurfaceDelegate(devSupportManager);
|
||||
}
|
||||
|
||||
UiThreadUtil.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mReactRootView == null && mDevSupportManager != null) {
|
||||
mReactRootView = mDevSupportManager.createRootView("LogBox");
|
||||
if (mReactRootView == null) {
|
||||
RNLog.e("Unable to launch logbox because react was unable to create the root view");
|
||||
}
|
||||
}
|
||||
mSurfaceDelegate.createContentView("LogBox");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -53,26 +56,17 @@ public class LogBoxModule extends NativeLogBoxSpec {
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (mReactRootView != null) {
|
||||
UiThreadUtil.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mLogBoxDialog == null && mReactRootView != null) {
|
||||
Activity context = getCurrentActivity();
|
||||
if (context == null || context.isFinishing()) {
|
||||
RNLog.e(
|
||||
"Unable to launch logbox because react activity "
|
||||
+ "is not available, here is the error that logbox would've displayed: ");
|
||||
return;
|
||||
}
|
||||
mLogBoxDialog = new LogBoxDialog(context, mReactRootView);
|
||||
mLogBoxDialog.setCancelable(false);
|
||||
mLogBoxDialog.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!mSurfaceDelegate.isContentViewReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UiThreadUtil.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSurfaceDelegate.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,13 +75,7 @@ public class LogBoxModule extends NativeLogBoxSpec {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mLogBoxDialog != null) {
|
||||
if (mReactRootView != null && mReactRootView.getParent() != null) {
|
||||
((ViewGroup) mReactRootView.getParent()).removeView(mReactRootView);
|
||||
}
|
||||
mLogBoxDialog.dismiss();
|
||||
mLogBoxDialog = null;
|
||||
}
|
||||
mSurfaceDelegate.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -98,10 +86,7 @@ public class LogBoxModule extends NativeLogBoxSpec {
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mReactRootView != null) {
|
||||
mDevSupportManager.destroyRootView(mReactRootView);
|
||||
mReactRootView = null;
|
||||
}
|
||||
mSurfaceDelegate.destroyContentView();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+14
@@ -7,11 +7,13 @@
|
||||
|
||||
package com.facebook.react.devsupport.interfaces;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.common.SurfaceDelegate;
|
||||
import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
|
||||
import java.io.File;
|
||||
|
||||
@@ -107,4 +109,16 @@ public interface DevSupportManager extends NativeModuleCallExceptionHandler {
|
||||
}
|
||||
|
||||
void setPackagerLocationCustomizer(PackagerLocationCustomizer packagerLocationCustomizer);
|
||||
|
||||
@Nullable
|
||||
Activity getCurrentActivity();
|
||||
|
||||
/**
|
||||
* Create the surface delegate that the provided module should use to interact with
|
||||
*
|
||||
* @param moduleName the module name that helps decide which surface it should interact with
|
||||
* @return a {@link SurfaceDelegate} instance
|
||||
*/
|
||||
@Nullable
|
||||
SurfaceDelegate createSurfaceDelegate(String moduleName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user