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 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 {
|
||||
/>}
|
||||
<View style={[styles.panelContainer, panelContainerStyle]}>
|
||||
<InspectorPanel
|
||||
devtoolsIsOpen={!!this.state.devtoolsBackend}
|
||||
inspecting={this.state.inspecting}
|
||||
perfing={this.state.perfing}
|
||||
setPerfing={this.setPerfing.bind(this)}
|
||||
|
@ -27,7 +27,11 @@ type EventLike = {
|
||||
|
||||
var InspectorOverlay = React.createClass({
|
||||
propTypes: {
|
||||
inspectedViewTag: PropTypes.object,
|
||||
inspected: PropTypes.shape({
|
||||
frame: PropTypes.object,
|
||||
style: PropTypes.any,
|
||||
}),
|
||||
inspectedViewTag: PropTypes.number,
|
||||
onTouchInstance: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
|
@ -58,7 +58,7 @@ class InspectorPanel extends React.Component {
|
||||
}
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{contents}
|
||||
{!this.props.devtoolsIsOpen && contents}
|
||||
<View style={styles.buttonRow}>
|
||||
<Button
|
||||
title={'Inspect'}
|
||||
@ -76,6 +76,7 @@ class InspectorPanel extends React.Component {
|
||||
}
|
||||
|
||||
InspectorPanel.propTypes = {
|
||||
devtoolsIsOpen: PropTypes.bool,
|
||||
inspecting: PropTypes.bool,
|
||||
setInspecting: PropTypes.func,
|
||||
inspected: PropTypes.object,
|
||||
|
@ -79,6 +79,12 @@ var ReactNativeMount = {
|
||||
|
||||
_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 {containerTag} containerView Handle to native view tag
|
||||
|
@ -1351,7 +1351,9 @@ RCT_EXPORT_METHOD(measure:(NSNumber *)reactTag
|
||||
[self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
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;
|
||||
}
|
||||
CGRect frame = view.frame;
|
||||
|
Loading…
x
Reference in New Issue
Block a user