- Add DevSetting native module (making it cross-platform) (#24441)

Summary:
React Native has a `NativeModule` to manipulate programmatically the dev menu options (live reload, hot reload, remote debugging, etc), called [`DevSettings`](https://github.com/facebook/react-native/blob/master/React/Modules/RCTDevSettings.mm#L120). However this module is only available for iOS.

This PR brings the same `DevSettings` for Android, making it a cross-platform NativeModule.

Motivation: Right now if your app needs to programmatically reload RN, one option is to install [`react-native-restart`](https://www.npmjs.com/package/react-native-restart). It's a tiny dependency, but it's annoying to have to install it, while the code to do so is inside RN codebase. According to NPM, react-native-restart has ~12k weekly downloads, shows it's a recurring feature for many apps (my case).

Thus making `NativeModules.DevSettings` is a small increment in the codebase, just exposing the dev menu methods, to improve the Development Experience

[Android] [Added] - Add DevSetting native module (making it cross-platform)

With expection of `setIsShakeToShowDevMenuEnabled`, the following methods will be available for both platforms:
* reload
* setHotLoadingEnabled
* setIsDebuggingRemotely
* setIsShakeToShowDevMenuEnabled
* setLiveReloadEnabled
* setProfilingEnabled
* toggleElementInspector
Pull Request resolved: https://github.com/facebook/react-native/pull/24441

Differential Revision: D14932751

Pulled By: cpojer

fbshipit-source-id: 465e6a89c3beb5fd1ea22e80ea02e9438f596a09
This commit is contained in:
Estevão Lucas 2019-04-17 10:56:49 -07:00 коммит произвёл Facebook Github Bot
Родитель 62ff7d6863
Коммит e76a7df5b5
6 изменённых файлов: 193 добавлений и 1 удалений

Просмотреть файл

@ -23,6 +23,7 @@ import com.facebook.react.modules.core.ExceptionsManagerModule;
import com.facebook.react.modules.core.Timing; import com.facebook.react.modules.core.Timing;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.HeadlessJsTaskSupportModule; import com.facebook.react.modules.core.HeadlessJsTaskSupportModule;
import com.facebook.react.modules.debug.DevSettingsModule;
import com.facebook.react.modules.debug.SourceCodeModule; import com.facebook.react.modules.debug.SourceCodeModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule; import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule; import com.facebook.react.modules.systeminfo.AndroidInfoModule;
@ -49,6 +50,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
AndroidInfoModule.class, AndroidInfoModule.class,
DeviceEventManagerModule.class, DeviceEventManagerModule.class,
DeviceInfoModule.class, DeviceInfoModule.class,
DevSettingsModule.class,
ExceptionsManagerModule.class, ExceptionsManagerModule.class,
HeadlessJsTaskSupportModule.class, HeadlessJsTaskSupportModule.class,
SourceCodeModule.class, SourceCodeModule.class,
@ -93,6 +95,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
AndroidInfoModule.class, AndroidInfoModule.class,
DeviceEventManagerModule.class, DeviceEventManagerModule.class,
DeviceInfoModule.class, DeviceInfoModule.class,
DevSettingsModule.class,
ExceptionsManagerModule.class, ExceptionsManagerModule.class,
HeadlessJsTaskSupportModule.class, HeadlessJsTaskSupportModule.class,
SourceCodeModule.class, SourceCodeModule.class,
@ -138,6 +141,8 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
return new AndroidInfoModule(reactContext); return new AndroidInfoModule(reactContext);
case DeviceEventManagerModule.NAME: case DeviceEventManagerModule.NAME:
return new DeviceEventManagerModule(reactContext, mHardwareBackBtnHandler); return new DeviceEventManagerModule(reactContext, mHardwareBackBtnHandler);
case DevSettingsModule.NAME:
return new DevSettingsModule(mReactInstanceManager.getDevSupportManager());
case ExceptionsManagerModule.NAME: case ExceptionsManagerModule.NAME:
return new ExceptionsManagerModule(mReactInstanceManager.getDevSupportManager()); return new ExceptionsManagerModule(mReactInstanceManager.getDevSupportManager());
case HeadlessJsTaskSupportModule.NAME: case HeadlessJsTaskSupportModule.NAME:

Просмотреть файл

@ -1040,6 +1040,90 @@ public class DevSupportManagerImpl implements
mDevServerHelper.closeInspectorConnection(); mDevServerHelper.closeInspectorConnection();
} }
@Override
public void setHotModuleReplacementEnabled(final boolean isHotModuleReplacementEnabled) {
if (!mIsDevSupportEnabled) {
return;
}
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
mDevSettings.setHotModuleReplacementEnabled(isHotModuleReplacementEnabled);
handleReloadJS();
}
}
);
}
@Override
public void setRemoteJSDebugEnabled(final boolean isRemoteJSDebugEnabled) {
if (!mIsDevSupportEnabled) {
return;
}
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
mDevSettings.setRemoteJSDebugEnabled(isRemoteJSDebugEnabled);
handleReloadJS();
}
}
);
}
@Override
public void setReloadOnJSChangeEnabled(final boolean isReloadOnJSChangeEnabled) {
if (!mIsDevSupportEnabled) {
return;
}
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
mDevSettings.setReloadOnJSChangeEnabled(isReloadOnJSChangeEnabled);
handleReloadJS();
}
}
);
}
@Override
public void setFpsDebugEnabled(final boolean isFpsDebugEnabled) {
if (!mIsDevSupportEnabled) {
return;
}
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
mDevSettings.setFpsDebugEnabled(isFpsDebugEnabled);
}
}
);
}
@Override
public void toggleElementInspector() {
if (!mIsDevSupportEnabled) {
return;
}
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
mDevSettings.setElementInspectorEnabled(!mDevSettings.isElementInspectorEnabled());
mReactInstanceManagerHelper.toggleElementInspector();
}
}
);
}
private void reload() { private void reload() {
UiThreadUtil.assertOnUiThread(); UiThreadUtil.assertOnUiThread();

Просмотреть файл

@ -78,6 +78,31 @@ public class DisabledDevSupportManager implements DevSupportManager {
} }
@Override
public void setHotModuleReplacementEnabled(boolean isHotModuleReplacementEnabled) {
}
@Override
public void setRemoteJSDebugEnabled(boolean isRemoteJSDebugEnabled) {
}
@Override
public void setReloadOnJSChangeEnabled(boolean isReloadOnJSChangeEnabled) {
}
@Override
public void setFpsDebugEnabled(boolean isFpsDebugEnabled) {
}
@Override
public void toggleElementInspector() {
}
@Override @Override
public boolean getDevSupportEnabled() { public boolean getDevSupportEnabled() {
return false; return false;
@ -162,7 +187,7 @@ public class DisabledDevSupportManager implements DevSupportManager {
@Override @Override
public void registerErrorCustomizer(ErrorCustomizer errorCustomizer) { public void registerErrorCustomizer(ErrorCustomizer errorCustomizer) {
} }
@Override @Override

Просмотреть файл

@ -45,6 +45,11 @@ public interface DevSupportManager extends NativeModuleCallExceptionHandler {
void handleReloadJS(); void handleReloadJS();
void reloadJSFromServer(final String bundleURL); void reloadJSFromServer(final String bundleURL);
void isPackagerRunning(PackagerStatusCallback callback); void isPackagerRunning(PackagerStatusCallback callback);
void setHotModuleReplacementEnabled(final boolean isHotModuleReplacementEnabled);
void setRemoteJSDebugEnabled(final boolean isRemoteJSDebugEnabled);
void setReloadOnJSChangeEnabled(final boolean isReloadOnJSChangeEnabled);
void setFpsDebugEnabled(final boolean isFpsDebugEnabled);
void toggleElementInspector();
@Nullable File downloadBundleResourceFromUrlSync( @Nullable File downloadBundleResourceFromUrlSync(
final String resourceURL, final String resourceURL,
final File outputFile); final File outputFile);

Просмотреть файл

@ -12,6 +12,7 @@ rn_android_library(
react_native_dep("third-party/java/jsr-305:jsr-305"), 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/bridge:bridge"),
react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/devsupport:interfaces"),
react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/module/annotations:annotations"),
react_native_target("java/com/facebook/react/modules/core:core"), react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/modules/debug:interfaces"), react_native_target("java/com/facebook/react/modules/debug:interfaces"),

Просмотреть файл

@ -0,0 +1,72 @@
/**
* 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.modules.debug;
import com.facebook.react.bridge.BaseJavaModule;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.bridge.UiThreadUtil;
/**
* Module that exposes the URL to the source code map (used for exception stack trace parsing) to JS
*/
@ReactModule(name = DevSettingsModule.NAME)
public class DevSettingsModule extends BaseJavaModule {
public static final String NAME = "DevSettings";
private final DevSupportManager mDevSupportManager;
public DevSettingsModule(DevSupportManager devSupportManager) {
mDevSupportManager = devSupportManager;
}
@Override
public String getName() {
return NAME;
}
@ReactMethod
public void reload() {
if (mDevSupportManager.getDevSupportEnabled()) {
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
mDevSupportManager.handleReloadJS();
}
});
}
}
@ReactMethod
public void setHotLoadingEnabled(boolean isHotLoadingEnabled) {
mDevSupportManager.setHotModuleReplacementEnabled(isHotLoadingEnabled);
}
@ReactMethod
public void setIsDebuggingRemotely(boolean isDebugginRemotelyEnabled) {
mDevSupportManager.setRemoteJSDebugEnabled(isDebugginRemotelyEnabled);
}
@ReactMethod
public void setLiveReloadEnabled(boolean isLiveReloadEnabled) {
mDevSupportManager.setReloadOnJSChangeEnabled(isLiveReloadEnabled);
}
@ReactMethod
public void setProfilingEnabled(boolean isProfilingEnabled) {
mDevSupportManager.setFpsDebugEnabled(isProfilingEnabled);
}
@ReactMethod
public void toggleElementInspector() {
mDevSupportManager.toggleElementInspector();
}
}