1+ import PropTypes from 'prop-types' ;
12import React , { PureComponent } from 'react' ;
23import { ScrollView , View , Text , TouchableOpacity , PanResponder , Animated , Dimensions , StyleSheet , TextInput , Keyboard , NativeModules , Platform , KeyboardAvoidingView } from 'react-native' ;
34import event from './src/event' ;
45import Network , { traceNetwork } from './src/network' ;
56import Log , { traceLog } from './src/log' ;
67import Info from './src/info' ;
8+ import HocComp from './src/hoc' ;
9+ 710const { width, height } = Dimensions . get ( 'window' ) ;
811
912let commandContext = global ;
@@ -19,29 +22,31 @@ export const initTrace = () => {
1922} ;
2023
2124class VDebug extends PureComponent {
25+ static propTypes = {
26+ // Info panel (Optional)
27+ info : PropTypes . object ,
28+ // Expansion panel (Optional)
29+ panels : PropTypes . array
30+ } ;
31+ 32+ static defaultProps = {
33+ info : { } ,
34+ panels : null
35+ } ;
36+ 2237 constructor ( props ) {
2338 super ( props ) ;
2439 initTrace ( ) ;
40+ this . containerHeight = ( height / 3 ) * 2 ;
41+ this . refsObj = { } ;
2542 this . state = {
2643 commandValue : '' ,
2744 showPanel : false ,
2845 currentPageIndex : 0 ,
2946 pan : new Animated . ValueXY ( ) ,
3047 scale : new Animated . Value ( 1 ) ,
31- panels : [
32- {
33- title : 'Log' ,
34- component : < Log />
35- } ,
36- {
37- title : 'Network' ,
38- component : < Network />
39- } ,
40- {
41- title : 'Info' ,
42- component : < Info info = { this . props . info || { } } />
43- }
44- ]
48+ panelHeight : new Animated . Value ( 0 ) ,
49+ panels : this . addPanels ( )
4550 } ;
4651 this . panResponder = PanResponder . create ( {
4752 onStartShouldSetPanResponder : ( ) => true ,
@@ -54,7 +59,7 @@ class VDebug extends PureComponent {
5459 Animated . spring ( this . state . scale , {
5560 useNativeDriver : true ,
5661 toValue : 1.3 ,
57- friction : 3
62+ friction : 7
5863 } ) . start ( ) ;
5964 } ,
6065 onPanResponderMove : Animated . event ( [ null , { dx : this . state . pan . x , dy : this . state . pan . y } ] ) ,
@@ -64,7 +69,7 @@ class VDebug extends PureComponent {
6469 Animated . spring ( this . state . scale , {
6570 useNativeDriver : true ,
6671 toValue : 1 ,
67- friction : 3
72+ friction : 7
6873 } ) . start ( ( ) => {
6974 this . setState ( {
7075 top : nativeEvent . pageY
@@ -80,10 +85,43 @@ class VDebug extends PureComponent {
8085 this . state . pan . setValue ( { x : 0 , y : 0 } ) ;
8186 }
8287
88+ getRef ( index ) {
89+ return ref => {
90+ if ( ! this . refsObj [ index ] ) this . refsObj [ index ] = ref ;
91+ } ;
92+ }
93+ 94+ addPanels ( ) {
95+ let defaultPanels = [
96+ {
97+ title : 'Log' ,
98+ component : HocComp ( Log , this . getRef ( 0 ) )
99+ } ,
100+ {
101+ title : 'Network' ,
102+ component : HocComp ( Network , this . getRef ( 1 ) )
103+ } ,
104+ {
105+ title : 'Info' ,
106+ component : HocComp ( Info , this . getRef ( 2 ) ) ,
107+ props : { info : this . props . info }
108+ }
109+ ] ;
110+ if ( this . props . panels && this . props . panels . length ) {
111+ this . props . panels . forEach ( ( item , index ) => {
112+ // support up to five extended panels
113+ if ( index >= 3 ) return ;
114+ if ( item . title && item . component ) {
115+ item . component = HocComp ( item . component , this . getRef ( defaultPanels . length ) ) ;
116+ defaultPanels . push ( item ) ;
117+ }
118+ } ) ;
119+ }
120+ return defaultPanels ;
121+ }
122+ 83123 togglePanel ( ) {
84- this . setState ( state => ( {
85- showPanel : ! state . showPanel
86- } ) ) ;
124+ this . state . panelHeight . setValue ( this . state . panelHeight . _value ? 0 : this . containerHeight ) ;
87125 }
88126
89127 clearLogs ( ) {
@@ -134,15 +172,30 @@ class VDebug extends PureComponent {
134172 }
135173 }
136174
175+ scrollToTop ( ) {
176+ const item = this . refsObj [ this . state . currentPageIndex ] ;
177+ const instance = item ?. getScrollRef && item ?. getScrollRef ( ) ;
178+ if ( instance ) {
179+ // FlatList
180+ instance . scrollToOffset && instance . scrollToOffset ( { animated : true , viewPosition : 0 , index : 0 } ) ;
181+ // ScrollView
182+ instance . scrollTo && instance . scrollTo ( { x : 0 , y : 0 , animated : true } ) ;
183+ }
184+ }
185+ 137186 renderPanelHeader ( ) {
138187 return (
139188 < View style = { styles . panelHeader } >
140189 { this . state . panels . map ( ( item , index ) => (
141190 < TouchableOpacity
142191 key = { index . toString ( ) }
143192 onPress = { ( ) => {
144- this . scrollToPage ( index ) ;
145- this . setState ( { currentPageIndex : index } ) ;
193+ if ( index != this . state . currentPageIndex ) {
194+ this . scrollToPage ( index ) ;
195+ this . setState ( { currentPageIndex : index } ) ;
196+ } else {
197+ this . scrollToTop ( ) ;
198+ }
146199 } }
147200 style = { [ styles . panelHeaderItem , index === this . state . currentPageIndex && styles . activeTab ] }
148201 >
@@ -155,7 +208,7 @@ class VDebug extends PureComponent {
155208
156209 renderCommandBar ( ) {
157210 return (
158- < View style = { styles . commandBar } >
211+ < KeyboardAvoidingView keyboardVerticalOffset = { Platform . OS == 'android' ? 0 : 300 } contentContainerStyle = { { flex : 1 , flexDirection : 'row' } } behavior = { 'position' } style = { styles . commandBar } >
159212 < TextInput
160213 ref = { ref => {
161214 this . textInput = ref ;
@@ -172,7 +225,7 @@ class VDebug extends PureComponent {
172225 < TouchableOpacity style = { styles . commandBarBtn } onPress = { this . execCommand . bind ( this ) } >
173226 < Text > OK</ Text >
174227 </ TouchableOpacity >
175- </ View >
228+ </ KeyboardAvoidingView >
176229 ) ;
177230 }
178231
@@ -204,7 +257,7 @@ class VDebug extends PureComponent {
204257
205258 renderPanel ( ) {
206259 return (
207- < KeyboardAvoidingView behavior = { Platform . OS === 'ios' ? 'padding' : 'height' } style = { styles . panel } >
260+ < Animated . View style = { [ styles . panel , { height : this . state . panelHeight } ] } >
208261 { this . renderPanelHeader ( ) }
209262 < ScrollView
210263 onMomentumScrollEnd = { this . onScrollAnimationEnd . bind ( this ) }
@@ -219,18 +272,18 @@ class VDebug extends PureComponent {
219272 { this . state . panels . map ( ( item , index ) => {
220273 return (
221274 < View key = { index } style = { { width : width } } >
222- { item . component }
275+ < item . component { ... ( item . props ?? { } ) } />
223276 </ View >
224277 ) ;
225278 } ) }
226279 </ ScrollView >
227280 { this . renderCommandBar ( ) }
228281 { this . renderPanelFooter ( ) }
229- </ KeyboardAvoidingView >
282+ </ Animated . View >
230283 ) ;
231284 }
232285
233- renderHomeBtn ( ) {
286+ renderDebugBtn ( ) {
234287 const { pan, scale } = this . state ;
235288 const [ translateX , translateY ] = [ pan . x , pan . y ] ;
236289 const btnStyle = { transform : [ { translateX } , { translateY } , { scale } ] } ;
@@ -243,7 +296,12 @@ class VDebug extends PureComponent {
243296 }
244297
245298 render ( ) {
246- return this . state . showPanel ? this . renderPanel ( ) : this . renderHomeBtn ( ) ;
299+ return (
300+ < View style = { { flex : 1 } } >
301+ { this . renderPanel ( ) }
302+ { this . renderDebugBtn ( ) }
303+ </ View >
304+ ) ;
247305 }
248306}
249307
@@ -253,14 +311,12 @@ const styles = StyleSheet.create({
253311 } ,
254312 panel : {
255313 position : 'absolute' ,
256- zIndex : 999999999 ,
257- elevation : 999999999 ,
314+ zIndex : 99998 ,
315+ elevation : 99998 ,
258316 backgroundColor : '#fff' ,
259317 width,
260- height : ( height / 3 ) * 2 ,
261318 bottom : 0 ,
262- right : 0 ,
263- flexDirection : 'column'
319+ right : 0
264320 } ,
265321 panelHeader : {
266322 width,
@@ -318,13 +374,13 @@ const styles = StyleSheet.create({
318374 alignItems : 'center' ,
319375 justifyContent : 'center' ,
320376 position : 'absolute' ,
321- zIndex : 999999999 ,
377+ zIndex : 99999 ,
322378 bottom : height / 2 ,
323379 right : 0 ,
324380 shadowColor : 'rgb(18,34,74)' ,
325381 shadowOffset : { width : 0 , height : 1 } ,
326382 shadowOpacity : 0.08 ,
327- elevation : 0.4
383+ elevation : 99999
328384 } ,
329385 homeBtnText : {
330386 color : '#fff'
0 commit comments