Export the DevSettings module, add addMenuItem method (#25848)

Summary:
I wanted to configure the RN dev menu without having to write native code. This is pretty useful in a greenfield app since it avoids having to write a custom native module for both platforms (and might enable the feature for expo too).

This ended up a bit more involved than planned since callbacks can only be called once. I needed to convert the `DevSettings` module to a `NativeEventEmitter` and use events when buttons are clicked. This means creating a JS wrapper for it. Currently it does not export all methods, they can be added in follow ups as needed.

## Changelog

[General] [Added] - Export the DevSettings module, add `addMenuItem` method
Pull Request resolved: https://github.com/facebook/react-native/pull/25848

Test Plan:
Tested in an app using the following code.

```js
if (__DEV__) {
 DevSettings.addMenuItem('Show Dev Screen', () => {
    dispatchNavigationAction(
      NavigationActions.navigate({
        routeName: 'dev',
      }),
    );
  });
}
```

Added an example in RN tester

![devmenu](https://user-images.githubusercontent.com/2677334/62000297-71624680-b0a1-11e9-8403-bc95c4747f0c.gif)

Differential Revision: D17394916

Pulled By: cpojer

fbshipit-source-id: f9d2c548b09821c594189d1436a27b97cf5a5737
This commit is contained in:
Janic Duplessis
2019-09-17 06:36:17 -07:00
committed by Facebook Github Bot
parent 15343863b0
commit cc068b0551
15 changed files with 190 additions and 22 deletions
@@ -139,7 +139,7 @@ import java.util.Map;
case DeviceEventManagerModule.NAME:
return new DeviceEventManagerModule(reactContext, mHardwareBackBtnHandler);
case DevSettingsModule.NAME:
return new DevSettingsModule(mReactInstanceManager.getDevSupportManager());
return new DevSettingsModule(reactContext, mReactInstanceManager.getDevSupportManager());
case ExceptionsManagerModule.NAME:
return new ExceptionsManagerModule(mReactInstanceManager.getDevSupportManager());
case HeadlessJsTaskSupportModule.NAME:
@@ -123,6 +123,11 @@ public class DevInternalSettings
return mPreferences.getBoolean(PREFS_START_SAMPLING_PROFILER_ON_INIT, false);
}
@Override
public void addMenuItem(String title) {
// Not supported.
}
public interface Listener {
void onInternalSettingsChanged();
}
@@ -6,23 +6,31 @@
*/
package com.facebook.react.modules.debug;
import com.facebook.react.bridge.BaseJavaModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.devsupport.interfaces.DevOptionHandler;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
/**
* 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 class DevSettingsModule extends ReactContextBaseJavaModule {
public static final String NAME = "DevSettings";
private final DevSupportManager mDevSupportManager;
public DevSettingsModule(DevSupportManager devSupportManager) {
public DevSettingsModule(
ReactApplicationContext reactContext, DevSupportManager devSupportManager) {
super(reactContext);
mDevSupportManager = devSupportManager;
}
@@ -63,4 +71,20 @@ public class DevSettingsModule extends BaseJavaModule {
public void toggleElementInspector() {
mDevSupportManager.toggleElementInspector();
}
@ReactMethod
public void addMenuItem(final String title) {
mDevSupportManager.addCustomDevOption(
title,
new DevOptionHandler() {
@Override
public void onOptionSelected() {
WritableMap data = Arguments.createMap();
data.putString("title", title);
getReactApplicationContext()
.getJSModule(RCTDeviceEventEmitter.class)
.emit("didPressMenuItem", data);
}
});
}
}
@@ -35,4 +35,7 @@ public interface DeveloperSettings {
/** @return Whether Start Sampling Profiler on App Start is enabled. */
boolean isStartSamplingProfilerOnInit();
/** Add an item to the dev menu. */
void addMenuItem(String title);
}