From b7933aef2ea9489772d1e6964d5c7b230a507702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=BCchele?= Date: Thu, 5 Sep 2019 03:13:23 -0700 Subject: [PATCH] publish react plugin Summary: Publishing React Dev tools plugin: - migrate to TS - move iOS and JS part to public folder (Android was already) Reviewed By: passy Differential Revision: D17164782 fbshipit-source-id: 20ccba71d807df2d33fe5348a62c6ee7f78ae8ba --- .../FlipperKitReactPlugin.h | 17 +++ .../FlipperKitReactPlugin.m | 40 +++++++ src/plugins/reactdevtools/ADB.tsx | 37 +++++++ src/plugins/reactdevtools/get-port.d.tsx | 14 +++ src/plugins/reactdevtools/index.tsx | 93 ++++++++++++++++ src/plugins/reactdevtools/package.json | 17 +++ .../reactdevtools/react-devtools-core.d.tsx | 15 +++ src/plugins/reactdevtools/yarn.lock | 103 ++++++++++++++++++ 8 files changed, 336 insertions(+) create mode 100644 iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.h create mode 100644 iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.m create mode 100644 src/plugins/reactdevtools/ADB.tsx create mode 100644 src/plugins/reactdevtools/get-port.d.tsx create mode 100644 src/plugins/reactdevtools/index.tsx create mode 100644 src/plugins/reactdevtools/package.json create mode 100644 src/plugins/reactdevtools/react-devtools-core.d.tsx create mode 100644 src/plugins/reactdevtools/yarn.lock diff --git a/iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.h b/iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.h new file mode 100644 index 000000000..78cc26284 --- /dev/null +++ b/iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.h @@ -0,0 +1,17 @@ +/* + * 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. + */ +#if FB_SONARKIT_ENABLED + +#import + +#import + +@interface FlipperKitReactPlugin : NSObject + +@end + +#endif diff --git a/iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.m b/iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.m new file mode 100644 index 000000000..a43c168e8 --- /dev/null +++ b/iOS/Plugins/FlipperKitReactPlugin/FlipperKitReactPlugin/FlipperKitReactPlugin.m @@ -0,0 +1,40 @@ +/* + * 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. + */ +#if FB_SONARKIT_ENABLED + +#import "FlipperKitReactPlugin.h" + +#import +#import +#import + +#import "Plugins.h" + +@implementation FlipperKitReactPlugin + +- (NSString*)identifier { + return @"React"; +} + +- (void)didConnect:(id)connection { + [connection receive:@"config" + withBlock:^(NSDictionary* params, id responder){ + // set received port and host to dev tools + }]; +} + +- (void)didDisconnect { +} + +@end + +void FlipperKitReactPluginInit(FlipperClient *client) +{ + [client addPlugin:[FlipperKitReactPlugin new]]; +} + +#endif diff --git a/src/plugins/reactdevtools/ADB.tsx b/src/plugins/reactdevtools/ADB.tsx new file mode 100644 index 000000000..b2bbbab74 --- /dev/null +++ b/src/plugins/reactdevtools/ADB.tsx @@ -0,0 +1,37 @@ +/** + * 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 + */ + +import proc from 'child_process'; + +function execADB( + command: string, + device: string | null, + ...args: Array +): Promise { + const deviceSpecifier = device != null && device !== '' ? `-s ${device}` : ''; + return new Promise((resolve, reject) => { + const adb = `adb ${deviceSpecifier} ${command} ${args.join(' ')}`; + proc.exec(adb, (error, stdout, _stderr) => { + if (error) { + reject(error); + } else { + resolve(stdout); + } + }); + }); +} + +export async function reverse( + local: number, + remote: number, + device?: string, +): Promise { + return await execADB( + `reverse tcp:${local} tcp:${remote}`, + device != null ? device : null, + ); +} diff --git a/src/plugins/reactdevtools/get-port.d.tsx b/src/plugins/reactdevtools/get-port.d.tsx new file mode 100644 index 000000000..6d6922243 --- /dev/null +++ b/src/plugins/reactdevtools/get-port.d.tsx @@ -0,0 +1,14 @@ +/** + * 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 + */ + +declare module 'get-port' { + const getPort: (options?: { + readonly port?: number; + readonly host?: string; + }) => Promise; + export default getPort; +} diff --git a/src/plugins/reactdevtools/index.tsx b/src/plugins/reactdevtools/index.tsx new file mode 100644 index 000000000..e6284e9a6 --- /dev/null +++ b/src/plugins/reactdevtools/index.tsx @@ -0,0 +1,93 @@ +/** + * 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 + */ + +import ReactDOM from 'react-dom'; +import ReactDevToolsStandalone from 'react-devtools-core/standalone'; +import {FlipperPlugin, AndroidDevice, styled} from 'flipper'; +import React from 'react'; +import getPort from 'get-port'; +import address from 'address'; +import {reverse} from './ADB'; + +const Container = styled('div')({ + display: 'flex', + flex: '1 1 0%', + justifyContent: 'center', + alignItems: 'stretch', +}); + +const DEV_TOOLS_NODE_ID = 'reactdevtools-out-of-react-node'; + +function createDevToolsNode(): HTMLElement { + const div = document.createElement('div'); + div.id = DEV_TOOLS_NODE_ID; + div.style.display = 'none'; + div.style.width = '100%'; + div.style.height = '100%'; + div.style.flex = '1 1 0%'; + div.style.justifyContent = 'center'; + div.style.alignItems = 'stretch'; + + document.body && document.body.appendChild(div); + + return div; +} + +function findDevToolsNode(): HTMLElement | null { + return document.querySelector('#' + DEV_TOOLS_NODE_ID); +} + +function attachDevTools(target: Element | Text, devToolsNode: HTMLElement) { + target.insertBefore(devToolsNode, target.childNodes[0]); + devToolsNode.style.display = 'flex'; +} + +function detachDevTools(devToolsNode: HTMLElement) { + devToolsNode.style.display = 'none'; + document.body && document.body.appendChild(devToolsNode); +} + +export default class extends FlipperPlugin<{}, any, {}> { + componentDidMount() { + let devToolsNode = findDevToolsNode(); + if (!devToolsNode) { + devToolsNode = createDevToolsNode(); + this.initializeDevTools(devToolsNode); + } + + const currentComponentNode = ReactDOM.findDOMNode(this); + currentComponentNode && attachDevTools(currentComponentNode, devToolsNode); + } + + componentWillUnmount() { + const devToolsNode = findDevToolsNode(); + devToolsNode && detachDevTools(devToolsNode); + } + + async initializeDevTools(devToolsNode: HTMLElement) { + const port = await getPort({port: 8097}); // default port for dev tools + ReactDevToolsStandalone.setContentDOMNode(devToolsNode).startServer(port); + const device = await this.getDevice(); + if (device) { + const host = + device.deviceType === 'physical' + ? address.ip() + : device instanceof AndroidDevice + ? '10.0.2.2' // Host IP for Android emulator host system + : 'localhost'; + this.client.call('config', {port, host}); + + if (['quest', 'go', 'pacific'].includes(device.title.toLowerCase())) { + reverse(port, port); + } + } + } + + render() { + return ; + } +} diff --git a/src/plugins/reactdevtools/package.json b/src/plugins/reactdevtools/package.json new file mode 100644 index 000000000..ab420ef64 --- /dev/null +++ b/src/plugins/reactdevtools/package.json @@ -0,0 +1,17 @@ +{ + "name": "React", + "version": "1.0.1", + "main": "index.tsx", + "license": "MIT", + "dependencies": { + "address": "^1.1.2", + "get-port": "^4.0.0", + "react-devtools-core": "^4.0.6" + }, + "title": "React Devtools", + "icon": "app-react", + "bugs": { + "email": "danielbuechele@fb.com" + }, + "devDependencies": {} +} diff --git a/src/plugins/reactdevtools/react-devtools-core.d.tsx b/src/plugins/reactdevtools/react-devtools-core.d.tsx new file mode 100644 index 000000000..4b6cb0134 --- /dev/null +++ b/src/plugins/reactdevtools/react-devtools-core.d.tsx @@ -0,0 +1,15 @@ +/** + * 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 + */ + +declare module 'react-devtools-core/standalone' { + interface DevTools { + setContentDOMNode(node: HTMLElement): DevTools; + startServer(port: number): DevTools; + } + const DevTools: DevTools; + export default DevTools; +} diff --git a/src/plugins/reactdevtools/yarn.lock b/src/plugins/reactdevtools/yarn.lock new file mode 100644 index 000000000..9a3fbbcb7 --- /dev/null +++ b/src/plugins/reactdevtools/yarn.lock @@ -0,0 +1,103 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +address@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +async-limiter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +d@1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14: + version "0.10.50" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.50.tgz#6d0e23a0abdb27018e5ac4fd09b412bc5517a778" + integrity sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + next-tick "^1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + dependencies: + d "1" + es5-ext "~0.10.14" + +get-port@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.0.0.tgz#373c85960138ee20027c070e3cb08019fea29816" + integrity sha512-Yy3yNI2oShgbaWg4cmPhWjkZfktEvpKI09aDX4PZzNtlU9obuYrX7x2mumQsrNxlF+Ls7OtMQW/u+X4s896bOQ== + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +next-tick@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +react-devtools-core@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.0.6.tgz#681c7349db618856d6df7d31a6a49edee9d9e428" + integrity sha512-IhAndVGmV74Bio1BRrlbsonH6bX3XFHgz2uixJFlNjg/Rm264mBveIMwM6+rV3yObSKVnggXRMtJuyWoPk2Smw== + dependencies: + es6-symbol "^3" + shell-quote "^1.6.1" + ws "^7" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +type@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/type/-/type-1.0.3.tgz#16f5d39f27a2d28d86e48f8981859e9d3296c179" + integrity sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg== + +ws@^7: + version "7.1.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.1.1.tgz#f9942dc868b6dffb72c14fd8f2ba05f77a4d5983" + integrity sha512-o41D/WmDeca0BqYhsr3nJzQyg9NF5X8l/UdnFNux9cS3lwB+swm8qGWX5rn+aD6xfBU3rGmtHij7g7x6LxFU3A== + dependencies: + async-limiter "^1.0.0"