mirror of
https://github.com/status-im/react-native.git
synced 2025-03-03 10:50:35 +00:00
[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 :)
This commit is contained in:
parent
ebd046ae21
commit
a43987309d
@ -20,10 +20,21 @@ var StyleSheet = require('StyleSheet');
|
|||||||
var UIManager = require('NativeModules').UIManager;
|
var UIManager = require('NativeModules').UIManager;
|
||||||
var View = require('View');
|
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 {
|
class Inspector extends React.Component {
|
||||||
|
_subs: ?Array<() => void>;
|
||||||
|
|
||||||
constructor(props: Object) {
|
constructor(props: Object) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
devtoolsBackend: null,
|
||||||
panelPos: 'bottom',
|
panelPos: 'bottom',
|
||||||
inspecting: true,
|
inspecting: true,
|
||||||
perfing: false,
|
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) {
|
setSelection(i: number) {
|
||||||
var instance = this.state.hierarchy[i];
|
var instance = this.state.hierarchy[i];
|
||||||
var publicInstance = instance.getPublicInstance();
|
var publicInstance = instance.getPublicInstance();
|
||||||
@ -46,6 +114,9 @@ class Inspector extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTouchInstance(instance: Object, frame: Object, pointerY: number) {
|
onTouchInstance(instance: Object, frame: Object, pointerY: number) {
|
||||||
|
if (this.state.devtoolsBackend) {
|
||||||
|
this.state.devtoolsBackend.selectFromReactInstance(instance, true);
|
||||||
|
}
|
||||||
var hierarchy = InspectorUtils.getOwnerHierarchy(instance);
|
var hierarchy = InspectorUtils.getOwnerHierarchy(instance);
|
||||||
var publicInstance = instance.getPublicInstance();
|
var publicInstance = instance.getPublicInstance();
|
||||||
var props = publicInstance.props || {};
|
var props = publicInstance.props || {};
|
||||||
@ -88,6 +159,7 @@ class Inspector extends React.Component {
|
|||||||
/>}
|
/>}
|
||||||
<View style={[styles.panelContainer, panelContainerStyle]}>
|
<View style={[styles.panelContainer, panelContainerStyle]}>
|
||||||
<InspectorPanel
|
<InspectorPanel
|
||||||
|
devtoolsIsOpen={!!this.state.devtoolsBackend}
|
||||||
inspecting={this.state.inspecting}
|
inspecting={this.state.inspecting}
|
||||||
perfing={this.state.perfing}
|
perfing={this.state.perfing}
|
||||||
setPerfing={this.setPerfing.bind(this)}
|
setPerfing={this.setPerfing.bind(this)}
|
||||||
|
@ -27,7 +27,11 @@ type EventLike = {
|
|||||||
|
|
||||||
var InspectorOverlay = React.createClass({
|
var InspectorOverlay = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
inspectedViewTag: PropTypes.object,
|
inspected: PropTypes.shape({
|
||||||
|
frame: PropTypes.object,
|
||||||
|
style: PropTypes.any,
|
||||||
|
}),
|
||||||
|
inspectedViewTag: PropTypes.number,
|
||||||
onTouchInstance: PropTypes.func.isRequired,
|
onTouchInstance: PropTypes.func.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class InspectorPanel extends React.Component {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{contents}
|
{!this.props.devtoolsIsOpen && contents}
|
||||||
<View style={styles.buttonRow}>
|
<View style={styles.buttonRow}>
|
||||||
<Button
|
<Button
|
||||||
title={'Inspect'}
|
title={'Inspect'}
|
||||||
@ -76,6 +76,7 @@ class InspectorPanel extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InspectorPanel.propTypes = {
|
InspectorPanel.propTypes = {
|
||||||
|
devtoolsIsOpen: PropTypes.bool,
|
||||||
inspecting: PropTypes.bool,
|
inspecting: PropTypes.bool,
|
||||||
setInspecting: PropTypes.func,
|
setInspecting: PropTypes.func,
|
||||||
inspected: PropTypes.object,
|
inspected: PropTypes.object,
|
||||||
|
@ -79,6 +79,12 @@ var ReactNativeMount = {
|
|||||||
|
|
||||||
_instancesByContainerID: {},
|
_instancesByContainerID: {},
|
||||||
|
|
||||||
|
// these two functions are needed by React Devtools
|
||||||
|
findNodeHandle: require('findNodeHandle'),
|
||||||
|
nativeTagToRootNodeID: function (nativeTag: number): string {
|
||||||
|
return ReactNativeTagHandles.tagToRootNodeID[nativeTag];
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ReactComponent} instance Instance to render.
|
* @param {ReactComponent} instance Instance to render.
|
||||||
* @param {containerTag} containerView Handle to native view tag
|
* @param {containerTag} containerView Handle to native view tag
|
||||||
|
@ -1351,7 +1351,9 @@ RCT_EXPORT_METHOD(measure:(NSNumber *)reactTag
|
|||||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||||
UIView *view = viewRegistry[reactTag];
|
UIView *view = viewRegistry[reactTag];
|
||||||
if (!view) {
|
if (!view) {
|
||||||
RCTLogError(@"measure cannot find view with tag #%@", reactTag);
|
// this view was probably collapsed out
|
||||||
|
RCTLogWarn(@"measure cannot find view with tag #%@", reactTag);
|
||||||
|
callback(@[]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CGRect frame = view.frame;
|
CGRect frame = view.frame;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user