react-native-inapp-inspector 2.3.11 → 2.3.13
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/HeadersSection.js +3 -2
- package/dist/commonjs/components/Inspector/BundleTab.js +4 -4
- package/dist/commonjs/components/Inspector/DebuggingTab.js +29 -16
- package/dist/commonjs/components/Inspector/NetworkDetail.js +2 -2
- package/dist/commonjs/components/Inspector/NetworkFilterModal.js +18 -12
- package/dist/commonjs/components/Inspector/StorageTab.js +10 -4
- package/dist/commonjs/components/JsonViewer.js +3 -2
- package/dist/commonjs/components/NetworkIcons.d.ts +4 -1
- package/dist/commonjs/components/NetworkIcons.js +26 -3
- package/dist/commonjs/components/QRCodeView.js +15 -12
- package/dist/commonjs/constants/telemetryConfig.d.ts +3 -3
- package/dist/commonjs/constants/telemetryConfig.js +3 -3
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/helpers/qrGenerator.js +31 -157
- package/dist/esm/components/HeadersSection.js +3 -2
- package/dist/esm/components/Inspector/BundleTab.js +5 -5
- package/dist/esm/components/Inspector/DebuggingTab.js +30 -17
- package/dist/esm/components/Inspector/NetworkDetail.js +2 -2
- package/dist/esm/components/Inspector/NetworkFilterModal.js +19 -13
- package/dist/esm/components/Inspector/StorageTab.js +11 -5
- package/dist/esm/components/JsonViewer.js +4 -3
- package/dist/esm/components/NetworkIcons.d.ts +4 -1
- package/dist/esm/components/NetworkIcons.js +22 -2
- package/dist/esm/components/QRCodeView.js +15 -12
- package/dist/esm/constants/telemetryConfig.d.ts +3 -3
- package/dist/esm/constants/telemetryConfig.js +3 -3
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/helpers/qrGenerator.js +28 -157
- package/package.json +4 -2
- package/src/components/HeadersSection.tsx +7 -2
- package/src/components/Inspector/BundleTab.tsx +9 -4
- package/src/components/Inspector/DebuggingTab.tsx +37 -17
- package/src/components/Inspector/NetworkDetail.tsx +2 -2
- package/src/components/Inspector/NetworkFilterModal.tsx +32 -12
- package/src/components/Inspector/StorageTab.tsx +15 -4
- package/src/components/JsonViewer.tsx +8 -3
- package/src/components/NetworkIcons.tsx +71 -1
- package/src/components/QRCodeView.tsx +21 -17
- package/src/constants/telemetryConfig.ts +3 -5
- package/src/constants/version.ts +1 -1
- package/src/helpers/qrGenerator.ts +34 -169
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/reports/problems/problems-report.html +0 -659
|
@@ -1,167 +1,38 @@
|
|
|
1
|
+
import qrcode from 'qrcode-generator';
|
|
1
2
|
export function generateQRMatrix(text, ecc = 'M') {
|
|
2
3
|
try {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (length > 14)
|
|
13
|
-
version = 2;
|
|
14
|
-
if (length > 26)
|
|
15
|
-
version = 3;
|
|
16
|
-
if (length > 42)
|
|
17
|
-
version = 4;
|
|
18
|
-
if (length > 62)
|
|
19
|
-
version = 5;
|
|
20
|
-
if (length > 84)
|
|
21
|
-
version = 6;
|
|
22
|
-
if (length > 106)
|
|
23
|
-
version = 7;
|
|
24
|
-
if (length > 122)
|
|
25
|
-
version = 8;
|
|
26
|
-
if (length > 152)
|
|
27
|
-
version = 9;
|
|
28
|
-
if (length > 180)
|
|
29
|
-
version = 10;
|
|
30
|
-
const size = version * 4 + 17;
|
|
31
|
-
const matrix = Array(size)
|
|
32
|
-
.fill(null)
|
|
33
|
-
.map(() => Array(size).fill(null));
|
|
34
|
-
addFinderPattern(matrix, 0, 0);
|
|
35
|
-
addFinderPattern(matrix, size - 7, 0);
|
|
36
|
-
addFinderPattern(matrix, 0, size - 7);
|
|
37
|
-
for (let i = 8; i < size - 8; i++) {
|
|
38
|
-
const val = i % 2 === 0;
|
|
39
|
-
if (matrix[6][i] === null)
|
|
40
|
-
matrix[6][i] = val;
|
|
41
|
-
if (matrix[i][6] === null)
|
|
42
|
-
matrix[i][6] = val;
|
|
43
|
-
}
|
|
44
|
-
if (version >= 2) {
|
|
45
|
-
const pos = getAlignmentPositions(version);
|
|
46
|
-
for (const r of pos) {
|
|
47
|
-
for (const c of pos) {
|
|
48
|
-
if (matrix[r][c] === null) {
|
|
49
|
-
addAlignmentPattern(matrix, r - 2, c - 2);
|
|
50
|
-
}
|
|
4
|
+
const qr = qrcode(0, ecc);
|
|
5
|
+
qr.addData(text);
|
|
6
|
+
qr.make();
|
|
7
|
+
const count = qr.getModuleCount();
|
|
8
|
+
const matrix = [];
|
|
9
|
+
for (let row = 0; row < count; row++) {
|
|
10
|
+
const rowData = [];
|
|
11
|
+
for (let col = 0; col < count; col++) {
|
|
12
|
+
rowData.push(qr.isDark(row, col));
|
|
51
13
|
}
|
|
14
|
+
matrix.push(rowData);
|
|
52
15
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
bits.push(false);
|
|
67
|
-
}
|
|
68
|
-
while (bits.length % 8 !== 0) {
|
|
69
|
-
bits.push(false);
|
|
70
|
-
}
|
|
71
|
-
const padBytes = [0xec, 0x11];
|
|
72
|
-
let padIdx = 0;
|
|
73
|
-
const totalDataBits = size * size * 0.6;
|
|
74
|
-
while (bits.length < totalDataBits) {
|
|
75
|
-
const b = padBytes[padIdx % 2];
|
|
76
|
-
padIdx++;
|
|
77
|
-
for (let bit = 7; bit >= 0; bit--) {
|
|
78
|
-
bits.push(((b >> bit) & 1) === 1);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
let bitIdx = 0;
|
|
82
|
-
let upwards = true;
|
|
83
|
-
for (let col = size - 1; col > 0; col -= 2) {
|
|
84
|
-
if (col === 6)
|
|
85
|
-
col--;
|
|
86
|
-
const rows = upwards
|
|
87
|
-
? Array.from({ length: size }, (_, i) => size - 1 - i)
|
|
88
|
-
: Array.from({ length: size }, (_, i) => i);
|
|
89
|
-
for (const row of rows) {
|
|
90
|
-
for (const c of [col, col - 1]) {
|
|
91
|
-
if (matrix[row][c] === null) {
|
|
92
|
-
const bit = bitIdx < bits.length ? bits[bitIdx++] : false;
|
|
93
|
-
const mask = (row + c) % 2 === 0;
|
|
94
|
-
matrix[row][c] = bit !== mask;
|
|
16
|
+
return matrix;
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
try {
|
|
20
|
+
const qr = qrcode(10, ecc);
|
|
21
|
+
qr.addData(text);
|
|
22
|
+
qr.make();
|
|
23
|
+
const count = qr.getModuleCount();
|
|
24
|
+
const matrix = [];
|
|
25
|
+
for (let row = 0; row < count; row++) {
|
|
26
|
+
const rowData = [];
|
|
27
|
+
for (let col = 0; col < count; col++) {
|
|
28
|
+
rowData.push(qr.isDark(row, col));
|
|
95
29
|
}
|
|
30
|
+
matrix.push(rowData);
|
|
96
31
|
}
|
|
32
|
+
return matrix;
|
|
97
33
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return matrix.map(row => row.map(cell => cell ?? false));
|
|
101
|
-
}
|
|
102
|
-
function addFinderPattern(matrix, row, col) {
|
|
103
|
-
for (let r = -1; r <= 7; r++) {
|
|
104
|
-
for (let c = -1; c <= 7; c++) {
|
|
105
|
-
const mr = row + r;
|
|
106
|
-
const mc = col + c;
|
|
107
|
-
if (mr >= 0 && mr < matrix.length && mc >= 0 && mc < matrix.length) {
|
|
108
|
-
if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||
|
|
109
|
-
(c >= 0 && c <= 6 && (r === 0 || r === 6)) ||
|
|
110
|
-
(r >= 2 && r <= 4 && c >= 2 && c <= 4)) {
|
|
111
|
-
matrix[mr][mc] = true;
|
|
112
|
-
}
|
|
113
|
-
else if (r >= 0 && r <= 6 && c >= 0 && c <= 6) {
|
|
114
|
-
matrix[mr][mc] = false;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
matrix[mr][mc] = false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
120
36
|
}
|
|
121
37
|
}
|
|
122
38
|
}
|
|
123
|
-
function addAlignmentPattern(matrix, row, col) {
|
|
124
|
-
for (let r = 0; r < 5; r++) {
|
|
125
|
-
for (let c = 0; c < 5; c++) {
|
|
126
|
-
const isOuter = r === 0 || r === 4 || c === 0 || c === 4;
|
|
127
|
-
const isCenter = r === 2 && c === 2;
|
|
128
|
-
matrix[row + r][col + c] = isOuter || isCenter;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function getAlignmentPositions(version) {
|
|
133
|
-
if (version === 1)
|
|
134
|
-
return [];
|
|
135
|
-
if (version === 2)
|
|
136
|
-
return [6, 18];
|
|
137
|
-
if (version === 3)
|
|
138
|
-
return [6, 22];
|
|
139
|
-
if (version === 4)
|
|
140
|
-
return [6, 26];
|
|
141
|
-
if (version === 5)
|
|
142
|
-
return [6, 30];
|
|
143
|
-
if (version === 6)
|
|
144
|
-
return [6, 34];
|
|
145
|
-
if (version === 7)
|
|
146
|
-
return [6, 22, 38];
|
|
147
|
-
if (version === 8)
|
|
148
|
-
return [6, 24, 42];
|
|
149
|
-
if (version === 9)
|
|
150
|
-
return [6, 26, 46];
|
|
151
|
-
return [6, 28, 50];
|
|
152
|
-
}
|
|
153
|
-
function createFallbackMatrix(text) {
|
|
154
|
-
const size = 25;
|
|
155
|
-
const matrix = Array(size)
|
|
156
|
-
.fill(false)
|
|
157
|
-
.map(() => Array(size).fill(false));
|
|
158
|
-
addFinderPattern(matrix, 0, 0);
|
|
159
|
-
addFinderPattern(matrix, size - 7, 0);
|
|
160
|
-
addFinderPattern(matrix, 0, size - 7);
|
|
161
|
-
for (let i = 0; i < text.length; i++) {
|
|
162
|
-
const r = (i * 3) % (size - 10) + 8;
|
|
163
|
-
const c = (i * 7) % (size - 10) + 8;
|
|
164
|
-
matrix[r][c] = true;
|
|
165
|
-
}
|
|
166
|
-
return matrix;
|
|
167
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.13",
|
|
4
4
|
"description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -174,6 +174,8 @@
|
|
|
174
174
|
"typescript": "5.8.3"
|
|
175
175
|
},
|
|
176
176
|
"dependencies": {
|
|
177
|
-
"@react-native-clipboard/clipboard": "1.16.3"
|
|
177
|
+
"@react-native-clipboard/clipboard": "1.16.3",
|
|
178
|
+
"@types/qrcode-generator": "^0.0.16",
|
|
179
|
+
"qrcode-generator": "^2.0.4"
|
|
178
180
|
}
|
|
179
181
|
}
|
|
@@ -79,10 +79,15 @@ const HeaderRow = React.memo(function HeaderRow({
|
|
|
79
79
|
{value}
|
|
80
80
|
</Text>
|
|
81
81
|
{isLong && (
|
|
82
|
-
<View style={styles.htExpandRow}>
|
|
82
|
+
<View style={[styles.htExpandRow, {flexDirection: 'row', alignItems: 'center', gap: 4}]}>
|
|
83
83
|
<Text style={styles.htExpandText}>
|
|
84
|
-
{expanded ? '
|
|
84
|
+
{expanded ? 'less' : 'more'}
|
|
85
85
|
</Text>
|
|
86
|
+
<ChevronIcon
|
|
87
|
+
direction={expanded ? 'up' : 'down'}
|
|
88
|
+
color={AppColors.purple}
|
|
89
|
+
size={10}
|
|
90
|
+
/>
|
|
86
91
|
</View>
|
|
87
92
|
)}
|
|
88
93
|
</Pressable>
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
AppleIcon,
|
|
49
49
|
AndroidIcon,
|
|
50
50
|
DownloadIcon,
|
|
51
|
+
ChevronIcon,
|
|
51
52
|
} from '../NetworkIcons';
|
|
52
53
|
|
|
53
54
|
import Svg, {
|
|
@@ -808,9 +809,13 @@ const BundleTreeNodeView: React.FC<{
|
|
|
808
809
|
onPress={() => toggleFolder(node.fullPath)}
|
|
809
810
|
style={[bundleStyles.treeFolderRow, {paddingLeft: indentLeft}]}>
|
|
810
811
|
<View style={bundleStyles.treeRowLeft}>
|
|
811
|
-
<
|
|
812
|
-
|
|
813
|
-
|
|
812
|
+
<View style={{marginRight: 4}}>
|
|
813
|
+
<ChevronIcon
|
|
814
|
+
direction={isCollapsed ? 'right' : 'down'}
|
|
815
|
+
size={12}
|
|
816
|
+
color={AppColors.grayTextWeak}
|
|
817
|
+
/>
|
|
818
|
+
</View>
|
|
814
819
|
{isCollapsed ? (
|
|
815
820
|
<FolderIcon color={AppColors.amber500} size={15} />
|
|
816
821
|
) : (
|
|
@@ -1465,7 +1470,7 @@ const BundleTab = React.memo(() => {
|
|
|
1465
1470
|
letterSpacing: 0.3,
|
|
1466
1471
|
textTransform: 'uppercase',
|
|
1467
1472
|
}}>
|
|
1468
|
-
Live Metro URL
|
|
1473
|
+
Live Metro URL
|
|
1469
1474
|
</Text>
|
|
1470
1475
|
</View>
|
|
1471
1476
|
<Text
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
ExternalLinkIcon,
|
|
32
32
|
RepeatIcon,
|
|
33
33
|
ShieldAlertIcon,
|
|
34
|
+
InfoCircleIcon,
|
|
34
35
|
} from '../NetworkIcons';
|
|
35
36
|
|
|
36
37
|
interface PortStatus {
|
|
@@ -137,14 +138,15 @@ export const DebuggingTab: React.FC = () => {
|
|
|
137
138
|
|
|
138
139
|
// Construct target URLs for QR codes
|
|
139
140
|
const metroBundleUrl = `http://${hostIp}:${selectedPort}/index.bundle?platform=android&dev=true`;
|
|
141
|
+
const directServerUrl = `http://${hostIp}:${selectedPort}`;
|
|
140
142
|
const apkDownloadUrl = `http://${hostIp}:${selectedPort}/${apkPath}`;
|
|
141
143
|
const devSettingsHost = `${hostIp}:${selectedPort}`;
|
|
142
144
|
|
|
143
145
|
const currentQrValue = useMemo(() => {
|
|
144
146
|
if (activeQrTab === 'apk') return apkDownloadUrl;
|
|
145
147
|
if (activeQrTab === 'host') return devSettingsHost;
|
|
146
|
-
return
|
|
147
|
-
}, [activeQrTab, apkDownloadUrl, devSettingsHost,
|
|
148
|
+
return directServerUrl;
|
|
149
|
+
}, [activeQrTab, apkDownloadUrl, devSettingsHost, directServerUrl]);
|
|
148
150
|
|
|
149
151
|
const activePortInfo = portsStatus[selectedPort];
|
|
150
152
|
|
|
@@ -179,10 +181,10 @@ export const DebuggingTab: React.FC = () => {
|
|
|
179
181
|
</View>
|
|
180
182
|
<Text style={styles.serverSubtitle}>
|
|
181
183
|
{activePortInfo?.status === 'active'
|
|
182
|
-
?
|
|
184
|
+
? `Active & Bundling (${activePortInfo.latencyMs}ms)`
|
|
183
185
|
: activePortInfo?.status === 'checking'
|
|
184
|
-
? '
|
|
185
|
-
: '
|
|
186
|
+
? 'Probing Metro Ports...'
|
|
187
|
+
: 'Standby / Select active port'}
|
|
186
188
|
</Text>
|
|
187
189
|
</View>
|
|
188
190
|
</View>
|
|
@@ -272,9 +274,12 @@ export const DebuggingTab: React.FC = () => {
|
|
|
272
274
|
/>
|
|
273
275
|
<Text style={styles.inputSuffix}>:{selectedPort}</Text>
|
|
274
276
|
</View>
|
|
275
|
-
<
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 6, marginTop: 6}}>
|
|
278
|
+
<InfoCircleIcon size={13} color={AppColors.grayTextWeak} />
|
|
279
|
+
<Text style={[styles.inputHint, {marginTop: 0, flex: 1}]}>
|
|
280
|
+
Ensure your physical Android device and Mac are connected to the same Wi-Fi network.
|
|
281
|
+
</Text>
|
|
282
|
+
</View>
|
|
278
283
|
</View>
|
|
279
284
|
|
|
280
285
|
{/* ─── Interactive QR Code Generator Card ──────────────────────── */}
|
|
@@ -352,13 +357,22 @@ export const DebuggingTab: React.FC = () => {
|
|
|
352
357
|
/>
|
|
353
358
|
|
|
354
359
|
<View style={styles.qrInfoBox}>
|
|
355
|
-
<
|
|
356
|
-
{activeQrTab === 'apk'
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 5, marginBottom: 2}}>
|
|
361
|
+
{activeQrTab === 'apk' ? (
|
|
362
|
+
<PackageIcon size={14} color={AppColors.purple} />
|
|
363
|
+
) : activeQrTab === 'host' ? (
|
|
364
|
+
<SmartphoneIcon size={14} color={AppColors.purple} />
|
|
365
|
+
) : (
|
|
366
|
+
<BoltIcon size={14} color={AppColors.amber500} />
|
|
367
|
+
)}
|
|
368
|
+
<Text style={styles.qrTargetTitle}>
|
|
369
|
+
{activeQrTab === 'apk'
|
|
370
|
+
? 'Direct APK Download URL'
|
|
371
|
+
: activeQrTab === 'host'
|
|
372
|
+
? 'Dev Settings Bundle Host'
|
|
373
|
+
: 'Live Metro Fast-Refresh Endpoint'}
|
|
374
|
+
</Text>
|
|
375
|
+
</View>
|
|
362
376
|
<Text style={styles.qrTargetUrl} numberOfLines={2} ellipsizeMode="middle">
|
|
363
377
|
{currentQrValue}
|
|
364
378
|
</Text>
|
|
@@ -388,7 +402,10 @@ export const DebuggingTab: React.FC = () => {
|
|
|
388
402
|
|
|
389
403
|
{/* ─── Bare React Native Multi-Device Setup Guide ───────────────── */}
|
|
390
404
|
<View style={styles.guideCard}>
|
|
391
|
-
<
|
|
405
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 6, marginBottom: 12}}>
|
|
406
|
+
<SmartphoneIcon size={15} color={AppColors.primaryLight} />
|
|
407
|
+
<Text style={[styles.guideHeading, {marginBottom: 0}]}>HOW TO CONNECT ANDROID DEVICE:</Text>
|
|
408
|
+
</View>
|
|
392
409
|
|
|
393
410
|
<View style={styles.stepRow}>
|
|
394
411
|
<View style={styles.stepNumberBadge}>
|
|
@@ -419,7 +436,10 @@ export const DebuggingTab: React.FC = () => {
|
|
|
419
436
|
<Text style={styles.stepNumberText}>3</Text>
|
|
420
437
|
</View>
|
|
421
438
|
<View style={{flex: 1}}>
|
|
422
|
-
<
|
|
439
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 4}}>
|
|
440
|
+
<Text style={styles.stepTitle}>Simultaneous Live Fast-Refresh</Text>
|
|
441
|
+
<BoltIcon size={13} color={AppColors.amber500} />
|
|
442
|
+
</View>
|
|
423
443
|
<Text style={styles.stepDesc}>
|
|
424
444
|
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!
|
|
425
445
|
</Text>
|
|
@@ -432,7 +432,7 @@ const NetworkDetail = React.memo(() => {
|
|
|
432
432
|
letterSpacing: 0.4,
|
|
433
433
|
textTransform: 'uppercase',
|
|
434
434
|
}}>
|
|
435
|
-
ENDPOINT URL
|
|
435
|
+
ENDPOINT URL
|
|
436
436
|
</Text>
|
|
437
437
|
</View>
|
|
438
438
|
|
|
@@ -473,7 +473,7 @@ const NetworkDetail = React.memo(() => {
|
|
|
473
473
|
fontSize: 9,
|
|
474
474
|
color: AppColors.sky600,
|
|
475
475
|
}}>
|
|
476
|
-
Open
|
|
476
|
+
Open
|
|
477
477
|
</Text>
|
|
478
478
|
</View>
|
|
479
479
|
</View>
|
|
@@ -27,6 +27,11 @@ import {
|
|
|
27
27
|
BoltIcon,
|
|
28
28
|
GlobeIcon,
|
|
29
29
|
LockIcon,
|
|
30
|
+
UnlockIcon,
|
|
31
|
+
RocketIcon,
|
|
32
|
+
TurtleIcon,
|
|
33
|
+
HourglassIcon,
|
|
34
|
+
PackageIcon,
|
|
30
35
|
} from '../NetworkIcons';
|
|
31
36
|
import TouchableScale from '../TouchableScale';
|
|
32
37
|
|
|
@@ -405,12 +410,13 @@ export const NetworkFilterModal: React.FC<NetworkFilterModalProps> = ({
|
|
|
405
410
|
<Text style={styles.sectionTitle}>LATENCY & SPEED</Text>
|
|
406
411
|
<View style={styles.chipsWrap}>
|
|
407
412
|
{[
|
|
408
|
-
{key: 'all' as const, label: 'All Speeds', color: AppColors.purple},
|
|
409
|
-
{key: 'fast' as const, label: '
|
|
410
|
-
{key: 'normal' as const, label: '
|
|
411
|
-
{key: 'slow' as const, label: '
|
|
413
|
+
{key: 'all' as const, label: 'All Speeds', color: AppColors.purple, icon: LayersIcon},
|
|
414
|
+
{key: 'fast' as const, label: 'Fast (<200ms)', color: AppColors.greenColor, icon: BoltIcon, count: counts.fastCount},
|
|
415
|
+
{key: 'normal' as const, label: 'Normal (200-500ms)', color: AppColors.skyBlue, icon: ClockIcon, count: counts.normalCount},
|
|
416
|
+
{key: 'slow' as const, label: 'Slow (>500ms)', color: AppColors.errorColor, icon: CircleAlertIcon, count: counts.slowCount},
|
|
412
417
|
].map(item => {
|
|
413
418
|
const isSelected = draft.latency === item.key;
|
|
419
|
+
const IconComp = item.icon;
|
|
414
420
|
return (
|
|
415
421
|
<TouchableOpacity
|
|
416
422
|
key={item.key}
|
|
@@ -423,6 +429,10 @@ export const NetworkFilterModal: React.FC<NetworkFilterModalProps> = ({
|
|
|
423
429
|
borderColor: item.color,
|
|
424
430
|
},
|
|
425
431
|
]}>
|
|
432
|
+
<IconComp
|
|
433
|
+
size={13}
|
|
434
|
+
color={isSelected ? item.color : AppColors.grayTextWeak}
|
|
435
|
+
/>
|
|
426
436
|
<Text
|
|
427
437
|
style={[
|
|
428
438
|
styles.chipLabel,
|
|
@@ -448,11 +458,12 @@ export const NetworkFilterModal: React.FC<NetworkFilterModalProps> = ({
|
|
|
448
458
|
<Text style={styles.sectionTitle}>PROTOCOL</Text>
|
|
449
459
|
<View style={styles.chipsWrap}>
|
|
450
460
|
{[
|
|
451
|
-
{key: 'all' as const, label: 'All Protocols', color: AppColors.purple},
|
|
452
|
-
{key: 'https' as const, label: '
|
|
453
|
-
{key: 'http' as const, label: '
|
|
461
|
+
{key: 'all' as const, label: 'All Protocols', color: AppColors.purple, icon: GlobeIcon},
|
|
462
|
+
{key: 'https' as const, label: 'HTTPS Secure', color: AppColors.mintGreenText, icon: LockIcon, count: counts.httpsCount},
|
|
463
|
+
{key: 'http' as const, label: 'HTTP Insecure', color: AppColors.amber700, icon: UnlockIcon, count: counts.httpCount},
|
|
454
464
|
].map(item => {
|
|
455
465
|
const isSelected = draft.protocol === item.key;
|
|
466
|
+
const IconComp = item.icon;
|
|
456
467
|
return (
|
|
457
468
|
<TouchableOpacity
|
|
458
469
|
key={item.key}
|
|
@@ -465,6 +476,10 @@ export const NetworkFilterModal: React.FC<NetworkFilterModalProps> = ({
|
|
|
465
476
|
borderColor: item.color,
|
|
466
477
|
},
|
|
467
478
|
]}>
|
|
479
|
+
<IconComp
|
|
480
|
+
size={13}
|
|
481
|
+
color={isSelected ? item.color : AppColors.grayTextWeak}
|
|
482
|
+
/>
|
|
468
483
|
<Text
|
|
469
484
|
style={[
|
|
470
485
|
styles.chipLabel,
|
|
@@ -490,13 +505,14 @@ export const NetworkFilterModal: React.FC<NetworkFilterModalProps> = ({
|
|
|
490
505
|
<Text style={styles.sectionTitle}>SORT BY</Text>
|
|
491
506
|
<View style={styles.chipsWrap}>
|
|
492
507
|
{[
|
|
493
|
-
{key: 'time_desc' as const, label: '
|
|
494
|
-
{key: 'time_asc' as const, label: '
|
|
495
|
-
{key: 'duration_desc' as const, label: '
|
|
496
|
-
{key: 'duration_asc' as const, label: '
|
|
497
|
-
{key: 'size_desc' as const, label: '
|
|
508
|
+
{key: 'time_desc' as const, label: 'Newest First (Default)', icon: ClockIcon},
|
|
509
|
+
{key: 'time_asc' as const, label: 'Oldest First', icon: HourglassIcon},
|
|
510
|
+
{key: 'duration_desc' as const, label: 'Slowest Response', icon: TurtleIcon},
|
|
511
|
+
{key: 'duration_asc' as const, label: 'Fastest Response', icon: RocketIcon},
|
|
512
|
+
{key: 'size_desc' as const, label: 'Largest Response Size', icon: PackageIcon},
|
|
498
513
|
].map(item => {
|
|
499
514
|
const isSelected = draft.sortBy === item.key;
|
|
515
|
+
const IconComp = item.icon;
|
|
500
516
|
return (
|
|
501
517
|
<TouchableOpacity
|
|
502
518
|
key={item.key}
|
|
@@ -509,6 +525,10 @@ export const NetworkFilterModal: React.FC<NetworkFilterModalProps> = ({
|
|
|
509
525
|
borderColor: AppColors.purple,
|
|
510
526
|
},
|
|
511
527
|
]}>
|
|
528
|
+
<IconComp
|
|
529
|
+
size={13}
|
|
530
|
+
color={isSelected ? AppColors.purple : AppColors.grayTextWeak}
|
|
531
|
+
/>
|
|
512
532
|
<Text
|
|
513
533
|
style={[
|
|
514
534
|
styles.chipLabel,
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
LayersIcon,
|
|
31
31
|
ResetIcon,
|
|
32
32
|
ChevronIcon,
|
|
33
|
+
WarningTriangleIcon,
|
|
33
34
|
} from '../NetworkIcons';
|
|
34
35
|
import {
|
|
35
36
|
fetchStorageEntries,
|
|
@@ -162,9 +163,16 @@ const StorageEntryCard = React.memo(function StorageEntryCard({
|
|
|
162
163
|
{displayValue}
|
|
163
164
|
</Text>
|
|
164
165
|
{entry.value.length > 80 && (
|
|
165
|
-
<
|
|
166
|
-
{
|
|
167
|
-
|
|
166
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 4, marginTop: 4}}>
|
|
167
|
+
<Text style={styles.expandHint}>
|
|
168
|
+
{isExpanded ? 'Collapse' : 'Expand'}
|
|
169
|
+
</Text>
|
|
170
|
+
<ChevronIcon
|
|
171
|
+
direction={isExpanded ? 'up' : 'down'}
|
|
172
|
+
size={10}
|
|
173
|
+
color={AppColors.purple}
|
|
174
|
+
/>
|
|
175
|
+
</View>
|
|
168
176
|
)}
|
|
169
177
|
</TouchableScale>
|
|
170
178
|
</View>
|
|
@@ -710,7 +718,10 @@ export const StorageTab = React.memo(() => {
|
|
|
710
718
|
autoCapitalize="none"
|
|
711
719
|
/>
|
|
712
720
|
{jsonError && (
|
|
713
|
-
<
|
|
721
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 5, marginTop: 4}}>
|
|
722
|
+
<WarningTriangleIcon size={12} color={AppColors.errorColor} />
|
|
723
|
+
<Text style={styles.errorText}>{jsonError}</Text>
|
|
724
|
+
</View>
|
|
714
725
|
)}
|
|
715
726
|
</View>
|
|
716
727
|
|
|
@@ -7,7 +7,7 @@ import TreeNode from './TreeNode';
|
|
|
7
7
|
import SegmentedTabs from './SegmentedTabs';
|
|
8
8
|
import HighlightText from './HighlightText';
|
|
9
9
|
import CopyButton from './CopyButton';
|
|
10
|
-
import {PrettyIcon, RawIcon, TableIcon} from './NetworkIcons';
|
|
10
|
+
import {PrettyIcon, RawIcon, TableIcon, ChevronIcon} from './NetworkIcons';
|
|
11
11
|
|
|
12
12
|
// Styles
|
|
13
13
|
import {AppColors} from '../styles/AppColors';
|
|
@@ -77,10 +77,15 @@ const JsonTableRow = React.memo(({
|
|
|
77
77
|
<TouchableOpacity
|
|
78
78
|
onPress={() => setExpanded(prev => !prev)}
|
|
79
79
|
hitSlop={6}
|
|
80
|
-
style={localStyles.showMoreBtn}>
|
|
80
|
+
style={[localStyles.showMoreBtn, {flexDirection: 'row', alignItems: 'center', gap: 4}]}>
|
|
81
81
|
<Text style={localStyles.showMoreText}>
|
|
82
|
-
{expanded ? 'Show less
|
|
82
|
+
{expanded ? 'Show less' : 'Show more'}
|
|
83
83
|
</Text>
|
|
84
|
+
<ChevronIcon
|
|
85
|
+
direction={expanded ? 'up' : 'down'}
|
|
86
|
+
size={10}
|
|
87
|
+
color={AppColors.purple}
|
|
88
|
+
/>
|
|
84
89
|
</TouchableOpacity>
|
|
85
90
|
)}
|
|
86
91
|
</View>
|
|
@@ -570,11 +570,16 @@ export const SortArrowIcon = ({
|
|
|
570
570
|
export const ChevronIcon = ({
|
|
571
571
|
color = AppColors.grayTextWeak,
|
|
572
572
|
size = 14,
|
|
573
|
+
direction = 'down',
|
|
573
574
|
}: IconProps) => {
|
|
575
|
+
let path = 'M6 9l6 6 6-6';
|
|
576
|
+
if (direction === 'up') path = 'M18 15l-6-6-6 6';
|
|
577
|
+
else if (direction === 'right') path = 'M9 18l6-6-6-6';
|
|
578
|
+
else if (direction === 'left') path = 'M15 18l-6-6 6-6';
|
|
574
579
|
return (
|
|
575
580
|
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
576
581
|
<Path
|
|
577
|
-
d=
|
|
582
|
+
d={path}
|
|
578
583
|
stroke={color}
|
|
579
584
|
strokeWidth="2.5"
|
|
580
585
|
strokeLinecap="round"
|
|
@@ -2285,3 +2290,68 @@ export const QrCodeIcon = ({
|
|
|
2285
2290
|
</Svg>
|
|
2286
2291
|
);
|
|
2287
2292
|
|
|
2293
|
+
export const UnlockIcon = ({
|
|
2294
|
+
color = AppColors.grayTextWeak,
|
|
2295
|
+
size = 14,
|
|
2296
|
+
}: IconProps) => (
|
|
2297
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2298
|
+
<Rect
|
|
2299
|
+
x="3"
|
|
2300
|
+
y="11"
|
|
2301
|
+
width="18"
|
|
2302
|
+
height="11"
|
|
2303
|
+
rx="2"
|
|
2304
|
+
ry="2"
|
|
2305
|
+
stroke={color}
|
|
2306
|
+
strokeWidth="2"
|
|
2307
|
+
strokeLinecap="round"
|
|
2308
|
+
strokeLinejoin="round"
|
|
2309
|
+
/>
|
|
2310
|
+
<Path
|
|
2311
|
+
d="M7 11V7a5 5 0 0 1 9.9-1"
|
|
2312
|
+
stroke={color}
|
|
2313
|
+
strokeWidth="2"
|
|
2314
|
+
strokeLinecap="round"
|
|
2315
|
+
strokeLinejoin="round"
|
|
2316
|
+
/>
|
|
2317
|
+
</Svg>
|
|
2318
|
+
);
|
|
2319
|
+
|
|
2320
|
+
export const RocketIcon = ({
|
|
2321
|
+
color = AppColors.grayTextWeak,
|
|
2322
|
+
size = 14,
|
|
2323
|
+
}: IconProps) => (
|
|
2324
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2325
|
+
<Path
|
|
2326
|
+
d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09zM12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6.05 11a22.35 22.35 0 0 1-3.95 2z"
|
|
2327
|
+
stroke={color}
|
|
2328
|
+
strokeWidth="2"
|
|
2329
|
+
strokeLinecap="round"
|
|
2330
|
+
strokeLinejoin="round"
|
|
2331
|
+
/>
|
|
2332
|
+
<Path
|
|
2333
|
+
d="M9 12l-4 4M15 6l-3 3"
|
|
2334
|
+
stroke={color}
|
|
2335
|
+
strokeWidth="2"
|
|
2336
|
+
strokeLinecap="round"
|
|
2337
|
+
strokeLinejoin="round"
|
|
2338
|
+
/>
|
|
2339
|
+
</Svg>
|
|
2340
|
+
);
|
|
2341
|
+
|
|
2342
|
+
export const TurtleIcon = ({
|
|
2343
|
+
color = AppColors.grayTextWeak,
|
|
2344
|
+
size = 14,
|
|
2345
|
+
}: IconProps) => (
|
|
2346
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2347
|
+
<Ellipse cx="12" cy="14" rx="7" ry="5" stroke={color} strokeWidth="2" />
|
|
2348
|
+
<Circle cx="12" cy="6" r="3" stroke={color} strokeWidth="2" />
|
|
2349
|
+
<Path
|
|
2350
|
+
d="M5 12l-2-2M19 12l2-2M6 18l-2 2M18 18l2 2"
|
|
2351
|
+
stroke={color}
|
|
2352
|
+
strokeWidth="2"
|
|
2353
|
+
strokeLinecap="round"
|
|
2354
|
+
/>
|
|
2355
|
+
</Svg>
|
|
2356
|
+
);
|
|
2357
|
+
|