diff --git a/android/sample/src/main/java/com/facebook/flipper/sample/FlipperSampleApplication.java b/android/sample/src/main/java/com/facebook/flipper/sample/FlipperSampleApplication.java index 46d5068cc..ea943271c 100644 --- a/android/sample/src/main/java/com/facebook/flipper/sample/FlipperSampleApplication.java +++ b/android/sample/src/main/java/com/facebook/flipper/sample/FlipperSampleApplication.java @@ -1,11 +1,17 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/* + * Copyright (c) 2004-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.sample; import android.app.Application; import android.content.Context; import com.facebook.flipper.android.AndroidFlipperClient; import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.example.ExampleFlipperPlugin; import com.facebook.flipper.plugins.inspector.DescriptorMapping; import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; import com.facebook.flipper.plugins.leakcanary.LeakCanaryFlipperPlugin; @@ -56,6 +62,7 @@ public class FlipperSampleApplication extends Application { new SharedPreferencesDescriptor("sample", Context.MODE_PRIVATE), new SharedPreferencesDescriptor("other_sample", Context.MODE_PRIVATE)))); client.addPlugin(new LeakCanaryFlipperPlugin()); + client.addPlugin(new ExampleFlipperPlugin()); client.start(); getSharedPreferences("sample", Context.MODE_PRIVATE).edit().putString("Hello", "world").apply(); diff --git a/android/sample/src/main/java/com/facebook/flipper/sample/MainActivity.java b/android/sample/src/main/java/com/facebook/flipper/sample/MainActivity.java index c02a4023d..0ec190dfd 100644 --- a/android/sample/src/main/java/com/facebook/flipper/sample/MainActivity.java +++ b/android/sample/src/main/java/com/facebook/flipper/sample/MainActivity.java @@ -1,9 +1,18 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/* + * Copyright (c) 2004-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.sample; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.core.FlipperPlugin; +import com.facebook.flipper.plugins.example.ExampleFlipperPlugin; import com.facebook.litho.ComponentContext; import com.facebook.litho.LithoView; @@ -14,5 +23,13 @@ public class MainActivity extends AppCompatActivity { super.onCreate(savedInstanceState); final ComponentContext c = new ComponentContext(this); setContentView(LithoView.create(c, RootComponent.create(c).build())); + + FlipperClient client = AndroidFlipperClient.getInstanceIfInitialized(); + if (client != null) { + FlipperPlugin samplePlugin = client.getPlugin(ExampleFlipperPlugin.ID); + if (samplePlugin instanceof ExampleFlipperPlugin) { + ((ExampleFlipperPlugin) samplePlugin).setActivity(this); + } + } } } diff --git a/android/sample/src/main/java/com/facebook/flipper/sample/RootComponentSpec.java b/android/sample/src/main/java/com/facebook/flipper/sample/RootComponentSpec.java index 9462f4979..c2fe53680 100644 --- a/android/sample/src/main/java/com/facebook/flipper/sample/RootComponentSpec.java +++ b/android/sample/src/main/java/com/facebook/flipper/sample/RootComponentSpec.java @@ -1,10 +1,19 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - +/* + * Copyright (c) 2004-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.sample; import android.content.Intent; import android.util.Log; +import com.facebook.flipper.android.AndroidFlipperClient; import com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.core.FlipperPlugin; +import com.facebook.flipper.plugins.example.ExampleFlipperPlugin; import com.facebook.litho.ClickEvent; import com.facebook.litho.Column; import com.facebook.litho.Component; @@ -39,6 +48,12 @@ public class RootComponentSpec { .key("2") .textSizeSp(20) .clickHandler(RootComponent.hitPostRequest(c))) + .child( + Text.create(c) + .text("Trigger Notification") + .key("3") + .textSizeSp(20) + .clickHandler(RootComponent.triggerNotification(c))) .child( Text.create(c) .text("Diagnose connection issues") @@ -107,9 +122,21 @@ public class RootComponentSpec { }); } + @OnEvent(ClickEvent.class) + static void triggerNotification(final ComponentContext c) { + FlipperClient client = AndroidFlipperClient.getInstanceIfInitialized(); + if (client != null) { + FlipperPlugin plugin = client.getPlugin(ExampleFlipperPlugin.ID); + if (plugin instanceof ExampleFlipperPlugin) { + ((ExampleFlipperPlugin) plugin).triggerNotification(); + } + } + } + @OnEvent(ClickEvent.class) static void openDiagnostics(final ComponentContext c) { Intent intent = new Intent(c, FlipperDiagnosticActivity.class); c.startActivity(intent); } + } diff --git a/android/src/main/java/com/facebook/flipper/plugins/example/ExampleFlipperPlugin.java b/android/src/main/java/com/facebook/flipper/plugins/example/ExampleFlipperPlugin.java new file mode 100644 index 000000000..ef813176f --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/plugins/example/ExampleFlipperPlugin.java @@ -0,0 +1,81 @@ +/* + * 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.plugins.example; + +import android.app.Activity; +import android.widget.Toast; +import com.facebook.flipper.core.FlipperConnection; +import com.facebook.flipper.core.FlipperObject; +import com.facebook.flipper.core.FlipperPlugin; +import com.facebook.flipper.core.FlipperReceiver; +import com.facebook.flipper.core.FlipperResponder; + +public class ExampleFlipperPlugin implements FlipperPlugin { + + public static final String ID = "Example"; + + private Activity mActivity; + private FlipperConnection mConnection; + + private int mNotificationsSent = 0; + + @Override + public String getId() { + return ID; + } + + /* + * Activity to be used to display incoming messages + */ + public void setActivity(Activity activity) { + mActivity = activity; + } + + @Override + public void onConnect(FlipperConnection connection) throws Exception { + mConnection = connection; + connection.receive( + "displayMessage", + new FlipperReceiver() { + @Override + public void onReceive(final FlipperObject params, FlipperResponder responder) + throws Exception { + if (mActivity != null) { + mActivity.runOnUiThread( + new Runnable() { + @Override + public void run() { + Toast.makeText(mActivity, params.getString("message"), Toast.LENGTH_SHORT) + .show(); + } + }); + } + + responder.success(new FlipperObject.Builder().put("greeting", "Hello").build()); + } + }); + } + + public void triggerNotification() { + if (mConnection != null) { + mConnection.send( + "triggerNotification", new FlipperObject.Builder().put("id", mNotificationsSent).build()); + mNotificationsSent++; + } + } + + @Override + public void onDisconnect() throws Exception { + mConnection = null; + } + + @Override + public boolean runInBackground() { + return true; + } +} diff --git a/android/src/test/java/com/facebook/flipper/plugins/example/ExampleFlipperPluginTest.java b/android/src/test/java/com/facebook/flipper/plugins/example/ExampleFlipperPluginTest.java new file mode 100644 index 000000000..c8822335e --- /dev/null +++ b/android/src/test/java/com/facebook/flipper/plugins/example/ExampleFlipperPluginTest.java @@ -0,0 +1,38 @@ +/* + * 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.plugins.example; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; + +import com.facebook.flipper.core.FlipperObject; +import com.facebook.flipper.testing.FlipperConnectionMock; +import com.facebook.flipper.testing.FlipperResponderMock; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class ExampleFlipperPluginTest { + + @Test + public void greetingTest() throws Exception { + final ExampleFlipperPlugin plugin = new ExampleFlipperPlugin(); + final FlipperConnectionMock connection = new FlipperConnectionMock(); + final FlipperResponderMock responder = new FlipperResponderMock(); + + plugin.onConnect(connection); + connection + .receivers + .get("displayMessage") + .onReceive(new FlipperObject.Builder().put("message", "test").build(), responder); + + assertThat( + responder.successes, hasItem(new FlipperObject.Builder().put("greeting", "Hello").build())); + } +} diff --git a/src/plugins/example/index.js b/src/plugins/example/index.js new file mode 100644 index 000000000..5d233bdf5 --- /dev/null +++ b/src/plugins/example/index.js @@ -0,0 +1,97 @@ +/** + * Copyright 2018-present Facebook. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @format + * @flow + */ + +import {Button, Input, FlipperPlugin, FlexColumn, styled, Text} from 'flipper'; + +type DisplayMessageResponse = { + greeting: string, +}; + +type State = { + prompt: string, + message: string, +}; + +type PersistedState = { + currentNotificationId: number, +}; + +const Container = styled(FlexColumn)({ + alignItems: 'center', + justifyContent: 'space-around', + padding: 20, +}); + +export default class extends FlipperPlugin<*, State, PersistedState> { + static title = 'Example'; + static id = 'Example'; + static icon = 'apps'; + + state = { + prompt: 'Type a message below to see it displayed on the mobile app', + message: '', + }; + + /* + * Reducer to process incoming "send" messages from the mobile counterpart. + */ + static persistedStateReducer = ( + persistedState: PersistedState, + method: string, + payload: Object, + ): PersistedState => { + if (method === 'triggerNotification') { + return { + currentNotificationId: payload.id, + }; + } + return persistedState || {}; + }; + + /* + * Callback to provide the currently active notifications. + */ + static getActiveNotifications = (persistedState: PersistedState) => { + return [ + { + id: 'test-notification:' + persistedState.currentNotificationId, + message: 'Example Notification', + severity: 'warning', + title: 'Notification: ' + persistedState.currentNotificationId, + }, + ]; + }; + + /* + * Call a method of the mobile counterpart, to display a message. + */ + sendMessage() { + this.client + .call('displayMessage', {message: this.state.message || 'Weeeee!'}) + .then((params: DisplayMessageResponse) => { + this.setState({ + prompt: 'Nice', + }); + }); + } + + render() { + return ( + + {this.state.prompt}, + { + this.setState({message: event.target.value}); + }} + />, + , + + ); + } +} diff --git a/src/plugins/example/package.json b/src/plugins/example/package.json new file mode 100644 index 000000000..ee022b39a --- /dev/null +++ b/src/plugins/example/package.json @@ -0,0 +1,6 @@ +{ + "name": "flipper-plugin-sample", + "version": "1.0.0", + "main": "index.js", + "license": "MIT" +} diff --git a/src/plugins/example/yarn.lock b/src/plugins/example/yarn.lock new file mode 100644 index 000000000..fb57ccd13 --- /dev/null +++ b/src/plugins/example/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +