Make it possible to write JS only plugins
Summary: This diff is part of the bigger task T60496135 This diff is based on D18706643, extracting only the react native module parts It implements the entire Android client api for JavaScript, so that there is feature parity. However this implementation is happy path only, and edge cases will be handled in separate diffs Reviewed By: jknoxville Differential Revision: D19310265 fbshipit-source-id: 589716fe059952bdde98df84ed250c5c6feaa118
This commit is contained in:
committed by
Facebook Github Bot
parent
3fab1f8fd6
commit
c7158f4517
1
react-native/react-native-flipper/.gitattributes
vendored
Normal file
1
react-native/react-native-flipper/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.pbxproj -text
|
||||
42
react-native/react-native-flipper/.gitignore
vendored
Normal file
42
react-native/react-native-flipper/.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
# node.js
|
||||
#
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Xcode
|
||||
#
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
project.xcworkspace
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
build/
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
|
||||
# BUCK
|
||||
buck-out/
|
||||
\.buckd/
|
||||
*.keystore
|
||||
0
react-native/react-native-flipper/.npmignore
Normal file
0
react-native/react-native-flipper/.npmignore
Normal file
17
react-native/react-native-flipper/README.md
Normal file
17
react-native/react-native-flipper/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# react-native-flipper
|
||||
|
||||
## Getting started
|
||||
|
||||
`$ npm install react-native-flipper --save`
|
||||
|
||||
### Mostly automatic installation
|
||||
|
||||
`$ react-native link react-native-flipper`
|
||||
|
||||
## Usage
|
||||
```javascript
|
||||
import Flipper from 'react-native-flipper';
|
||||
|
||||
// TODO: What to do with the module?
|
||||
Flipper;
|
||||
```
|
||||
14
react-native/react-native-flipper/android/README.md
Normal file
14
react-native/react-native-flipper/android/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
README
|
||||
======
|
||||
|
||||
If you want to publish the lib as a maven dependency, follow these steps before publishing a new version to npm:
|
||||
|
||||
1. Be sure to have the Android [SDK](https://developer.android.com/studio/index.html) and [NDK](https://developer.android.com/ndk/guides/index.html) installed
|
||||
2. Be sure to have a `local.properties` file in this folder that points to the Android SDK and NDK
|
||||
```
|
||||
ndk.dir=/Users/{username}/Library/Android/sdk/ndk-bundle
|
||||
sdk.dir=/Users/{username}/Library/Android/sdk
|
||||
```
|
||||
3. Delete the `maven` folder
|
||||
4. Run `./gradlew installArchives`
|
||||
5. Verify that latest set of generated files is in the maven folder with the correct version number
|
||||
163
react-native/react-native-flipper/android/build.gradle
Normal file
163
react-native/react-native-flipper/android/build.gradle
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// android/build.gradle
|
||||
|
||||
// based on:
|
||||
//
|
||||
// * https://github.com/facebook/react-native/blob/0.60-stable/template/android/build.gradle
|
||||
// original location:
|
||||
// - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/build.gradle
|
||||
//
|
||||
// * https://github.com/facebook/react-native/blob/0.60-stable/template/android/app/build.gradle
|
||||
// original location:
|
||||
// - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/app/build.gradle
|
||||
|
||||
def DEFAULT_COMPILE_SDK_VERSION = 28
|
||||
def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3'
|
||||
def DEFAULT_MIN_SDK_VERSION = 16
|
||||
def DEFAULT_TARGET_SDK_VERSION = 28
|
||||
|
||||
def safeExtGet(prop, fallback) {
|
||||
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven'
|
||||
|
||||
buildscript {
|
||||
// The Android Gradle plugin is only required when opening the android folder stand-alone.
|
||||
// This avoids unnecessary downloads and potential conflicts when the library is included as a
|
||||
// module dependency in an application project.
|
||||
// ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies
|
||||
if (project == rootProject) {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven'
|
||||
|
||||
android {
|
||||
compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
|
||||
buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
|
||||
defaultConfig {
|
||||
minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)
|
||||
targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
// ref: https://www.baeldung.com/maven-local-repository
|
||||
mavenLocal()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url "$rootDir/../node_modules/react-native/android"
|
||||
}
|
||||
maven {
|
||||
// Android JSC is installed from npm
|
||||
url "$rootDir/../node_modules/jsc-android/dist"
|
||||
}
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation 'com.facebook.react:react-native:+' // From node_modules
|
||||
|
||||
implementation 'com.facebook.soloader:soloader:0.6.0+'
|
||||
|
||||
implementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.facebook.yoga'
|
||||
exclude group:'com.facebook.flipper', module: 'fbjni'
|
||||
exclude group:'com.facebook.litho', module: 'litho-annotations'
|
||||
exclude group:'com.squareup.okhttp3'
|
||||
}
|
||||
}
|
||||
|
||||
def configureReactNativePom(def pom) {
|
||||
def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text)
|
||||
|
||||
pom.project {
|
||||
name packageJson.title
|
||||
artifactId packageJson.name
|
||||
version = packageJson.version
|
||||
group = "com.facebook.flipper.reactnative"
|
||||
description packageJson.description
|
||||
url packageJson.repository.baseUrl
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name packageJson.license
|
||||
url packageJson.repository.baseUrl + '/blob/master/' + packageJson.licenseFilename
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id packageJson.author.username
|
||||
name packageJson.author.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate { project ->
|
||||
// some Gradle build hooks ref:
|
||||
// https://www.oreilly.com/library/view/gradle-beyond-the/9781449373801/ch03.html
|
||||
task androidJavadoc(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += files(android.bootClasspath)
|
||||
classpath += files(project.getConfigurations().getByName('compile').asList())
|
||||
include '**/*.java'
|
||||
}
|
||||
|
||||
task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
|
||||
classifier = 'javadoc'
|
||||
from androidJavadoc.destinationDir
|
||||
}
|
||||
|
||||
task androidSourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
include '**/*.java'
|
||||
}
|
||||
|
||||
android.libraryVariants.all { variant ->
|
||||
def name = variant.name.capitalize()
|
||||
task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) {
|
||||
from variant.javaCompile.destinationDir
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives androidSourcesJar
|
||||
archives androidJavadocJar
|
||||
}
|
||||
|
||||
task installArchives(type: Upload) {
|
||||
configuration = configurations.archives
|
||||
repositories.mavenDeployer {
|
||||
// Deploy to react-native-event-bridge/maven, ready to publish to npm
|
||||
repository url: "file://${projectDir}/../android/maven"
|
||||
configureReactNativePom pom
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.flipper.reactnative">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.flipper.reactnative;
|
||||
|
||||
import com.facebook.flipper.android.AndroidFlipperClient;
|
||||
import com.facebook.flipper.core.FlipperArray;
|
||||
import com.facebook.flipper.core.FlipperClient;
|
||||
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;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
@ReactModule(name = FlipperModule.NAME)
|
||||
public class FlipperModule extends ReactContextBaseJavaModule {
|
||||
|
||||
public static final String NAME = "Flipper";
|
||||
|
||||
private final ReactApplicationContext reactContext;
|
||||
private final FlipperClient flipperClient;
|
||||
private final Map<String, FlipperConnection> connections;
|
||||
private final Map<String, FlipperResponder> responders;
|
||||
private final AtomicLong responderId = new AtomicLong();
|
||||
|
||||
public FlipperModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.reactContext = reactContext;
|
||||
this.flipperClient = AndroidFlipperClient.getInstanceIfInitialized();
|
||||
this.connections = new ConcurrentHashMap<>();
|
||||
this.responders = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void registerPlugin(
|
||||
final String pluginId,
|
||||
final Boolean inBackground,
|
||||
final Callback onConnect,
|
||||
final Callback onDisconnect) {
|
||||
FlipperPlugin plugin =
|
||||
new FlipperPlugin() {
|
||||
@Override
|
||||
public String getId() {
|
||||
return pluginId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnect(FlipperConnection connection) throws Exception {
|
||||
FlipperModule.this.connections.put(pluginId, connection);
|
||||
onConnect.invoke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect() throws Exception {
|
||||
FlipperModule.this.connections.remove(pluginId);
|
||||
onDisconnect.invoke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runInBackground() {
|
||||
return inBackground;
|
||||
}
|
||||
};
|
||||
this.flipperClient.addPlugin(plugin);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void send(String pluginId, String method, String data) {
|
||||
// Optimization: throwing raw strings around to the desktop would probably avoid some double
|
||||
// parsing...
|
||||
Object parsedData = FlipperModule.parseJSON(data);
|
||||
FlipperConnection connection = this.connections.get(pluginId);
|
||||
if (parsedData instanceof FlipperArray) {
|
||||
connection.send(method, (FlipperArray) parsedData);
|
||||
} else {
|
||||
connection.send(method, (FlipperObject) parsedData);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void reportErrorWithMetadata(String pluginId, String reason, String stackTrace) {
|
||||
this.connections.get(pluginId).reportErrorWithMetadata(reason, stackTrace);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void reportError(String pluginId, String error) {
|
||||
this.connections.get(pluginId).reportError(new Error(error));
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void subscribe(String pluginId, String method, final Callback callback) {
|
||||
this.connections
|
||||
.get(pluginId)
|
||||
.receive(
|
||||
method,
|
||||
new FlipperReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(FlipperObject params, FlipperResponder responder)
|
||||
throws Exception {
|
||||
String id = String.valueOf(FlipperModule.this.responderId.incrementAndGet());
|
||||
FlipperModule.this.responders.put(id, responder);
|
||||
callback.invoke(params.toJsonString(), id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void respondSuccess(String responderId, String data) {
|
||||
FlipperResponder responder = FlipperModule.this.responders.remove(responderId);
|
||||
if (data == null) {
|
||||
responder.success();
|
||||
} else {
|
||||
Object parsedData = FlipperModule.parseJSON(data);
|
||||
if (parsedData instanceof FlipperArray) {
|
||||
responder.success((FlipperArray) parsedData);
|
||||
} else {
|
||||
responder.success((FlipperObject) parsedData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void respondError(String responderId, String data) {
|
||||
FlipperResponder responder = FlipperModule.this.responders.remove(responderId);
|
||||
Object parsedData = FlipperModule.parseJSON(data);
|
||||
if (parsedData instanceof FlipperArray) {
|
||||
responder.success((FlipperArray) parsedData);
|
||||
} else {
|
||||
responder.success((FlipperObject) parsedData);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object /* FlipperArray | FlipperObject */ parseJSON(String json) {
|
||||
// returns either a FlipperObject or Flipper array, pending the data
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(json);
|
||||
if (tokener.nextClean() == '[') {
|
||||
tokener.back();
|
||||
return new FlipperArray(new JSONArray(tokener));
|
||||
} else {
|
||||
tokener.back();
|
||||
return new FlipperObject(new JSONObject(tokener));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.flipper.reactnative;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FlipperPackage implements ReactPackage {
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||
return Arrays.<NativeModule>asList(new FlipperModule(reactContext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
83
react-native/react-native-flipper/index.d.ts
vendored
Normal file
83
react-native/react-native-flipper/index.d.ts
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
declare namespace Flipper {
|
||||
/**
|
||||
* A FlipperPlugin is an object which exposes an API to the Desktop Flipper application. When a
|
||||
* connection is established the plugin is given a FlipperConnection on which it can register
|
||||
* request handlers and send messages. When the FlipperConnection is invalid onDisconnect is called.
|
||||
* onConnect may be called again on the same plugin object if Flipper re-connects, this will provide
|
||||
* a new FlipperConnection, do not attempt to re-use the previous connection.
|
||||
*/
|
||||
interface FlipperPlugin {
|
||||
/**
|
||||
* @return The id of this plugin. This is the namespace which Flipper desktop plugins will call
|
||||
* methods on to route them to your plugin. This should match the id specified in your React
|
||||
* plugin.
|
||||
*/
|
||||
getId(): string;
|
||||
|
||||
/**
|
||||
* Called when a connection has been established. The connection passed to this method is valid
|
||||
* until {@link FlipperPlugin#onDisconnect()} is called.
|
||||
*/
|
||||
onConnect(connection: FlipperConnection): void;
|
||||
|
||||
/**
|
||||
* Called when the connection passed to `FlipperPlugin#onConnect(FlipperConnection)` is no
|
||||
* longer valid. Do not try to use the connection in or after this method has been called.
|
||||
*/
|
||||
onDisconnect(): void;
|
||||
|
||||
/**
|
||||
* Returns true if the plugin is meant to be run in background too, otherwise it returns false.
|
||||
*/
|
||||
runInBackground(): boolean;
|
||||
}
|
||||
|
||||
export interface FlipperResponder {
|
||||
success(response?: any): void;
|
||||
error(response: any): void;
|
||||
}
|
||||
|
||||
export interface FlipperConnection {
|
||||
send(method: string, data: any): void;
|
||||
reportErrorWithMetadata(reason: string, stackTrace: string): void;
|
||||
reportError(error: Error): void;
|
||||
receive(
|
||||
method: string,
|
||||
listener: (params: any, responder: FlipperResponder) => void,
|
||||
): void;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'Flipper' {
|
||||
export function registerPlugin(
|
||||
pluginId: string,
|
||||
runInBackground: boolean,
|
||||
onConnect: () => void,
|
||||
onDisconnect: () => void,
|
||||
): void;
|
||||
export function send(pluginId: string, method: string, data: string): void;
|
||||
export function reportErrorWithMetadata(
|
||||
pluginId: string,
|
||||
reason: string,
|
||||
stackTrace: string,
|
||||
): void;
|
||||
export function reportError(pluginId: string, error: string): void;
|
||||
export function subscribe(
|
||||
pluginId: string,
|
||||
method: string,
|
||||
listener: (data: string, responderId: number) => void,
|
||||
): void;
|
||||
export function respondSuccess(responderId: string, data?: string): void;
|
||||
export function respondError(responderId: string, error: string): void;
|
||||
}
|
||||
|
||||
export function addPlugin(plugin: Flipper.FlipperPlugin): void;
|
||||
100
react-native/react-native-flipper/index.js
vendored
Normal file
100
react-native/react-native-flipper/index.js
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
// $FlowFixMe
|
||||
import {NativeModules} from 'react-native';
|
||||
|
||||
const {Flipper} = NativeModules;
|
||||
|
||||
export default Flipper;
|
||||
|
||||
class Connection {
|
||||
connected;
|
||||
pluginId;
|
||||
|
||||
constructor(pluginId) {
|
||||
this.connected = false;
|
||||
this.pluginId = pluginId;
|
||||
}
|
||||
|
||||
send(method, data) {
|
||||
if (!this.connected) {
|
||||
throw new Error('Cannot send data, not connected');
|
||||
}
|
||||
Flipper.send(this.pluginId, method, JSON.stringify(data));
|
||||
}
|
||||
|
||||
reportErrorWithMetadata(reason, stackTrace) {
|
||||
Flipper.reportErrorWithMetadata(this.pluginId, reason, stackTrace);
|
||||
}
|
||||
|
||||
reportError(error) {
|
||||
Flipper.reportError(this.pluginId, error);
|
||||
}
|
||||
|
||||
receive(method, listener) {
|
||||
if (!this.connected) {
|
||||
throw new Error('Cannot receive data, not connected');
|
||||
}
|
||||
Flipper.subscribe(this.pluginId, method, (data, responderId) => {
|
||||
const responder = new Responder(responderId);
|
||||
listener(JSON.parse(data), responder);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Responder {
|
||||
responderId;
|
||||
|
||||
constructor(responderId) {
|
||||
this.responderId = responderId;
|
||||
}
|
||||
|
||||
success(response) {
|
||||
Flipper.respondSuccess(
|
||||
this.responderId,
|
||||
response == null ? null : JSON.stringify(response),
|
||||
);
|
||||
}
|
||||
|
||||
error(response) {
|
||||
Flipper.respondError(this.responderId, JSON.stringify(response));
|
||||
}
|
||||
}
|
||||
|
||||
// $FlowFixMe
|
||||
export function addPlugin(plugin) {
|
||||
if (!plugin || typeof plugin !== 'object') {
|
||||
throw new Error('Expected plugin, got ' + plugin);
|
||||
}
|
||||
['getId', 'onConnect', 'onDisconnect'].forEach(method => {
|
||||
if (typeof plugin[method] !== 'function') {
|
||||
throw new Error(`Plugin misses an implementation for '${method}'`);
|
||||
}
|
||||
});
|
||||
const runInBackground =
|
||||
typeof plugin.runInBackground === 'function'
|
||||
? !!plugin.runInBackground()
|
||||
: false;
|
||||
const id = plugin.getId();
|
||||
const connection = new Connection(id);
|
||||
|
||||
Flipper.registerPlugin(
|
||||
id,
|
||||
runInBackground,
|
||||
function onConnect() {
|
||||
connection.connected = true;
|
||||
plugin.onConnect(connection);
|
||||
},
|
||||
function onDisconnect() {
|
||||
connection.connected = false;
|
||||
plugin.onDisconnect();
|
||||
},
|
||||
);
|
||||
}
|
||||
12
react-native/react-native-flipper/ios/Flipper.h
Normal file
12
react-native/react-native-flipper/ios/Flipper.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface Flipper : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
21
react-native/react-native-flipper/ios/Flipper.m
Normal file
21
react-native/react-native-flipper/ios/Flipper.m
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "Flipper.h"
|
||||
|
||||
|
||||
@implementation Flipper
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
RCT_EXPORT_METHOD(sampleMethod:(NSString *)stringArgument numberParameter:(nonnull NSNumber *)numberArgument callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
// TODO: Implement some actually useful functionality
|
||||
callback(@[[NSString stringWithFormat: @"numberArgument: %@ stringArgument: %@", numberArgument, stringArgument]]);
|
||||
}
|
||||
|
||||
@end
|
||||
34
react-native/react-native-flipper/package.json
Normal file
34
react-native/react-native-flipper/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "react-native-flipper",
|
||||
"title": "React Native Flipper",
|
||||
"version": "1.0.0",
|
||||
"description": "TODO",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/github_account/react-native-flipper.git",
|
||||
"baseUrl": "https://github.com/github_account/react-native-flipper"
|
||||
},
|
||||
"keywords": [
|
||||
"react-native"
|
||||
],
|
||||
"author": {
|
||||
"name": "Your Name",
|
||||
"email": "yourname@email.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"licenseFilename": "LICENSE",
|
||||
"readmeFilename": "README.md",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.1",
|
||||
"react-native": ">=0.59.0-rc.0 <1.0.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react": "^16.8.3",
|
||||
"react-native": "^0.59.10"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "react-native-flipper"
|
||||
s.version = package["version"]
|
||||
s.summary = package["description"]
|
||||
s.description = <<-DESC
|
||||
react-native-flipper
|
||||
DESC
|
||||
s.homepage = "https://github.com/github_account/react-native-flipper"
|
||||
s.license = "MIT"
|
||||
# s.license = { :type => "MIT", :file => "FILE_LICENSE" }
|
||||
s.authors = { "Your Name" => "yourname@email.com" }
|
||||
s.platforms = { :ios => "9.0" }
|
||||
s.source = { :git => "https://github.com/github_account/react-native-flipper.git", :tag => "#{s.version}" }
|
||||
|
||||
s.source_files = "ios/**/*.{h,m,swift}"
|
||||
s.requires_arc = true
|
||||
|
||||
s.dependency "React"
|
||||
# ...
|
||||
# s.dependency "..."
|
||||
end
|
||||
|
||||
4515
react-native/react-native-flipper/yarn.lock
Normal file
4515
react-native/react-native-flipper/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
56
src/plugins/rn-example-plugin/index.tsx
Normal file
56
src/plugins/rn-example-plugin/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {View, FlipperPlugin, Button} from 'flipper';
|
||||
import React from 'react';
|
||||
|
||||
type State = {};
|
||||
|
||||
type PersistedState = {
|
||||
count: number;
|
||||
last: any;
|
||||
};
|
||||
|
||||
export default class RnExamplePlugin extends FlipperPlugin<
|
||||
State,
|
||||
any,
|
||||
PersistedState
|
||||
> {
|
||||
static defaultPersistedState = {count: 0, last: null};
|
||||
|
||||
static persistedStateReducer(
|
||||
persistedState: PersistedState,
|
||||
method: string,
|
||||
payload: any,
|
||||
) {
|
||||
return {
|
||||
count: persistedState.count + 1,
|
||||
last: payload,
|
||||
};
|
||||
}
|
||||
|
||||
state = {};
|
||||
|
||||
render() {
|
||||
const {persistedState} = this.props;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const result = await this.client.call('FromDesktop', {test: 123});
|
||||
window.alert(result.test);
|
||||
}}>
|
||||
Send message
|
||||
</Button>
|
||||
<pre>{JSON.stringify(persistedState, null, 2)}</pre>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
13
src/plugins/rn-example-plugin/package.json
Normal file
13
src/plugins/rn-example-plugin/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "ReactNativeExamplePlugin",
|
||||
"version": "1.0.0",
|
||||
"main": "index.tsx",
|
||||
"license": "MIT",
|
||||
"keywords": ["flipper-plugin"],
|
||||
"icon": "apps",
|
||||
"title": "React Native Example Plugin",
|
||||
"category": "Example Plugin",
|
||||
"bugs": {
|
||||
"email": "mweststrate@fb.com"
|
||||
}
|
||||
}
|
||||
4
src/plugins/rn-example-plugin/yarn.lock
Normal file
4
src/plugins/rn-example-plugin/yarn.lock
Normal file
@@ -0,0 +1,4 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user