From ff6988ddaf64a68c3ccd24b76e273c9a89da7ea5 Mon Sep 17 00:00:00 2001 From: John Knox Date: Thu, 28 Mar 2019 06:42:07 -0700 Subject: [PATCH] Java side of NativePlugins Summary: Adds abstract classes NativePlugin and TableNativePlugin. Extend NativePlugin to implement a new NativePlugin type/template. TableNativePlugin is an example of that. Extend TableNativePlugin to add a particular instance of a table plugin. See the stacked diff for an example of that (newsfeed inspector). I think I'm going to change the NativePlugin implementation so it uses composition instead of inheriting from FlipperPlugin, so that the concrete subclasses don't get access to the FlipperPlugin primitive methods like onConnect etc. But I don't mind shipping this as is and changing it separately. Reviewed By: passy Differential Revision: D14505912 fbshipit-source-id: 0534147112aaf4c5a41d2d3e08de855767b2a010 --- .../flipper/nativeplugins/NativePlugin.java | 31 ++++ .../nativeplugins/components/Sidebar.java | 17 ++ .../components/SidebarSection.java | 8 + .../nativeplugins/table/TableMetadata.java | 26 +++ .../nativeplugins/table/TablePlugin.java | 157 ++++++++++++++++++ .../flipper/nativeplugins/table/TableRow.java | 86 ++++++++++ 6 files changed, 325 insertions(+) create mode 100644 android/src/main/java/com/facebook/flipper/nativeplugins/NativePlugin.java create mode 100644 android/src/main/java/com/facebook/flipper/nativeplugins/components/Sidebar.java create mode 100644 android/src/main/java/com/facebook/flipper/nativeplugins/components/SidebarSection.java create mode 100644 android/src/main/java/com/facebook/flipper/nativeplugins/table/TableMetadata.java create mode 100644 android/src/main/java/com/facebook/flipper/nativeplugins/table/TablePlugin.java create mode 100644 android/src/main/java/com/facebook/flipper/nativeplugins/table/TableRow.java diff --git a/android/src/main/java/com/facebook/flipper/nativeplugins/NativePlugin.java b/android/src/main/java/com/facebook/flipper/nativeplugins/NativePlugin.java new file mode 100644 index 000000000..6a2ec8a12 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/nativeplugins/NativePlugin.java @@ -0,0 +1,31 @@ +package com.facebook.flipper.nativeplugins; + +import com.facebook.flipper.core.FlipperPlugin; + +/** + * Subclass of {@link FlipperPlugin} for mobile-defined plugins that conform to a template. + * Implementations should call {@link #NativePlugin(String, String)} to specify which template will + * be used. See {@link com.facebook.flipper.nativeplugins.table.TablePlugin} for an example + * subclass. + */ +public abstract class NativePlugin implements FlipperPlugin { + private final String pluginType; + private final String id; + + /** + * Call super() inside subclass constructors to provide the template name and id of the concrete + * plugin instance. + * + * @param pluginType This needs to correspond to a plugin template defined in Flipper. + * @param id This will uniquely + */ + public NativePlugin(final String pluginType, final String id) { + this.pluginType = pluginType; + this.id = id; + } + + @Override + public final String getId() { + return "_nativeplugin_" + pluginType + "_" + id; + } +} diff --git a/android/src/main/java/com/facebook/flipper/nativeplugins/components/Sidebar.java b/android/src/main/java/com/facebook/flipper/nativeplugins/components/Sidebar.java new file mode 100644 index 000000000..0216788b7 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/nativeplugins/components/Sidebar.java @@ -0,0 +1,17 @@ +package com.facebook.flipper.nativeplugins.components; + +import com.facebook.flipper.core.FlipperArray; + +public class Sidebar { + + private final FlipperArray.Builder sections = new FlipperArray.Builder(); + + public Sidebar addSection(SidebarSection section) { + sections.put(section.serialize()); + return this; + } + + public FlipperArray serialize() { + return sections.build(); + } +} diff --git a/android/src/main/java/com/facebook/flipper/nativeplugins/components/SidebarSection.java b/android/src/main/java/com/facebook/flipper/nativeplugins/components/SidebarSection.java new file mode 100644 index 000000000..0d3c4d9b4 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/nativeplugins/components/SidebarSection.java @@ -0,0 +1,8 @@ +package com.facebook.flipper.nativeplugins.components; + +import com.facebook.flipper.core.FlipperObject; + +interface SidebarSection { + + FlipperObject serialize(); +} diff --git a/android/src/main/java/com/facebook/flipper/nativeplugins/table/TableMetadata.java b/android/src/main/java/com/facebook/flipper/nativeplugins/table/TableMetadata.java new file mode 100644 index 000000000..9a4288f95 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/nativeplugins/table/TableMetadata.java @@ -0,0 +1,26 @@ +package com.facebook.flipper.nativeplugins.table; + +public class TableMetadata { + + final TablePlugin.Column[] mColumns; + + private TableMetadata(TablePlugin.Column[] columns) { + if (columns == null) { + throw new IllegalArgumentException("columns must not be null"); + } + this.mColumns = columns; + } + + public static class Builder { + private TablePlugin.Column[] columns; + + public Builder columns(TablePlugin.Column... columns) { + this.columns = columns; + return this; + } + + public TableMetadata build() { + return new TableMetadata(columns); + } + } +} diff --git a/android/src/main/java/com/facebook/flipper/nativeplugins/table/TablePlugin.java b/android/src/main/java/com/facebook/flipper/nativeplugins/table/TablePlugin.java new file mode 100644 index 000000000..99ccf44e6 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/nativeplugins/table/TablePlugin.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * 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.flipper.nativeplugins.table; + +import com.facebook.flipper.core.FlipperArray; +import com.facebook.flipper.core.FlipperConnection; +import com.facebook.flipper.core.FlipperObject; +import com.facebook.flipper.core.FlipperReceiver; +import com.facebook.flipper.core.FlipperResponder; +import com.facebook.flipper.nativeplugins.NativePlugin; +import java.util.List; + +public abstract class TablePlugin extends NativePlugin { + + public static class Column { + public final String id; + final String displayName; + final String displayWidth; + final boolean showByDefault; + final boolean isFilterable; + + Column( + String id, + String displayName, + String displayWidth, + boolean showByDefault, + boolean isFilterable) { + if (id == null) { + throw new IllegalArgumentException("id must not be null"); + } + if (displayName == null) { + throw new IllegalArgumentException("displayName must not be null"); + } + this.id = id; + this.displayName = displayName; + this.displayWidth = displayWidth; + this.showByDefault = showByDefault; + this.isFilterable = isFilterable; + } + + public static class Builder { + private final String id; + private String displayName; + private String displayWidth; + private boolean showByDefault = true; + private boolean isFilterable = false; + + public Builder(String id) { + this.id = id; + } + + public Builder displayName(String displayName) { + this.displayName = displayName; + return this; + } + + public Builder displayWidthPx(int displayWidth) { + this.displayWidth = Integer.toString(displayWidth); + return this; + } + + public Builder displayWidthPercent(int displayWidth) { + this.displayWidth = Integer.toString(displayWidth) + "%"; + return this; + } + + public Builder showByDefault(boolean showByDefault) { + this.showByDefault = showByDefault; + return this; + } + + public Builder isFilterable(boolean isFilterable) { + this.isFilterable = isFilterable; + return this; + } + + public Column build() { + return new Column(id, displayName, displayWidth, showByDefault, isFilterable); + } + } + } + + private FlipperConnection mConnection; + + public TablePlugin(final String id) { + super("Table", id); + } + + @Override + public final void onConnect(FlipperConnection connection) { + this.mConnection = connection; + connection.receive( + "getMetadata", + new FlipperReceiver() { + @Override + public void onReceive(FlipperObject params, FlipperResponder responder) throws Exception { + final FlipperObject.Builder columns = new FlipperObject.Builder(); + final FlipperObject.Builder columnSizes = new FlipperObject.Builder(); + final FlipperArray.Builder columnOrder = new FlipperArray.Builder(); + final FlipperArray.Builder filterableColumns = new FlipperArray.Builder(); + for (Column c : getMetadata().mColumns) { + columns.put(c.id, new FlipperObject.Builder().put("value", c.displayName).build()); + columnSizes.put(c.id, c.displayWidth); + columnOrder.put( + new FlipperObject.Builder().put("key", c.id).put("visible", c.showByDefault)); + if (c.isFilterable) { + filterableColumns.put(c.id); + } + } + + responder.success( + new FlipperObject.Builder() + .put("columns", columns.build()) + .put("columnSizes", columnSizes.build()) + .put("columnOrder", columnOrder.build()) + .put("filterableColumns", filterableColumns.build()) + .build()); + } + }); + } + + protected abstract void onConnected(); + + protected abstract void onDisconnected(); + + protected final void updateRows(List rows) { + final FlipperArray.Builder array = new FlipperArray.Builder(); + for (TableRow r : rows) { + array.put(r.serialize()); + } + this.mConnection.send("updateRows", array.build()); + } + + public abstract TableMetadata getMetadata(); + + public List getRows() { + throw new UnsupportedOperationException( + "getRows not implemented in " + + getClass().getSimpleName() + + ". Perhaps this is a streaming plugin?"); + } + + @Override + public void onDisconnect() throws Exception { + this.onDisconnected(); + } + + @Override + public final boolean runInBackground() { + return false; + } +} diff --git a/android/src/main/java/com/facebook/flipper/nativeplugins/table/TableRow.java b/android/src/main/java/com/facebook/flipper/nativeplugins/table/TableRow.java new file mode 100644 index 000000000..bea22630e --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/nativeplugins/table/TableRow.java @@ -0,0 +1,86 @@ +package com.facebook.flipper.nativeplugins.table; + +import com.facebook.flipper.core.FlipperObject; +import com.facebook.flipper.nativeplugins.components.Sidebar; +import java.util.Map; + +public abstract class TableRow { + interface Value { + FlipperObject serialize(); + } + + public static class StringValue implements Value { + private String val; + + public StringValue(String s) { + this.val = s; + } + + @Override + public FlipperObject serialize() { + return new FlipperObject.Builder().put("type", "string").put("value", val).build(); + } + } + + public static class IntValue implements Value { + private int val; + + public IntValue(int i) { + this.val = i; + } + + @Override + public FlipperObject serialize() { + return new FlipperObject.Builder().put("type", "int").put("value", val).build(); + } + } + + public static class TimeValue implements Value { + private long millis; + + public TimeValue(long millis) { + this.millis = millis; + } + + @Override + public FlipperObject serialize() { + return new FlipperObject.Builder().put("type", "time").put("value", millis).build(); + } + } + + public static class DurationValue implements Value { + private long millis; + + public DurationValue(long millis) { + this.millis = millis; + } + + @Override + public FlipperObject serialize() { + return new FlipperObject.Builder().put("type", "duration").put("value", millis).build(); + } + } + + final String id; + final Map values; + final Sidebar sidebar; + + public TableRow(String id, Map values, Sidebar sidebar) { + this.id = id; + this.values = values; + this.sidebar = sidebar; + } + + FlipperObject serialize() { + FlipperObject.Builder columnsObject = new FlipperObject.Builder(); + for (Map.Entry e : values.entrySet()) { + columnsObject.put(e.getKey().id, e.getValue().serialize()); + } + columnsObject.put("id", id); + return new FlipperObject.Builder() + .put("columns", columnsObject.build()) + .put("sidebar", sidebar.serialize()) + .put("id", id) + .build(); + } +}