From b40810080cd3723d038d287722545bde004f494b Mon Sep 17 00:00:00 2001 From: Hilal Alsibai Date: Sat, 6 Oct 2018 11:31:39 -0700 Subject: [PATCH] Add support for multiple shared preference files Summary: Adds the ability to view multiple shared preference files in Flipper Reviewed By: danielbuechele Differential Revision: D10181908 fbshipit-source-id: 723b71d7bd87c51c0fabc77204b5a26a2b7aa782 --- .../SharedPreferencesFlipperPlugin.java | 95 +++++++-- src/plugins/shared_preferences/index.js | 193 ++++++++++++------ 2 files changed, 214 insertions(+), 74 deletions(-) diff --git a/android/src/main/java/com/facebook/flipper/plugins/sharedpreferences/SharedPreferencesFlipperPlugin.java b/android/src/main/java/com/facebook/flipper/plugins/sharedpreferences/SharedPreferencesFlipperPlugin.java index 4236e4dea..649c29c1f 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/sharedpreferences/SharedPreferencesFlipperPlugin.java +++ b/android/src/main/java/com/facebook/flipper/plugins/sharedpreferences/SharedPreferencesFlipperPlugin.java @@ -17,12 +17,15 @@ import com.facebook.flipper.core.FlipperObject; import com.facebook.flipper.core.FlipperPlugin; import com.facebook.flipper.core.FlipperReceiver; import com.facebook.flipper.core.FlipperResponder; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; public class SharedPreferencesFlipperPlugin implements FlipperPlugin { private FlipperConnection mConnection; - private final SharedPreferences mSharedPreferences; + private final Map mSharedPreferences; private final SharedPreferences.OnSharedPreferenceChangeListener onSharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @@ -31,13 +34,18 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { if (mConnection == null) { return; } + SharedPreferencesDescriptor descriptor = mSharedPreferences.get(sharedPreferences); + if (descriptor == null) { + return; + } mConnection.send( "sharedPreferencesChange", new FlipperObject.Builder() + .put("preferences", descriptor.name) .put("name", key) - .put("deleted", !mSharedPreferences.contains(key)) + .put("deleted", !sharedPreferences.contains(key)) .put("time", System.currentTimeMillis()) - .put("value", mSharedPreferences.getAll().get(key)) + .put("value", sharedPreferences.getAll().get(key)) .build()); } }; @@ -71,8 +79,26 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { * @param mode The Context mode to utilize. */ public SharedPreferencesFlipperPlugin(Context context, String name, int mode) { - mSharedPreferences = context.getSharedPreferences(name, mode); - mSharedPreferences.registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener); + this(context, Arrays.asList(new SharedPreferencesDescriptor(name, mode))); + } + + /** + * Creates a {@link android.content.SharedPreferences} plugin for Flipper + * + * @param context The context to retrieve the preferences from. + * @param descriptors A list of {@link SharedPreferencesDescriptor}s + * that describe the list of preferences to retrieve. + */ + public SharedPreferencesFlipperPlugin(Context context, List descriptors) { + if (context == null) { + throw new IllegalArgumentException("Given null context"); + } + mSharedPreferences = new HashMap<>(descriptors.size()); + for (SharedPreferencesDescriptor descriptor : descriptors) { + SharedPreferences preferences = context.getSharedPreferences(descriptor.name, descriptor.mode); + preferences.registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener); + mSharedPreferences.put(preferences, descriptor); + } } @Override @@ -80,15 +106,26 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { return "Preferences"; } - private FlipperObject getSharedPreferencesObject() { - final FlipperObject.Builder builder = new FlipperObject.Builder(); - final Map map = mSharedPreferences.getAll(); + private SharedPreferences getSharedPreferencesFor(String name) { + for (Map.Entry entry : mSharedPreferences.entrySet()) { + if (entry.getValue().name.equals(name)) { + return entry.getKey(); + } + } + throw new IllegalStateException("Unknown shared preferences " +name); + } + private FlipperObject getFlipperObjectFor(String name) { + return getFlipperObjectFor(getSharedPreferencesFor(name)); + } + + private FlipperObject getFlipperObjectFor(SharedPreferences sharedPreferences) { + FlipperObject.Builder builder = new FlipperObject.Builder(); + Map map = sharedPreferences.getAll(); for (Map.Entry entry : map.entrySet()) { final Object val = entry.getValue(); builder.put(entry.getKey(), val); } - return builder.build(); } @@ -96,12 +133,28 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { public void onConnect(FlipperConnection connection) { mConnection = connection; + connection.receive( + "getAllSharedPreferences", + new FlipperReceiver() { + @Override + public void onReceive(FlipperObject params, FlipperResponder responder) { + FlipperObject.Builder builder = new FlipperObject.Builder(); + for (Map.Entry entry : mSharedPreferences.entrySet()) { + builder.put(entry.getValue().name, getFlipperObjectFor(entry.getKey())); + } + responder.success(builder.build()); + } + }); + connection.receive( "getSharedPreferences", new FlipperReceiver() { @Override public void onReceive(FlipperObject params, FlipperResponder responder) { - responder.success(getSharedPreferencesObject()); + String name = params.getString("name"); + if (name != null) { + responder.success(getFlipperObjectFor(name)); + } } }); @@ -111,10 +164,11 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { @Override public void onReceive(FlipperObject params, FlipperResponder responder) throws IllegalArgumentException { - + String sharedPreferencesName = params.getString("sharedPreferencesName"); String preferenceName = params.getString("preferenceName"); - Object originalValue = mSharedPreferences.getAll().get(preferenceName); - SharedPreferences.Editor editor = mSharedPreferences.edit(); + SharedPreferences sharedPrefs = getSharedPreferencesFor(sharedPreferencesName); + Object originalValue = sharedPrefs.getAll().get(preferenceName); + SharedPreferences.Editor editor = sharedPrefs.edit(); if (originalValue instanceof Boolean) { editor.putBoolean(preferenceName, params.getBoolean("preferenceValue")); @@ -132,7 +186,7 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { editor.apply(); - responder.success(getSharedPreferencesObject()); + responder.success(getFlipperObjectFor(sharedPreferencesName)); } }); } @@ -141,4 +195,17 @@ public class SharedPreferencesFlipperPlugin implements FlipperPlugin { public void onDisconnect() { mConnection = null; } + + public static class SharedPreferencesDescriptor { + public final String name; + public final int mode; + + public SharedPreferencesDescriptor(String name, int mode) { + if (name == null || name.length() == 0) { + throw new IllegalArgumentException("Given null or empty name"); + } + this.name = name; + this.mode = mode; + } + } } diff --git a/src/plugins/shared_preferences/index.js b/src/plugins/shared_preferences/index.js index e5307075f..1796af5ca 100644 --- a/src/plugins/shared_preferences/index.js +++ b/src/plugins/shared_preferences/index.js @@ -12,27 +12,38 @@ import { FlexColumn, colors, FlexRow, - DataInspector, + ManagedDataInspector, styled, + Select, } from 'flipper'; import {FlipperPlugin} from 'flipper'; const {clone} = require('lodash'); type SharedPreferencesChangeEvent = {| + preferences: string, name: string, time: number, deleted: boolean, value: string, |}; -export type SharedPreferences = { +export type SharedPreferences = {| [name: string]: any, +|}; + +type SharedPreferencesEntry = { + preferences: SharedPreferences, + changesList: Array, +}; + +type SharedPreferencesMap = { + [name: string]: SharedPreferencesEntry, }; type SharedPreferencesState = {| - sharedPreferences: ?SharedPreferences, - changesList: Array, + selectedPreferences: ?string, + sharedPreferences: SharedPreferencesMap, |}; const CHANGELOG_COLUMNS = { @@ -58,12 +69,17 @@ const DELETED_LABEL = Deleted; const InspectorColumn = styled(FlexColumn)({ flexGrow: 0.2, - padding: '16px', }); const ChangelogColumn = styled(FlexColumn)({ flexGrow: 0.8, - padding: '16px', + paddingLeft: '16px', +}); + +const RootColumn = styled(FlexColumn)({ + paddingLeft: '16px', + paddingRight: '16px', + paddingTop: '16px', }); export default class extends FlipperPlugin { @@ -71,37 +87,59 @@ export default class extends FlipperPlugin { static id = 'Preferences'; state = { - changesList: [], - sharedPreferences: null, + selectedPreferences: null, + sharedPreferences: {}, }; reducers = { UpdateSharedPreferences(state: SharedPreferencesState, results: Object) { + let update = results.update; + let entry = state.sharedPreferences[update.name] || {changesList: []}; + entry.preferences = update.preferences; + state.sharedPreferences[update.name] = entry; return { - changesList: state.changesList, - sharedPreferences: results.results, + selectedPreferences: state.selectedPreferences || update.name, + sharedPreferences: state.sharedPreferences, }; }, ChangeSharedPreferences(state: SharedPreferencesState, event: Object) { - const sharedPreferences = {...(state.sharedPreferences || {})}; - if (event.change.deleted) { - delete sharedPreferences[event.change.name]; - } else { - sharedPreferences[event.change.name] = event.change.value; + const change = event.change; + const entry = state.sharedPreferences[change.preferences]; + if (entry == null) { + return; } + if (change.deleted) { + delete entry.preferences[change.name]; + } else { + entry.preferences[change.name] = change.value; + } + entry.changesList = [change, ...entry.changesList]; return { - changesList: [event.change, ...state.changesList], - sharedPreferences, + selectedPreferences: state.selectedPreferences, + sharedPreferences: state.sharedPreferences, + }; + }, + + UpdateSelectedSharedPreferences( + state: SharedPreferencesState, + event: Object, + ) { + return { + selectedPreferences: event.selected, + sharedPreferences: state.sharedPreferences, }; }, }; init() { this.client - .call('getSharedPreferences') - .then((results: SharedPreferences) => { - this.dispatchAction({results, type: 'UpdateSharedPreferences'}); + .call('getAllSharedPreferences') + .then((results: {[name: string]: SharedPreferences}) => { + Object.entries(results).forEach(([name, prefs]) => { + const update = {name: name, preferences: prefs}; + this.dispatchAction({update, type: 'UpdateSharedPreferences'}); + }); }); this.client.subscribe( @@ -110,17 +148,19 @@ export default class extends FlipperPlugin { this.dispatchAction({change, type: 'ChangeSharedPreferences'}); }, ); - this.client.subscribe( - 'newSharedPreferences', - (results: SharedPreferences) => { - this.dispatchAction({results, type: 'UpdateSharedPreferences'}); - }, - ); } onSharedPreferencesChanged = (path: Array, value: any) => { - const values = this.state.sharedPreferences; + const selectedPreferences = this.state.selectedPreferences; + if (selectedPreferences == null) { + return; + } + const entry = this.state.sharedPreferences[selectedPreferences]; + if (entry == null) { + return; + } + const values = entry.preferences; let newValue = value; if (path.length === 2 && values) { newValue = clone(values[path[0]]); @@ -128,54 +168,87 @@ export default class extends FlipperPlugin { } this.client .call('setSharedPreference', { + sharedPreferencesName: this.state.selectedPreferences, preferenceName: path[0], preferenceValue: newValue, }) .then((results: SharedPreferences) => { - this.dispatchAction({results, type: 'UpdateSharedPreferences'}); + let update = { + name: this.state.selectedPreferences, + preferences: results, + }; + this.dispatchAction({update, type: 'UpdateSharedPreferences'}); }); }; + onSharedPreferencesSelected = (selected: string) => { + this.dispatchAction({ + selected: selected, + type: 'UpdateSelectedSharedPreferences', + }); + }; + render() { - if (this.state.sharedPreferences == null) { + const selectedPreferences = this.state.selectedPreferences; + if (selectedPreferences == null) { + return null; + } + + const entry = this.state.sharedPreferences[selectedPreferences]; + if (entry == null) { return null; } return ( - - - Inspector - + + Preference File +