react-native-inapp-inspector 2.0.7 → 2.2.0

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