1414const ListView = require ( 'ListView' ) ;
1515const React = require ( 'React' ) ;
1616const RecyclerViewBackedScrollView = require ( 'RecyclerViewBackedScrollView' ) ;
17+ const ScrollView = require ( 'ScrollView' ) ;
1718const StyleSheet = require ( 'StyleSheet' ) ;
1819const Text = require ( 'Text' ) ;
1920const TouchableHighlight = require ( 'TouchableHighlight' ) ;
@@ -46,35 +47,46 @@ class NetworkOverlay extends React.Component {
4647 _listViewDataSource : ListView . DataSource ;
4748 _listView : ?ListView ;
4849 _listViewHighlighted : bool ;
49- _listViewHeight : ?number ;
50+ _listViewHeight : number ;
51+ _scrollView : ?ScrollView ;
52+ _detailViewItems : Array < Array < ReactElement < any >>> ;
5053 _listViewOnLayout : ( event : Event ) => void ;
51- _captureRequestList : ( listRef : ?ListView ) => void ;
54+ _captureRequestListView : ( listRef : ?ListView ) => void ;
55+ _captureDetailScrollView : ( scrollRef : ?ScrollView ) => void ;
5256 _renderRow : (
5357 rowData : NetworkRequestInfo ,
5458 sectionID : number ,
5559 rowID : number ,
5660 highlightRow : ( sectionID : number , rowID : number ) = > void ,
5761 ) => ReactElement < any > ;
5862 _renderScrollComponent : ( props : Object ) = > ReactElement < any > ;
63+ _closeButtonClicked : ( ) = > void ;
5964
6065 state : {
6166 dataSource : ListView . DataSource ,
67+ newDetailInfo : bool ,
68+ detailRowID : ?number ,
6269 } ;
6370
6471 constructor ( props : Object ) {
6572 super ( props ) ;
6673 this . _requests = [ ] ;
74+ this . _detailViewItems = [ ] ;
6775 this . _listViewDataSource =
6876 new ListView . DataSource ( { rowHasChanged : ( r1 , r2 ) => r1 !== r2 } ) ;
6977 this . state = {
7078 dataSource : this . _listViewDataSource . cloneWithRows ( [ ] ) ,
79+ newDetailInfo : false ,
80+ detailRowID : null ,
7181 } ;
7282 this . _listViewHighlighted = false ;
73- this . _listViewHeight = null ;
74- this . _captureRequestList = this . _captureRequestList . bind ( this ) ;
83+ this . _listViewHeight = 0 ;
84+ this . _captureRequestListView = this . _captureRequestListView . bind ( this ) ;
85+ this . _captureDetailScrollView = this . _captureDetailScrollView . bind ( this ) ;
7586 this . _listViewOnLayout = this . _listViewOnLayout . bind ( this ) ;
7687 this . _renderRow = this . _renderRow . bind ( this ) ;
7788 this . _renderScrollComponent = this . _renderScrollComponent . bind ( this ) ;
89+ this . _closeButtonClicked = this . _closeButtonClicked . bind ( this ) ;
7890 }
7991
8092 _enableInterception ( ) : void {
@@ -87,29 +99,36 @@ class NetworkOverlay extends React.Component {
8799 // so that we can distinguish different xhr objects in callbacks.
88100 xhr . _index = this . _requests . length ;
89101 const _xhr : NetworkRequestInfo = { 'method' : method , 'url' : url } ;
90- this . _requests = this . _requests . concat ( _xhr ) ;
102+ this . _requests . push ( _xhr ) ;
103+ this . _detailViewItems . push ( [ ] ) ;
104+ this . _genDetailViewItem ( xhr . _index ) ;
91105 this . setState (
92106 { dataSource : this . _listViewDataSource . cloneWithRows ( this . _requests ) } ,
93107 this . _scrollToBottom ( ) ,
94108 ) ;
95109 } . bind ( this ) ) ;
96110
97111 XHRInterceptor . setRequestHeaderCallback ( function ( header , value , xhr ) {
98- if ( ! this . _requests [ xhr . _index ] . requestHeaders ) {
99- this . _requests [ xhr . _index ] . requestHeaders = { } ;
112+ const networkInfo = this . _requests [ xhr . _index ] ;
113+ if ( ! networkInfo . requestHeaders ) {
114+ networkInfo . requestHeaders = { } ;
100115 }
101- this . _requests [ xhr . _index ] . requestHeaders [ header ] = value ;
116+ networkInfo . requestHeaders [ header ] = value ;
117+ this . _genDetailViewItem ( xhr . _index ) ;
102118 } . bind ( this ) ) ;
103119
104120 XHRInterceptor . setSendCallback ( function ( data , xhr ) {
105121 this . _requests [ xhr . _index ] . dataSent = data ;
122+ this . _genDetailViewItem ( xhr . _index ) ;
106123 } . bind ( this ) ) ;
107124
108125 XHRInterceptor . setHeaderReceivedCallback (
109126 function ( type , size , responseHeaders , xhr ) {
110- this . _requests [ xhr . _index ] . responseContentType = type ;
111- this . _requests [ xhr . _index ] . responseSize = size ;
112- this . _requests [ xhr . _index ] . responseHeaders = responseHeaders ;
127+ const networkInfo = this . _requests [ xhr . _index ] ;
128+ networkInfo . responseContentType = type ;
129+ networkInfo . responseSize = size ;
130+ networkInfo . responseHeaders = responseHeaders ;
131+ this . _genDetailViewItem ( xhr . _index ) ;
113132 } . bind ( this )
114133 ) ;
115134
@@ -122,11 +141,13 @@ class NetworkOverlay extends React.Component {
122141 responseType ,
123142 xhr ,
124143 ) {
125- this . _requests [ xhr . _index ] . status = status ;
126- this . _requests [ xhr . _index ] . timeout = timeout ;
127- this . _requests [ xhr . _index ] . response = response ;
128- this . _requests [ xhr . _index ] . responseURL = responseURL ;
129- this . _requests [ xhr . _index ] . responseType = responseType ;
144+ const networkInfo = this . _requests [ xhr . _index ] ;
145+ networkInfo . status = status ;
146+ networkInfo . timeout = timeout ;
147+ networkInfo . response = response ;
148+ networkInfo . responseURL = responseURL ;
149+ networkInfo . responseType = responseType ;
150+ this . _genDetailViewItem ( xhr . _index ) ;
130151 } . bind ( this )
131152 ) ;
132153
@@ -193,7 +214,7 @@ class NetworkOverlay extends React.Component {
193214 }
194215
195216 _scrollToBottom ( ) : void {
196- if ( ! ! this . _listView && ! ! this . _listViewHeight ) {
217+ if ( this . _listView ) {
197218 const scrollResponder = this . _listView . getScrollResponder ( ) ;
198219 if ( scrollResponder ) {
199220 const scrollY = Math . max (
@@ -211,7 +232,7 @@ class NetworkOverlay extends React.Component {
211232 }
212233 }
213234
214- _captureRequestList ( listRef : ?ListView ) : void {
235+ _captureRequestListView ( listRef : ?ListView ) : void {
215236 this . _listView = listRef ;
216237 }
217238
@@ -227,29 +248,106 @@ class NetworkOverlay extends React.Component {
227248 }
228249
229250 /**
230- * TODO: When item is pressed, should pop up another view to show details.
251+ * Popup a scrollView to dynamically show detailed information of
252+ * the request, when pressing a row in the network flow listView.
231253 */
232254 _pressRow ( rowID : number ) : void {
233255 this. _listViewHighlighted = true ;
256+ this . setState (
257+ { detailRowID : rowID } ,
258+ this . _scrollToTop ( ) ,
259+ ) ;
260+ }
261+
262+ _scrollToTop ( ) : void {
263+ if ( this . _scrollView ) {
264+ this . _scrollView . scrollTo ( {
265+ y : 0 ,
266+ animated : false ,
267+ } ) ;
268+ }
269+ }
270+
271+ _captureDetailScrollView ( scrollRef : ?ScrollView ) : void {
272+ this. _scrollView = scrollRef ;
273+ }
274+
275+ _closeButtonClicked ( ) {
276+ this . setState ( { detailRowID : null } ) ;
277+ }
278+
279+ _getStringByValue ( value : any ) : string {
280+ if ( value === undefined ) {
281+ return 'undefined' ;
282+ }
283+ if ( typeof value === 'object' ) {
284+ return JSON . stringify ( value ) ;
285+ }
286+ if ( typeof value === 'string' && value . length > 500 ) {
287+ return String ( value ) . substr ( 0 , 500 ) . concat ( '\n***TRUNCATED TO 500 CHARACTERS***' ) ;
288+ }
289+ return value ;
290+ }
291+
292+ /**
293+ * Generate a list of views containing network request information for
294+ * a XHR object, to be shown in the detail scrollview. This function
295+ * should be called every time there is a new update of the XHR object,
296+ * in order to show network request/response information in real time.
297+ */
298+ _genDetailViewItem ( index : number ) : void {
299+ this. _detailViewItems [ index ] = [ ] ;
300+ const detailViewItem = this . _detailViewItems [ index ] ;
301+ const requestItem = this . _requests [ index ] ;
302+ for ( let key in requestItem ) {
303+ detailViewItem . push (
304+ < View style = { styles . detailViewRow } key = { key } >
305+ < Text style = { [ styles . detailViewText , styles . detailKeyCellView ] } >
306+ { key }
307+ </ Text >
308+ < Text style = { [ styles . detailViewText , styles . detailValueCellView ] } >
309+ { this . _getStringByValue ( requestItem [ key ] ) }
310+ </ Text >
311+ </ View >
312+ ) ;
313+ }
314+ // Re-render if this network request is showing in the detail view.
315+ if ( this . state . detailRowID != null && this . state . detailRowID == index ) {
316+ this . setState ( { newDetailInfo : true } ) ;
317+ }
234318 }
235319
236320 render ( ) {
237321 return (
238322 < View style = { styles . container } >
239- { this . _requests . length > 0 &&
240- < View >
323+ { this . state . detailRowID != null &&
324+ < TouchableHighlight
325+ style = { styles . closeButton }
326+ onPress = { this . _closeButtonClicked } >
327+ < View >
328+ < Text style = { styles . clostButtonText } > v</ Text >
329+ </ View >
330+ </ TouchableHighlight > }
331+ { this . state . detailRowID != null &&
332+ < ScrollView
333+ style = { styles . detailScrollView }
334+ ref = { this . _captureDetailScrollView } >
335+ { this . _detailViewItems [ this . state . detailRowID ] }
336+ </ ScrollView > }
337+ < View style = { styles . listViewTitle } >
338+ { this . _requests . length > 0 &&
241339 < View style = { styles . tableRow } >
242340 < View style = { styles . urlTitleCellView } >
243341 < Text style = { styles . cellText } numberOfLines = { 1 } > URL</ Text >
244342 </ View >
245343 < View style = { styles . methodTitleCellView } >
246344 < Text style = { styles . cellText } numberOfLines = { 1 } > Method</ Text >
247345 </ View >
248- </ View >
249- </ View > }
346+ </ View > }
347+ </ View >
250348 < ListView
251349 style = { styles . listView }
252- ref = { this . _captureRequestList }
350+ ref = { this . _captureRequestListView }
253351 dataSource = { this . state . dataSource }
254352 renderRow = { this . _renderRow }
255353 renderScrollComponent = { this . _renderScrollComponent }
@@ -264,14 +362,17 @@ class NetworkOverlay extends React.Component {
264362
265363const styles = StyleSheet . create ( {
266364 container : {
267- height : 100 ,
268365 paddingTop : 10 ,
269366 paddingBottom : 10 ,
270367 paddingLeft : 5 ,
271368 paddingRight : 5 ,
272369 } ,
370+ listViewTitle : {
371+ height : 20 ,
372+ } ,
273373 listView : {
274374 flex : 1 ,
375+ height : 60 ,
275376 } ,
276377 tableRow : {
277378 flexDirection : 'row' ,
@@ -342,6 +443,36 @@ const styles = StyleSheet.create({
342443 flex : 5 ,
343444 paddingLeft : 3 ,
344445 } ,
446+ detailScrollView : {
447+ flex : 1 ,
448+ height : 180 ,
449+ marginTop : 5 ,
450+ marginBottom : 5 ,
451+ } ,
452+ detailKeyCellView : {
453+ flex : 1.3 ,
454+ } ,
455+ detailValueCellView : {
456+ flex : 2 ,
457+ } ,
458+ detailViewRow : {
459+ flexDirection : 'row' ,
460+ paddingHorizontal : 3 ,
461+ } ,
462+ detailViewText : {
463+ color : 'white' ,
464+ fontSize : 11 ,
465+ } ,
466+ clostButtonText : {
467+ color : 'white' ,
468+ fontSize : 10 ,
469+ } ,
470+ closeButton : {
471+ backgroundColor : '#888' ,
472+ justifyContent : 'center' ,
473+ alignItems : 'center' ,
474+ right : 0 ,
475+ } ,
345476} ) ;
346477
347478module . exports = NetworkOverlay ;
0 commit comments