react-native-inapp-inspector 2.0.5 → 2.0.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.
Files changed (77) hide show
  1. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +11 -0
  2. package/dist/commonjs/components/Inspector/AuditTab.d.ts +3 -0
  3. package/dist/commonjs/components/Inspector/AuditTab.js +741 -0
  4. package/dist/commonjs/components/Inspector/DeviceTab.d.ts +3 -0
  5. package/dist/commonjs/components/Inspector/DeviceTab.js +717 -0
  6. package/dist/commonjs/components/Inspector/InspectorHeader.js +28 -25
  7. package/dist/commonjs/components/Inspector/MainScreen.js +15 -2
  8. package/dist/commonjs/components/Inspector/NetworkDetail.js +15 -0
  9. package/dist/commonjs/components/Inspector/PerformanceHud.d.ts +7 -0
  10. package/dist/commonjs/components/Inspector/PerformanceHud.js +210 -0
  11. package/dist/commonjs/components/Inspector/PerformanceTab.js +30 -18
  12. package/dist/commonjs/components/Inspector/RequestReplayModal.d.ts +9 -0
  13. package/dist/commonjs/components/Inspector/RequestReplayModal.js +792 -0
  14. package/dist/commonjs/components/Inspector/RequestReplayView.d.ts +8 -0
  15. package/dist/commonjs/components/Inspector/RequestReplayView.js +871 -0
  16. package/dist/commonjs/components/Inspector/SettingsPanel.js +326 -15
  17. package/dist/commonjs/components/Inspector/StorageTab.d.ts +3 -0
  18. package/dist/commonjs/components/Inspector/StorageTab.js +610 -0
  19. package/dist/commonjs/components/Inspector/TabBar.js +23 -2
  20. package/dist/commonjs/components/NetworkIcons.d.ts +12 -0
  21. package/dist/commonjs/components/NetworkIcons.js +72 -3
  22. package/dist/commonjs/constants/version.d.ts +1 -1
  23. package/dist/commonjs/constants/version.js +1 -1
  24. package/dist/commonjs/customHooks/storageInspector.d.ts +13 -0
  25. package/dist/commonjs/customHooks/storageInspector.js +179 -0
  26. package/dist/commonjs/helpers/deviceInfo.d.ts +4 -0
  27. package/dist/commonjs/helpers/deviceInfo.js +94 -0
  28. package/dist/commonjs/helpers/index.d.ts +2 -0
  29. package/dist/commonjs/helpers/index.js +12 -1
  30. package/dist/commonjs/helpers/packageAuditor.d.ts +5 -0
  31. package/dist/commonjs/helpers/packageAuditor.js +182 -0
  32. package/dist/commonjs/i18n/locales/en.json +3 -2
  33. package/dist/commonjs/index.d.ts +1 -0
  34. package/dist/commonjs/index.js +113 -9
  35. package/dist/commonjs/native/NativeInspector.d.ts +1 -0
  36. package/dist/commonjs/types/enums.d.ts +7 -0
  37. package/dist/commonjs/types/enums.js +7 -0
  38. package/dist/commonjs/types/interfaces.d.ts +73 -0
  39. package/dist/esm/components/Inspector/AuditTab.d.ts +3 -0
  40. package/dist/esm/components/Inspector/AuditTab.js +702 -0
  41. package/dist/esm/components/Inspector/DeviceTab.d.ts +3 -0
  42. package/dist/esm/components/Inspector/DeviceTab.js +678 -0
  43. package/dist/esm/components/Inspector/InspectorHeader.js +28 -25
  44. package/dist/esm/components/Inspector/MainScreen.js +15 -2
  45. package/dist/esm/components/Inspector/NetworkDetail.js +16 -1
  46. package/dist/esm/components/Inspector/PerformanceHud.d.ts +7 -0
  47. package/dist/esm/components/Inspector/PerformanceHud.js +170 -0
  48. package/dist/esm/components/Inspector/PerformanceTab.js +31 -19
  49. package/dist/esm/components/Inspector/RequestReplayModal.d.ts +9 -0
  50. package/dist/esm/components/Inspector/RequestReplayModal.js +752 -0
  51. package/dist/esm/components/Inspector/RequestReplayView.d.ts +8 -0
  52. package/dist/esm/components/Inspector/RequestReplayView.js +831 -0
  53. package/dist/esm/components/Inspector/SettingsPanel.js +327 -16
  54. package/dist/esm/components/Inspector/StorageTab.d.ts +3 -0
  55. package/dist/esm/components/Inspector/StorageTab.js +571 -0
  56. package/dist/esm/components/Inspector/TabBar.js +24 -3
  57. package/dist/esm/components/NetworkIcons.d.ts +12 -0
  58. package/dist/esm/components/NetworkIcons.js +57 -0
  59. package/dist/esm/constants/version.d.ts +1 -1
  60. package/dist/esm/constants/version.js +1 -1
  61. package/dist/esm/customHooks/storageInspector.d.ts +13 -0
  62. package/dist/esm/customHooks/storageInspector.js +170 -0
  63. package/dist/esm/helpers/deviceInfo.d.ts +4 -0
  64. package/dist/esm/helpers/deviceInfo.js +89 -0
  65. package/dist/esm/helpers/index.d.ts +2 -0
  66. package/dist/esm/helpers/index.js +10 -0
  67. package/dist/esm/helpers/packageAuditor.d.ts +5 -0
  68. package/dist/esm/helpers/packageAuditor.js +173 -0
  69. package/dist/esm/i18n/locales/en.json +3 -2
  70. package/dist/esm/index.d.ts +1 -0
  71. package/dist/esm/index.js +109 -8
  72. package/dist/esm/native/NativeInspector.d.ts +1 -0
  73. package/dist/esm/types/enums.d.ts +7 -0
  74. package/dist/esm/types/enums.js +7 -0
  75. package/dist/esm/types/interfaces.d.ts +73 -0
  76. package/ios/NetworkInspectorModule.mm +12 -5
  77. package/package.json +4 -1
@@ -0,0 +1,752 @@
1
+ import React, { useState } from 'react';
2
+ import { ActivityIndicator, Alert, Platform, ScrollView, StyleSheet, Text, TextInput, View, } from 'react-native';
3
+ import TouchableScale from '../TouchableScale';
4
+ import CopyButton from '../CopyButton';
5
+ import JsonViewer from '../JsonViewer';
6
+ import { AppColors } from '../../styles/AppColors';
7
+ import { AppFonts } from '../../styles/AppFonts';
8
+ import { METHOD_COLORS } from '../../constants';
9
+ import { getStatusColor, getSize } from '../../helpers';
10
+ import { showToast } from '../../helpers/toast';
11
+ import { ClearIcon, CloseWhite, HeadersIcon, RequestIcon, ResponseIcon, TerminalIcon, } from '../NetworkIcons';
12
+ const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
13
+ export const RequestReplayModal = ({ visible, onClose, request, }) => {
14
+ const [method, setMethod] = useState(request.method?.toUpperCase() || 'GET');
15
+ const [url, setUrl] = useState(request.url || '');
16
+ const [activeTab, setActiveTab] = useState('headers');
17
+ // Initialize headers list from request
18
+ const [headers, setHeaders] = useState(() => {
19
+ const rawHeaders = request.requestHeaders || request.headers || {};
20
+ const list = [];
21
+ Object.entries(rawHeaders).forEach(([k, v], idx) => {
22
+ list.push({
23
+ id: `h-${idx}-${Date.now()}`,
24
+ key: k,
25
+ value: typeof v === 'string' ? v : JSON.stringify(v),
26
+ enabled: true,
27
+ });
28
+ });
29
+ if (list.length === 0) {
30
+ list.push({
31
+ id: `h-init-1`,
32
+ key: 'Content-Type',
33
+ value: 'application/json',
34
+ enabled: true,
35
+ });
36
+ }
37
+ return list;
38
+ });
39
+ // Request Body
40
+ const [requestBody, setRequestBody] = useState(() => {
41
+ const raw = request.request ?? request.requestBody;
42
+ if (raw == null)
43
+ return '';
44
+ if (typeof raw === 'string') {
45
+ try {
46
+ return JSON.stringify(JSON.parse(raw), null, 2);
47
+ }
48
+ catch {
49
+ return raw;
50
+ }
51
+ }
52
+ try {
53
+ return JSON.stringify(raw, null, 2);
54
+ }
55
+ catch {
56
+ return String(raw);
57
+ }
58
+ });
59
+ const [isExecuting, setIsExecuting] = useState(false);
60
+ const [executionResult, setExecutionResult] = useState(null);
61
+ const [responseSearch, setResponseSearch] = useState('');
62
+ const handleAddHeader = () => {
63
+ setHeaders(prev => [
64
+ ...prev,
65
+ {
66
+ id: `h-${Date.now()}-${Math.random().toString(36).substring(2, 6)}`,
67
+ key: '',
68
+ value: '',
69
+ enabled: true,
70
+ },
71
+ ]);
72
+ };
73
+ const handleToggleHeader = (id) => {
74
+ setHeaders(prev => prev.map(h => (h.id === id ? { ...h, enabled: !h.enabled } : h)));
75
+ };
76
+ const handleUpdateHeader = (id, field, val) => {
77
+ setHeaders(prev => prev.map(h => (h.id === id ? { ...h, [field]: val } : h)));
78
+ };
79
+ const handleDeleteHeader = (id) => {
80
+ setHeaders(prev => prev.filter(h => h.id !== id));
81
+ };
82
+ const handlePrettifyBody = () => {
83
+ if (!requestBody.trim())
84
+ return;
85
+ try {
86
+ const parsed = JSON.parse(requestBody);
87
+ setRequestBody(JSON.stringify(parsed, null, 2));
88
+ showToast('JSON formatted');
89
+ }
90
+ catch (e) {
91
+ Alert.alert('JSON Parse Error', e.message || 'Invalid JSON syntax');
92
+ }
93
+ };
94
+ const handleExecute = async () => {
95
+ if (!url.trim()) {
96
+ Alert.alert('Missing URL', 'Please enter a valid request URL.');
97
+ return;
98
+ }
99
+ setIsExecuting(true);
100
+ const startTime = Date.now();
101
+ const assembledHeaders = {};
102
+ headers.forEach(h => {
103
+ if (h.enabled && h.key.trim()) {
104
+ assembledHeaders[h.key.trim()] = h.value;
105
+ }
106
+ });
107
+ try {
108
+ const options = {
109
+ method,
110
+ headers: assembledHeaders,
111
+ };
112
+ if (method !== 'GET' &&
113
+ requestBody.trim().length > 0) {
114
+ options.body = requestBody;
115
+ }
116
+ const res = await fetch(url.trim(), options);
117
+ const duration = Date.now() - startTime;
118
+ const resHeaders = {};
119
+ res.headers.forEach((val, key) => {
120
+ resHeaders[key] = val;
121
+ });
122
+ const rawText = await res.text();
123
+ const sizeBytes = new Blob([rawText]).size || rawText.length;
124
+ setExecutionResult({
125
+ status: res.status,
126
+ statusText: res.statusText || (res.status === 200 ? 'OK' : ''),
127
+ duration,
128
+ headers: resHeaders,
129
+ body: rawText,
130
+ sizeBytes,
131
+ isError: res.status >= 400 || res.status === 0,
132
+ });
133
+ setActiveTab('response');
134
+ showToast(`Finished: ${res.status} in ${duration}ms`);
135
+ }
136
+ catch (err) {
137
+ const duration = Date.now() - startTime;
138
+ setExecutionResult({
139
+ status: 0,
140
+ statusText: err.message || 'Network Request Failed',
141
+ duration,
142
+ headers: {},
143
+ body: JSON.stringify({
144
+ error: true,
145
+ name: err.name || 'FetchError',
146
+ message: err.message || 'Network Request Failed',
147
+ timestamp: new Date().toISOString(),
148
+ }, null, 2),
149
+ sizeBytes: 0,
150
+ isError: true,
151
+ });
152
+ setActiveTab('response');
153
+ showToast('Network error during replay');
154
+ }
155
+ finally {
156
+ setIsExecuting(false);
157
+ }
158
+ };
159
+ if (!visible)
160
+ return null;
161
+ return (<View style={styles.backdrop}>
162
+ <View style={styles.modalCard}>
163
+ {/* ─── 1. MODAL HEADER ────────────────────────────────────────── */}
164
+ <View style={styles.headerRow}>
165
+ <View style={styles.headerTitleBox}>
166
+ <View style={styles.headerTag}>
167
+ <Text style={styles.headerTagText}>ISOLATED API REPLAY</Text>
168
+ </View>
169
+ <Text style={styles.headerTitle} numberOfLines={1}>
170
+ Edit & Resend Request
171
+ </Text>
172
+ </View>
173
+
174
+ <TouchableScale onPress={onClose} style={styles.closeBtn}>
175
+ <CloseWhite size={14} color={AppColors.grayText}/>
176
+ </TouchableScale>
177
+ </View>
178
+
179
+ {/* ─── 2. METHOD & URL BAR ────────────────────────────────────── */}
180
+ <View style={styles.urlSection}>
181
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.methodList}>
182
+ {HTTP_METHODS.map(m => {
183
+ const isSelected = method === m;
184
+ const mColor = METHOD_COLORS[m] || AppColors.purple;
185
+ return (<TouchableScale key={m} onPress={() => setMethod(m)} style={[
186
+ styles.methodPill,
187
+ isSelected && {
188
+ backgroundColor: mColor,
189
+ borderColor: mColor,
190
+ },
191
+ ]}>
192
+ <Text style={[
193
+ styles.methodPillText,
194
+ isSelected && { color: AppColors.white },
195
+ ]}>
196
+ {m}
197
+ </Text>
198
+ </TouchableScale>);
199
+ })}
200
+ </ScrollView>
201
+
202
+ <View style={styles.urlInputRow}>
203
+ <TextInput style={styles.urlInput} value={url} onChangeText={setUrl} placeholder="https://api.example.com/endpoint..." placeholderTextColor={AppColors.grayTextWeak} autoCapitalize="none" autoCorrect={false} multiline={false}/>
204
+ {url.length > 0 && (<TouchableScale onPress={() => setUrl('')} style={styles.urlClearBtn}>
205
+ <ClearIcon size={13} color={AppColors.grayTextWeak}/>
206
+ </TouchableScale>)}
207
+ </View>
208
+ </View>
209
+
210
+ {/* ─── 3. TAB CONTROLS ────────────────────────────────────────── */}
211
+ <View style={styles.tabBar}>
212
+ <TouchableScale onPress={() => setActiveTab('headers')} style={[
213
+ styles.tabBtn,
214
+ activeTab === 'headers' && styles.tabBtnActive,
215
+ ]}>
216
+ <HeadersIcon size={12} color={activeTab === 'headers'
217
+ ? AppColors.purple
218
+ : AppColors.grayTextWeak}/>
219
+ <Text style={[
220
+ styles.tabBtnText,
221
+ activeTab === 'headers' && styles.tabBtnTextActive,
222
+ ]}>
223
+ Headers ({headers.filter(h => h.enabled && h.key.trim()).length}
224
+ )
225
+ </Text>
226
+ </TouchableScale>
227
+
228
+ {method !== 'GET' && (<TouchableScale onPress={() => setActiveTab('body')} style={[
229
+ styles.tabBtn,
230
+ activeTab === 'body' && styles.tabBtnActive,
231
+ ]}>
232
+ <RequestIcon size={12} color={activeTab === 'body'
233
+ ? AppColors.purple
234
+ : AppColors.grayTextWeak}/>
235
+ <Text style={[
236
+ styles.tabBtnText,
237
+ activeTab === 'body' && styles.tabBtnTextActive,
238
+ ]}>
239
+ Body {requestBody.trim() ? '●' : ''}
240
+ </Text>
241
+ </TouchableScale>)}
242
+
243
+ <TouchableScale onPress={() => setActiveTab('response')} style={[
244
+ styles.tabBtn,
245
+ activeTab === 'response' && styles.tabBtnActive,
246
+ ]}>
247
+ <ResponseIcon size={12} color={activeTab === 'response'
248
+ ? AppColors.purple
249
+ : AppColors.grayTextWeak}/>
250
+ <Text style={[
251
+ styles.tabBtnText,
252
+ activeTab === 'response' && styles.tabBtnTextActive,
253
+ ]}>
254
+ Response{' '}
255
+ {executionResult
256
+ ? `(${executionResult.status})`
257
+ : isExecuting
258
+ ? '...'
259
+ : ''}
260
+ </Text>
261
+ </TouchableScale>
262
+ </View>
263
+
264
+ {/* ─── 4. TAB BODY CONTENT ────────────────────────────────────── */}
265
+ <ScrollView style={styles.contentScroll} contentContainerStyle={styles.contentInner} keyboardShouldPersistTaps="handled">
266
+ {/* ── HEADERS TAB ── */}
267
+ {activeTab === 'headers' && (<View style={styles.headersContainer}>
268
+ <View style={styles.headersHeaderRow}>
269
+ <Text style={styles.sectionHeading}>HTTP HEADERS</Text>
270
+ <TouchableScale onPress={handleAddHeader} style={styles.addHeaderBtn}>
271
+ <Text style={styles.addHeaderBtnText}>+ Add Header</Text>
272
+ </TouchableScale>
273
+ </View>
274
+
275
+ {headers.map(h => (<View key={h.id} style={styles.headerRowItem}>
276
+ <TouchableScale onPress={() => handleToggleHeader(h.id)} style={[
277
+ styles.headerCheck,
278
+ h.enabled && styles.headerCheckActive,
279
+ ]}>
280
+ <Text style={styles.headerCheckText}>
281
+ {h.enabled ? '✓' : ''}
282
+ </Text>
283
+ </TouchableScale>
284
+
285
+ <TextInput style={[styles.headerKeyInput, !h.enabled && { opacity: 0.5 }]} value={h.key} onChangeText={val => handleUpdateHeader(h.id, 'key', val)} placeholder="Header Key" placeholderTextColor={AppColors.grayTextWeak} autoCapitalize="none" autoCorrect={false}/>
286
+
287
+ <TextInput style={[
288
+ styles.headerValInput,
289
+ !h.enabled && { opacity: 0.5 },
290
+ ]} value={h.value} onChangeText={val => handleUpdateHeader(h.id, 'value', val)} placeholder="Value" placeholderTextColor={AppColors.grayTextWeak} autoCapitalize="none" autoCorrect={false}/>
291
+
292
+ <TouchableScale onPress={() => handleDeleteHeader(h.id)} style={styles.deleteHeaderBtn}>
293
+ <ClearIcon size={12} color={AppColors.errorColor}/>
294
+ </TouchableScale>
295
+ </View>))}
296
+ </View>)}
297
+
298
+ {/* ── BODY TAB ── */}
299
+ {activeTab === 'body' && (<View style={styles.bodyContainer}>
300
+ <View style={styles.bodyActionRow}>
301
+ <Text style={styles.sectionHeading}>REQUEST JSON / RAW PAYLOAD</Text>
302
+ <TouchableScale onPress={handlePrettifyBody} style={styles.prettifyBtn}>
303
+ <Text style={styles.prettifyBtnText}>✨ Prettify JSON</Text>
304
+ </TouchableScale>
305
+ </View>
306
+
307
+ <TextInput style={styles.bodyTextInput} value={requestBody} onChangeText={setRequestBody} placeholder={`{\n "key": "value"\n}`} placeholderTextColor={AppColors.grayTextWeak} multiline autoCapitalize="none" autoCorrect={false} textAlignVertical="top"/>
308
+ </View>)}
309
+
310
+ {/* ── RESPONSE TAB ── */}
311
+ {activeTab === 'response' && (<View style={styles.responseContainer}>
312
+ {isExecuting ? (<View style={styles.loadingBox}>
313
+ <ActivityIndicator size="large" color={AppColors.purple}/>
314
+ <Text style={styles.loadingText}>
315
+ Sending request to {url}...
316
+ </Text>
317
+ </View>) : executionResult ? (<View style={{ gap: 12 }}>
318
+ {/* Status Pill Card */}
319
+ <View style={styles.resStatusBar}>
320
+ <View style={styles.resStatusLeft}>
321
+ <View style={[
322
+ styles.resStatusPill,
323
+ {
324
+ backgroundColor: `${getStatusColor(executionResult.status)}16`,
325
+ borderColor: `${getStatusColor(executionResult.status)}40`,
326
+ },
327
+ ]}>
328
+ <View style={[
329
+ styles.statusDot,
330
+ {
331
+ backgroundColor: getStatusColor(executionResult.status),
332
+ },
333
+ ]}/>
334
+ <Text style={[
335
+ styles.resStatusText,
336
+ {
337
+ color: getStatusColor(executionResult.status),
338
+ },
339
+ ]}>
340
+ {executionResult.status}{' '}
341
+ {executionResult.statusText}
342
+ </Text>
343
+ </View>
344
+
345
+ <View style={styles.resMetaPill}>
346
+ <Text style={styles.resMetaPillText}>
347
+ ⏱ {executionResult.duration}ms
348
+ </Text>
349
+ </View>
350
+
351
+ <View style={styles.resMetaPill}>
352
+ <Text style={styles.resMetaPillText}>
353
+ 📦 {getSize(executionResult.body)}
354
+ </Text>
355
+ </View>
356
+ </View>
357
+
358
+ <CopyButton value={executionResult.body} label="Copy Body" iconType="copy"/>
359
+ </View>
360
+
361
+ {/* Response Body Output */}
362
+ <View style={styles.responseBox}>
363
+ <JsonViewer data={executionResult.body} search={responseSearch}/>
364
+ </View>
365
+ </View>) : (<View style={styles.emptyResponseBox}>
366
+ <TerminalIcon size={32} color={AppColors.grayTextWeak}/>
367
+ <Text style={styles.emptyResponseTitle}>
368
+ No execution yet
369
+ </Text>
370
+ <Text style={styles.emptyResponseSub}>
371
+ Tap "Send Request" below to trigger this API and view the
372
+ live response.
373
+ </Text>
374
+ </View>)}
375
+ </View>)}
376
+ </ScrollView>
377
+
378
+ {/* ─── 5. BOTTOM EXECUTE BAR ──────────────────────────────────── */}
379
+ <View style={styles.bottomBar}>
380
+ <TouchableScale onPress={handleExecute} disabled={isExecuting} style={[
381
+ styles.sendBtn,
382
+ isExecuting && { backgroundColor: AppColors.grayBorderSecondary },
383
+ ]}>
384
+ {isExecuting ? (<ActivityIndicator size="small" color={AppColors.white}/>) : (<>
385
+ <Text style={styles.sendBtnIcon}>⚡</Text>
386
+ <Text style={styles.sendBtnText}>Send Request</Text>
387
+ </>)}
388
+ </TouchableScale>
389
+ </View>
390
+ </View>
391
+ </View>);
392
+ };
393
+ const styles = StyleSheet.create({
394
+ backdrop: {
395
+ ...StyleSheet.absoluteFillObject,
396
+ backgroundColor: 'rgba(0, 0, 0, 0.65)',
397
+ justifyContent: 'flex-end',
398
+ zIndex: 999999,
399
+ elevation: 999999,
400
+ },
401
+ modalCard: {
402
+ height: '90%',
403
+ backgroundColor: AppColors.contentBg,
404
+ borderTopLeftRadius: 20,
405
+ borderTopRightRadius: 20,
406
+ overflow: 'hidden',
407
+ },
408
+ headerRow: {
409
+ flexDirection: 'row',
410
+ alignItems: 'center',
411
+ justifyContent: 'space-between',
412
+ paddingHorizontal: 16,
413
+ paddingTop: 14,
414
+ paddingBottom: 10,
415
+ borderBottomWidth: 1,
416
+ borderBottomColor: AppColors.grayBorderSecondary,
417
+ },
418
+ headerTitleBox: {
419
+ flex: 1,
420
+ },
421
+ headerTag: {
422
+ backgroundColor: `${AppColors.purple}14`,
423
+ paddingHorizontal: 6,
424
+ paddingVertical: 2,
425
+ borderRadius: 4,
426
+ alignSelf: 'flex-start',
427
+ marginBottom: 4,
428
+ },
429
+ headerTagText: {
430
+ fontFamily: AppFonts.interBold,
431
+ fontSize: 9.5,
432
+ color: AppColors.purple,
433
+ letterSpacing: 0.5,
434
+ },
435
+ headerTitle: {
436
+ fontFamily: AppFonts.interBold,
437
+ fontSize: 16,
438
+ color: AppColors.primaryBlack,
439
+ },
440
+ closeBtn: {
441
+ width: 32,
442
+ height: 32,
443
+ borderRadius: 16,
444
+ backgroundColor: AppColors.grayBackground,
445
+ alignItems: 'center',
446
+ justifyContent: 'center',
447
+ },
448
+ urlSection: {
449
+ padding: 12,
450
+ backgroundColor: AppColors.primaryLight,
451
+ borderBottomWidth: 1,
452
+ borderBottomColor: AppColors.grayBorderSecondary,
453
+ gap: 8,
454
+ },
455
+ methodList: {
456
+ flexDirection: 'row',
457
+ gap: 6,
458
+ },
459
+ methodPill: {
460
+ paddingHorizontal: 10,
461
+ paddingVertical: 5,
462
+ borderRadius: 6,
463
+ borderWidth: 1,
464
+ borderColor: AppColors.grayBorderSecondary,
465
+ backgroundColor: AppColors.contentBg,
466
+ },
467
+ methodPillText: {
468
+ fontFamily: AppFonts.interBold,
469
+ fontSize: 11,
470
+ color: AppColors.grayText,
471
+ },
472
+ urlInputRow: {
473
+ flexDirection: 'row',
474
+ alignItems: 'center',
475
+ backgroundColor: AppColors.contentBg,
476
+ borderRadius: 8,
477
+ borderWidth: 1,
478
+ borderColor: AppColors.grayBorderSecondary,
479
+ paddingHorizontal: 10,
480
+ },
481
+ urlInput: {
482
+ flex: 1,
483
+ paddingVertical: 8,
484
+ fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
485
+ fontSize: 12,
486
+ color: AppColors.primaryBlack,
487
+ },
488
+ urlClearBtn: {
489
+ padding: 4,
490
+ },
491
+ tabBar: {
492
+ flexDirection: 'row',
493
+ backgroundColor: AppColors.grayBackground,
494
+ borderBottomWidth: 1,
495
+ borderBottomColor: AppColors.grayBorderSecondary,
496
+ },
497
+ tabBtn: {
498
+ flex: 1,
499
+ flexDirection: 'row',
500
+ alignItems: 'center',
501
+ justifyContent: 'center',
502
+ paddingVertical: 10,
503
+ gap: 6,
504
+ borderBottomWidth: 2,
505
+ borderBottomColor: 'transparent',
506
+ },
507
+ tabBtnActive: {
508
+ borderBottomColor: AppColors.purple,
509
+ backgroundColor: AppColors.contentBg,
510
+ },
511
+ tabBtnText: {
512
+ fontFamily: AppFonts.interMedium,
513
+ fontSize: 12,
514
+ color: AppColors.grayTextWeak,
515
+ },
516
+ tabBtnTextActive: {
517
+ fontFamily: AppFonts.interBold,
518
+ color: AppColors.purple,
519
+ },
520
+ contentScroll: {
521
+ flex: 1,
522
+ },
523
+ contentInner: {
524
+ padding: 14,
525
+ },
526
+ sectionHeading: {
527
+ fontFamily: AppFonts.interBold,
528
+ fontSize: 11,
529
+ color: AppColors.grayTextWeak,
530
+ letterSpacing: 0.5,
531
+ },
532
+ headersContainer: {
533
+ gap: 8,
534
+ },
535
+ headersHeaderRow: {
536
+ flexDirection: 'row',
537
+ alignItems: 'center',
538
+ justifyContent: 'space-between',
539
+ marginBottom: 4,
540
+ },
541
+ addHeaderBtn: {
542
+ backgroundColor: `${AppColors.purple}14`,
543
+ paddingHorizontal: 8,
544
+ paddingVertical: 4,
545
+ borderRadius: 6,
546
+ },
547
+ addHeaderBtnText: {
548
+ fontFamily: AppFonts.interBold,
549
+ fontSize: 11,
550
+ color: AppColors.purple,
551
+ },
552
+ headerRowItem: {
553
+ flexDirection: 'row',
554
+ alignItems: 'center',
555
+ gap: 6,
556
+ },
557
+ headerCheck: {
558
+ width: 22,
559
+ height: 22,
560
+ borderRadius: 4,
561
+ borderWidth: 1,
562
+ borderColor: AppColors.grayBorderSecondary,
563
+ alignItems: 'center',
564
+ justifyContent: 'center',
565
+ backgroundColor: AppColors.contentBg,
566
+ },
567
+ headerCheckActive: {
568
+ backgroundColor: AppColors.purple,
569
+ borderColor: AppColors.purple,
570
+ },
571
+ headerCheckText: {
572
+ fontFamily: AppFonts.interBold,
573
+ fontSize: 12,
574
+ color: AppColors.white,
575
+ },
576
+ headerKeyInput: {
577
+ flex: 1,
578
+ backgroundColor: AppColors.primaryLight,
579
+ borderRadius: 6,
580
+ borderWidth: 1,
581
+ borderColor: AppColors.grayBorderSecondary,
582
+ paddingHorizontal: 8,
583
+ paddingVertical: 6,
584
+ fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
585
+ fontSize: 11.5,
586
+ color: AppColors.primaryBlack,
587
+ },
588
+ headerValInput: {
589
+ flex: 1.5,
590
+ backgroundColor: AppColors.primaryLight,
591
+ borderRadius: 6,
592
+ borderWidth: 1,
593
+ borderColor: AppColors.grayBorderSecondary,
594
+ paddingHorizontal: 8,
595
+ paddingVertical: 6,
596
+ fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
597
+ fontSize: 11.5,
598
+ color: AppColors.primaryBlack,
599
+ },
600
+ deleteHeaderBtn: {
601
+ padding: 6,
602
+ },
603
+ bodyContainer: {
604
+ gap: 8,
605
+ },
606
+ bodyActionRow: {
607
+ flexDirection: 'row',
608
+ alignItems: 'center',
609
+ justifyContent: 'space-between',
610
+ marginBottom: 4,
611
+ },
612
+ prettifyBtn: {
613
+ backgroundColor: `${AppColors.purple}14`,
614
+ paddingHorizontal: 8,
615
+ paddingVertical: 4,
616
+ borderRadius: 6,
617
+ },
618
+ prettifyBtnText: {
619
+ fontFamily: AppFonts.interBold,
620
+ fontSize: 11,
621
+ color: AppColors.purple,
622
+ },
623
+ bodyTextInput: {
624
+ height: 260,
625
+ backgroundColor: AppColors.primaryLight,
626
+ borderRadius: 8,
627
+ borderWidth: 1,
628
+ borderColor: AppColors.grayBorderSecondary,
629
+ padding: 10,
630
+ fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
631
+ fontSize: 11.5,
632
+ color: AppColors.primaryBlack,
633
+ },
634
+ responseContainer: {
635
+ minHeight: 200,
636
+ },
637
+ loadingBox: {
638
+ alignItems: 'center',
639
+ justifyContent: 'center',
640
+ paddingVertical: 40,
641
+ gap: 12,
642
+ },
643
+ loadingText: {
644
+ fontFamily: AppFonts.interMedium,
645
+ fontSize: 13,
646
+ color: AppColors.grayText,
647
+ },
648
+ resStatusBar: {
649
+ flexDirection: 'row',
650
+ alignItems: 'center',
651
+ justifyContent: 'space-between',
652
+ backgroundColor: AppColors.primaryLight,
653
+ padding: 10,
654
+ borderRadius: 10,
655
+ borderWidth: 1,
656
+ borderColor: AppColors.grayBorderSecondary,
657
+ },
658
+ resStatusLeft: {
659
+ flexDirection: 'row',
660
+ alignItems: 'center',
661
+ gap: 6,
662
+ flexWrap: 'wrap',
663
+ },
664
+ resStatusPill: {
665
+ flexDirection: 'row',
666
+ alignItems: 'center',
667
+ gap: 5,
668
+ paddingHorizontal: 8,
669
+ paddingVertical: 3.5,
670
+ borderRadius: 6,
671
+ borderWidth: 1,
672
+ },
673
+ statusDot: {
674
+ width: 6,
675
+ height: 6,
676
+ borderRadius: 3,
677
+ },
678
+ resStatusText: {
679
+ fontFamily: AppFonts.interBold,
680
+ fontSize: 11,
681
+ },
682
+ resMetaPill: {
683
+ backgroundColor: AppColors.contentBg,
684
+ paddingHorizontal: 6,
685
+ paddingVertical: 3,
686
+ borderRadius: 5,
687
+ borderWidth: 1,
688
+ borderColor: AppColors.grayBorderSecondary,
689
+ },
690
+ resMetaPillText: {
691
+ fontFamily: AppFonts.interMedium,
692
+ fontSize: 10.5,
693
+ color: AppColors.grayText,
694
+ },
695
+ responseBox: {
696
+ backgroundColor: AppColors.primaryLight,
697
+ borderRadius: 10,
698
+ borderWidth: 1,
699
+ borderColor: AppColors.grayBorderSecondary,
700
+ padding: 10,
701
+ minHeight: 200,
702
+ },
703
+ emptyResponseBox: {
704
+ alignItems: 'center',
705
+ justifyContent: 'center',
706
+ paddingVertical: 50,
707
+ gap: 8,
708
+ },
709
+ emptyResponseTitle: {
710
+ fontFamily: AppFonts.interBold,
711
+ fontSize: 14,
712
+ color: AppColors.primaryBlack,
713
+ },
714
+ emptyResponseSub: {
715
+ fontFamily: AppFonts.interRegular,
716
+ fontSize: 12,
717
+ color: AppColors.grayTextWeak,
718
+ textAlign: 'center',
719
+ paddingHorizontal: 24,
720
+ },
721
+ bottomBar: {
722
+ paddingHorizontal: 16,
723
+ paddingTop: 12,
724
+ paddingBottom: Platform.OS === 'ios' ? 34 : 16,
725
+ backgroundColor: AppColors.contentBg,
726
+ borderTopWidth: 1,
727
+ borderTopColor: AppColors.grayBorderSecondary,
728
+ },
729
+ sendBtn: {
730
+ backgroundColor: AppColors.purple,
731
+ flexDirection: 'row',
732
+ alignItems: 'center',
733
+ justifyContent: 'center',
734
+ gap: 6,
735
+ paddingVertical: 12,
736
+ borderRadius: 10,
737
+ shadowColor: AppColors.purple,
738
+ shadowOpacity: 0.3,
739
+ shadowRadius: 6,
740
+ shadowOffset: { width: 0, height: 2 },
741
+ },
742
+ sendBtnIcon: {
743
+ fontSize: 14,
744
+ color: AppColors.white,
745
+ },
746
+ sendBtnText: {
747
+ fontFamily: AppFonts.interBold,
748
+ fontSize: 14,
749
+ color: AppColors.white,
750
+ },
751
+ });
752
+ export default RequestReplayModal;