From 0fac9817df403e31d8256befe52409c948614706 Mon Sep 17 00:00:00 2001 From: Robert Balicki Date: Tue, 25 Oct 2022 21:01:25 -0700 Subject: [PATCH] Support persisted settings in Android + iOS (#34964) Summary: * Add a DevToolsSettingsManager, which has android and iOS variants, which uses a new TM (Android) or takes advantage of the Settings TM (iOS) to get/set console patch settings * This is backed by either the existing Settings module (iOS) or a new Java TM, which uses the SharedPreferences AP ## Testing Manual testing ## Changelog [General] [Added] - Add DevToolsSettingsManager Pull Request resolved: https://github.com/facebook/react-native/pull/34964 Test Plan: * Extensive manual testing Reviewed By: NickGerleman Differential Revision: D40333083 Pulled By: rbalicki2 fbshipit-source-id: f3816e3bd7dea3086f6f2269c3a099af14aebb3b --- Libraries/Core/setUpReactDevTools.js | 2 + .../DevToolsSettingsManager.android.js | 13 +++++ .../DevToolsSettingsManager.ios.js | 33 +++++++++++++ .../NativeDevToolsSettingsManager.js | 22 +++++++++ React/CoreModules/BUCK | 1 + .../src/main/java/com/facebook/react/BUCK | 1 + .../react/modules/devtoolssettings/BUCK | 28 +++++++++++ .../DevToolsSettingsManagerModule.java | 49 +++++++++++++++++++ .../main/java/com/facebook/react/shell/BUCK | 1 + .../react/shell/MainReactPackage.java | 7 ++- .../test/java/com/facebook/react/modules/BUCK | 1 + 11 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 Libraries/DevToolsSettings/DevToolsSettingsManager.android.js create mode 100644 Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js create mode 100644 Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js create mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/DevToolsSettingsManagerModule.java diff --git a/Libraries/Core/setUpReactDevTools.js b/Libraries/Core/setUpReactDevTools.js index be647e33b4d2ca..ecdd14a44a65e4 100644 --- a/Libraries/Core/setUpReactDevTools.js +++ b/Libraries/Core/setUpReactDevTools.js @@ -62,6 +62,7 @@ if (__DEV__) { }); const ReactNativeStyleAttributes = require('../Components/View/ReactNativeStyleAttributes'); + const devToolsSettingsManager = require('../DevToolsSettings/DevToolsSettingsManager'); reactDevTools.connectToDevTools({ isAppActive, @@ -70,6 +71,7 @@ if (__DEV__) { ReactNativeStyleAttributes, ), websocket: ws, + devToolsSettingsManager, }); } }; diff --git a/Libraries/DevToolsSettings/DevToolsSettingsManager.android.js b/Libraries/DevToolsSettings/DevToolsSettingsManager.android.js new file mode 100644 index 00000000000000..262aafbcb0d69b --- /dev/null +++ b/Libraries/DevToolsSettings/DevToolsSettingsManager.android.js @@ -0,0 +1,13 @@ +/** + * 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. + * + * @flow strict + * @format + */ + +import NativeDevToolsSettingsManager from './NativeDevToolsSettingsManager'; + +module.exports = NativeDevToolsSettingsManager; diff --git a/Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js b/Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js new file mode 100644 index 00000000000000..fdc61730166bf4 --- /dev/null +++ b/Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js @@ -0,0 +1,33 @@ +/** + * 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. + * + * @flow strict-local + * @format + */ + +import type {Spec} from './NativeDevToolsSettingsManager'; + +import Settings from '../Settings/Settings'; + +const CONSOLE_PATCH_SETTINGS_KEY = 'ReactDevTools::ConsolePatchSettings'; + +const DevToolsSettingsManager = { + setConsolePatchSettings: (newConsolePatchSettings: string) => { + Settings.set({ + [CONSOLE_PATCH_SETTINGS_KEY]: newConsolePatchSettings, + }); + }, + getConsolePatchSettings: () => { + const value = Settings.get(CONSOLE_PATCH_SETTINGS_KEY); + if (typeof value === 'string') { + // $FlowFixMe[unclear-type] + return ((value: any): string); + } + return null; + }, +}; + +module.exports = (DevToolsSettingsManager: Spec); diff --git a/Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js b/Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js new file mode 100644 index 00000000000000..904e8d6701c756 --- /dev/null +++ b/Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js @@ -0,0 +1,22 @@ +/** + * 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. + * + * @flow strict + * @format + */ + +import type {TurboModule} from '../TurboModule/RCTExport'; + +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +setConsolePatchSettings: (newConsolePatchSettings: string) => void; + +getConsolePatchSettings: () => ?string; +} + +export default (TurboModuleRegistry.get( + 'DevToolsSettingsManager', +): ?Spec); diff --git a/React/CoreModules/BUCK b/React/CoreModules/BUCK index 5608bacdaea311..eda0220f3bd7df 100644 --- a/React/CoreModules/BUCK +++ b/React/CoreModules/BUCK @@ -137,6 +137,7 @@ rn_apple_library( "//xplat/js/react-native-github:FBReactNativeSpecApple", "//xplat/js/react-native-github:RCTLinkingApple", "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:RCTSettingsApple", "//xplat/js/react-native-github:ReactInternalApple", ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index dd21088699dab5..08f8c1176bc528 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -41,6 +41,7 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/appearance:appearance"), react_native_target("java/com/facebook/react/modules/bundleloader:bundleloader"), react_native_target("java/com/facebook/react/modules/debug:debug"), + react_native_target("java/com/facebook/react/modules/devtoolssettings:devtoolssettings"), react_native_target("java/com/facebook/react/modules/fabric:fabric"), react_native_target("java/com/facebook/react/modules/debug:interfaces"), react_native_target("java/com/facebook/react/modules/deviceinfo:deviceinfo"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/BUCK new file mode 100644 index 00000000000000..50f0d888a9cdf4 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/BUCK @@ -0,0 +1,28 @@ +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") + +rn_android_library( + name = "devtoolssettings", + srcs = glob(["**/*.java"]), + autoglob = False, + labels = [ + "pfh:ReactNative_CommonInfrastructurePlaceholder", + "supermodule:xplat/default/public.react_native.infra", + ], + language = "JAVA", + provided_deps = [ + react_native_dep("third-party/android/androidx:annotation"), + ], + visibility = [ + "PUBLIC", + ], + deps = [ + react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), + react_native_dep("third-party/java/infer-annotations:infer-annotations"), + 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/module/annotations:annotations"), + react_native_target("java/com/facebook/react/modules/core:core"), + ], + exported_deps = [react_native_root_target(":FBReactNativeSpec")], +) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/DevToolsSettingsManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/DevToolsSettingsManagerModule.java new file mode 100644 index 00000000000000..0164de2788292f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/devtoolssettings/DevToolsSettingsManagerModule.java @@ -0,0 +1,49 @@ +/* + * 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.modules.devtoolssettings; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import androidx.annotation.Nullable; +import com.facebook.fbreact.specs.NativeDevToolsSettingsManagerSpec; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.module.annotations.ReactModule; + +@ReactModule(name = DevToolsSettingsManagerModule.NAME) +public class DevToolsSettingsManagerModule extends NativeDevToolsSettingsManagerSpec { + public static final String NAME = "DevToolsSettingsManager"; + + private static final String SHARED_PREFERENCES_PREFIX = "ReactNative__DevToolsSettings"; + private static final String KEY_CONSOLE_PATCH_SETTINGS = "ConsolePatchSettings"; + + private final SharedPreferences mSharedPreferences; + + public DevToolsSettingsManagerModule(ReactApplicationContext reactContext) { + super(reactContext); + mSharedPreferences = + reactContext.getSharedPreferences(SHARED_PREFERENCES_PREFIX, Context.MODE_PRIVATE); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public @Nullable String getConsolePatchSettings() { + return mSharedPreferences.getString(KEY_CONSOLE_PATCH_SETTINGS, null); + } + + @Override + public void setConsolePatchSettings(String newSettings) { + Editor editor = mSharedPreferences.edit(); + editor.putString(KEY_CONSOLE_PATCH_SETTINGS, newSettings); + editor.apply(); + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK index c79b69687e0654..f1ee669920aa9f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK @@ -37,6 +37,7 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/clipboard:clipboard"), react_native_target("java/com/facebook/react/modules/core:core"), react_native_target("java/com/facebook/react/modules/debug:debug"), + react_native_target("java/com/facebook/react/modules/devtoolssettings:devtoolssettings"), react_native_target("java/com/facebook/react/modules/dialog:dialog"), react_native_target("java/com/facebook/react/modules/fresco:fresco"), react_native_target("java/com/facebook/react/modules/i18nmanager:i18nmanager"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index 6fc4a536e2b1f7..e9c0297a529a65 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -23,6 +23,7 @@ import com.facebook.react.modules.blob.FileReaderModule; import com.facebook.react.modules.camera.ImageStoreManager; import com.facebook.react.modules.clipboard.ClipboardModule; +import com.facebook.react.modules.devtoolssettings.DevToolsSettingsManagerModule; import com.facebook.react.modules.dialog.DialogModule; import com.facebook.react.modules.fresco.FrescoModule; import com.facebook.react.modules.i18nmanager.I18nManagerModule; @@ -145,6 +146,8 @@ public MainReactPackage(MainPackageConfig config) { return new VibrationModule(context); case WebSocketModule.NAME: return new WebSocketModule(context); + case DevToolsSettingsManagerModule.NAME: + return new DevToolsSettingsManagerModule(context); default: return null; } @@ -185,7 +188,8 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { Class.forName("com.facebook.react.shell.MainReactPackage$$ReactModuleInfoProvider"); return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance(); } catch (ClassNotFoundException e) { - // In OSS case, the annotation processor does not run. We fall back on creating this byhand + // In the OSS case, the annotation processor does not run. We fall back to creating this by + // hand Class[] moduleList = new Class[] { AccessibilityInfoModule.class, @@ -204,6 +208,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { NativeAnimatedModule.class, NetworkingModule.class, PermissionsModule.class, + DevToolsSettingsManagerModule.class, ShareModule.class, StatusBarModule.class, SoundManagerModule.class, diff --git a/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK b/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK index 7ab27c360a9714..d8581c32d5dd90 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK @@ -34,6 +34,7 @@ rn_robolectric_test( react_native_target("java/com/facebook/react/modules/core:core"), react_native_target("java/com/facebook/react/modules/debug:debug"), react_native_target("java/com/facebook/react/modules/deviceinfo:deviceinfo"), + react_native_target("java/com/facebook/react/modules/devtoolssettings:devtoolssettings"), react_native_target("java/com/facebook/react/modules/dialog:dialog"), react_native_target("java/com/facebook/react/modules/network:network"), react_native_target("java/com/facebook/react/modules/share:share"),