Fix inspector overflow

Summary:
Puts hierarchy and other inspector data in a fixed height scrollview so it never takes up
too much space and you can always scroll to see everything you want.

Reviewed By: fkgozali

Differential Revision: D4374819

fbshipit-source-id: 89356670c984c693db345ad66a97d4cb54a98aee
This commit is contained in:
Spencer Ahrens 2017-01-03 13:38:50 -08:00 committed by Facebook Github Bot
parent 257794762e
commit 21ba956560
3 changed files with 72 additions and 67 deletions

View File

@ -11,20 +11,20 @@
*/ */
'use strict'; 'use strict';
var BoxInspector = require('BoxInspector'); const BoxInspector = require('BoxInspector');
var React = require('React'); const React = require('React');
var StyleInspector = require('StyleInspector'); const StyleInspector = require('StyleInspector');
var StyleSheet = require('StyleSheet'); const StyleSheet = require('StyleSheet');
var Text = require('Text'); const Text = require('Text');
var TouchableHighlight = require('TouchableHighlight'); const TouchableHighlight = require('TouchableHighlight');
var TouchableWithoutFeedback = require('TouchableWithoutFeedback'); const TouchableWithoutFeedback = require('TouchableWithoutFeedback');
var View = require('View'); const View = require('View');
var flattenStyle = require('flattenStyle'); const flattenStyle = require('flattenStyle');
var mapWithSeparator = require('mapWithSeparator'); const mapWithSeparator = require('mapWithSeparator');
var openFileInEditor = require('openFileInEditor'); const openFileInEditor = require('openFileInEditor');
var PropTypes = React.PropTypes; const PropTypes = React.PropTypes;
class ElementProperties extends React.Component { class ElementProperties extends React.Component {
props: { props: {
@ -50,15 +50,15 @@ class ElementProperties extends React.Component {
}; };
render() { render() {
var style = flattenStyle(this.props.style); const style = flattenStyle(this.props.style);
// $FlowFixMe found when converting React.createClass to ES6 // $FlowFixMe found when converting React.createClass to ES6
var selection = this.props.selection; const selection = this.props.selection;
var openFileButton; let openFileButton;
var source = this.props.source; const source = this.props.source;
var {fileName, lineNumber} = source || {}; const {fileName, lineNumber} = source || {};
if (fileName && lineNumber) { if (fileName && lineNumber) {
var parts = fileName.split('/'); const parts = fileName.split('/');
var fileNameShort = parts[parts.length - 1]; const fileNameShort = parts[parts.length - 1];
openFileButton = ( openFileButton = (
<TouchableHighlight <TouchableHighlight
style={styles.openButton} style={styles.openButton}
@ -120,7 +120,7 @@ function getInstanceName(instance) {
return 'Unknown'; return 'Unknown';
} }
var styles = StyleSheet.create({ const styles = StyleSheet.create({
breadSep: { breadSep: {
fontSize: 8, fontSize: 8,
color: 'white', color: 'white',
@ -156,10 +156,6 @@ var styles = StyleSheet.create({
info: { info: {
padding: 10, padding: 10,
}, },
path: {
color: 'white',
fontSize: 9,
},
openButton: { openButton: {
padding: 10, padding: 10,
backgroundColor: '#000', backgroundColor: '#000',

View File

@ -14,15 +14,16 @@
'use strict'; 'use strict';
var Dimensions = require('Dimensions'); const Dimensions = require('Dimensions');
var InspectorOverlay = require('InspectorOverlay'); const InspectorOverlay = require('InspectorOverlay');
var InspectorPanel = require('InspectorPanel'); const InspectorPanel = require('InspectorPanel');
var InspectorUtils = require('InspectorUtils'); const InspectorUtils = require('InspectorUtils');
var React = require('React'); const Platform = require('Platform');
var StyleSheet = require('StyleSheet'); const React = require('React');
var Touchable = require('Touchable'); const StyleSheet = require('StyleSheet');
var UIManager = require('UIManager'); const Touchable = require('Touchable');
var View = require('View'); const UIManager = require('UIManager');
const View = require('View');
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) { if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
// required for devtools to be able to edit react native styles // required for devtools to be able to edit react native styles
@ -89,9 +90,9 @@ class Inspector extends React.Component {
this.setState({inspectedViewTag: newProps.inspectedViewTag}); this.setState({inspectedViewTag: newProps.inspectedViewTag});
} }
attachToDevtools(agent: Object) { attachToDevtools = (agent: Object) => {
var _hideWait = null; let _hideWait = null;
var hlSub = agent.sub('highlight', ({node, name, props}) => { const hlSub = agent.sub('highlight', ({node, name, props}) => {
clearTimeout(_hideWait); clearTimeout(_hideWait);
UIManager.measure(node, (x, y, width, height, left, top) => { UIManager.measure(node, (x, y, width, height, left, top) => {
this.setState({ this.setState({
@ -103,7 +104,7 @@ class Inspector extends React.Component {
}); });
}); });
}); });
var hideSub = agent.sub('hideHighlight', () => { const hideSub = agent.sub('hideHighlight', () => {
if (this.state.inspected === null) { if (this.state.inspected === null) {
return; return;
} }
@ -123,14 +124,14 @@ class Inspector extends React.Component {
this.setState({ this.setState({
devtoolsAgent: agent, devtoolsAgent: agent,
}); });
} };
setSelection(i: number) { setSelection(i: number) {
var instance = this.state.hierarchy[i]; const instance = this.state.hierarchy[i];
// if we inspect a stateless component we can't use the getPublicInstance method // if we inspect a stateless component we can't use the getPublicInstance method
// therefore we use the internal _instance property directly. // therefore we use the internal _instance property directly.
var publicInstance = instance['_instance'] || {}; const publicInstance = instance['_instance'] || {};
var source = instance['_currentElement'] && instance['_currentElement']['_source']; const source = instance['_currentElement'] && instance['_currentElement']['_source'];
UIManager.measure(instance.getHostNode(), (x, y, width, height, left, top) => { UIManager.measure(instance.getHostNode(), (x, y, width, height, left, top) => {
this.setState({ this.setState({
inspected: { inspected: {
@ -147,8 +148,8 @@ class Inspector extends React.Component {
// Most likely the touched instance is a native wrapper (like RCTView) // Most likely the touched instance is a native wrapper (like RCTView)
// which is not very interesting. Most likely user wants a composite // which is not very interesting. Most likely user wants a composite
// instance that contains it (like View) // instance that contains it (like View)
var hierarchy = InspectorUtils.getOwnerHierarchy(touched); const hierarchy = InspectorUtils.getOwnerHierarchy(touched);
var instance = InspectorUtils.lastNotNativeInstance(hierarchy); const instance = InspectorUtils.lastNotNativeInstance(hierarchy);
if (this.state.devtoolsAgent) { if (this.state.devtoolsAgent) {
this.state.devtoolsAgent.selectFromReactInstance(instance, true); this.state.devtoolsAgent.selectFromReactInstance(instance, true);
@ -156,9 +157,9 @@ class Inspector extends React.Component {
// if we inspect a stateless component we can't use the getPublicInstance method // if we inspect a stateless component we can't use the getPublicInstance method
// therefore we use the internal _instance property directly. // therefore we use the internal _instance property directly.
var publicInstance = instance['_instance'] || {}; const publicInstance = instance['_instance'] || {};
var props = publicInstance.props || {}; const props = publicInstance.props || {};
var source = instance['_currentElement'] && instance['_currentElement']['_source']; const source = instance['_currentElement'] && instance['_currentElement']['_source'];
this.setState({ this.setState({
panelPos: pointerY > Dimensions.get('window').height / 2 ? 'top' : 'bottom', panelPos: pointerY > Dimensions.get('window').height / 2 ? 'top' : 'bottom',
selection: hierarchy.indexOf(instance), selection: hierarchy.indexOf(instance),
@ -204,7 +205,9 @@ class Inspector extends React.Component {
} }
render() { render() {
var panelContainerStyle = (this.state.panelPos === 'bottom') ? {bottom: 0} : {top: 0}; const panelContainerStyle = (this.state.panelPos === 'bottom') ?
{bottom: 0} :
{top: Platform.OS === 'ios' ? 20 : 0};
return ( return (
<View style={styles.container} pointerEvents="box-none"> <View style={styles.container} pointerEvents="box-none">
{this.state.inspecting && {this.state.inspecting &&
@ -235,7 +238,7 @@ class Inspector extends React.Component {
} }
} }
var styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
position: 'absolute', position: 'absolute',
backgroundColor: 'transparent', backgroundColor: 'transparent',

View File

@ -11,16 +11,17 @@
*/ */
'use strict'; 'use strict';
var React = require('React'); const ElementProperties = require('ElementProperties');
var StyleSheet = require('StyleSheet'); const NetworkOverlay = require('NetworkOverlay');
var Text = require('Text'); const PerformanceOverlay = require('PerformanceOverlay');
var View = require('View'); const React = require('React');
var ElementProperties = require('ElementProperties'); const ScrollView = require('ScrollView');
var PerformanceOverlay = require('PerformanceOverlay'); const StyleSheet = require('StyleSheet');
var TouchableHighlight = require('TouchableHighlight'); const Text = require('Text');
var NetworkOverlay = require('NetworkOverlay'); const TouchableHighlight = require('TouchableHighlight');
const View = require('View');
var PropTypes = React.PropTypes; const PropTypes = React.PropTypes;
class InspectorPanel extends React.Component { class InspectorPanel extends React.Component {
renderWaiting() { renderWaiting() {
@ -35,17 +36,19 @@ class InspectorPanel extends React.Component {
} }
render() { render() {
var contents; let contents;
if (this.props.inspected) { if (this.props.inspected) {
contents = ( contents = (
<ElementProperties <ScrollView style={styles.properties}>
style={this.props.inspected.style} <ElementProperties
frame={this.props.inspected.frame} style={this.props.inspected.style}
source={this.props.inspected.source} frame={this.props.inspected.frame}
hierarchy={this.props.hierarchy} source={this.props.inspected.source}
selection={this.props.selection} hierarchy={this.props.hierarchy}
setSelection={this.props.setSelection} selection={this.props.selection}
/> setSelection={this.props.setSelection}
/>
</ScrollView>
); );
} else if (this.props.perfing) { } else if (this.props.perfing) {
contents = ( contents = (
@ -115,7 +118,7 @@ class Button extends React.Component {
} }
} }
var styles = StyleSheet.create({ const styles = StyleSheet.create({
buttonRow: { buttonRow: {
flexDirection: 'row', flexDirection: 'row',
}, },
@ -137,6 +140,9 @@ var styles = StyleSheet.create({
container: { container: {
backgroundColor: 'rgba(0, 0, 0, 0.7)', backgroundColor: 'rgba(0, 0, 0, 0.7)',
}, },
properties: {
height: 200,
},
waiting: { waiting: {
height: 100, height: 100,
}, },