From a43987309d00036c050c79e9f7d5d15a79f4c1b8 Mon Sep 17 00:00:00 2001 From: Jared Forsyth Date: Tue, 14 Jul 2015 12:03:17 -0700 Subject: [PATCH 01/16] [react native] prepare the react native inspector for the new react devtools Summary: These are the changes needed for full interop with the (as yet unreleased) new version of React Devtools. - the on-device inspector is minimized when devtools is open - devtools highlight -> device and device touch -> devtools select works - editing react native styles :) --- Libraries/Inspector/Inspector.js | 72 +++++++++++++++++++++++ Libraries/Inspector/InspectorOverlay.js | 6 +- Libraries/Inspector/InspectorPanel.js | 3 +- Libraries/ReactNative/ReactNativeMount.js | 6 ++ React/Modules/RCTUIManager.m | 4 +- 5 files changed, 88 insertions(+), 3 deletions(-) diff --git a/Libraries/Inspector/Inspector.js b/Libraries/Inspector/Inspector.js index 6b1ac5789df..6015bcf3ff2 100644 --- a/Libraries/Inspector/Inspector.js +++ b/Libraries/Inspector/Inspector.js @@ -20,10 +20,21 @@ var StyleSheet = require('StyleSheet'); var UIManager = require('NativeModules').UIManager; var View = require('View'); +var REACT_DEVTOOLS_HOOK: ?Object = typeof window !== 'undefined' ? window.__REACT_DEVTOOLS_BACKEND__ : null; + +if (REACT_DEVTOOLS_HOOK) { + // required for devtools to be able to edit react native styles + REACT_DEVTOOLS_HOOK.resolveRNStyle = require('flattenStyle'); +} + class Inspector extends React.Component { + _subs: ?Array<() => void>; + constructor(props: Object) { super(props); + this.state = { + devtoolsBackend: null, panelPos: 'bottom', inspecting: true, perfing: false, @@ -31,6 +42,63 @@ class Inspector extends React.Component { }; } + componentDidMount() { + if (REACT_DEVTOOLS_HOOK) { + this.attachToDevtools = this.attachToDevtools.bind(this); + REACT_DEVTOOLS_HOOK.addStartupListener(this.attachToDevtools); + // if devtools is already started + // TODO(jared): should addStartupListener just go ahead and call the + // listener if the devtools is already started? might be unexpected... + // is there some name other than `addStartupListener` that would be + // better? + if (REACT_DEVTOOLS_HOOK.backend) { + this.attachToDevtools(REACT_DEVTOOLS_HOOK.backend); + } + } + } + + componentWillUnmount() { + if (this._subs) { + this._subs.map(fn => fn()); + } + if (REACT_DEVTOOLS_HOOK) { + REACT_DEVTOOLS_HOOK.removeStartupListener(this.attachToDevtools); + } + } + + attachToDevtools(backend: Object) { + var _hideWait = null; + var hlSub = backend.sub('highlight', ({node, name, props}) => { + clearTimeout(_hideWait); + UIManager.measure(node, (x, y, width, height, left, top) => { + this.setState({ + hierarchy: [], + inspected: { + frame: {left, top, width, height}, + style: props ? props.style : {}, + }, + }); + }); + }); + var hideSub = backend.sub('hideHighlight', () => { + // we wait to actually hide in order to avoid flicker + _hideWait = setTimeout(() => { + this.setState({ + inspected: null, + }); + }, 100); + }); + this._subs = [hlSub, hideSub]; + + backend.on('shutdown', () => { + this.setState({devtoolsBackend: null}); + this._subs = null; + }); + this.setState({ + devtoolsBackend: backend, + }); + } + setSelection(i: number) { var instance = this.state.hierarchy[i]; var publicInstance = instance.getPublicInstance(); @@ -46,6 +114,9 @@ class Inspector extends React.Component { } onTouchInstance(instance: Object, frame: Object, pointerY: number) { + if (this.state.devtoolsBackend) { + this.state.devtoolsBackend.selectFromReactInstance(instance, true); + } var hierarchy = InspectorUtils.getOwnerHierarchy(instance); var publicInstance = instance.getPublicInstance(); var props = publicInstance.props || {}; @@ -88,6 +159,7 @@ class Inspector extends React.Component { />} - {contents} + {!this.props.devtoolsIsOpen && contents}