react-native-inapp-inspector 1.1.25 → 1.1.27

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 (70) hide show
  1. package/android/build.gradle +37 -0
  2. package/android/src/main/AndroidManifest.xml +3 -0
  3. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +114 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +28 -0
  5. package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
  6. package/dist/commonjs/components/ErrorBoundary.js +9 -145
  7. package/dist/commonjs/components/Inspector/CrashDetail.d.ts +3 -0
  8. package/dist/commonjs/components/Inspector/CrashDetail.js +796 -0
  9. package/dist/commonjs/components/Inspector/CrashFilterModal.d.ts +20 -0
  10. package/dist/commonjs/components/Inspector/CrashFilterModal.js +597 -0
  11. package/dist/commonjs/components/Inspector/CrashTab.d.ts +3 -0
  12. package/dist/commonjs/components/Inspector/CrashTab.js +727 -0
  13. package/dist/commonjs/components/Inspector/InspectorHeader.js +52 -23
  14. package/dist/commonjs/components/Inspector/LogDetail.js +4 -3
  15. package/dist/commonjs/components/Inspector/MainScreen.js +12 -3
  16. package/dist/commonjs/components/Inspector/SettingsPanel.js +90 -1
  17. package/dist/commonjs/components/Inspector/TabBar.js +15 -3
  18. package/dist/commonjs/components/NetworkIcons.d.ts +11 -0
  19. package/dist/commonjs/components/NetworkIcons.js +96 -1
  20. package/dist/commonjs/components/SegmentedTabs.js +2 -1
  21. package/dist/commonjs/constants/version.d.ts +1 -1
  22. package/dist/commonjs/constants/version.js +1 -1
  23. package/dist/commonjs/customHooks/analyticsLogger.js +70 -44
  24. package/dist/commonjs/customHooks/consoleLogger.d.ts +1 -0
  25. package/dist/commonjs/customHooks/consoleLogger.js +70 -6
  26. package/dist/commonjs/customHooks/crashHandler.d.ts +64 -0
  27. package/dist/commonjs/customHooks/crashHandler.js +681 -0
  28. package/dist/commonjs/customHooks/networkLogger.js +64 -48
  29. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +1 -1
  30. package/dist/commonjs/i18n/locales/en.json +131 -0
  31. package/dist/commonjs/index.d.ts +3 -1
  32. package/dist/commonjs/index.js +95 -1
  33. package/dist/commonjs/types/enums.d.ts +41 -0
  34. package/dist/commonjs/types/enums.js +37 -1
  35. package/dist/commonjs/types/interfaces.d.ts +51 -1
  36. package/dist/esm/components/ErrorBoundary.d.ts +1 -1
  37. package/dist/esm/components/ErrorBoundary.js +10 -113
  38. package/dist/esm/components/Inspector/CrashDetail.d.ts +3 -0
  39. package/dist/esm/components/Inspector/CrashDetail.js +758 -0
  40. package/dist/esm/components/Inspector/CrashFilterModal.d.ts +20 -0
  41. package/dist/esm/components/Inspector/CrashFilterModal.js +557 -0
  42. package/dist/esm/components/Inspector/CrashTab.d.ts +3 -0
  43. package/dist/esm/components/Inspector/CrashTab.js +689 -0
  44. package/dist/esm/components/Inspector/InspectorHeader.js +52 -23
  45. package/dist/esm/components/Inspector/LogDetail.js +4 -3
  46. package/dist/esm/components/Inspector/MainScreen.js +12 -3
  47. package/dist/esm/components/Inspector/SettingsPanel.js +91 -2
  48. package/dist/esm/components/Inspector/TabBar.js +16 -4
  49. package/dist/esm/components/NetworkIcons.d.ts +11 -0
  50. package/dist/esm/components/NetworkIcons.js +83 -0
  51. package/dist/esm/components/SegmentedTabs.js +2 -1
  52. package/dist/esm/constants/version.d.ts +1 -1
  53. package/dist/esm/constants/version.js +1 -1
  54. package/dist/esm/customHooks/analyticsLogger.js +70 -44
  55. package/dist/esm/customHooks/consoleLogger.d.ts +1 -0
  56. package/dist/esm/customHooks/consoleLogger.js +68 -5
  57. package/dist/esm/customHooks/crashHandler.d.ts +64 -0
  58. package/dist/esm/customHooks/crashHandler.js +659 -0
  59. package/dist/esm/customHooks/networkLogger.js +64 -48
  60. package/dist/esm/helpers/gaAnalyticsRegistry.js +1 -1
  61. package/dist/esm/i18n/locales/en.json +131 -0
  62. package/dist/esm/index.d.ts +3 -1
  63. package/dist/esm/index.js +73 -1
  64. package/dist/esm/types/enums.d.ts +41 -0
  65. package/dist/esm/types/enums.js +36 -0
  66. package/dist/esm/types/interfaces.d.ts +51 -1
  67. package/ios/NetworkInspectorModule.h +8 -0
  68. package/ios/NetworkInspectorModule.m +125 -0
  69. package/package.json +5 -2
  70. package/react-native-inapp-inspector.podspec +18 -0
@@ -0,0 +1,796 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const react_1 = __importStar(require("react"));
40
+ const react_native_1 = require("react-native");
41
+ const i18n_1 = require("../../i18n");
42
+ const InspectorContext_1 = require("./InspectorContext");
43
+ const TouchableScale_1 = __importDefault(require("../TouchableScale"));
44
+ const SegmentedTabs_1 = __importDefault(require("../SegmentedTabs"));
45
+ const HighlightText_1 = __importDefault(require("../HighlightText"));
46
+ const JsonViewer_1 = __importDefault(require("../JsonViewer"));
47
+ const AppColors_1 = require("../../styles/AppColors");
48
+ const AppFonts_1 = require("../../styles/AppFonts");
49
+ const crashHandler_1 = require("../../customHooks/crashHandler");
50
+ const helpers_1 = require("../../helpers");
51
+ const NetworkIcons_1 = require("../NetworkIcons");
52
+ const CrashDetail = react_1.default.memo(() => {
53
+ const { t } = (0, i18n_1.useTranslation)();
54
+ const { selectedCrash } = (0, InspectorContext_1.useInspector)();
55
+ const [activeSubTab, setActiveSubTab] = (0, react_1.useState)('stack');
56
+ const [searchQuery, setSearchQuery] = (0, react_1.useState)('');
57
+ const [stackFilter, setStackFilter] = (0, react_1.useState)('app');
58
+ const [copiedSuccess, setCopiedSuccess] = (0, react_1.useState)(false);
59
+ const [copiedFrameIndex, setCopiedFrameIndex] = (0, react_1.useState)(null);
60
+ if (!selectedCrash)
61
+ return null;
62
+ const stackFrames = (0, react_1.useMemo)(() => {
63
+ if (selectedCrash.parsedStack && selectedCrash.parsedStack.length > 0) {
64
+ return selectedCrash.parsedStack;
65
+ }
66
+ if (selectedCrash.stack) {
67
+ return (0, crashHandler_1.parseCrashStackTrace)(selectedCrash.stack);
68
+ }
69
+ return [];
70
+ }, [selectedCrash]);
71
+ // Strip keys holding explicit undefined values (e.g. componentStack) so the
72
+ // Raw JSON tab never renders a literal "undefined".
73
+ const rawCrashData = (0, react_1.useMemo)(() => {
74
+ try {
75
+ return JSON.parse(JSON.stringify(selectedCrash));
76
+ }
77
+ catch {
78
+ return selectedCrash;
79
+ }
80
+ }, [selectedCrash]);
81
+ const appStackFrames = (0, react_1.useMemo)(() => {
82
+ return stackFrames.filter(f => f.isAppCode);
83
+ }, [stackFrames]);
84
+ const displayedFrames = (0, react_1.useMemo)(() => {
85
+ if (stackFilter === 'app' && appStackFrames.length > 0) {
86
+ return appStackFrames;
87
+ }
88
+ return stackFrames;
89
+ }, [stackFilter, appStackFrames, stackFrames]);
90
+ const originFrame = (0, react_1.useMemo)(() => {
91
+ return appStackFrames[0] || stackFrames[0] || null;
92
+ }, [appStackFrames, stackFrames]);
93
+ const handleCopyReport = () => {
94
+ const report = (0, crashHandler_1.exportCrashReport)(selectedCrash);
95
+ (0, helpers_1.copyToClipboard)(report, 'Crash Report');
96
+ setCopiedSuccess(true);
97
+ setTimeout(() => setCopiedSuccess(false), 2000);
98
+ };
99
+ const handleCopyFrame = (frame, index) => {
100
+ const text = frame.raw || `${frame.method}@${frame.file}:${frame.lineNumber}:${frame.column}`;
101
+ (0, helpers_1.copyToClipboard)(text, 'Stack Frame');
102
+ setCopiedFrameIndex(index);
103
+ setTimeout(() => setCopiedFrameIndex(null), 1500);
104
+ };
105
+ const tabsConfig = [
106
+ {
107
+ key: 'stack',
108
+ label: t('crash.tabStack', { count: stackFrames.length }),
109
+ icon: (isActive) => (<NetworkIcons_1.StackTraceIcon size={12} color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText}/>),
110
+ },
111
+ {
112
+ key: 'diagnostics',
113
+ label: t('crash.tabDiagnostics'),
114
+ icon: (isActive) => (<NetworkIcons_1.DiagnosticsIcon size={12} color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText}/>),
115
+ },
116
+ {
117
+ key: 'breadcrumbs',
118
+ label: t('crash.tabTrail', { count: selectedCrash.breadcrumbs?.length || 0 }),
119
+ icon: (isActive) => (<NetworkIcons_1.TrailIcon size={12} color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText}/>),
120
+ },
121
+ {
122
+ key: 'raw',
123
+ label: t('crash.tabRawJson'),
124
+ icon: (isActive) => (<NetworkIcons_1.RawJsonIcon size={12} color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayText}/>),
125
+ },
126
+ ];
127
+ return (<react_native_1.View style={{ flex: 1, backgroundColor: AppColors_1.AppColors.grayBackground }}>
128
+ {/* ─── Top Info Bar (Similar to NetworkDetail / LogDetail) ─── */}
129
+ <react_native_1.View style={{ paddingHorizontal: 8, paddingTop: 6 }}>
130
+ <react_native_1.View style={localStyles.infoBar}>
131
+ {/* Top Status Badges Row */}
132
+ <react_native_1.View style={localStyles.badgeRow}>
133
+ {/* Fatal / Non-fatal Pill */}
134
+ <react_native_1.View style={[
135
+ localStyles.pillBadge,
136
+ {
137
+ backgroundColor: selectedCrash.isFatal
138
+ ? '#FEE2E2'
139
+ : '#FEF3C7',
140
+ borderColor: selectedCrash.isFatal ? '#FCA5A5' : '#FCD34D',
141
+ },
142
+ ]}>
143
+ <react_native_1.View style={[
144
+ localStyles.statusDot,
145
+ {
146
+ backgroundColor: selectedCrash.isFatal
147
+ ? '#DC2626'
148
+ : '#D97706',
149
+ },
150
+ ]}/>
151
+ <react_native_1.Text style={[
152
+ localStyles.pillBadgeText,
153
+ {
154
+ color: selectedCrash.isFatal ? '#991B1B' : '#92400E',
155
+ },
156
+ ]}>
157
+ {selectedCrash.isFatal ? t('crash.fatalCrash') : t('crash.handledException')}
158
+ </react_native_1.Text>
159
+ </react_native_1.View>
160
+
161
+ {/* Type Pill */}
162
+ <react_native_1.View style={[
163
+ localStyles.pillBadge,
164
+ {
165
+ backgroundColor: '#EDE9FE',
166
+ borderColor: '#C4B5FD',
167
+ },
168
+ ]}>
169
+ <react_native_1.Text style={[localStyles.pillBadgeText, { color: '#6D28D9' }]}>
170
+ {selectedCrash.type.toUpperCase()}
171
+ </react_native_1.Text>
172
+ </react_native_1.View>
173
+
174
+ <react_native_1.View style={{ flex: 1 }}/>
175
+
176
+ {/* Copy Report Action */}
177
+ <TouchableScale_1.default onPress={handleCopyReport} hitSlop={10} style={[
178
+ localStyles.actionButton,
179
+ copiedSuccess && { backgroundColor: '#ECFDF5', borderColor: '#6EE7B7' },
180
+ ]}>
181
+ {copiedSuccess ? (<NetworkIcons_1.CircleCheckIcon color="#059669" size={12}/>) : (<NetworkIcons_1.CopyIcon color={AppColors_1.AppColors.purple} size={12}/>)}
182
+ <react_native_1.Text style={[
183
+ localStyles.actionButtonText,
184
+ copiedSuccess && { color: '#059669' },
185
+ ]}>
186
+ {copiedSuccess ? t('crash.copied') : t('crash.copyReport')}
187
+ </react_native_1.Text>
188
+ </TouchableScale_1.default>
189
+ </react_native_1.View>
190
+
191
+ {/* Crash Title / Message */}
192
+ <react_native_1.Text style={localStyles.titleText}>
193
+ {selectedCrash.message}
194
+ </react_native_1.Text>
195
+
196
+ {/* Metadata Row */}
197
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.metaRow}>
198
+ {originFrame && (<react_native_1.View style={localStyles.metaChip}>
199
+ <NetworkIcons_1.TerminalIcon color={AppColors_1.AppColors.grayText} size={11}/>
200
+ <react_native_1.Text style={localStyles.metaChipText} numberOfLines={2}>
201
+ {originFrame.file}:{originFrame.lineNumber}
202
+ </react_native_1.Text>
203
+ </react_native_1.View>)}
204
+
205
+ <react_native_1.View style={localStyles.metaChip}>
206
+ <NetworkIcons_1.ClockIcon color={AppColors_1.AppColors.grayText} size={11}/>
207
+ <react_native_1.Text style={localStyles.metaChipText}>
208
+ {selectedCrash.timeStr || new Date(selectedCrash.timestamp).toLocaleTimeString()}
209
+ </react_native_1.Text>
210
+ </react_native_1.View>
211
+
212
+ {selectedCrash.deviceInfo?.platform && (<react_native_1.View style={localStyles.metaChip}>
213
+ {selectedCrash.deviceInfo.platform === 'ios' ? (<NetworkIcons_1.AppleIcon color={AppColors_1.AppColors.grayText} size={11}/>) : (<NetworkIcons_1.AndroidIcon color={AppColors_1.AppColors.grayText} size={11}/>)}
214
+ <react_native_1.Text style={localStyles.metaChipText}>
215
+ {selectedCrash.deviceInfo.platform.toUpperCase()} {selectedCrash.deviceInfo.osVersion}
216
+ </react_native_1.Text>
217
+ </react_native_1.View>)}
218
+ </react_native_1.ScrollView>
219
+ </react_native_1.View>
220
+ </react_native_1.View>
221
+
222
+ {/* ─── Segmented Sub Tabs ─── */}
223
+ <react_native_1.View style={{ paddingHorizontal: 8, paddingTop: 6, paddingBottom: 4 }}>
224
+ <SegmentedTabs_1.default tabs={tabsConfig} activeKey={activeSubTab} onChange={tab => setActiveSubTab(tab)}/>
225
+ </react_native_1.View>
226
+
227
+ {/* ─── Search Bar (for Stack & Raw tabs) ─── */}
228
+ {(activeSubTab === 'stack' || activeSubTab === 'raw') && (<react_native_1.View style={{ paddingHorizontal: 12, paddingBottom: 6 }}>
229
+ <react_native_1.View style={localStyles.searchContainer}>
230
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayText} size={14}/>
231
+ <react_native_1.TextInput style={localStyles.searchInput} placeholder={t('crash.searchDetailPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={searchQuery} onChangeText={setSearchQuery} autoCapitalize="none" autoCorrect={false}/>
232
+ {searchQuery.length > 0 && (<TouchableScale_1.default onPress={() => setSearchQuery('')} hitSlop={10}>
233
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayText} size={13}/>
234
+ </TouchableScale_1.default>)}
235
+ </react_native_1.View>
236
+ </react_native_1.View>)}
237
+
238
+ {/* ─── Tab Content ScrollView ─── */}
239
+ <react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 12, paddingBottom: 40, gap: 12 }}>
240
+ {/* 1. STACK TRACE TAB */}
241
+ {activeSubTab === 'stack' && (<react_native_1.View style={{ gap: 10 }}>
242
+ {/* Filter Chips (App Code vs All Frames) */}
243
+ <react_native_1.View style={localStyles.filterChipsRow}>
244
+ <TouchableScale_1.default onPress={() => setStackFilter('app')} style={[
245
+ localStyles.filterChip,
246
+ stackFilter === 'app' && localStyles.filterChipActive,
247
+ ]}>
248
+ <NetworkIcons_1.AppFramesIcon size={12} color={stackFilter === 'app'
249
+ ? AppColors_1.AppColors.white
250
+ : AppColors_1.AppColors.purple}/>
251
+ <react_native_1.Text style={[
252
+ localStyles.filterChipText,
253
+ stackFilter === 'app' && localStyles.filterChipTextActive,
254
+ ]}>
255
+ {t('crash.appFrames', { count: appStackFrames.length })}
256
+ </react_native_1.Text>
257
+ </TouchableScale_1.default>
258
+
259
+ <TouchableScale_1.default onPress={() => setStackFilter('all')} style={[
260
+ localStyles.filterChip,
261
+ stackFilter === 'all' && localStyles.filterChipActive,
262
+ ]}>
263
+ <NetworkIcons_1.AllFramesIcon size={12} color={stackFilter === 'all'
264
+ ? AppColors_1.AppColors.white
265
+ : AppColors_1.AppColors.purple}/>
266
+ <react_native_1.Text style={[
267
+ localStyles.filterChipText,
268
+ stackFilter === 'all' && localStyles.filterChipTextActive,
269
+ ]}>
270
+ {t('crash.allFrames', { count: stackFrames.length })}
271
+ </react_native_1.Text>
272
+ </TouchableScale_1.default>
273
+ </react_native_1.View>
274
+
275
+ {/* Frames List */}
276
+ {displayedFrames.length > 0 ? (displayedFrames
277
+ .filter(frame => {
278
+ if (!searchQuery.trim())
279
+ return true;
280
+ const q = searchQuery.toLowerCase();
281
+ return (frame.method.toLowerCase().includes(q) ||
282
+ frame.file.toLowerCase().includes(q));
283
+ })
284
+ .map((frame, index) => {
285
+ const isOrigin = index === 0 && frame.isAppCode;
286
+ return (<react_native_1.View key={`frame_${index}`} style={[
287
+ localStyles.frameCard,
288
+ isOrigin && localStyles.originFrameCard,
289
+ ]}>
290
+ <react_native_1.View style={localStyles.frameCardHeader}>
291
+ <react_native_1.View style={localStyles.frameIndexBadge}>
292
+ <react_native_1.Text style={localStyles.frameIndexBadgeText}>
293
+ #{index + 1}
294
+ </react_native_1.Text>
295
+ </react_native_1.View>
296
+ <react_native_1.View style={[
297
+ localStyles.frameTypeBadge,
298
+ frame.isAppCode
299
+ ? { backgroundColor: '#ECFDF5', borderColor: '#A7F3D0' }
300
+ : { backgroundColor: '#F1F5F9', borderColor: '#E2E8F0' },
301
+ ]}>
302
+ <react_native_1.Text style={[
303
+ localStyles.frameTypeBadgeText,
304
+ frame.isAppCode
305
+ ? { color: '#059669' }
306
+ : { color: '#64748B' },
307
+ ]}>
308
+ {frame.isAppCode ? t('crash.frameApp') : t('crash.frameLib')}
309
+ </react_native_1.Text>
310
+ </react_native_1.View>
311
+
312
+ <react_native_1.Text style={localStyles.frameMethodText} numberOfLines={1}>
313
+ <HighlightText_1.default text={frame.method || t('crash.anonymous')} highlight={searchQuery}/>
314
+ </react_native_1.Text>
315
+
316
+ <TouchableScale_1.default onPress={() => handleCopyFrame(frame, index)} hitSlop={8} style={localStyles.frameCopyBtn}>
317
+ {copiedFrameIndex === index ? (<NetworkIcons_1.CircleCheckIcon color={AppColors_1.AppColors.greenColor} size={12}/>) : (<NetworkIcons_1.CopyIcon color={AppColors_1.AppColors.grayText} size={12}/>)}
318
+ <react_native_1.Text style={localStyles.frameCopyBtnText}>
319
+ {copiedFrameIndex === index
320
+ ? t('crash.frameCopied')
321
+ : t('crash.frameCopy')}
322
+ </react_native_1.Text>
323
+ </TouchableScale_1.default>
324
+ </react_native_1.View>
325
+
326
+ <react_native_1.View style={localStyles.frameLocationRow}>
327
+ <react_native_1.Text style={localStyles.frameFileText} numberOfLines={1}>
328
+ <HighlightText_1.default text={frame.file} highlight={searchQuery}/>
329
+ </react_native_1.Text>
330
+ <react_native_1.Text style={localStyles.frameLineText}>
331
+ :{frame.lineNumber}
332
+ {frame.column ? `:${frame.column}` : ''}
333
+ </react_native_1.Text>
334
+ </react_native_1.View>
335
+
336
+ {frame.raw && (<react_native_1.Text style={localStyles.frameRawText} numberOfLines={2}>
337
+ {frame.raw}
338
+ </react_native_1.Text>)}
339
+ </react_native_1.View>);
340
+ })) : (<react_native_1.View style={localStyles.emptyContainer}>
341
+ <react_native_1.Text style={localStyles.emptyText}>
342
+ {selectedCrash.stack
343
+ ? selectedCrash.stack
344
+ : t('crash.noStackTrace')}
345
+ </react_native_1.Text>
346
+ </react_native_1.View>)}
347
+
348
+ {selectedCrash.componentStack && (<react_native_1.View style={localStyles.sectionCard}>
349
+ <react_native_1.View style={localStyles.sectionCardHeader}>
350
+ <NetworkIcons_1.LayersIcon color={AppColors_1.AppColors.purple} size={14}/>
351
+ <react_native_1.Text style={localStyles.sectionCardTitle}>
352
+ {t('crash.componentHierarchy')}
353
+ </react_native_1.Text>
354
+ </react_native_1.View>
355
+ <react_native_1.Text style={localStyles.componentStackText}>
356
+ {selectedCrash.componentStack}
357
+ </react_native_1.Text>
358
+ </react_native_1.View>)}
359
+ </react_native_1.View>)}
360
+
361
+ {/* 2. DIAGNOSTICS TAB */}
362
+ {activeSubTab === 'diagnostics' && (<react_native_1.View style={{ gap: 12 }}>
363
+ {/* Device & OS Diagnostics Card */}
364
+ <react_native_1.View style={localStyles.sectionCard}>
365
+ <react_native_1.View style={localStyles.sectionCardHeader}>
366
+ <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.purple} size={14}/>
367
+ <react_native_1.Text style={localStyles.sectionCardTitle}>{t('crash.deviceEnvironment')}</react_native_1.Text>
368
+ </react_native_1.View>
369
+
370
+ <react_native_1.View style={localStyles.diagGrid}>
371
+ <react_native_1.View style={localStyles.diagItem}>
372
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.platform')}</react_native_1.Text>
373
+ <react_native_1.Text style={localStyles.diagValue}>
374
+ {selectedCrash.deviceInfo?.platform?.toUpperCase() || react_native_1.Platform.OS.toUpperCase()}
375
+ </react_native_1.Text>
376
+ </react_native_1.View>
377
+
378
+ <react_native_1.View style={localStyles.diagItem}>
379
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.osVersion')}</react_native_1.Text>
380
+ <react_native_1.Text style={localStyles.diagValue}>
381
+ {selectedCrash.deviceInfo?.osVersion || String(react_native_1.Platform.Version)}
382
+ </react_native_1.Text>
383
+ </react_native_1.View>
384
+
385
+ <react_native_1.View style={localStyles.diagItem}>
386
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.reactNative')}</react_native_1.Text>
387
+ <react_native_1.Text style={localStyles.diagValue}>
388
+ {selectedCrash.deviceInfo?.rnVersion || '0.74+'}
389
+ </react_native_1.Text>
390
+ </react_native_1.View>
391
+
392
+ <react_native_1.View style={localStyles.diagItem}>
393
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.jsEngine')}</react_native_1.Text>
394
+ <react_native_1.Text style={localStyles.diagValue}>
395
+ {selectedCrash.deviceInfo?.isHermes ? t('crash.hermesEngine') : t('crash.jsc')}
396
+ </react_native_1.Text>
397
+ </react_native_1.View>
398
+
399
+ <react_native_1.View style={localStyles.diagItem}>
400
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.architecture')}</react_native_1.Text>
401
+ <react_native_1.Text style={localStyles.diagValue}>
402
+ {selectedCrash.deviceInfo?.isFabric ? t('crash.fabricNewArch') : t('crash.paperLegacy')}
403
+ </react_native_1.Text>
404
+ </react_native_1.View>
405
+
406
+ <react_native_1.View style={localStyles.diagItem}>
407
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.appState')}</react_native_1.Text>
408
+ <react_native_1.Text style={localStyles.diagValue}>
409
+ {selectedCrash.deviceInfo?.appState || 'active'}
410
+ </react_native_1.Text>
411
+ </react_native_1.View>
412
+ </react_native_1.View>
413
+ </react_native_1.View>
414
+
415
+ {/* Memory Metrics Card */}
416
+ {selectedCrash.memoryInfo && (<react_native_1.View style={localStyles.sectionCard}>
417
+ <react_native_1.View style={localStyles.sectionCardHeader}>
418
+ <NetworkIcons_1.LayersIcon color={AppColors_1.AppColors.purple} size={14}/>
419
+ <react_native_1.Text style={localStyles.sectionCardTitle}>{t('crash.jsHeapMemory')}</react_native_1.Text>
420
+ </react_native_1.View>
421
+
422
+ <react_native_1.View style={localStyles.diagGrid}>
423
+ <react_native_1.View style={localStyles.diagItem}>
424
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.usedHeap')}</react_native_1.Text>
425
+ <react_native_1.Text style={localStyles.diagValue}>
426
+ {selectedCrash.memoryInfo.usedJSHeapSize} MB
427
+ </react_native_1.Text>
428
+ </react_native_1.View>
429
+
430
+ <react_native_1.View style={localStyles.diagItem}>
431
+ <react_native_1.Text style={localStyles.diagLabel}>{t('crash.totalHeap')}</react_native_1.Text>
432
+ <react_native_1.Text style={localStyles.diagValue}>
433
+ {selectedCrash.memoryInfo.totalJSHeapSize} MB
434
+ </react_native_1.Text>
435
+ </react_native_1.View>
436
+ </react_native_1.View>
437
+ </react_native_1.View>)}
438
+ </react_native_1.View>)}
439
+
440
+ {/* 3. BREADCRUMBS TAB */}
441
+ {activeSubTab === 'breadcrumbs' && (<react_native_1.View style={{ gap: 10 }}>
442
+ {selectedCrash.breadcrumbs && selectedCrash.breadcrumbs.length > 0 ? (selectedCrash.breadcrumbs.map((b, idx) => (<react_native_1.View key={`crumb_${idx}`} style={localStyles.breadcrumbCard}>
443
+ <react_native_1.View style={localStyles.breadcrumbHeader}>
444
+ <react_native_1.View style={localStyles.breadcrumbTag}>
445
+ <react_native_1.Text style={localStyles.breadcrumbTagText}>
446
+ {b.type.toUpperCase()}
447
+ </react_native_1.Text>
448
+ </react_native_1.View>
449
+ <react_native_1.Text style={localStyles.breadcrumbTime}>
450
+ {new Date(b.timestamp).toLocaleTimeString()}
451
+ </react_native_1.Text>
452
+ </react_native_1.View>
453
+ <react_native_1.Text style={localStyles.breadcrumbMessage}>{b.message}</react_native_1.Text>
454
+ {b.data && (<react_native_1.View style={{ marginTop: 6 }}>
455
+ <JsonViewer_1.default data={b.data} search="" wrap/>
456
+ </react_native_1.View>)}
457
+ </react_native_1.View>))) : (<react_native_1.View style={localStyles.emptyContainer}>
458
+ <react_native_1.Text style={localStyles.emptyText}>
459
+ {t('crash.noBreadcrumbs')}
460
+ </react_native_1.Text>
461
+ </react_native_1.View>)}
462
+ </react_native_1.View>)}
463
+
464
+ {/* 4. RAW JSON TAB */}
465
+ {activeSubTab === 'raw' && (<react_native_1.View style={localStyles.rawContainer}>
466
+ <JsonViewer_1.default data={rawCrashData} search={searchQuery} wrap/>
467
+ </react_native_1.View>)}
468
+ </react_native_1.ScrollView>
469
+ </react_native_1.View>);
470
+ });
471
+ exports.default = CrashDetail;
472
+ const localStyles = react_native_1.StyleSheet.create({
473
+ infoBar: {
474
+ backgroundColor: AppColors_1.AppColors.primaryLight,
475
+ borderRadius: 12,
476
+ padding: 12,
477
+ borderWidth: 1,
478
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
479
+ shadowColor: AppColors_1.AppColors.black,
480
+ shadowOffset: { width: 0, height: 1 },
481
+ shadowOpacity: 0.05,
482
+ shadowRadius: 3,
483
+ elevation: 2,
484
+ gap: 8,
485
+ },
486
+ badgeRow: {
487
+ flexDirection: 'row',
488
+ alignItems: 'center',
489
+ gap: 8,
490
+ },
491
+ pillBadge: {
492
+ flexDirection: 'row',
493
+ alignItems: 'center',
494
+ paddingHorizontal: 8,
495
+ paddingVertical: 3,
496
+ borderRadius: 12,
497
+ borderWidth: 1,
498
+ gap: 5,
499
+ },
500
+ statusDot: {
501
+ width: 6,
502
+ height: 6,
503
+ borderRadius: 3,
504
+ },
505
+ pillBadgeText: {
506
+ fontFamily: AppFonts_1.AppFonts.interBold,
507
+ fontSize: 9.5,
508
+ letterSpacing: 0.4,
509
+ },
510
+ actionButton: {
511
+ flexDirection: 'row',
512
+ alignItems: 'center',
513
+ gap: 4,
514
+ backgroundColor: `${AppColors_1.AppColors.purple}14`,
515
+ borderColor: `${AppColors_1.AppColors.purple}33`,
516
+ borderWidth: 1,
517
+ paddingHorizontal: 8,
518
+ paddingVertical: 4,
519
+ borderRadius: 8,
520
+ },
521
+ actionButtonText: {
522
+ fontFamily: AppFonts_1.AppFonts.interBold,
523
+ fontSize: 10.5,
524
+ color: AppColors_1.AppColors.purple,
525
+ },
526
+ titleText: {
527
+ fontFamily: AppFonts_1.AppFonts.interBold,
528
+ fontSize: 14,
529
+ color: AppColors_1.AppColors.primaryBlack,
530
+ lineHeight: 19,
531
+ },
532
+ metaRow: {
533
+ flexDirection: 'row',
534
+ alignItems: 'center',
535
+ gap: 6,
536
+ paddingVertical: 2,
537
+ },
538
+ metaChip: {
539
+ flexDirection: 'row',
540
+ alignItems: 'center',
541
+ gap: 4,
542
+ backgroundColor: AppColors_1.AppColors.grayBackground,
543
+ paddingHorizontal: 7,
544
+ paddingVertical: 3,
545
+ borderRadius: 6,
546
+ borderWidth: 1,
547
+ borderColor: AppColors_1.AppColors.dividerColor,
548
+ },
549
+ metaChipText: {
550
+ fontFamily: AppFonts_1.AppFonts.interMedium,
551
+ fontSize: 10,
552
+ color: AppColors_1.AppColors.grayText,
553
+ },
554
+ searchContainer: {
555
+ flexDirection: 'row',
556
+ alignItems: 'center',
557
+ backgroundColor: AppColors_1.AppColors.primaryLight,
558
+ borderWidth: 1,
559
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
560
+ borderRadius: 8,
561
+ paddingHorizontal: 10,
562
+ height: 36,
563
+ gap: 8,
564
+ },
565
+ searchInput: {
566
+ flex: 1,
567
+ fontFamily: AppFonts_1.AppFonts.interRegular,
568
+ fontSize: 12,
569
+ color: AppColors_1.AppColors.primaryBlack,
570
+ paddingVertical: 0,
571
+ },
572
+ filterChipsRow: {
573
+ flexDirection: 'row',
574
+ alignItems: 'center',
575
+ gap: 8,
576
+ },
577
+ filterChip: {
578
+ flexDirection: 'row',
579
+ alignItems: 'center',
580
+ gap: 5,
581
+ paddingHorizontal: 10,
582
+ paddingVertical: 5,
583
+ borderRadius: 8,
584
+ backgroundColor: AppColors_1.AppColors.primaryLight,
585
+ borderWidth: 1,
586
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
587
+ },
588
+ filterChipActive: {
589
+ backgroundColor: AppColors_1.AppColors.purple,
590
+ borderColor: AppColors_1.AppColors.purple,
591
+ },
592
+ filterChipText: {
593
+ fontFamily: AppFonts_1.AppFonts.interMedium,
594
+ fontSize: 11,
595
+ color: AppColors_1.AppColors.grayText,
596
+ },
597
+ filterChipTextActive: {
598
+ fontFamily: AppFonts_1.AppFonts.interBold,
599
+ color: AppColors_1.AppColors.white,
600
+ },
601
+ frameCard: {
602
+ backgroundColor: AppColors_1.AppColors.primaryLight,
603
+ borderRadius: 8,
604
+ padding: 10,
605
+ borderWidth: 1,
606
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
607
+ gap: 4,
608
+ },
609
+ originFrameCard: {
610
+ borderColor: '#6EE7B7',
611
+ backgroundColor: '#F0FDF4',
612
+ },
613
+ frameCardHeader: {
614
+ flexDirection: 'row',
615
+ alignItems: 'center',
616
+ gap: 8,
617
+ },
618
+ frameIndexBadge: {
619
+ minWidth: 24,
620
+ height: 18,
621
+ paddingHorizontal: 4,
622
+ borderRadius: 4,
623
+ backgroundColor: `${AppColors_1.AppColors.purple}14`,
624
+ alignItems: 'center',
625
+ justifyContent: 'center',
626
+ },
627
+ frameIndexBadgeText: {
628
+ fontFamily: AppFonts_1.AppFonts.interBold,
629
+ fontSize: 9,
630
+ color: AppColors_1.AppColors.purple,
631
+ },
632
+ frameTypeBadge: {
633
+ paddingHorizontal: 5,
634
+ paddingVertical: 2,
635
+ borderRadius: 4,
636
+ borderWidth: 1,
637
+ },
638
+ frameTypeBadgeText: {
639
+ fontFamily: AppFonts_1.AppFonts.interBold,
640
+ fontSize: 8.5,
641
+ },
642
+ frameMethodText: {
643
+ fontFamily: AppFonts_1.AppFonts.interBold,
644
+ fontSize: 12,
645
+ color: AppColors_1.AppColors.primaryBlack,
646
+ flex: 1,
647
+ },
648
+ frameLocationRow: {
649
+ flexDirection: 'row',
650
+ alignItems: 'center',
651
+ },
652
+ frameFileText: {
653
+ fontFamily: AppFonts_1.AppFonts.interRegular,
654
+ fontSize: 11,
655
+ color: AppColors_1.AppColors.grayText,
656
+ flex: 1,
657
+ },
658
+ frameLineText: {
659
+ fontFamily: AppFonts_1.AppFonts.interBold,
660
+ fontSize: 11,
661
+ color: AppColors_1.AppColors.purple,
662
+ },
663
+ frameCopyBtn: {
664
+ flexDirection: 'row',
665
+ alignItems: 'center',
666
+ gap: 3,
667
+ paddingHorizontal: 6,
668
+ paddingVertical: 3,
669
+ borderRadius: 5,
670
+ backgroundColor: AppColors_1.AppColors.grayBackground,
671
+ borderWidth: 1,
672
+ borderColor: AppColors_1.AppColors.dividerColor,
673
+ },
674
+ frameCopyBtnText: {
675
+ fontFamily: AppFonts_1.AppFonts.interBold,
676
+ fontSize: 9,
677
+ color: AppColors_1.AppColors.grayText,
678
+ },
679
+ frameRawText: {
680
+ fontFamily: AppFonts_1.AppFonts.interRegular,
681
+ fontSize: 9.5,
682
+ color: AppColors_1.AppColors.grayTextWeak,
683
+ backgroundColor: `${AppColors_1.AppColors.primaryBlack}06`,
684
+ borderRadius: 5,
685
+ paddingHorizontal: 7,
686
+ paddingVertical: 4,
687
+ overflow: 'hidden',
688
+ },
689
+ componentStackText: {
690
+ fontFamily: AppFonts_1.AppFonts.interRegular,
691
+ fontSize: 11,
692
+ lineHeight: 16,
693
+ color: AppColors_1.AppColors.grayText,
694
+ backgroundColor: `${AppColors_1.AppColors.primaryBlack}06`,
695
+ borderRadius: 6,
696
+ padding: 10,
697
+ },
698
+ sectionCard: {
699
+ backgroundColor: AppColors_1.AppColors.primaryLight,
700
+ borderRadius: 10,
701
+ padding: 12,
702
+ borderWidth: 1,
703
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
704
+ gap: 10,
705
+ },
706
+ sectionCardHeader: {
707
+ flexDirection: 'row',
708
+ alignItems: 'center',
709
+ gap: 6,
710
+ paddingBottom: 6,
711
+ borderBottomWidth: 1,
712
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
713
+ },
714
+ sectionCardTitle: {
715
+ fontFamily: AppFonts_1.AppFonts.interBold,
716
+ fontSize: 12.5,
717
+ color: AppColors_1.AppColors.primaryBlack,
718
+ },
719
+ diagGrid: {
720
+ flexDirection: 'row',
721
+ flexWrap: 'wrap',
722
+ rowGap: 8,
723
+ columnGap: 12,
724
+ },
725
+ diagItem: {
726
+ width: '47%',
727
+ gap: 2,
728
+ },
729
+ diagLabel: {
730
+ fontFamily: AppFonts_1.AppFonts.interRegular,
731
+ fontSize: 10,
732
+ color: AppColors_1.AppColors.grayTextWeak,
733
+ },
734
+ diagValue: {
735
+ fontFamily: AppFonts_1.AppFonts.interBold,
736
+ fontSize: 11.5,
737
+ color: AppColors_1.AppColors.primaryBlack,
738
+ },
739
+ breadcrumbCard: {
740
+ backgroundColor: AppColors_1.AppColors.primaryLight,
741
+ borderRadius: 8,
742
+ padding: 10,
743
+ borderWidth: 1,
744
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
745
+ gap: 4,
746
+ },
747
+ breadcrumbHeader: {
748
+ flexDirection: 'row',
749
+ alignItems: 'center',
750
+ justifyContent: 'space-between',
751
+ },
752
+ breadcrumbTag: {
753
+ backgroundColor: `${AppColors_1.AppColors.purple}14`,
754
+ paddingHorizontal: 6,
755
+ paddingVertical: 2,
756
+ borderRadius: 4,
757
+ },
758
+ breadcrumbTagText: {
759
+ fontFamily: AppFonts_1.AppFonts.interBold,
760
+ fontSize: 9,
761
+ color: AppColors_1.AppColors.purple,
762
+ },
763
+ breadcrumbTime: {
764
+ fontFamily: AppFonts_1.AppFonts.interRegular,
765
+ fontSize: 10,
766
+ color: AppColors_1.AppColors.grayTextWeak,
767
+ },
768
+ breadcrumbMessage: {
769
+ fontFamily: AppFonts_1.AppFonts.interRegular,
770
+ fontSize: 11.5,
771
+ color: AppColors_1.AppColors.primaryBlack,
772
+ marginTop: 2,
773
+ },
774
+ rawContainer: {
775
+ backgroundColor: AppColors_1.AppColors.primaryLight,
776
+ borderRadius: 10,
777
+ padding: 10,
778
+ borderWidth: 1,
779
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
780
+ },
781
+ emptyContainer: {
782
+ padding: 16,
783
+ alignItems: 'center',
784
+ justifyContent: 'center',
785
+ backgroundColor: AppColors_1.AppColors.primaryLight,
786
+ borderRadius: 8,
787
+ borderWidth: 1,
788
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
789
+ },
790
+ emptyText: {
791
+ fontFamily: AppFonts_1.AppFonts.interRegular,
792
+ fontSize: 11,
793
+ color: AppColors_1.AppColors.grayText,
794
+ textAlign: 'center',
795
+ },
796
+ });