react-native-inapp-inspector 1.1.26 → 1.1.28

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 (67) hide show
  1. package/android/build.gradle +1 -0
  2. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +34 -0
  3. package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
  4. package/dist/commonjs/components/ErrorBoundary.js +530 -100
  5. package/dist/commonjs/components/Inspector/AnalyticsTab.js +176 -126
  6. package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -0
  7. package/dist/commonjs/components/Inspector/BundleTab.js +145 -21
  8. package/dist/commonjs/components/Inspector/CrashTab.js +0 -8
  9. package/dist/commonjs/components/Inspector/NetworkDetail.js +41 -0
  10. package/dist/commonjs/components/Inspector/PerformanceTab.d.ts +5 -0
  11. package/dist/commonjs/components/Inspector/PerformanceTab.js +588 -155
  12. package/dist/commonjs/components/Inspector/SettingsPanel.js +57 -22
  13. package/dist/commonjs/components/Inspector/TabBar.js +13 -1
  14. package/dist/commonjs/components/LogCard.js +75 -34
  15. package/dist/commonjs/components/NetworkIcons.d.ts +112 -102
  16. package/dist/commonjs/constants/version.d.ts +1 -1
  17. package/dist/commonjs/constants/version.js +1 -1
  18. package/dist/commonjs/customHooks/analyticsLogger.d.ts +1 -11
  19. package/dist/commonjs/customHooks/analyticsLogger.js +8 -1
  20. package/dist/commonjs/customHooks/bundleAnalyzer.js +121 -124
  21. package/dist/commonjs/customHooks/networkLogger.d.ts +1 -0
  22. package/dist/commonjs/customHooks/networkLogger.js +16 -0
  23. package/dist/commonjs/customHooks/performanceTracker.d.ts +74 -0
  24. package/dist/commonjs/customHooks/performanceTracker.js +546 -392
  25. package/dist/commonjs/customHooks/reduxLogger.d.ts +1 -0
  26. package/dist/commonjs/customHooks/reduxLogger.js +3 -1
  27. package/dist/commonjs/helpers/index.js +27 -3
  28. package/dist/commonjs/i18n/locales/en.json +225 -4
  29. package/dist/commonjs/index.d.ts +1 -1
  30. package/dist/commonjs/index.js +36 -2
  31. package/dist/commonjs/styles/index.d.ts +3 -1
  32. package/dist/commonjs/styles/index.js +8 -6
  33. package/dist/commonjs/types/interfaces.d.ts +3 -0
  34. package/dist/esm/components/ErrorBoundary.d.ts +1 -1
  35. package/dist/esm/components/ErrorBoundary.js +498 -101
  36. package/dist/esm/components/Inspector/AnalyticsTab.js +177 -127
  37. package/dist/esm/components/Inspector/BundleTab.d.ts +1 -0
  38. package/dist/esm/components/Inspector/BundleTab.js +145 -23
  39. package/dist/esm/components/Inspector/CrashTab.js +0 -8
  40. package/dist/esm/components/Inspector/NetworkDetail.js +41 -0
  41. package/dist/esm/components/Inspector/PerformanceTab.d.ts +5 -0
  42. package/dist/esm/components/Inspector/PerformanceTab.js +591 -158
  43. package/dist/esm/components/Inspector/SettingsPanel.js +57 -22
  44. package/dist/esm/components/Inspector/TabBar.js +13 -1
  45. package/dist/esm/components/LogCard.js +75 -34
  46. package/dist/esm/components/NetworkIcons.d.ts +112 -102
  47. package/dist/esm/constants/version.d.ts +1 -1
  48. package/dist/esm/constants/version.js +1 -1
  49. package/dist/esm/customHooks/analyticsLogger.d.ts +1 -11
  50. package/dist/esm/customHooks/analyticsLogger.js +6 -0
  51. package/dist/esm/customHooks/bundleAnalyzer.js +121 -124
  52. package/dist/esm/customHooks/networkLogger.d.ts +1 -0
  53. package/dist/esm/customHooks/networkLogger.js +16 -0
  54. package/dist/esm/customHooks/performanceTracker.d.ts +74 -0
  55. package/dist/esm/customHooks/performanceTracker.js +531 -391
  56. package/dist/esm/customHooks/reduxLogger.d.ts +1 -0
  57. package/dist/esm/customHooks/reduxLogger.js +1 -0
  58. package/dist/esm/helpers/index.js +27 -3
  59. package/dist/esm/i18n/locales/en.json +225 -4
  60. package/dist/esm/index.d.ts +1 -1
  61. package/dist/esm/index.js +24 -3
  62. package/dist/esm/styles/index.d.ts +3 -1
  63. package/dist/esm/styles/index.js +8 -6
  64. package/dist/esm/types/interfaces.d.ts +3 -0
  65. package/ios/NetworkInspectorModule.h +2 -0
  66. package/ios/NetworkInspectorModule.m +10 -0
  67. package/package.json +1 -1
@@ -1,42 +1,74 @@
1
- import { Component } from 'react';
2
- import { StyleSheet } from 'react-native';
1
+ import React, { Component } from 'react';
2
+ import { StyleSheet, Text, View, ScrollView, TouchableOpacity, SafeAreaView, } from 'react-native';
3
3
  import { AppColors } from '../styles/AppColors';
4
4
  import { AppFonts } from '../styles/AppFonts';
5
5
  import { copyToClipboard } from '../helpers';
6
+ import { t } from '../i18n';
7
+ import { WarningTriangleIcon, CopyIcon, RefreshCcwIcon, ClearIcon, CircleAlertIcon, } from './NetworkIcons';
6
8
  import { handleInterceptedCrash } from '../customHooks/crashHandler';
7
9
  import { CrashType } from '../types/enums';
8
10
  function parseStackTrace(stack) {
9
11
  if (!stack)
10
- return null;
12
+ return { rootFrame: null, frames: [] };
11
13
  const lines = stack.split('\n');
14
+ const frames = [];
12
15
  for (const line of lines) {
13
16
  if (line.includes('ErrorBoundary') ||
14
17
  line.includes('getDerivedStateFromError') ||
15
- line.includes('componentDidCatch')) {
18
+ line.includes('componentDidCatch') ||
19
+ line.includes('handleInterceptedCrash')) {
16
20
  continue;
17
21
  }
18
- // Matching ios format: method@url:line:col
19
- const iosMatch = line.match(/^([^@]+)@(.*):(\d+):(\d+)$/);
22
+ // iOS format: method@url:line:col
23
+ const iosMatch = line.match(/^([^@]*)@(.*):(\d+):(\d+)$/);
20
24
  if (iosMatch) {
21
- const [, method, file, lineNum, colNum] = iosMatch;
22
- const cleanFile = file.split('?')[0].split('/').pop() || file;
23
- return { method: method.trim(), file: cleanFile, line: lineNum, column: colNum };
25
+ const [, method, fullPath, lineNum, colNum] = iosMatch;
26
+ const cleanFile = fullPath.split('?')[0].split('/').pop() || fullPath;
27
+ const isProject = !fullPath.includes('node_modules') && !fullPath.includes('Libraries/Core');
28
+ frames.push({
29
+ method: method.trim() || 'anonymous',
30
+ file: cleanFile,
31
+ fullPath: fullPath.split('?')[0],
32
+ line: lineNum,
33
+ column: colNum,
34
+ isProjectFile: isProject,
35
+ });
36
+ continue;
24
37
  }
25
- // Matching android format: at method (url:line:col) or at url:line:col
38
+ // Android format: at method (url:line:col) or at url:line:col
26
39
  const androidMatch = line.match(/^\s*at\s+(.+)\s+\((.+):(\d+):(\d+)\)$/);
27
40
  if (androidMatch) {
28
- const [, method, file, lineNum, colNum] = androidMatch;
29
- const cleanFile = file.split('?')[0].split('/').pop() || file;
30
- return { method: method.trim(), file: cleanFile, line: lineNum, column: colNum };
41
+ const [, method, fullPath, lineNum, colNum] = androidMatch;
42
+ const cleanFile = fullPath.split('?')[0].split('/').pop() || fullPath;
43
+ const isProject = !fullPath.includes('node_modules') && !fullPath.includes('Libraries/Core');
44
+ frames.push({
45
+ method: method.trim(),
46
+ file: cleanFile,
47
+ fullPath: fullPath.split('?')[0],
48
+ line: lineNum,
49
+ column: colNum,
50
+ isProjectFile: isProject,
51
+ });
52
+ continue;
31
53
  }
32
54
  const androidMatchSimple = line.match(/^\s*at\s+(.+):(\d+):(\d+)$/);
33
55
  if (androidMatchSimple) {
34
- const [, file, lineNum, colNum] = androidMatchSimple;
35
- const cleanFile = file.split('?')[0].split('/').pop() || file;
36
- return { method: 'anonymous', file: cleanFile, line: lineNum, column: colNum };
56
+ const [, fullPath, lineNum, colNum] = androidMatchSimple;
57
+ const cleanFile = fullPath.split('?')[0].split('/').pop() || fullPath;
58
+ const isProject = !fullPath.includes('node_modules') && !fullPath.includes('Libraries/Core');
59
+ frames.push({
60
+ method: 'anonymous',
61
+ file: cleanFile,
62
+ fullPath: fullPath.split('?')[0],
63
+ line: lineNum,
64
+ column: colNum,
65
+ isProjectFile: isProject,
66
+ });
37
67
  }
38
68
  }
39
- return null;
69
+ // Find topmost project frame, or fallback to first frame
70
+ const rootFrame = frames.find(f => f.isProjectFile) || frames[0] || null;
71
+ return { rootFrame, frames };
40
72
  }
41
73
  export class ErrorBoundary extends Component {
42
74
  constructor() {
@@ -54,14 +86,19 @@ export class ErrorBoundary extends Component {
54
86
  this.handleCopyTrace = () => {
55
87
  const error = this.state.error;
56
88
  if (error) {
57
- const isNativeCrash = error.message.includes('Native') || error.message.includes('native') || error.message.includes('Swift') || error.message.includes('Java');
58
- const parsed = error.stack ? parseStackTrace(error.stack) : null;
59
- const detailStr = `Crash Source: ${isNativeCrash ? 'Native Crash' : 'JavaScript Crash'}
89
+ const { rootFrame } = parseStackTrace(error.stack || '');
90
+ const detailStr = `─────────────────────────────────────────────────────────────
91
+ IN-APP INSPECTOR INTERCEPTED CRASH REPORT
92
+ ─────────────────────────────────────────────────────────────
93
+ Error: ${error.name || 'Error'}
60
94
  Message: ${error.message}
61
- ${parsed ? `Method: ${parsed.method}\nFile: ${parsed.file}\nLine: ${parsed.line}:${parsed.column}` : ''}
95
+ ${rootFrame ? `Location: ${rootFrame.file}:${rootFrame.line}:${rootFrame.column}\nMethod: ${rootFrame.method}\nPath: ${rootFrame.fullPath}` : ''}
96
+ Timestamp: ${new Date().toISOString()}
97
+
62
98
  Stack Trace:
63
- ${error.stack}`;
64
- copyToClipboard(detailStr, 'Crash traceback');
99
+ ${error.stack || 'No stack trace available'}
100
+ ─────────────────────────────────────────────────────────────`;
101
+ copyToClipboard(detailStr, t('errors.errorReport'));
65
102
  }
66
103
  };
67
104
  }
@@ -70,132 +107,492 @@ ${error.stack}`;
70
107
  }
71
108
  componentDidCatch(error, errorInfo) {
72
109
  try {
73
- const stack = error?.stack || errorInfo?.componentStack;
110
+ const stack = error?.stack || errorInfo?.componentStack || '';
74
111
  handleInterceptedCrash(error, stack, false, CrashType.Render, errorInfo?.componentStack);
75
112
  }
76
113
  catch { }
77
114
  }
78
115
  render() {
79
- if (this.state.hasError) {
80
- return null;
116
+ const { hasError, error } = this.state;
117
+ if (!hasError || !error) {
118
+ return this.props.children;
81
119
  }
82
- return this.props.children;
120
+ const { rootFrame, frames } = parseStackTrace(error.stack || '');
121
+ const errorType = error.name || t('errors.title');
122
+ const isSyntaxOrType = errorType.includes('Syntax') ||
123
+ errorType.includes('Type') ||
124
+ errorType.includes('Reference');
125
+ // ─── Inline Fallback View ─────────────────────────────────────────────
126
+ if (this.props.fallbackType === 'inline') {
127
+ return (<View style={styles.inlineContainer}>
128
+ <View style={styles.inlineHeader}>
129
+ <WarningTriangleIcon color={AppColors.red600} size={18}/>
130
+ <View style={{ flex: 1 }}>
131
+ <Text style={styles.inlineTitle} numberOfLines={1}>
132
+ {errorType}: {error.message}
133
+ </Text>
134
+ {rootFrame && (<Text style={styles.inlineLoc} numberOfLines={1}>
135
+ {rootFrame.file}:{rootFrame.line} ({rootFrame.method})
136
+ </Text>)}
137
+ </View>
138
+ </View>
139
+ <View style={styles.inlineActions}>
140
+ <TouchableOpacity onPress={this.handleReset} style={styles.inlineBtn} activeOpacity={0.7}>
141
+ <RefreshCcwIcon size={12} color={AppColors.white}/>
142
+ <Text style={styles.inlineBtnText}>{t('errors.retry')}</Text>
143
+ </TouchableOpacity>
144
+ <TouchableOpacity onPress={this.handleCopyTrace} style={styles.inlineCopyBtn} activeOpacity={0.7}>
145
+ <CopyIcon size={12} color={AppColors.redErrorText}/>
146
+ <Text style={styles.inlineCopyBtnText}>{t('errors.copy')}</Text>
147
+ </TouchableOpacity>
148
+ </View>
149
+ </View>);
150
+ }
151
+ // ─── Full-Screen Custom Native Recovery Modal ─────────────────────────
152
+ return (<SafeAreaView style={styles.safeArea}>
153
+ <View style={styles.container}>
154
+ {/* Header Banner */}
155
+ <View style={styles.header}>
156
+ <View style={styles.iconGlowWrap}>
157
+ <WarningTriangleIcon color={AppColors.red500} size={28}/>
158
+ </View>
159
+ <View style={{ flex: 1 }}>
160
+ <View style={styles.badgeRow}>
161
+ <View style={styles.crashBadge}>
162
+ <Text style={styles.crashBadgeText}>
163
+ {isSyntaxOrType ? `JS ${errorType.toUpperCase()}` : t('errors.crashIntercepted')}
164
+ </Text>
165
+ </View>
166
+ <View style={styles.shieldBadge}>
167
+ <Text style={styles.shieldBadgeText}>{t('errors.protected')}</Text>
168
+ </View>
169
+ </View>
170
+ <Text style={styles.title}>{t('errors.rootCauseTitle')}</Text>
171
+ <Text style={styles.subtitle}>{t('errors.rootCauseSubtitle')}</Text>
172
+ </View>
173
+ {this.props.onClose && (<TouchableOpacity onPress={this.props.onClose} style={styles.closeIconBtn} activeOpacity={0.7}>
174
+ <ClearIcon size={16} color={AppColors.slate400}/>
175
+ </TouchableOpacity>)}
176
+ </View>
177
+
178
+ <ScrollView style={styles.scrollArea} contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
179
+ {/* Error Message Box */}
180
+ <View style={styles.errorBox}>
181
+ <View style={styles.errorBoxHeader}>
182
+ <CircleAlertIcon size={14} color={AppColors.red500}/>
183
+ <Text style={styles.errorBoxTitle}>{errorType}</Text>
184
+ </View>
185
+ <Text style={styles.errorMessage}>{error.message}</Text>
186
+ </View>
187
+
188
+ {/* Root Cause Location Card */}
189
+ {rootFrame && (<View style={styles.locationCard}>
190
+ <Text style={styles.cardHeaderTitle}>{t('errors.exactLocation')}</Text>
191
+ <View style={styles.locRow}>
192
+ <Text style={styles.locLabel}>{t('errors.file')}</Text>
193
+ <Text style={styles.locValFile} numberOfLines={1}>
194
+ {rootFrame.file}
195
+ </Text>
196
+ </View>
197
+ <View style={styles.locRow}>
198
+ <Text style={styles.locLabel}>{t('errors.lineCol')}</Text>
199
+ <Text style={styles.locValNum}>
200
+ {t('errors.lineColVal', { line: rootFrame.line, col: rootFrame.column })}
201
+ </Text>
202
+ </View>
203
+ <View style={styles.locRow}>
204
+ <Text style={styles.locLabel}>{t('errors.function')}</Text>
205
+ <Text style={styles.locValMethod}>{rootFrame.method}()</Text>
206
+ </View>
207
+ {rootFrame.fullPath ? (<Text style={styles.fullPathText} numberOfLines={2}>
208
+ {rootFrame.fullPath}
209
+ </Text>) : null}
210
+ </View>)}
211
+
212
+ {/* Formatted Stack Frames */}
213
+ <View style={styles.stackCard}>
214
+ <View style={styles.stackCardHeader}>
215
+ <Text style={styles.cardHeaderTitle}>{t('errors.callStack')}</Text>
216
+ <Text style={styles.frameCountText}>
217
+ {t('errors.framesCount', { count: frames.length })}
218
+ </Text>
219
+ </View>
220
+
221
+ {frames.slice(0, 8).map((frame, idx) => (<View key={idx} style={[
222
+ styles.frameItem,
223
+ frame.isProjectFile && styles.frameItemProject,
224
+ ]}>
225
+ <View style={styles.frameNumBadge}>
226
+ <Text style={[
227
+ styles.frameNumText,
228
+ frame.isProjectFile && { color: AppColors.sky400 },
229
+ ]}>
230
+ #{idx + 1}
231
+ </Text>
232
+ </View>
233
+ <View style={{ flex: 1 }}>
234
+ <Text style={[
235
+ styles.frameMethod,
236
+ frame.isProjectFile && styles.frameMethodProject,
237
+ ]} numberOfLines={1}>
238
+ {frame.method}
239
+ </Text>
240
+ <Text style={styles.frameLoc} numberOfLines={1}>
241
+ {frame.file}:{frame.line}:{frame.column}
242
+ </Text>
243
+ </View>
244
+ {frame.isProjectFile && (<View style={styles.appTag}>
245
+ <Text style={styles.appTagText}>{t('errors.appTag')}</Text>
246
+ </View>)}
247
+ </View>))}
248
+ </View>
249
+ </ScrollView>
250
+
251
+ {/* Action Buttons Footer */}
252
+ <View style={styles.footer}>
253
+ <TouchableOpacity onPress={this.handleReset} style={styles.retryBtn} activeOpacity={0.8}>
254
+ <RefreshCcwIcon size={16} color={AppColors.white}/>
255
+ <Text style={styles.retryBtnText}>{t('errors.tryAgainRecover')}</Text>
256
+ </TouchableOpacity>
257
+
258
+ <TouchableOpacity onPress={this.handleCopyTrace} style={styles.copyBtn} activeOpacity={0.8}>
259
+ <CopyIcon size={16} color={AppColors.slate900}/>
260
+ <Text style={styles.copyBtnText}>{t('errors.copyDiagnostics')}</Text>
261
+ </TouchableOpacity>
262
+ </View>
263
+ </View>
264
+ </SafeAreaView>);
83
265
  }
84
266
  }
85
- const monoFont = AppFonts.interRegular;
86
267
  const styles = StyleSheet.create({
268
+ safeArea: {
269
+ flex: 1,
270
+ backgroundColor: AppColors.slate850,
271
+ },
87
272
  container: {
88
273
  flex: 1,
89
- backgroundColor: `${AppColors.black}4D`,
90
- justifyContent: 'center',
274
+ backgroundColor: AppColors.slate850,
275
+ },
276
+ header: {
277
+ flexDirection: 'row',
278
+ alignItems: 'flex-start',
279
+ paddingHorizontal: 16,
280
+ paddingTop: 14,
281
+ paddingBottom: 12,
282
+ borderBottomWidth: 1,
283
+ borderBottomColor: AppColors.slate800,
284
+ gap: 12,
285
+ },
286
+ iconGlowWrap: {
287
+ width: 44,
288
+ height: 44,
289
+ borderRadius: 12,
290
+ backgroundColor: `${AppColors.red500}26`,
291
+ borderWidth: 1,
292
+ borderColor: `${AppColors.red500}59`,
91
293
  alignItems: 'center',
92
- padding: 16,
294
+ justifyContent: 'center',
295
+ marginTop: 2,
93
296
  },
94
- card: {
95
- width: '100%',
96
- maxWidth: 400,
97
- backgroundColor: AppColors.white,
98
- borderRadius: 16,
99
- padding: 20,
297
+ badgeRow: {
298
+ flexDirection: 'row',
100
299
  alignItems: 'center',
101
- shadowColor: AppColors.black,
102
- shadowOffset: { width: 0, height: 4 },
103
- shadowOpacity: 0.1,
104
- shadowRadius: 12,
105
- elevation: 8,
300
+ gap: 6,
301
+ marginBottom: 4,
302
+ },
303
+ crashBadge: {
304
+ backgroundColor: `${AppColors.red500}33`,
305
+ paddingHorizontal: 7,
306
+ paddingVertical: 2,
307
+ borderRadius: 4,
308
+ borderWidth: 1,
309
+ borderColor: `${AppColors.red500}66`,
310
+ },
311
+ crashBadgeText: {
312
+ fontFamily: AppFonts.interBold,
313
+ fontSize: 9.5,
314
+ color: AppColors.red500,
315
+ letterSpacing: 0.5,
316
+ },
317
+ shieldBadge: {
318
+ backgroundColor: `${AppColors.emerald500}26`,
319
+ paddingHorizontal: 6,
320
+ paddingVertical: 2,
321
+ borderRadius: 4,
322
+ borderWidth: 1,
323
+ borderColor: `${AppColors.emerald500}4D`,
324
+ },
325
+ shieldBadgeText: {
326
+ fontFamily: AppFonts.interBold,
327
+ fontSize: 9,
328
+ color: AppColors.emerald500,
329
+ letterSpacing: 0.5,
106
330
  },
107
331
  title: {
108
- fontFamily: AppFonts.interBold || 'System',
109
- fontSize: 18,
110
- color: AppColors.slate900,
111
- marginBottom: 8,
112
- textAlign: 'center',
332
+ fontFamily: AppFonts.interBold,
333
+ fontSize: 16,
334
+ color: AppColors.white,
335
+ letterSpacing: -0.2,
113
336
  },
114
337
  subtitle: {
115
- fontFamily: AppFonts.interRegular || 'System',
116
- fontSize: 12,
117
- color: AppColors.slate500,
118
- lineHeight: 18,
119
- textAlign: 'center',
120
- marginBottom: 16,
121
- },
122
- scroll: {
123
- width: '100%',
124
- maxHeight: 180,
125
- backgroundColor: AppColors.slate50,
338
+ fontFamily: AppFonts.interRegular,
339
+ fontSize: 11,
340
+ color: AppColors.slate400,
341
+ marginTop: 1,
342
+ },
343
+ closeIconBtn: {
344
+ padding: 6,
126
345
  borderRadius: 8,
127
- borderWidth: 1,
128
- borderColor: AppColors.slate200,
129
- padding: 10,
130
- marginBottom: 20,
346
+ backgroundColor: AppColors.slate800,
347
+ },
348
+ scrollArea: {
349
+ flex: 1,
131
350
  },
132
351
  scrollContent: {
133
- paddingBottom: 10,
352
+ padding: 16,
353
+ gap: 12,
134
354
  },
135
- code: {
136
- fontFamily: monoFont,
137
- fontSize: 11,
138
- color: AppColors.rose600,
355
+ errorBox: {
356
+ backgroundColor: `${AppColors.red500}1A`,
357
+ borderRadius: 12,
358
+ borderWidth: 1,
359
+ borderColor: `${AppColors.red500}40`,
360
+ padding: 14,
361
+ gap: 6,
139
362
  },
140
- btnRow: {
363
+ errorBoxHeader: {
141
364
  flexDirection: 'row',
142
- gap: 12,
143
- width: '100%',
365
+ alignItems: 'center',
366
+ gap: 6,
367
+ },
368
+ errorBoxTitle: {
369
+ fontFamily: AppFonts.interBold,
370
+ fontSize: 12,
371
+ color: AppColors.red500,
372
+ letterSpacing: 0.3,
373
+ },
374
+ errorMessage: {
375
+ fontFamily: AppFonts.interBold,
376
+ fontSize: 13.5,
377
+ color: AppColors.red100,
378
+ lineHeight: 19,
379
+ },
380
+ locationCard: {
381
+ backgroundColor: AppColors.slate800,
382
+ borderRadius: 12,
383
+ padding: 14,
384
+ borderWidth: 1,
385
+ borderColor: AppColors.slate700,
386
+ gap: 8,
144
387
  },
145
- resetBtn: {
388
+ cardHeaderTitle: {
389
+ fontFamily: AppFonts.interBold,
390
+ fontSize: 10.5,
391
+ color: AppColors.slate400,
392
+ letterSpacing: 0.8,
393
+ },
394
+ locRow: {
395
+ flexDirection: 'row',
396
+ alignItems: 'center',
397
+ justifyContent: 'space-between',
398
+ gap: 8,
399
+ },
400
+ locLabel: {
401
+ fontFamily: AppFonts.interMedium,
402
+ fontSize: 12,
403
+ color: AppColors.slate400,
404
+ minWidth: 80,
405
+ },
406
+ locValFile: {
407
+ fontFamily: AppFonts.interBold,
408
+ fontSize: 12.5,
409
+ color: AppColors.sky400,
146
410
  flex: 1,
147
- backgroundColor: AppColors.purple,
148
- height: 40,
411
+ textAlign: 'right',
412
+ },
413
+ locValNum: {
414
+ fontFamily: AppFonts.interBold,
415
+ fontSize: 12,
416
+ color: AppColors.white,
417
+ },
418
+ locValMethod: {
419
+ fontFamily: AppFonts.interMedium,
420
+ fontSize: 12,
421
+ color: AppColors.purple400,
422
+ },
423
+ fullPathText: {
424
+ fontFamily: AppFonts.interRegular,
425
+ fontSize: 10,
426
+ color: AppColors.slate500,
427
+ marginTop: 2,
428
+ paddingTop: 6,
429
+ borderTopWidth: 1,
430
+ borderTopColor: AppColors.slate700,
431
+ },
432
+ stackCard: {
433
+ backgroundColor: AppColors.slate800,
434
+ borderRadius: 12,
435
+ padding: 14,
436
+ borderWidth: 1,
437
+ borderColor: AppColors.slate700,
438
+ gap: 8,
439
+ },
440
+ stackCardHeader: {
441
+ flexDirection: 'row',
442
+ justifyContent: 'space-between',
443
+ alignItems: 'center',
444
+ marginBottom: 4,
445
+ },
446
+ frameCountText: {
447
+ fontFamily: AppFonts.interMedium,
448
+ fontSize: 10.5,
449
+ color: AppColors.slate400,
450
+ },
451
+ frameItem: {
452
+ flexDirection: 'row',
453
+ alignItems: 'center',
454
+ backgroundColor: AppColors.slate850,
455
+ padding: 10,
149
456
  borderRadius: 8,
150
- justifyContent: 'center',
457
+ gap: 10,
458
+ borderWidth: 1,
459
+ borderColor: AppColors.slate800,
460
+ },
461
+ frameItemProject: {
462
+ borderColor: `${AppColors.sky400}4D`,
463
+ backgroundColor: `${AppColors.sky400}0D`,
464
+ },
465
+ frameNumBadge: {
466
+ width: 24,
151
467
  alignItems: 'center',
152
468
  },
153
- resetBtnText: {
154
- fontFamily: AppFonts.interBold || 'System',
469
+ frameNumText: {
470
+ fontFamily: AppFonts.interBold,
471
+ fontSize: 10.5,
472
+ color: AppColors.slate500,
473
+ },
474
+ frameMethod: {
475
+ fontFamily: AppFonts.interBold,
476
+ fontSize: 11.5,
477
+ color: AppColors.slate200,
478
+ },
479
+ frameMethodProject: {
480
+ color: AppColors.white,
481
+ },
482
+ frameLoc: {
483
+ fontFamily: AppFonts.interRegular,
484
+ fontSize: 10,
485
+ color: AppColors.slate400,
486
+ marginTop: 1,
487
+ },
488
+ appTag: {
489
+ backgroundColor: `${AppColors.sky400}33`,
490
+ paddingHorizontal: 5,
491
+ paddingVertical: 2,
492
+ borderRadius: 4,
493
+ },
494
+ appTagText: {
495
+ fontFamily: AppFonts.interBold,
496
+ fontSize: 8.5,
497
+ color: AppColors.sky400,
498
+ },
499
+ footer: {
500
+ flexDirection: 'row',
501
+ padding: 14,
502
+ backgroundColor: AppColors.slate800,
503
+ borderTopWidth: 1,
504
+ borderTopColor: AppColors.slate700,
505
+ gap: 10,
506
+ },
507
+ retryBtn: {
508
+ flex: 1.2,
509
+ flexDirection: 'row',
510
+ alignItems: 'center',
511
+ justifyContent: 'center',
512
+ gap: 8,
513
+ backgroundColor: AppColors.purple,
514
+ height: 44,
515
+ borderRadius: 10,
516
+ },
517
+ retryBtnText: {
518
+ fontFamily: AppFonts.interBold,
155
519
  fontSize: 13,
156
520
  color: AppColors.white,
157
521
  },
158
- closeBtn: {
522
+ copyBtn: {
159
523
  flex: 1,
160
- backgroundColor: AppColors.slate100,
161
- borderWidth: 1,
162
- borderColor: AppColors.slate200,
163
- height: 40,
164
- borderRadius: 8,
165
- justifyContent: 'center',
524
+ flexDirection: 'row',
166
525
  alignItems: 'center',
526
+ justifyContent: 'center',
527
+ gap: 8,
528
+ backgroundColor: AppColors.slate100,
529
+ height: 44,
530
+ borderRadius: 10,
167
531
  },
168
- closeBtnText: {
169
- fontFamily: AppFonts.interBold || 'System',
532
+ copyBtnText: {
533
+ fontFamily: AppFonts.interBold,
170
534
  fontSize: 13,
171
- color: AppColors.slate600,
535
+ color: AppColors.slate900,
172
536
  },
173
537
  inlineContainer: {
174
- padding: 8,
175
- backgroundColor: AppColors.roseBg,
538
+ padding: 12,
539
+ backgroundColor: AppColors.red50,
176
540
  borderWidth: 1,
177
541
  borderColor: AppColors.errorBorder,
178
- borderRadius: 8,
179
- flexDirection: 'row',
180
- alignItems: 'center',
181
- justifyContent: 'space-between',
542
+ borderRadius: 10,
182
543
  margin: 8,
544
+ gap: 10,
545
+ },
546
+ inlineHeader: {
547
+ flexDirection: 'row',
548
+ alignItems: 'flex-start',
549
+ gap: 10,
183
550
  },
184
551
  inlineTitle: {
185
- fontFamily: AppFonts.interBold || 'System',
186
- fontSize: 11,
552
+ fontFamily: AppFonts.interBold,
553
+ fontSize: 12,
554
+ color: AppColors.red600,
555
+ },
556
+ inlineLoc: {
557
+ fontFamily: AppFonts.interMedium,
558
+ fontSize: 10.5,
187
559
  color: AppColors.redErrorText,
560
+ marginTop: 2,
188
561
  },
189
- inlineResetBtn: {
190
- backgroundColor: AppColors.redErrorText,
562
+ inlineActions: {
563
+ flexDirection: 'row',
564
+ gap: 8,
565
+ justifyContent: 'flex-end',
566
+ },
567
+ inlineBtn: {
568
+ flexDirection: 'row',
569
+ alignItems: 'center',
570
+ gap: 4,
571
+ backgroundColor: AppColors.red600,
191
572
  paddingHorizontal: 10,
192
- paddingVertical: 4,
193
- borderRadius: 4,
573
+ paddingVertical: 5,
574
+ borderRadius: 6,
194
575
  },
195
- inlineResetText: {
196
- fontFamily: AppFonts.interBold || 'System',
197
- fontSize: 10,
576
+ inlineBtnText: {
577
+ fontFamily: AppFonts.interBold,
578
+ fontSize: 11,
198
579
  color: AppColors.white,
199
580
  },
581
+ inlineCopyBtn: {
582
+ flexDirection: 'row',
583
+ alignItems: 'center',
584
+ gap: 4,
585
+ backgroundColor: AppColors.red100,
586
+ borderWidth: 1,
587
+ borderColor: AppColors.errorBorder,
588
+ paddingHorizontal: 10,
589
+ paddingVertical: 5,
590
+ borderRadius: 6,
591
+ },
592
+ inlineCopyBtnText: {
593
+ fontFamily: AppFonts.interMedium,
594
+ fontSize: 11,
595
+ color: AppColors.redErrorText,
596
+ },
200
597
  });
201
598
  export default ErrorBoundary;