react-native-debug-toolkit 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description:
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are an expert in TypeScript, React Native, Expo, and Mobile App Development.
|
|
8
|
+
|
|
9
|
+
Code Style and Structure:
|
|
10
|
+
- Write concise, type-safe TypeScript code.
|
|
11
|
+
- Use functional components and hooks over class components.
|
|
12
|
+
- Ensure components are modular, reusable, and maintainable.
|
|
13
|
+
- Organize files by feature, grouping related components, hooks, and styles.
|
|
14
|
+
|
|
15
|
+
Naming Conventions:
|
|
16
|
+
- Use camelCase for variable and function names (e.g., `isFetchingData`, `handleUserInput`).
|
|
17
|
+
- Use PascalCase for component names (e.g., `UserProfile`, `ChatScreen`).
|
|
18
|
+
|
|
19
|
+
TypeScript Usage:
|
|
20
|
+
- Use TypeScript for all components, favoring interfaces for props and state.
|
|
21
|
+
- Enable strict typing in `tsconfig.json`.
|
|
22
|
+
- Avoid using `any`; strive for precise types.
|
|
23
|
+
- Utilize `React.FC` for defining functional components with props.
|
|
24
|
+
|
|
25
|
+
Performance Optimization:
|
|
26
|
+
- Minimize `useEffect`, `useState`, and heavy computations inside render methods.
|
|
27
|
+
- Use `React.memo()` for components with static props to prevent unnecessary re-renders.
|
|
28
|
+
- Optimize FlatLists with props like `removeClippedSubviews`, `maxToRenderPerBatch`, and `windowSize`.
|
|
29
|
+
- Use `getItemLayout` for FlatLists when items have a consistent size to improve performance.
|
|
30
|
+
- Avoid anonymous functions in `renderItem` or event handlers to prevent re-renders.
|
|
31
|
+
|
|
32
|
+
UI and Styling:
|
|
33
|
+
- Use consistent styling, either through `StyleSheet.create()` or Styled Components.
|
|
34
|
+
- Ensure responsive design by considering different screen sizes and orientations.
|
|
35
|
+
- Optimize image handling using libraries designed for React Native
|
|
36
|
+
|
|
37
|
+
Best Practices:
|
|
38
|
+
- Follow React Native's threading model to ensure smooth UI performance.
|
|
39
|
+
- Utilize CodePush Build and Updates for continuous deployment and Over-The-Air (OTA) updates.
|
|
40
|
+
- Use React Navigation for handling navigation and deep linking with best practices.
|
|
41
|
+
|
|
@@ -12,6 +12,7 @@ class NetworkFeature {
|
|
|
12
12
|
this.logs = []
|
|
13
13
|
this.pendingAxiosRequests = new Map()
|
|
14
14
|
this.originalFetch = null
|
|
15
|
+
this.blacklist = [] // URL patterns to exclude from logging
|
|
15
16
|
|
|
16
17
|
NetworkFeature.instance = this
|
|
17
18
|
}
|
|
@@ -39,6 +40,39 @@ class NetworkFeature {
|
|
|
39
40
|
this.pendingAxiosRequests.clear()
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
// Check if a URL matches any pattern in the blacklist
|
|
44
|
+
isUrlBlacklisted(url) {
|
|
45
|
+
if (!url) return false
|
|
46
|
+
|
|
47
|
+
return this.blacklist.some(pattern => {
|
|
48
|
+
if (pattern instanceof RegExp) {
|
|
49
|
+
return pattern.test(url)
|
|
50
|
+
}
|
|
51
|
+
return url.includes(pattern)
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Add a URL pattern to blacklist
|
|
56
|
+
addUrlToBlacklist(pattern) {
|
|
57
|
+
if (!this.blacklist.some(p =>
|
|
58
|
+
(p instanceof RegExp && pattern instanceof RegExp) ?
|
|
59
|
+
p.toString() === pattern.toString() : p === pattern)) {
|
|
60
|
+
this.blacklist.push(pattern)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Remove a URL pattern from blacklist
|
|
65
|
+
removeUrlFromBlacklist(pattern) {
|
|
66
|
+
this.blacklist = this.blacklist.filter(p =>
|
|
67
|
+
(p instanceof RegExp && pattern instanceof RegExp) ?
|
|
68
|
+
p.toString() !== pattern.toString() : p !== pattern)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Clear all patterns from blacklist
|
|
72
|
+
clearBlacklist() {
|
|
73
|
+
this.blacklist = []
|
|
74
|
+
}
|
|
75
|
+
|
|
42
76
|
setupAxiosInterceptors(axiosInstance) {
|
|
43
77
|
if (!__DEV__) {
|
|
44
78
|
return
|
|
@@ -94,6 +128,14 @@ class NetworkFeature {
|
|
|
94
128
|
return
|
|
95
129
|
}
|
|
96
130
|
|
|
131
|
+
const url = `${response.config.baseURL || ''}${response.config.url}`
|
|
132
|
+
|
|
133
|
+
// Skip logging if URL is blacklisted
|
|
134
|
+
if (this.isUrlBlacklisted(url)) {
|
|
135
|
+
this.pendingAxiosRequests.delete(trackId)
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
97
139
|
if (this.logs.length >= NetworkFeature.MAX_LOGS) {
|
|
98
140
|
this.logs.shift()
|
|
99
141
|
}
|
|
@@ -105,7 +147,7 @@ class NetworkFeature {
|
|
|
105
147
|
timestamp: pendingRequest.timestamp,
|
|
106
148
|
duration: Math.round(duration),
|
|
107
149
|
request: {
|
|
108
|
-
url:
|
|
150
|
+
url: url,
|
|
109
151
|
method: response.config.method?.toUpperCase() || 'GET',
|
|
110
152
|
headers: response.config.headers,
|
|
111
153
|
body: response.config.data || response.config.params,
|
|
@@ -148,6 +190,14 @@ class NetworkFeature {
|
|
|
148
190
|
const startTime = pendingRequest
|
|
149
191
|
? pendingRequest.startTime
|
|
150
192
|
: Date.now() - 100
|
|
193
|
+
|
|
194
|
+
const url = `${error.config.baseURL || ''}${error.config.url}`
|
|
195
|
+
|
|
196
|
+
// Skip logging if URL is blacklisted
|
|
197
|
+
if (this.isUrlBlacklisted(url)) {
|
|
198
|
+
this.pendingAxiosRequests.delete(trackId)
|
|
199
|
+
return
|
|
200
|
+
}
|
|
151
201
|
|
|
152
202
|
if (this.logs.length >= NetworkFeature.MAX_LOGS) {
|
|
153
203
|
this.logs.shift()
|
|
@@ -159,7 +209,7 @@ class NetworkFeature {
|
|
|
159
209
|
timestamp: pendingRequest ? pendingRequest.timestamp : new Date(),
|
|
160
210
|
duration: Math.round(duration),
|
|
161
211
|
request: {
|
|
162
|
-
url:
|
|
212
|
+
url: url,
|
|
163
213
|
method: error.config.method?.toUpperCase() || 'GET',
|
|
164
214
|
headers: error.config.headers,
|
|
165
215
|
body: error.config.data || error.config.params,
|
|
@@ -206,12 +256,18 @@ class NetworkFeature {
|
|
|
206
256
|
}
|
|
207
257
|
|
|
208
258
|
_logFetchResponse(request, options, response, startTime) {
|
|
259
|
+
const requestUrl = typeof request === 'string' ? request : request.url
|
|
260
|
+
|
|
261
|
+
// Skip logging if URL is blacklisted
|
|
262
|
+
if (this.isUrlBlacklisted(requestUrl)) {
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
|
|
209
266
|
if (this.logs.length >= NetworkFeature.MAX_LOGS) {
|
|
210
267
|
this.logs.shift()
|
|
211
268
|
}
|
|
212
269
|
|
|
213
270
|
const duration = Date.now() - startTime
|
|
214
|
-
const requestUrl = typeof request === 'string' ? request : request.url
|
|
215
271
|
|
|
216
272
|
const commonData = {
|
|
217
273
|
timestamp: new Date(),
|
|
@@ -276,6 +332,13 @@ class NetworkFeature {
|
|
|
276
332
|
}
|
|
277
333
|
|
|
278
334
|
_logFetchError(request, options, error, startTime) {
|
|
335
|
+
const requestUrl = typeof request === 'string' ? request : request.url
|
|
336
|
+
|
|
337
|
+
// Skip logging if URL is blacklisted
|
|
338
|
+
if (this.isUrlBlacklisted(requestUrl)) {
|
|
339
|
+
return
|
|
340
|
+
}
|
|
341
|
+
|
|
279
342
|
if (this.logs.length >= NetworkFeature.MAX_LOGS) {
|
|
280
343
|
this.logs.shift()
|
|
281
344
|
}
|
|
@@ -286,7 +349,7 @@ class NetworkFeature {
|
|
|
286
349
|
timestamp: new Date(),
|
|
287
350
|
duration: Math.round(duration),
|
|
288
351
|
request: {
|
|
289
|
-
url:
|
|
352
|
+
url: requestUrl,
|
|
290
353
|
method: options.method || 'GET',
|
|
291
354
|
headers: options.headers || {},
|
|
292
355
|
body: options.body,
|
|
@@ -326,5 +389,10 @@ export const createNetworkFeature = () => {
|
|
|
326
389
|
cleanup: () => feature.cleanup(),
|
|
327
390
|
setupAxiosInterceptors: (axiosInstance) =>
|
|
328
391
|
feature.setupAxiosInterceptors(axiosInstance),
|
|
392
|
+
// Expose blacklist management methods
|
|
393
|
+
addUrlToBlacklist: (pattern) => feature.addUrlToBlacklist(pattern),
|
|
394
|
+
removeUrlFromBlacklist: (pattern) => feature.removeUrlFromBlacklist(pattern),
|
|
395
|
+
clearBlacklist: () => feature.clearBlacklist(),
|
|
396
|
+
getBlacklist: () => feature.blacklist,
|
|
329
397
|
}
|
|
330
398
|
}
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import React, { useState, useCallback } from 'react'
|
|
2
2
|
import { View, Text, StyleSheet, Clipboard, Dimensions } from 'react-native'
|
|
3
3
|
import { ScrollView, Pressable } from 'react-native'
|
|
4
|
-
|
|
4
|
+
import JSONTree from 'react-native-json-tree'
|
|
5
5
|
const { width: SCREEN_WIDTH } = Dimensions.get('window')
|
|
6
|
+
const theme = {
|
|
7
|
+
scheme: 'monokai',
|
|
8
|
+
author: 'wimer hazenberg (http://www.monokai.nl)',
|
|
9
|
+
base00: '#272822',
|
|
10
|
+
base01: '#383830',
|
|
11
|
+
base02: '#49483e',
|
|
12
|
+
base03: '#75715e',
|
|
13
|
+
base04: '#a59f85',
|
|
14
|
+
base05: '#f8f8f2',
|
|
15
|
+
base06: '#f5f4f1',
|
|
16
|
+
base07: '#f9f8f5',
|
|
17
|
+
base08: '#f92672',
|
|
18
|
+
base09: '#fd971f',
|
|
19
|
+
base0A: '#f4bf75',
|
|
20
|
+
base0B: '#a6e22e',
|
|
21
|
+
base0C: '#a1efe4',
|
|
22
|
+
base0D: '#66d9ef',
|
|
23
|
+
base0E: '#ae81ff',
|
|
24
|
+
base0F: '#cc6633'
|
|
25
|
+
};
|
|
6
26
|
|
|
7
27
|
const CopyButton = ({ text, style }) => {
|
|
8
28
|
const [copied, setCopied] = useState(false)
|
|
@@ -38,15 +58,18 @@ const CollapsibleSection = ({ title, children, initiallyExpanded = false }) => {
|
|
|
38
58
|
|
|
39
59
|
const LongTextContent = ({ text }) => {
|
|
40
60
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
<View style={styles.longTextWrapper}>
|
|
62
|
+
<ScrollView
|
|
63
|
+
style={styles.longTextContainer}
|
|
64
|
+
contentContainerStyle={styles.longTextContent}
|
|
65
|
+
showsVerticalScrollIndicator={true}
|
|
66
|
+
nestedScrollEnabled={true}
|
|
67
|
+
bounces={false}>
|
|
68
|
+
<Text style={styles.jsonString} selectable={true}>
|
|
69
|
+
{text}
|
|
70
|
+
</Text>
|
|
71
|
+
</ScrollView>
|
|
72
|
+
</View>
|
|
50
73
|
)
|
|
51
74
|
}
|
|
52
75
|
|
|
@@ -283,8 +306,7 @@ const HttpLogDetails = ({ log }) => {
|
|
|
283
306
|
contentContainerStyle={styles.contentContainer}
|
|
284
307
|
showsVerticalScrollIndicator={true}
|
|
285
308
|
scrollEventThrottle={16}
|
|
286
|
-
keyboardShouldPersistTaps='handled'
|
|
287
|
-
nestedScrollEnabled={true}>
|
|
309
|
+
keyboardShouldPersistTaps='handled'>
|
|
288
310
|
<View style={styles.header}>
|
|
289
311
|
<View style={styles.headerInfo}>
|
|
290
312
|
<Text style={styles.url} numberOfLines={2} selectable={true}>
|
|
@@ -299,6 +321,7 @@ const HttpLogDetails = ({ log }) => {
|
|
|
299
321
|
{(request.method || 'GET').toUpperCase()}
|
|
300
322
|
</Text>
|
|
301
323
|
{status && <ApiStatus status={status} success={success} />}
|
|
324
|
+
{duration && <Text style={styles.duration}>(duration:{duration}ms)</Text>}
|
|
302
325
|
</View>
|
|
303
326
|
</View>
|
|
304
327
|
<CopyButton text={request.url || ''} />
|
|
@@ -320,16 +343,28 @@ const HttpLogDetails = ({ log }) => {
|
|
|
320
343
|
}
|
|
321
344
|
/>
|
|
322
345
|
</View>
|
|
323
|
-
<
|
|
324
|
-
<
|
|
325
|
-
|
|
346
|
+
<View style={styles.dataContentWrapper}>
|
|
347
|
+
<ScrollView
|
|
348
|
+
style={styles.dataContent}
|
|
349
|
+
nestedScrollEnabled={true}
|
|
350
|
+
bounces={false}
|
|
351
|
+
showsVerticalScrollIndicator={true}>
|
|
352
|
+
<JSONValue value={requestData} maxExpandLevel={1} />
|
|
353
|
+
</ScrollView>
|
|
354
|
+
</View>
|
|
326
355
|
</View>
|
|
327
356
|
)}
|
|
328
357
|
|
|
329
358
|
<CollapsibleSection title='Headers'>
|
|
330
|
-
<
|
|
331
|
-
<
|
|
332
|
-
|
|
359
|
+
<View style={styles.dataContentWrapper}>
|
|
360
|
+
<ScrollView
|
|
361
|
+
style={styles.dataContent}
|
|
362
|
+
nestedScrollEnabled={true}
|
|
363
|
+
bounces={false}
|
|
364
|
+
showsVerticalScrollIndicator={true}>
|
|
365
|
+
<JSONValue value={request.headers || {}} maxExpandLevel={0} />
|
|
366
|
+
</ScrollView>
|
|
367
|
+
</View>
|
|
333
368
|
</CollapsibleSection>
|
|
334
369
|
</View>
|
|
335
370
|
</CollapsibleSection>
|
|
@@ -338,12 +373,12 @@ const HttpLogDetails = ({ log }) => {
|
|
|
338
373
|
title={`Response ${responseSize}`}
|
|
339
374
|
initiallyExpanded={true}>
|
|
340
375
|
<View style={styles.content}>
|
|
341
|
-
<View style={styles.row}>
|
|
342
|
-
<Text style={styles.label}>Status:{status || (success === false ? 'Error' : 'Unknown')}
|
|
376
|
+
{/* <View style={styles.row}>
|
|
377
|
+
<Text style={styles.label}>Status: {status || (success === false ? 'Error' : 'Unknown')}
|
|
343
378
|
{status && response.statusText ? ` (${response.statusText})` : ''}
|
|
344
|
-
{duration && `
|
|
379
|
+
{duration && ` Duration: (${duration}ms)`}
|
|
345
380
|
</Text>
|
|
346
|
-
</View>
|
|
381
|
+
</View> */}
|
|
347
382
|
|
|
348
383
|
{error && (
|
|
349
384
|
<View style={styles.errorSection}>
|
|
@@ -366,24 +401,28 @@ const HttpLogDetails = ({ log }) => {
|
|
|
366
401
|
}
|
|
367
402
|
/>
|
|
368
403
|
</View>
|
|
404
|
+
<View style={styles.dataContentWrapper}>
|
|
405
|
+
<ScrollView
|
|
406
|
+
style={styles.dataContent}
|
|
407
|
+
nestedScrollEnabled={true}
|
|
408
|
+
bounces={false}
|
|
409
|
+
showsVerticalScrollIndicator={true}>
|
|
410
|
+
<JSONTree data={responseData} theme={theme} invertTheme={true} />
|
|
411
|
+
</ScrollView>
|
|
412
|
+
</View>
|
|
413
|
+
</View>
|
|
414
|
+
)}
|
|
415
|
+
|
|
416
|
+
<CollapsibleSection title='Headers'>
|
|
417
|
+
<View style={styles.dataContentWrapper}>
|
|
369
418
|
<ScrollView
|
|
370
419
|
style={styles.dataContent}
|
|
371
|
-
contentContainerStyle={{ flexGrow: 1 }}
|
|
372
420
|
nestedScrollEnabled={true}
|
|
421
|
+
bounces={false}
|
|
373
422
|
showsVerticalScrollIndicator={true}>
|
|
374
|
-
<JSONValue value={
|
|
423
|
+
<JSONValue value={response.headers || {}} maxExpandLevel={0} />
|
|
375
424
|
</ScrollView>
|
|
376
425
|
</View>
|
|
377
|
-
)}
|
|
378
|
-
|
|
379
|
-
<CollapsibleSection title='Headers'>
|
|
380
|
-
<ScrollView
|
|
381
|
-
style={styles.dataContent}
|
|
382
|
-
contentContainerStyle={{ flexGrow: 1 }}
|
|
383
|
-
nestedScrollEnabled={true}
|
|
384
|
-
showsVerticalScrollIndicator={true}>
|
|
385
|
-
<JSONValue value={response.headers || {}} maxExpandLevel={0} />
|
|
386
|
-
</ScrollView>
|
|
387
426
|
</CollapsibleSection>
|
|
388
427
|
</View>
|
|
389
428
|
</CollapsibleSection>
|
|
@@ -395,10 +434,16 @@ const HttpLogDetails = ({ log }) => {
|
|
|
395
434
|
<Text style={styles.codeBlockLabel}>Debug with cURL</Text>
|
|
396
435
|
<CopyButton text={generateCurl()} />
|
|
397
436
|
</View>
|
|
398
|
-
<View style={styles.
|
|
399
|
-
<
|
|
400
|
-
{
|
|
401
|
-
|
|
437
|
+
<View style={styles.dataContentWrapper}>
|
|
438
|
+
<ScrollView
|
|
439
|
+
style={styles.codeBlock}
|
|
440
|
+
nestedScrollEnabled={true}
|
|
441
|
+
bounces={false}
|
|
442
|
+
showsVerticalScrollIndicator={true}>
|
|
443
|
+
<Text style={styles.codeText} selectable={true}>
|
|
444
|
+
{generateCurl()}
|
|
445
|
+
</Text>
|
|
446
|
+
</ScrollView>
|
|
402
447
|
</View>
|
|
403
448
|
</View>
|
|
404
449
|
</View>
|
|
@@ -559,6 +604,9 @@ const styles = StyleSheet.create({
|
|
|
559
604
|
fontWeight: 'bold',
|
|
560
605
|
color: '#666',
|
|
561
606
|
},
|
|
607
|
+
dataContentWrapper: {
|
|
608
|
+
flex: 1,
|
|
609
|
+
},
|
|
562
610
|
dataContent: {
|
|
563
611
|
flex: 1,
|
|
564
612
|
backgroundColor: '#f8f9fa',
|
|
@@ -582,6 +630,7 @@ const styles = StyleSheet.create({
|
|
|
582
630
|
fontWeight: 'bold',
|
|
583
631
|
},
|
|
584
632
|
codeBlock: {
|
|
633
|
+
flex: 1,
|
|
585
634
|
backgroundColor: '#f8f9fa',
|
|
586
635
|
padding: 10,
|
|
587
636
|
borderRadius: 4,
|
|
@@ -662,9 +711,13 @@ const styles = StyleSheet.create({
|
|
|
662
711
|
color: '#666',
|
|
663
712
|
},
|
|
664
713
|
longTextContainer: {
|
|
665
|
-
|
|
714
|
+
flex: 1,
|
|
666
715
|
paddingHorizontal: 8,
|
|
667
716
|
paddingVertical: 5,
|
|
717
|
+
backgroundColor: '#f8f9fa',
|
|
718
|
+
},
|
|
719
|
+
longTextContent: {
|
|
720
|
+
paddingBottom: 10,
|
|
668
721
|
},
|
|
669
722
|
})
|
|
670
723
|
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
StyleSheet,
|
|
6
6
|
FlatList,
|
|
7
7
|
TouchableOpacity,
|
|
8
|
-
Modal,
|
|
9
8
|
} from 'react-native'
|
|
10
9
|
import HttpLogDetails from './HttpLogDetails'
|
|
11
10
|
|
|
@@ -76,6 +75,44 @@ const SubViewHTTPLogs = ({ logs = [] }) => {
|
|
|
76
75
|
)
|
|
77
76
|
}
|
|
78
77
|
|
|
78
|
+
// If a log is selected, show the details view with a back button
|
|
79
|
+
if (selectedLog) {
|
|
80
|
+
return (
|
|
81
|
+
<View style={styles.container}>
|
|
82
|
+
<View style={styles.detailsHeader}>
|
|
83
|
+
<TouchableOpacity
|
|
84
|
+
style={styles.backButton}
|
|
85
|
+
onPress={() => setSelectedLog(null)}>
|
|
86
|
+
<Text style={styles.backButtonText}>← Back</Text>
|
|
87
|
+
</TouchableOpacity>
|
|
88
|
+
<View style={styles.headerMethodStatus}>
|
|
89
|
+
<Text
|
|
90
|
+
style={[
|
|
91
|
+
styles.headerMethod,
|
|
92
|
+
{ color: getMethodColor(selectedLog.request?.method) },
|
|
93
|
+
]}>
|
|
94
|
+
{(selectedLog.request?.method || 'GET').toUpperCase()}
|
|
95
|
+
</Text>
|
|
96
|
+
<Text
|
|
97
|
+
style={[
|
|
98
|
+
styles.headerStatus,
|
|
99
|
+
{
|
|
100
|
+
color:
|
|
101
|
+
selectedLog.response?.status >= 400
|
|
102
|
+
? '#ff4444'
|
|
103
|
+
: '#00C851',
|
|
104
|
+
},
|
|
105
|
+
]}>
|
|
106
|
+
{selectedLog.response?.status || 'Error'}
|
|
107
|
+
</Text>
|
|
108
|
+
</View>
|
|
109
|
+
</View>
|
|
110
|
+
<HttpLogDetails log={selectedLog} />
|
|
111
|
+
</View>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Otherwise show the list view
|
|
79
116
|
return (
|
|
80
117
|
<View style={styles.container}>
|
|
81
118
|
{logs.length === 0 ? (
|
|
@@ -88,56 +125,6 @@ const SubViewHTTPLogs = ({ logs = [] }) => {
|
|
|
88
125
|
style={styles.list}
|
|
89
126
|
/>
|
|
90
127
|
)}
|
|
91
|
-
|
|
92
|
-
<Modal
|
|
93
|
-
visible={!!selectedLog}
|
|
94
|
-
animationType='slide'
|
|
95
|
-
transparent={true}
|
|
96
|
-
onRequestClose={() => setSelectedLog(null)}>
|
|
97
|
-
{selectedLog && (
|
|
98
|
-
<TouchableOpacity
|
|
99
|
-
style={styles.modalContainer}
|
|
100
|
-
activeOpacity={1}
|
|
101
|
-
onPress={() => setSelectedLog(null)}>
|
|
102
|
-
<TouchableOpacity
|
|
103
|
-
style={styles.modalContent}
|
|
104
|
-
activeOpacity={1}
|
|
105
|
-
onPress={(e) => e.stopPropagation()}>
|
|
106
|
-
<View style={styles.modalHeader}>
|
|
107
|
-
<View style={styles.modalHeaderContent}>
|
|
108
|
-
<View style={styles.modalMethodStatus}>
|
|
109
|
-
<Text
|
|
110
|
-
style={[
|
|
111
|
-
styles.modalMethod,
|
|
112
|
-
{ color: getMethodColor(selectedLog.request?.method) },
|
|
113
|
-
]}>
|
|
114
|
-
{(selectedLog.request?.method || 'GET').toUpperCase()}
|
|
115
|
-
</Text>
|
|
116
|
-
<Text
|
|
117
|
-
style={[
|
|
118
|
-
styles.modalStatus,
|
|
119
|
-
{
|
|
120
|
-
color:
|
|
121
|
-
selectedLog.response?.status >= 400
|
|
122
|
-
? '#ff4444'
|
|
123
|
-
: '#00C851',
|
|
124
|
-
},
|
|
125
|
-
]}>
|
|
126
|
-
{selectedLog.response?.status || 'Error'}
|
|
127
|
-
</Text>
|
|
128
|
-
</View>
|
|
129
|
-
</View>
|
|
130
|
-
<TouchableOpacity
|
|
131
|
-
style={styles.closeButton}
|
|
132
|
-
onPress={() => setSelectedLog(null)}>
|
|
133
|
-
<Text style={styles.closeButtonText}>×</Text>
|
|
134
|
-
</TouchableOpacity>
|
|
135
|
-
</View>
|
|
136
|
-
<HttpLogDetails log={selectedLog} />
|
|
137
|
-
</TouchableOpacity>
|
|
138
|
-
</TouchableOpacity>
|
|
139
|
-
)}
|
|
140
|
-
</Modal>
|
|
141
128
|
</View>
|
|
142
129
|
)
|
|
143
130
|
}
|
|
@@ -211,20 +198,7 @@ const styles = StyleSheet.create({
|
|
|
211
198
|
fontSize: 12,
|
|
212
199
|
marginLeft: 8,
|
|
213
200
|
},
|
|
214
|
-
|
|
215
|
-
flex: 1,
|
|
216
|
-
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
217
|
-
justifyContent: 'flex-end',
|
|
218
|
-
alignItems: 'center',
|
|
219
|
-
},
|
|
220
|
-
modalContent: {
|
|
221
|
-
width: '100%',
|
|
222
|
-
height: '90%',
|
|
223
|
-
backgroundColor: '#fff',
|
|
224
|
-
borderRadius: 10,
|
|
225
|
-
overflow: 'hidden',
|
|
226
|
-
},
|
|
227
|
-
modalHeader: {
|
|
201
|
+
detailsHeader: {
|
|
228
202
|
flexDirection: 'row',
|
|
229
203
|
alignItems: 'center',
|
|
230
204
|
padding: 15,
|
|
@@ -232,36 +206,30 @@ const styles = StyleSheet.create({
|
|
|
232
206
|
borderBottomColor: '#eee',
|
|
233
207
|
backgroundColor: '#f8f9fa',
|
|
234
208
|
},
|
|
235
|
-
|
|
236
|
-
|
|
209
|
+
backButton: {
|
|
210
|
+
paddingHorizontal: 10,
|
|
211
|
+
paddingVertical: 5,
|
|
212
|
+
borderRadius: 4,
|
|
213
|
+
backgroundColor: '#eee',
|
|
237
214
|
marginRight: 10,
|
|
238
215
|
},
|
|
239
|
-
|
|
216
|
+
backButtonText: {
|
|
217
|
+
color: '#333',
|
|
218
|
+
fontWeight: '500',
|
|
219
|
+
},
|
|
220
|
+
headerMethodStatus: {
|
|
240
221
|
flexDirection: 'row',
|
|
241
222
|
alignItems: 'center',
|
|
242
223
|
},
|
|
243
|
-
|
|
224
|
+
headerMethod: {
|
|
244
225
|
fontSize: 16,
|
|
245
226
|
fontWeight: 'bold',
|
|
246
227
|
marginRight: 10,
|
|
247
228
|
},
|
|
248
|
-
|
|
229
|
+
headerStatus: {
|
|
249
230
|
fontSize: 14,
|
|
250
231
|
fontWeight: '600',
|
|
251
232
|
},
|
|
252
|
-
closeButton: {
|
|
253
|
-
width: 30,
|
|
254
|
-
height: 30,
|
|
255
|
-
alignItems: 'center',
|
|
256
|
-
justifyContent: 'center',
|
|
257
|
-
borderRadius: 15,
|
|
258
|
-
backgroundColor: '#eee',
|
|
259
|
-
},
|
|
260
|
-
closeButtonText: {
|
|
261
|
-
fontSize: 20,
|
|
262
|
-
color: '#666',
|
|
263
|
-
lineHeight: 20,
|
|
264
|
-
},
|
|
265
233
|
})
|
|
266
234
|
|
|
267
235
|
export default SubViewHTTPLogs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-debug-toolkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A simple yet powerful debugging toolkit for React Native with a convenient floating UI for development",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"author": "zcj",
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"react-native-root-siblings": "^4.0.0"
|
|
26
|
+
"react-native-root-siblings": "^4.0.0",
|
|
27
|
+
"react-native-json-tree": "^1.5.0"
|
|
27
28
|
},
|
|
28
29
|
"peerDependencies": {
|
|
29
30
|
"react": "*",
|