react-native-inapp-inspector 2.3.9 → 2.3.11
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.
- package/dist/commonjs/components/Inspector/DebuggingTab.d.ts +3 -0
- package/dist/commonjs/components/Inspector/DebuggingTab.js +682 -0
- package/dist/commonjs/components/Inspector/MainScreen.js +2 -0
- package/dist/commonjs/components/Inspector/NetworkDetail.js +2 -1
- package/dist/commonjs/components/Inspector/NetworkFilterModal.d.ts +19 -0
- package/dist/commonjs/components/Inspector/NetworkFilterModal.js +648 -0
- package/dist/commonjs/components/Inspector/NetworkTab.js +89 -147
- package/dist/commonjs/components/Inspector/SettingsPanel.js +12 -0
- package/dist/commonjs/components/Inspector/TabBar.js +9 -0
- package/dist/commonjs/components/LogCard.js +5 -26
- package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
- package/dist/commonjs/components/NetworkIcons.js +13 -1
- package/dist/commonjs/components/QRCodeView.d.ts +9 -0
- package/dist/commonjs/components/QRCodeView.js +79 -0
- package/dist/commonjs/constants/index.js +3 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/helpers/qrGenerator.d.ts +2 -0
- package/dist/commonjs/helpers/qrGenerator.js +170 -0
- package/dist/commonjs/index.js +2 -0
- package/dist/commonjs/styles/index.d.ts +11 -0
- package/dist/commonjs/styles/index.js +20 -5
- package/dist/commonjs/types/enums.d.ts +5 -0
- package/dist/commonjs/types/enums.js +5 -0
- package/dist/esm/components/Inspector/DebuggingTab.d.ts +3 -0
- package/dist/esm/components/Inspector/DebuggingTab.js +642 -0
- package/dist/esm/components/Inspector/MainScreen.js +2 -0
- package/dist/esm/components/Inspector/NetworkDetail.js +2 -1
- package/dist/esm/components/Inspector/NetworkFilterModal.d.ts +19 -0
- package/dist/esm/components/Inspector/NetworkFilterModal.js +607 -0
- package/dist/esm/components/Inspector/NetworkTab.js +91 -149
- package/dist/esm/components/Inspector/SettingsPanel.js +13 -1
- package/dist/esm/components/Inspector/TabBar.js +10 -1
- package/dist/esm/components/LogCard.js +5 -26
- package/dist/esm/components/NetworkIcons.d.ts +2 -0
- package/dist/esm/components/NetworkIcons.js +10 -0
- package/dist/esm/components/QRCodeView.d.ts +9 -0
- package/dist/esm/components/QRCodeView.js +42 -0
- package/dist/esm/constants/index.js +3 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/helpers/qrGenerator.d.ts +2 -0
- package/dist/esm/helpers/qrGenerator.js +167 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/styles/index.d.ts +11 -0
- package/dist/esm/styles/index.js +20 -5
- package/dist/esm/types/enums.d.ts +5 -0
- package/dist/esm/types/enums.js +5 -0
- package/package.json +2 -2
- package/src/components/Inspector/DebuggingTab.tsx +755 -0
- package/src/components/Inspector/MainScreen.tsx +2 -0
- package/src/components/Inspector/NetworkDetail.tsx +2 -1
- package/src/components/Inspector/NetworkFilterModal.tsx +710 -0
- package/src/components/Inspector/NetworkTab.tsx +127 -204
- package/src/components/Inspector/SettingsPanel.tsx +20 -0
- package/src/components/Inspector/TabBar.tsx +11 -0
- package/src/components/LogCard.tsx +5 -30
- package/src/components/NetworkIcons.tsx +66 -0
- package/src/components/QRCodeView.tsx +71 -0
- package/src/constants/index.ts +3 -0
- package/src/constants/version.ts +1 -1
- package/src/helpers/qrGenerator.ts +184 -0
- package/src/index.tsx +2 -0
- package/src/styles/index.ts +20 -5
- package/src/types/enums.ts +5 -0
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
import React, { useState, useEffect, useMemo, useCallback } from 'react';
|
|
2
|
+
import { View, Text, ScrollView, StyleSheet, TextInput, TouchableOpacity, NativeModules, Share, } from 'react-native';
|
|
3
|
+
import { AppColors } from '../../styles/AppColors';
|
|
4
|
+
import { AppFonts } from '../../styles/AppFonts';
|
|
5
|
+
import QRCodeView from '../QRCodeView';
|
|
6
|
+
import TouchableScale from '../TouchableScale';
|
|
7
|
+
import { copyToClipboard } from '../../helpers';
|
|
8
|
+
import { showToast } from '../../helpers/toast';
|
|
9
|
+
import { useTranslation } from '../../i18n';
|
|
10
|
+
import { BoltIcon, SmartphoneIcon, PackageIcon, RepeatIcon, } from '../NetworkIcons';
|
|
11
|
+
const COMMON_PORTS = [8081, 8082, 8083, 19000];
|
|
12
|
+
export const DebuggingTab = () => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const detectedConfig = useMemo(() => {
|
|
15
|
+
const scriptURL = NativeModules.SourceCode?.scriptURL || '';
|
|
16
|
+
let host = 'localhost';
|
|
17
|
+
let port = 8081;
|
|
18
|
+
try {
|
|
19
|
+
if (scriptURL.includes('://')) {
|
|
20
|
+
const urlWithoutScheme = scriptURL.split('://')[1];
|
|
21
|
+
const hostAndPort = urlWithoutScheme.split('/')[0];
|
|
22
|
+
if (hostAndPort.includes(':')) {
|
|
23
|
+
const parts = hostAndPort.split(':');
|
|
24
|
+
host = parts[0];
|
|
25
|
+
const parsedPort = parseInt(parts[1], 10);
|
|
26
|
+
if (!isNaN(parsedPort))
|
|
27
|
+
port = parsedPort;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
host = hostAndPort;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
return { host, port, scriptURL };
|
|
36
|
+
}, []);
|
|
37
|
+
const [hostIp, setHostIp] = useState(() => {
|
|
38
|
+
if (detectedConfig.host === 'localhost' ||
|
|
39
|
+
detectedConfig.host === '127.0.0.1' ||
|
|
40
|
+
detectedConfig.host === '10.0.2.2') {
|
|
41
|
+
return '192.168.1.15';
|
|
42
|
+
}
|
|
43
|
+
return detectedConfig.host;
|
|
44
|
+
});
|
|
45
|
+
const [selectedPort, setSelectedPort] = useState(detectedConfig.port);
|
|
46
|
+
const [apkPath, setApkPath] = useState('app-debug.apk');
|
|
47
|
+
const [activeQrTab, setActiveQrTab] = useState('metro');
|
|
48
|
+
const [isAutoDetecting, setIsAutoDetecting] = useState(false);
|
|
49
|
+
const [portsStatus, setPortsStatus] = useState({});
|
|
50
|
+
const probePorts = useCallback(async () => {
|
|
51
|
+
setIsAutoDetecting(true);
|
|
52
|
+
const results = {};
|
|
53
|
+
for (const p of COMMON_PORTS) {
|
|
54
|
+
results[p] = { port: p, status: 'checking' };
|
|
55
|
+
}
|
|
56
|
+
setPortsStatus({ ...results });
|
|
57
|
+
let foundActivePort = null;
|
|
58
|
+
for (const p of COMMON_PORTS) {
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
try {
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
const timeoutId = setTimeout(() => controller.abort(), 1500);
|
|
63
|
+
const res = await fetch(`http://localhost:${p}/status`, {
|
|
64
|
+
signal: controller.signal,
|
|
65
|
+
});
|
|
66
|
+
clearTimeout(timeoutId);
|
|
67
|
+
const text = await res.text();
|
|
68
|
+
const latency = Date.now() - startTime;
|
|
69
|
+
if (res.ok && text.includes('packager-status:running')) {
|
|
70
|
+
results[p] = { port: p, status: 'active', latencyMs: latency };
|
|
71
|
+
if (!foundActivePort)
|
|
72
|
+
foundActivePort = p;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
results[p] = { port: p, status: 'inactive' };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
results[p] = { port: p, status: 'inactive' };
|
|
80
|
+
}
|
|
81
|
+
setPortsStatus({ ...results });
|
|
82
|
+
}
|
|
83
|
+
if (foundActivePort) {
|
|
84
|
+
setSelectedPort(foundActivePort);
|
|
85
|
+
showToast(`Detected Metro running on Port ${foundActivePort}!`);
|
|
86
|
+
}
|
|
87
|
+
setIsAutoDetecting(false);
|
|
88
|
+
}, []);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
probePorts();
|
|
91
|
+
}, [probePorts]);
|
|
92
|
+
const metroBundleUrl = `http://${hostIp}:${selectedPort}/index.bundle?platform=android&dev=true`;
|
|
93
|
+
const apkDownloadUrl = `http://${hostIp}:${selectedPort}/${apkPath}`;
|
|
94
|
+
const devSettingsHost = `${hostIp}:${selectedPort}`;
|
|
95
|
+
const currentQrValue = useMemo(() => {
|
|
96
|
+
if (activeQrTab === 'apk')
|
|
97
|
+
return apkDownloadUrl;
|
|
98
|
+
if (activeQrTab === 'host')
|
|
99
|
+
return devSettingsHost;
|
|
100
|
+
return metroBundleUrl;
|
|
101
|
+
}, [activeQrTab, apkDownloadUrl, devSettingsHost, metroBundleUrl]);
|
|
102
|
+
const activePortInfo = portsStatus[selectedPort];
|
|
103
|
+
return (<ScrollView style={styles.container} contentContainerStyle={styles.content} showsVerticalScrollIndicator={false}>
|
|
104
|
+
|
|
105
|
+
<View style={styles.serverCard}>
|
|
106
|
+
<View style={styles.serverCardTop}>
|
|
107
|
+
<View style={styles.serverStatusLeft}>
|
|
108
|
+
<View style={[
|
|
109
|
+
styles.statusDot,
|
|
110
|
+
{
|
|
111
|
+
backgroundColor: activePortInfo?.status === 'active'
|
|
112
|
+
? AppColors.greenColor
|
|
113
|
+
: activePortInfo?.status === 'checking'
|
|
114
|
+
? AppColors.warningIconGold
|
|
115
|
+
: AppColors.errorColor,
|
|
116
|
+
},
|
|
117
|
+
]}/>
|
|
118
|
+
<View>
|
|
119
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
120
|
+
<Text style={styles.serverTitle}>Metro Dev Server</Text>
|
|
121
|
+
<View style={styles.portPill}>
|
|
122
|
+
<Text style={styles.portPillText}>Port {selectedPort}</Text>
|
|
123
|
+
</View>
|
|
124
|
+
</View>
|
|
125
|
+
<Text style={styles.serverSubtitle}>
|
|
126
|
+
{activePortInfo?.status === 'active'
|
|
127
|
+
? `🟢 Active & Bundling (${activePortInfo.latencyMs}ms)`
|
|
128
|
+
: activePortInfo?.status === 'checking'
|
|
129
|
+
? '🟡 Probing Metro Ports...'
|
|
130
|
+
: '🔴 Standby / Select active port'}
|
|
131
|
+
</Text>
|
|
132
|
+
</View>
|
|
133
|
+
</View>
|
|
134
|
+
|
|
135
|
+
<TouchableScale onPress={probePorts} style={styles.scanBtn} hitSlop={8}>
|
|
136
|
+
<RepeatIcon size={12} color={AppColors.purple}/>
|
|
137
|
+
<Text style={styles.scanBtnText}>Re-scan</Text>
|
|
138
|
+
</TouchableScale>
|
|
139
|
+
</View>
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
<View style={styles.portsRow}>
|
|
143
|
+
{COMMON_PORTS.map(p => {
|
|
144
|
+
const isSelected = selectedPort === p;
|
|
145
|
+
const pInfo = portsStatus[p];
|
|
146
|
+
const isActive = pInfo?.status === 'active';
|
|
147
|
+
return (<TouchableOpacity key={p} activeOpacity={0.7} onPress={() => setSelectedPort(p)} style={[
|
|
148
|
+
styles.portChip,
|
|
149
|
+
isSelected && styles.portChipSelected,
|
|
150
|
+
isActive && { borderColor: AppColors.greenColor },
|
|
151
|
+
]}>
|
|
152
|
+
<View style={[
|
|
153
|
+
styles.portMiniDot,
|
|
154
|
+
{
|
|
155
|
+
backgroundColor: isActive
|
|
156
|
+
? AppColors.greenColor
|
|
157
|
+
: AppColors.grayTextWeak,
|
|
158
|
+
},
|
|
159
|
+
]}/>
|
|
160
|
+
<Text style={[
|
|
161
|
+
styles.portChipText,
|
|
162
|
+
isSelected && styles.portChipTextSelected,
|
|
163
|
+
]}>
|
|
164
|
+
{p}
|
|
165
|
+
</Text>
|
|
166
|
+
{isActive && (<View style={styles.liveBadge}>
|
|
167
|
+
<Text style={styles.liveBadgeText}>LIVE</Text>
|
|
168
|
+
</View>)}
|
|
169
|
+
</TouchableOpacity>);
|
|
170
|
+
})}
|
|
171
|
+
</View>
|
|
172
|
+
</View>
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
<View style={styles.card}>
|
|
176
|
+
<View style={styles.cardHeader}>
|
|
177
|
+
<Text style={styles.cardTitle}>HOST IP & BUNDLE LOCATION</Text>
|
|
178
|
+
<TouchableOpacity onPress={() => {
|
|
179
|
+
if (detectedConfig.host !== 'localhost' &&
|
|
180
|
+
detectedConfig.host !== '127.0.0.1' &&
|
|
181
|
+
detectedConfig.host !== '10.0.2.2') {
|
|
182
|
+
setHostIp(detectedConfig.host);
|
|
183
|
+
showToast(`Reset to detected IP: ${detectedConfig.host}`);
|
|
184
|
+
}
|
|
185
|
+
}}>
|
|
186
|
+
<Text style={styles.headerActionText}>Reset to Detected</Text>
|
|
187
|
+
</TouchableOpacity>
|
|
188
|
+
</View>
|
|
189
|
+
|
|
190
|
+
<View style={styles.inputContainer}>
|
|
191
|
+
<Text style={styles.inputPrefix}>http://</Text>
|
|
192
|
+
<TextInput style={styles.input} value={hostIp} onChangeText={setHostIp} placeholder="192.168.1.15" placeholderTextColor={AppColors.grayTextWeak} autoCapitalize="none" autoCorrect={false}/>
|
|
193
|
+
<Text style={styles.inputSuffix}>:{selectedPort}</Text>
|
|
194
|
+
</View>
|
|
195
|
+
<Text style={styles.inputHint}>
|
|
196
|
+
💡 Ensure your physical Android device and Mac are connected to the same Wi-Fi network.
|
|
197
|
+
</Text>
|
|
198
|
+
</View>
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
<View style={styles.qrCard}>
|
|
202
|
+
|
|
203
|
+
<View style={styles.qrTabsRow}>
|
|
204
|
+
<TouchableOpacity activeOpacity={0.7} onPress={() => setActiveQrTab('metro')} style={[
|
|
205
|
+
styles.qrTab,
|
|
206
|
+
activeQrTab === 'metro' && styles.qrTabActive,
|
|
207
|
+
]}>
|
|
208
|
+
<BoltIcon size={13} color={activeQrTab === 'metro' ? AppColors.white : AppColors.grayText}/>
|
|
209
|
+
<Text style={[
|
|
210
|
+
styles.qrTabText,
|
|
211
|
+
activeQrTab === 'metro' && styles.qrTabTextActive,
|
|
212
|
+
]}>
|
|
213
|
+
Metro Live Reload
|
|
214
|
+
</Text>
|
|
215
|
+
</TouchableOpacity>
|
|
216
|
+
|
|
217
|
+
<TouchableOpacity activeOpacity={0.7} onPress={() => setActiveQrTab('apk')} style={[
|
|
218
|
+
styles.qrTab,
|
|
219
|
+
activeQrTab === 'apk' && styles.qrTabActive,
|
|
220
|
+
]}>
|
|
221
|
+
<PackageIcon size={13} color={activeQrTab === 'apk' ? AppColors.white : AppColors.grayText}/>
|
|
222
|
+
<Text style={[
|
|
223
|
+
styles.qrTabText,
|
|
224
|
+
activeQrTab === 'apk' && styles.qrTabTextActive,
|
|
225
|
+
]}>
|
|
226
|
+
Install Debug APK
|
|
227
|
+
</Text>
|
|
228
|
+
</TouchableOpacity>
|
|
229
|
+
|
|
230
|
+
<TouchableOpacity activeOpacity={0.7} onPress={() => setActiveQrTab('host')} style={[
|
|
231
|
+
styles.qrTab,
|
|
232
|
+
activeQrTab === 'host' && styles.qrTabActive,
|
|
233
|
+
]}>
|
|
234
|
+
<SmartphoneIcon size={13} color={activeQrTab === 'host' ? AppColors.white : AppColors.grayText}/>
|
|
235
|
+
<Text style={[
|
|
236
|
+
styles.qrTabText,
|
|
237
|
+
activeQrTab === 'host' && styles.qrTabTextActive,
|
|
238
|
+
]}>
|
|
239
|
+
Dev Host Info
|
|
240
|
+
</Text>
|
|
241
|
+
</TouchableOpacity>
|
|
242
|
+
</View>
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
<View style={styles.qrWrapper}>
|
|
246
|
+
<QRCodeView value={currentQrValue} size={190} color={AppColors.primaryBlack} backgroundColor={AppColors.white}/>
|
|
247
|
+
|
|
248
|
+
<View style={styles.qrInfoBox}>
|
|
249
|
+
<Text style={styles.qrTargetTitle}>
|
|
250
|
+
{activeQrTab === 'apk'
|
|
251
|
+
? '📦 Direct APK Download URL'
|
|
252
|
+
: activeQrTab === 'host'
|
|
253
|
+
? '📱 Dev Settings Bundle Host'
|
|
254
|
+
: '⚡ Live Metro Fast-Refresh Endpoint'}
|
|
255
|
+
</Text>
|
|
256
|
+
<Text style={styles.qrTargetUrl} numberOfLines={2} ellipsizeMode="middle">
|
|
257
|
+
{currentQrValue}
|
|
258
|
+
</Text>
|
|
259
|
+
</View>
|
|
260
|
+
</View>
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
<View style={styles.qrActionsRow}>
|
|
264
|
+
<TouchableScale onPress={() => copyToClipboard(currentQrValue, 'QR Link')} style={styles.actionBtn}>
|
|
265
|
+
<Text style={styles.actionBtnText}>Copy Link</Text>
|
|
266
|
+
</TouchableScale>
|
|
267
|
+
|
|
268
|
+
<TouchableScale onPress={() => {
|
|
269
|
+
Share.share({
|
|
270
|
+
message: currentQrValue,
|
|
271
|
+
title: 'Metro Debug Link',
|
|
272
|
+
});
|
|
273
|
+
}} style={[styles.actionBtn, styles.actionBtnPrimary]}>
|
|
274
|
+
<Text style={styles.actionBtnPrimaryText}>Share to Device</Text>
|
|
275
|
+
</TouchableScale>
|
|
276
|
+
</View>
|
|
277
|
+
</View>
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
<View style={styles.guideCard}>
|
|
281
|
+
<Text style={styles.guideHeading}>📱 HOW TO CONNECT ANDROID DEVICE:</Text>
|
|
282
|
+
|
|
283
|
+
<View style={styles.stepRow}>
|
|
284
|
+
<View style={styles.stepNumberBadge}>
|
|
285
|
+
<Text style={styles.stepNumberText}>1</Text>
|
|
286
|
+
</View>
|
|
287
|
+
<View style={{ flex: 1 }}>
|
|
288
|
+
<Text style={styles.stepTitle}>Connect to Same Wi-Fi</Text>
|
|
289
|
+
<Text style={styles.stepDesc}>
|
|
290
|
+
Make sure your Android phone is connected to the same Wi-Fi router or Mac Mobile Hotspot.
|
|
291
|
+
</Text>
|
|
292
|
+
</View>
|
|
293
|
+
</View>
|
|
294
|
+
|
|
295
|
+
<View style={styles.stepRow}>
|
|
296
|
+
<View style={styles.stepNumberBadge}>
|
|
297
|
+
<Text style={styles.stepNumberText}>2</Text>
|
|
298
|
+
</View>
|
|
299
|
+
<View style={{ flex: 1 }}>
|
|
300
|
+
<Text style={styles.stepTitle}>Scan to Install / Connect</Text>
|
|
301
|
+
<Text style={styles.stepDesc}>
|
|
302
|
+
Open Android Camera or browser, scan the QR code above to download the APK or connect Metro.
|
|
303
|
+
</Text>
|
|
304
|
+
</View>
|
|
305
|
+
</View>
|
|
306
|
+
|
|
307
|
+
<View style={styles.stepRow}>
|
|
308
|
+
<View style={styles.stepNumberBadge}>
|
|
309
|
+
<Text style={styles.stepNumberText}>3</Text>
|
|
310
|
+
</View>
|
|
311
|
+
<View style={{ flex: 1 }}>
|
|
312
|
+
<Text style={styles.stepTitle}>Simultaneous Live Fast-Refresh ⚡</Text>
|
|
313
|
+
<Text style={styles.stepDesc}>
|
|
314
|
+
Any changes saved in VS Code will immediately update <Text style={{ fontWeight: '700' }}>both the iOS Simulator and physical Android phone</Text> in real-time!
|
|
315
|
+
</Text>
|
|
316
|
+
</View>
|
|
317
|
+
</View>
|
|
318
|
+
</View>
|
|
319
|
+
</ScrollView>);
|
|
320
|
+
};
|
|
321
|
+
const styles = StyleSheet.create({
|
|
322
|
+
container: {
|
|
323
|
+
flex: 1,
|
|
324
|
+
backgroundColor: AppColors.contentBg,
|
|
325
|
+
},
|
|
326
|
+
content: {
|
|
327
|
+
padding: 12,
|
|
328
|
+
gap: 12,
|
|
329
|
+
paddingBottom: 40,
|
|
330
|
+
},
|
|
331
|
+
serverCard: {
|
|
332
|
+
backgroundColor: AppColors.primaryLight,
|
|
333
|
+
borderRadius: 14,
|
|
334
|
+
padding: 14,
|
|
335
|
+
borderWidth: 1,
|
|
336
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
337
|
+
shadowColor: AppColors.black,
|
|
338
|
+
shadowOffset: { width: 0, height: 2 },
|
|
339
|
+
shadowOpacity: 0.05,
|
|
340
|
+
shadowRadius: 4,
|
|
341
|
+
elevation: 2,
|
|
342
|
+
gap: 12,
|
|
343
|
+
},
|
|
344
|
+
serverCardTop: {
|
|
345
|
+
flexDirection: 'row',
|
|
346
|
+
alignItems: 'center',
|
|
347
|
+
justifyContent: 'space-between',
|
|
348
|
+
},
|
|
349
|
+
serverStatusLeft: {
|
|
350
|
+
flexDirection: 'row',
|
|
351
|
+
alignItems: 'center',
|
|
352
|
+
gap: 10,
|
|
353
|
+
flex: 1,
|
|
354
|
+
},
|
|
355
|
+
statusDot: {
|
|
356
|
+
width: 12,
|
|
357
|
+
height: 12,
|
|
358
|
+
borderRadius: 6,
|
|
359
|
+
},
|
|
360
|
+
serverTitle: {
|
|
361
|
+
fontFamily: AppFonts.interBold,
|
|
362
|
+
fontSize: 15,
|
|
363
|
+
color: AppColors.primaryBlack,
|
|
364
|
+
},
|
|
365
|
+
serverSubtitle: {
|
|
366
|
+
fontFamily: AppFonts.interMedium,
|
|
367
|
+
fontSize: 11,
|
|
368
|
+
color: AppColors.grayText,
|
|
369
|
+
marginTop: 2,
|
|
370
|
+
},
|
|
371
|
+
portPill: {
|
|
372
|
+
backgroundColor: `${AppColors.purple}18`,
|
|
373
|
+
paddingHorizontal: 6,
|
|
374
|
+
paddingVertical: 2,
|
|
375
|
+
borderRadius: 6,
|
|
376
|
+
},
|
|
377
|
+
portPillText: {
|
|
378
|
+
fontFamily: AppFonts.interBold,
|
|
379
|
+
fontSize: 10,
|
|
380
|
+
color: AppColors.purple,
|
|
381
|
+
},
|
|
382
|
+
scanBtn: {
|
|
383
|
+
flexDirection: 'row',
|
|
384
|
+
alignItems: 'center',
|
|
385
|
+
gap: 4,
|
|
386
|
+
paddingHorizontal: 8,
|
|
387
|
+
paddingVertical: 4,
|
|
388
|
+
borderRadius: 6,
|
|
389
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
390
|
+
borderWidth: 1,
|
|
391
|
+
borderColor: `${AppColors.purple}30`,
|
|
392
|
+
},
|
|
393
|
+
scanBtnText: {
|
|
394
|
+
fontFamily: AppFonts.interBold,
|
|
395
|
+
fontSize: 11,
|
|
396
|
+
color: AppColors.purple,
|
|
397
|
+
},
|
|
398
|
+
portsRow: {
|
|
399
|
+
flexDirection: 'row',
|
|
400
|
+
gap: 8,
|
|
401
|
+
},
|
|
402
|
+
portChip: {
|
|
403
|
+
flex: 1,
|
|
404
|
+
flexDirection: 'row',
|
|
405
|
+
alignItems: 'center',
|
|
406
|
+
justifyContent: 'center',
|
|
407
|
+
gap: 4,
|
|
408
|
+
paddingVertical: 7,
|
|
409
|
+
borderRadius: 8,
|
|
410
|
+
backgroundColor: AppColors.grayBackground,
|
|
411
|
+
borderWidth: 1,
|
|
412
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
413
|
+
},
|
|
414
|
+
portChipSelected: {
|
|
415
|
+
backgroundColor: `${AppColors.purple}18`,
|
|
416
|
+
borderColor: AppColors.purple,
|
|
417
|
+
},
|
|
418
|
+
portMiniDot: {
|
|
419
|
+
width: 5,
|
|
420
|
+
height: 5,
|
|
421
|
+
borderRadius: 2.5,
|
|
422
|
+
},
|
|
423
|
+
portChipText: {
|
|
424
|
+
fontFamily: AppFonts.interBold,
|
|
425
|
+
fontSize: 11,
|
|
426
|
+
color: AppColors.grayTextStrong,
|
|
427
|
+
},
|
|
428
|
+
portChipTextSelected: {
|
|
429
|
+
color: AppColors.purple,
|
|
430
|
+
},
|
|
431
|
+
liveBadge: {
|
|
432
|
+
backgroundColor: AppColors.greenColor,
|
|
433
|
+
paddingHorizontal: 3,
|
|
434
|
+
paddingVertical: 0.5,
|
|
435
|
+
borderRadius: 3,
|
|
436
|
+
},
|
|
437
|
+
liveBadgeText: {
|
|
438
|
+
fontFamily: AppFonts.interBold,
|
|
439
|
+
fontSize: 7.5,
|
|
440
|
+
color: AppColors.white,
|
|
441
|
+
},
|
|
442
|
+
card: {
|
|
443
|
+
backgroundColor: AppColors.primaryLight,
|
|
444
|
+
borderRadius: 14,
|
|
445
|
+
padding: 14,
|
|
446
|
+
borderWidth: 1,
|
|
447
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
448
|
+
shadowColor: AppColors.black,
|
|
449
|
+
shadowOffset: { width: 0, height: 2 },
|
|
450
|
+
shadowOpacity: 0.05,
|
|
451
|
+
shadowRadius: 4,
|
|
452
|
+
elevation: 2,
|
|
453
|
+
gap: 8,
|
|
454
|
+
},
|
|
455
|
+
cardHeader: {
|
|
456
|
+
flexDirection: 'row',
|
|
457
|
+
alignItems: 'center',
|
|
458
|
+
justifyContent: 'space-between',
|
|
459
|
+
},
|
|
460
|
+
cardTitle: {
|
|
461
|
+
fontFamily: AppFonts.interBold,
|
|
462
|
+
fontSize: 11,
|
|
463
|
+
color: AppColors.grayTextWeak,
|
|
464
|
+
letterSpacing: 0.6,
|
|
465
|
+
},
|
|
466
|
+
headerActionText: {
|
|
467
|
+
fontFamily: AppFonts.interBold,
|
|
468
|
+
fontSize: 11,
|
|
469
|
+
color: AppColors.purple,
|
|
470
|
+
},
|
|
471
|
+
inputContainer: {
|
|
472
|
+
flexDirection: 'row',
|
|
473
|
+
alignItems: 'center',
|
|
474
|
+
backgroundColor: AppColors.grayBackground,
|
|
475
|
+
borderRadius: 10,
|
|
476
|
+
borderWidth: 1,
|
|
477
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
478
|
+
paddingHorizontal: 10,
|
|
479
|
+
height: 40,
|
|
480
|
+
},
|
|
481
|
+
inputPrefix: {
|
|
482
|
+
fontFamily: AppFonts.interMedium,
|
|
483
|
+
fontSize: 12.5,
|
|
484
|
+
color: AppColors.grayTextWeak,
|
|
485
|
+
},
|
|
486
|
+
input: {
|
|
487
|
+
flex: 1,
|
|
488
|
+
fontFamily: AppFonts.interBold,
|
|
489
|
+
fontSize: 13,
|
|
490
|
+
color: AppColors.primaryBlack,
|
|
491
|
+
paddingVertical: 0,
|
|
492
|
+
},
|
|
493
|
+
inputSuffix: {
|
|
494
|
+
fontFamily: AppFonts.interBold,
|
|
495
|
+
fontSize: 12.5,
|
|
496
|
+
color: AppColors.purple,
|
|
497
|
+
},
|
|
498
|
+
inputHint: {
|
|
499
|
+
fontFamily: AppFonts.interRegular,
|
|
500
|
+
fontSize: 11,
|
|
501
|
+
color: AppColors.grayTextWeak,
|
|
502
|
+
lineHeight: 15,
|
|
503
|
+
},
|
|
504
|
+
qrCard: {
|
|
505
|
+
backgroundColor: AppColors.primaryLight,
|
|
506
|
+
borderRadius: 14,
|
|
507
|
+
padding: 14,
|
|
508
|
+
borderWidth: 1,
|
|
509
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
510
|
+
shadowColor: AppColors.black,
|
|
511
|
+
shadowOffset: { width: 0, height: 2 },
|
|
512
|
+
shadowOpacity: 0.05,
|
|
513
|
+
shadowRadius: 4,
|
|
514
|
+
elevation: 2,
|
|
515
|
+
alignItems: 'center',
|
|
516
|
+
gap: 14,
|
|
517
|
+
},
|
|
518
|
+
qrTabsRow: {
|
|
519
|
+
flexDirection: 'row',
|
|
520
|
+
backgroundColor: AppColors.grayBackground,
|
|
521
|
+
borderRadius: 10,
|
|
522
|
+
padding: 3,
|
|
523
|
+
width: '100%',
|
|
524
|
+
gap: 4,
|
|
525
|
+
},
|
|
526
|
+
qrTab: {
|
|
527
|
+
flex: 1,
|
|
528
|
+
flexDirection: 'row',
|
|
529
|
+
alignItems: 'center',
|
|
530
|
+
justifyContent: 'center',
|
|
531
|
+
gap: 4,
|
|
532
|
+
paddingVertical: 7,
|
|
533
|
+
borderRadius: 8,
|
|
534
|
+
},
|
|
535
|
+
qrTabActive: {
|
|
536
|
+
backgroundColor: AppColors.purple,
|
|
537
|
+
},
|
|
538
|
+
qrTabText: {
|
|
539
|
+
fontFamily: AppFonts.interMedium,
|
|
540
|
+
fontSize: 11,
|
|
541
|
+
color: AppColors.grayText,
|
|
542
|
+
},
|
|
543
|
+
qrTabTextActive: {
|
|
544
|
+
color: AppColors.white,
|
|
545
|
+
fontFamily: AppFonts.interBold,
|
|
546
|
+
},
|
|
547
|
+
qrWrapper: {
|
|
548
|
+
alignItems: 'center',
|
|
549
|
+
gap: 12,
|
|
550
|
+
},
|
|
551
|
+
qrInfoBox: {
|
|
552
|
+
alignItems: 'center',
|
|
553
|
+
maxWidth: 280,
|
|
554
|
+
gap: 2,
|
|
555
|
+
},
|
|
556
|
+
qrTargetTitle: {
|
|
557
|
+
fontFamily: AppFonts.interBold,
|
|
558
|
+
fontSize: 11.5,
|
|
559
|
+
color: AppColors.primaryBlack,
|
|
560
|
+
},
|
|
561
|
+
qrTargetUrl: {
|
|
562
|
+
fontFamily: AppFonts.interRegular,
|
|
563
|
+
fontSize: 10.5,
|
|
564
|
+
color: AppColors.skyBlue,
|
|
565
|
+
textAlign: 'center',
|
|
566
|
+
},
|
|
567
|
+
qrActionsRow: {
|
|
568
|
+
flexDirection: 'row',
|
|
569
|
+
gap: 10,
|
|
570
|
+
width: '100%',
|
|
571
|
+
},
|
|
572
|
+
actionBtn: {
|
|
573
|
+
flex: 1,
|
|
574
|
+
paddingVertical: 10,
|
|
575
|
+
borderRadius: 10,
|
|
576
|
+
borderWidth: 1,
|
|
577
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
578
|
+
backgroundColor: AppColors.grayBackground,
|
|
579
|
+
alignItems: 'center',
|
|
580
|
+
justifyContent: 'center',
|
|
581
|
+
},
|
|
582
|
+
actionBtnText: {
|
|
583
|
+
fontFamily: AppFonts.interBold,
|
|
584
|
+
fontSize: 12,
|
|
585
|
+
color: AppColors.grayTextStrong,
|
|
586
|
+
},
|
|
587
|
+
actionBtnPrimary: {
|
|
588
|
+
backgroundColor: AppColors.purple,
|
|
589
|
+
borderColor: AppColors.purple,
|
|
590
|
+
},
|
|
591
|
+
actionBtnPrimaryText: {
|
|
592
|
+
fontFamily: AppFonts.interBold,
|
|
593
|
+
fontSize: 12,
|
|
594
|
+
color: AppColors.white,
|
|
595
|
+
},
|
|
596
|
+
guideCard: {
|
|
597
|
+
backgroundColor: AppColors.primaryLight,
|
|
598
|
+
borderRadius: 14,
|
|
599
|
+
padding: 14,
|
|
600
|
+
borderWidth: 1,
|
|
601
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
602
|
+
gap: 10,
|
|
603
|
+
},
|
|
604
|
+
guideHeading: {
|
|
605
|
+
fontFamily: AppFonts.interBold,
|
|
606
|
+
fontSize: 11,
|
|
607
|
+
color: AppColors.grayTextWeak,
|
|
608
|
+
letterSpacing: 0.6,
|
|
609
|
+
},
|
|
610
|
+
stepRow: {
|
|
611
|
+
flexDirection: 'row',
|
|
612
|
+
alignItems: 'flex-start',
|
|
613
|
+
gap: 10,
|
|
614
|
+
},
|
|
615
|
+
stepNumberBadge: {
|
|
616
|
+
width: 22,
|
|
617
|
+
height: 22,
|
|
618
|
+
borderRadius: 11,
|
|
619
|
+
backgroundColor: `${AppColors.purple}18`,
|
|
620
|
+
alignItems: 'center',
|
|
621
|
+
justifyContent: 'center',
|
|
622
|
+
marginTop: 1,
|
|
623
|
+
},
|
|
624
|
+
stepNumberText: {
|
|
625
|
+
fontFamily: AppFonts.interBold,
|
|
626
|
+
fontSize: 11,
|
|
627
|
+
color: AppColors.purple,
|
|
628
|
+
},
|
|
629
|
+
stepTitle: {
|
|
630
|
+
fontFamily: AppFonts.interBold,
|
|
631
|
+
fontSize: 12.5,
|
|
632
|
+
color: AppColors.primaryBlack,
|
|
633
|
+
},
|
|
634
|
+
stepDesc: {
|
|
635
|
+
fontFamily: AppFonts.interRegular,
|
|
636
|
+
fontSize: 11,
|
|
637
|
+
color: AppColors.grayText,
|
|
638
|
+
lineHeight: 16,
|
|
639
|
+
marginTop: 1,
|
|
640
|
+
},
|
|
641
|
+
});
|
|
642
|
+
export default DebuggingTab;
|
|
@@ -19,6 +19,7 @@ import CrashTab from './CrashTab';
|
|
|
19
19
|
import CrashDetail from './CrashDetail';
|
|
20
20
|
import DeviceInfoTab from './DeviceInfoTab';
|
|
21
21
|
import StorageTab from './StorageTab';
|
|
22
|
+
import DebuggingTab from './DebuggingTab';
|
|
22
23
|
import SettingsPanel from './SettingsPanel';
|
|
23
24
|
import NpmUpdateToast from './NpmUpdateToast';
|
|
24
25
|
import Toast from '../Toast';
|
|
@@ -118,6 +119,7 @@ const MainScreen = () => {
|
|
|
118
119
|
{activeTab === 'crash' && <CrashTab />}
|
|
119
120
|
{activeTab === 'device' && <DeviceInfoTab />}
|
|
120
121
|
{activeTab === 'storage' && <StorageTab />}
|
|
122
|
+
{activeTab === 'debugging' && <DebuggingTab />}
|
|
121
123
|
</Animated.View>
|
|
122
124
|
|
|
123
125
|
|
|
@@ -44,7 +44,7 @@ const NetworkDetail = React.memo(() => {
|
|
|
44
44
|
return null;
|
|
45
45
|
return (<View style={{ flex: 1 }}>
|
|
46
46
|
|
|
47
|
-
<View style={{ paddingHorizontal:
|
|
47
|
+
<View style={{ paddingHorizontal: 8, paddingTop: 4 }}>
|
|
48
48
|
<View style={styles.detailInfoBar}>
|
|
49
49
|
{(() => {
|
|
50
50
|
let schemeStr = '';
|
|
@@ -94,6 +94,7 @@ const NetworkDetail = React.memo(() => {
|
|
|
94
94
|
gap: 6,
|
|
95
95
|
flexWrap: 'wrap',
|
|
96
96
|
flex: 1,
|
|
97
|
+
minWidth: 0,
|
|
97
98
|
}}>
|
|
98
99
|
|
|
99
100
|
<View style={[
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface NetworkFilterState {
|
|
3
|
+
statusCodes: Set<string>;
|
|
4
|
+
methods: Set<string>;
|
|
5
|
+
latency: 'all' | 'fast' | 'normal' | 'slow';
|
|
6
|
+
protocol: 'all' | 'https' | 'http';
|
|
7
|
+
sortBy: 'time_desc' | 'time_asc' | 'duration_desc' | 'duration_asc' | 'size_desc';
|
|
8
|
+
}
|
|
9
|
+
export declare const DEFAULT_NETWORK_FILTERS: NetworkFilterState;
|
|
10
|
+
export declare const isNetworkFiltersDefault: (f: NetworkFilterState) => boolean;
|
|
11
|
+
interface NetworkFilterModalProps {
|
|
12
|
+
visible: boolean;
|
|
13
|
+
onClose: () => void;
|
|
14
|
+
filters: NetworkFilterState;
|
|
15
|
+
onApply: (filters: NetworkFilterState) => void;
|
|
16
|
+
searchQuery?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const NetworkFilterModal: React.FC<NetworkFilterModalProps>;
|
|
19
|
+
export default NetworkFilterModal;
|