react-native-inapp-inspector 1.1.34 → 2.0.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 (122) hide show
  1. package/README.md +123 -101
  2. package/android/build.gradle +13 -1
  3. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +904 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
  5. package/dist/commonjs/components/ConsoleLogCard.js +57 -56
  6. package/dist/commonjs/components/CopyButton.js +10 -1
  7. package/dist/commonjs/components/ErrorBoundary.js +3 -0
  8. package/dist/commonjs/components/Inspector/AnalyticsTab.js +7 -3
  9. package/dist/commonjs/components/Inspector/BundleTab.js +20 -20
  10. package/dist/commonjs/components/Inspector/ConsoleTab.js +1 -1
  11. package/dist/commonjs/components/Inspector/CrashDetail.js +16 -12
  12. package/dist/commonjs/components/Inspector/CrashTab.js +97 -90
  13. package/dist/commonjs/components/Inspector/InspectorHeader.js +28 -24
  14. package/dist/commonjs/components/Inspector/MainScreen.js +20 -103
  15. package/dist/commonjs/components/Inspector/NetworkTab.js +143 -10
  16. package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
  17. package/dist/commonjs/components/Inspector/ReduxDetail.js +24 -19
  18. package/dist/commonjs/components/Inspector/ReduxTab.js +30 -18
  19. package/dist/commonjs/components/Inspector/SettingsPanel.js +1578 -754
  20. package/dist/commonjs/components/Inspector/TabBar.js +6 -3
  21. package/dist/commonjs/components/LogCard.js +27 -9
  22. package/dist/commonjs/components/MetaAccordion.js +42 -0
  23. package/dist/commonjs/components/NetworkIcons.d.ts +10 -0
  24. package/dist/commonjs/components/NetworkIcons.js +53 -1
  25. package/dist/commonjs/components/Toast.js +3 -3
  26. package/dist/commonjs/components/TouchableScale.d.ts +5 -2
  27. package/dist/commonjs/components/TouchableScale.js +30 -32
  28. package/dist/commonjs/constants/index.d.ts +1 -2
  29. package/dist/commonjs/constants/index.js +4 -0
  30. package/dist/commonjs/constants/version.d.ts +1 -1
  31. package/dist/commonjs/constants/version.js +1 -1
  32. package/dist/commonjs/customHooks/analyticsLogger.d.ts +6 -0
  33. package/dist/commonjs/customHooks/analyticsLogger.js +16 -5
  34. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +2 -0
  35. package/dist/commonjs/customHooks/bundleAnalyzer.js +26 -17
  36. package/dist/commonjs/customHooks/consoleLogger.d.ts +2 -0
  37. package/dist/commonjs/customHooks/consoleLogger.js +10 -1
  38. package/dist/commonjs/customHooks/crashHandler.d.ts +2 -0
  39. package/dist/commonjs/customHooks/crashHandler.js +17 -1
  40. package/dist/commonjs/customHooks/networkLogger.d.ts +2 -0
  41. package/dist/commonjs/customHooks/networkLogger.js +12 -1
  42. package/dist/commonjs/customHooks/performanceTracker.d.ts +3 -1
  43. package/dist/commonjs/customHooks/performanceTracker.js +18 -4
  44. package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -0
  45. package/dist/commonjs/customHooks/reduxLogger.js +10 -1
  46. package/dist/commonjs/helpers/index.js +10 -1
  47. package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
  48. package/dist/commonjs/helpers/settingsStore.js +59 -3
  49. package/dist/commonjs/i18n/locales/en.json +96 -28
  50. package/dist/commonjs/index.d.ts +1 -0
  51. package/dist/commonjs/index.js +307 -73
  52. package/dist/commonjs/native/NativeInspector.d.ts +125 -0
  53. package/dist/commonjs/native/NativeInspector.js +313 -0
  54. package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
  55. package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
  56. package/dist/commonjs/styles/AppColors.d.ts +28 -0
  57. package/dist/commonjs/styles/AppColors.js +30 -0
  58. package/dist/commonjs/styles/index.js +6 -6
  59. package/dist/commonjs/types/enums.d.ts +1 -1
  60. package/dist/commonjs/types/interfaces.d.ts +9 -0
  61. package/dist/esm/components/ConsoleLogCard.js +58 -57
  62. package/dist/esm/components/CopyButton.js +10 -1
  63. package/dist/esm/components/ErrorBoundary.js +3 -0
  64. package/dist/esm/components/Inspector/AnalyticsTab.js +7 -3
  65. package/dist/esm/components/Inspector/BundleTab.js +20 -20
  66. package/dist/esm/components/Inspector/ConsoleTab.js +1 -1
  67. package/dist/esm/components/Inspector/CrashDetail.js +16 -12
  68. package/dist/esm/components/Inspector/CrashTab.js +97 -90
  69. package/dist/esm/components/Inspector/InspectorHeader.js +29 -25
  70. package/dist/esm/components/Inspector/MainScreen.js +21 -71
  71. package/dist/esm/components/Inspector/NetworkTab.js +145 -12
  72. package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
  73. package/dist/esm/components/Inspector/ReduxDetail.js +24 -19
  74. package/dist/esm/components/Inspector/ReduxTab.js +30 -18
  75. package/dist/esm/components/Inspector/SettingsPanel.js +1582 -758
  76. package/dist/esm/components/Inspector/TabBar.js +7 -4
  77. package/dist/esm/components/LogCard.js +27 -9
  78. package/dist/esm/components/MetaAccordion.js +42 -0
  79. package/dist/esm/components/NetworkIcons.d.ts +10 -0
  80. package/dist/esm/components/NetworkIcons.js +42 -0
  81. package/dist/esm/components/Toast.js +3 -3
  82. package/dist/esm/components/TouchableScale.d.ts +5 -2
  83. package/dist/esm/components/TouchableScale.js +31 -33
  84. package/dist/esm/constants/index.d.ts +1 -2
  85. package/dist/esm/constants/index.js +4 -0
  86. package/dist/esm/constants/version.d.ts +1 -1
  87. package/dist/esm/constants/version.js +1 -1
  88. package/dist/esm/customHooks/analyticsLogger.d.ts +6 -0
  89. package/dist/esm/customHooks/analyticsLogger.js +12 -4
  90. package/dist/esm/customHooks/bundleAnalyzer.d.ts +2 -0
  91. package/dist/esm/customHooks/bundleAnalyzer.js +23 -16
  92. package/dist/esm/customHooks/consoleLogger.d.ts +2 -0
  93. package/dist/esm/customHooks/consoleLogger.js +7 -0
  94. package/dist/esm/customHooks/crashHandler.d.ts +2 -0
  95. package/dist/esm/customHooks/crashHandler.js +14 -0
  96. package/dist/esm/customHooks/networkLogger.d.ts +2 -0
  97. package/dist/esm/customHooks/networkLogger.js +9 -0
  98. package/dist/esm/customHooks/performanceTracker.d.ts +3 -1
  99. package/dist/esm/customHooks/performanceTracker.js +15 -3
  100. package/dist/esm/customHooks/reduxLogger.d.ts +2 -0
  101. package/dist/esm/customHooks/reduxLogger.js +7 -0
  102. package/dist/esm/helpers/index.js +10 -1
  103. package/dist/esm/helpers/settingsStore.d.ts +9 -0
  104. package/dist/esm/helpers/settingsStore.js +58 -3
  105. package/dist/esm/i18n/locales/en.json +96 -28
  106. package/dist/esm/index.d.ts +1 -0
  107. package/dist/esm/index.js +279 -59
  108. package/dist/esm/native/NativeInspector.d.ts +125 -0
  109. package/dist/esm/native/NativeInspector.js +289 -0
  110. package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
  111. package/dist/esm/native/NativeNetworkInspector.js +2 -0
  112. package/dist/esm/styles/AppColors.d.ts +28 -0
  113. package/dist/esm/styles/AppColors.js +30 -0
  114. package/dist/esm/styles/index.js +6 -6
  115. package/dist/esm/types/enums.d.ts +1 -1
  116. package/dist/esm/types/interfaces.d.ts +9 -0
  117. package/ios/NetworkInspectorModule.h +6 -0
  118. package/ios/NetworkInspectorModule.m +720 -5
  119. package/package.json +15 -3
  120. package/react-native-inapp-inspector.podspec +7 -2
  121. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
  122. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +0 -28
@@ -0,0 +1,17 @@
1
+ package com.inappinspector
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+ import java.util.Collections
8
+
9
+ class NetworkInspectorPackage : ReactPackage {
10
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
+ return listOf(NetworkInspectorModule(reactContext))
12
+ }
13
+
14
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
+ return Collections.emptyList()
16
+ }
17
+ }
@@ -26,44 +26,45 @@ const getLogMessageWithBadges = (message, searchStr, textStyle, highlightStyle,
26
26
  const getTagDecorator = (tag) => {
27
27
  const clean = tag.replace(/[\[\]]/g, '').trim().toUpperCase();
28
28
  if (clean === 'AXIOS') {
29
- return { color: AppColors_1.AppColors.emerald600, icon: '⚡', label: 'AXIOS' };
29
+ return { color: AppColors_1.AppColors.emerald600, Icon: NetworkIcons_1.ZapIcon, label: 'AXIOS' };
30
30
  }
31
31
  if (clean === 'API' || clean === 'FETCH' || clean === 'HTTP' || clean === 'NETWORK') {
32
- return { color: AppColors_1.AppColors.sky600, icon: '🌐', label: clean };
32
+ return { color: AppColors_1.AppColors.sky600, Icon: NetworkIcons_1.GlobeIcon, label: clean };
33
33
  }
34
34
  if (clean === 'SAMPLE' || clean === 'BATCH') {
35
- return { color: AppColors_1.AppColors.indigo600Alt, icon: '🎲', label: clean };
35
+ return { color: AppColors_1.AppColors.indigo600Alt, Icon: NetworkIcons_1.DiceIcon, label: clean };
36
36
  }
37
37
  if (clean === 'REDUX' || clean === 'STORE' || clean === 'STATE') {
38
- return { color: AppColors_1.AppColors.violet600, icon: '⚛️', label: clean };
38
+ return { color: AppColors_1.AppColors.violet600, Icon: NetworkIcons_1.AtomIcon, label: clean };
39
39
  }
40
40
  if (clean === 'ANALYTICS' || clean === 'FIREBASE' || clean === 'GA4' || clean === 'GA') {
41
- return { color: AppColors_1.AppColors.teal600, icon: '📊', label: clean };
41
+ return { color: AppColors_1.AppColors.teal600, Icon: NetworkIcons_1.BarChartIcon, label: clean };
42
42
  }
43
43
  if (clean === 'AUTH' || clean === 'TOKEN' || clean === 'SESSION') {
44
- return { color: AppColors_1.AppColors.amber600, icon: '🔑', label: clean };
44
+ return { color: AppColors_1.AppColors.amber600, Icon: NetworkIcons_1.KeyIcon, label: clean };
45
45
  }
46
46
  if (clean === 'APP') {
47
- return { color: AppColors_1.AppColors.indigo600Alt, icon: '📱', label: 'APP' };
47
+ return { color: AppColors_1.AppColors.indigo600Alt, Icon: NetworkIcons_1.SmartphoneIcon, label: 'APP' };
48
48
  }
49
49
  if (clean === 'TEST') {
50
- return { color: AppColors_1.AppColors.emerald500, icon: '🧪', label: 'TEST' };
50
+ return { color: AppColors_1.AppColors.emerald500, Icon: NetworkIcons_1.FlaskIcon, label: 'TEST' };
51
51
  }
52
52
  if (clean === 'WARN' || clean === 'WARNING') {
53
- return { color: AppColors_1.AppColors.amber600, icon: '⚠️', label: 'WARN' };
53
+ return { color: AppColors_1.AppColors.amber600, Icon: NetworkIcons_1.AlertTriangleIcon, label: 'WARN' };
54
54
  }
55
55
  if (clean === 'ERROR' || clean === 'CRASH' || clean === 'BUG') {
56
- return { color: AppColors_1.AppColors.red600, icon: '💥', label: 'ERROR' };
56
+ return { color: AppColors_1.AppColors.red600, Icon: NetworkIcons_1.BugIcon, label: 'ERROR' };
57
57
  }
58
58
  if (clean === 'PERF' || clean === 'RENDER') {
59
- return { color: AppColors_1.AppColors.violet500, icon: '⚡', label: clean };
59
+ return { color: AppColors_1.AppColors.violet500, Icon: NetworkIcons_1.ZapIcon, label: clean };
60
60
  }
61
- return { color: AppColors_1.AppColors.slate600, icon: '🏷️', label: clean };
61
+ return { color: AppColors_1.AppColors.slate600, Icon: NetworkIcons_1.TagIcon, label: clean };
62
62
  };
63
63
  return (<react_native_1.View style={{ flexDirection: 'column', gap: 6 }}>
64
64
  <react_native_1.View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 5 }}>
65
65
  {tags.map((tag, i) => {
66
66
  const dec = getTagDecorator(tag);
67
+ const IconComp = dec.Icon;
67
68
  return (<react_native_1.View key={i} style={[
68
69
  styles.prefixTag,
69
70
  {
@@ -71,7 +72,7 @@ const getLogMessageWithBadges = (message, searchStr, textStyle, highlightStyle,
71
72
  borderColor: `${dec.color}35`,
72
73
  },
73
74
  ]}>
74
- <react_native_1.Text style={{ fontSize: 9.5 }}>{dec.icon}</react_native_1.Text>
75
+ <IconComp color={dec.color} size={10}/>
75
76
  <react_native_1.Text style={[styles.prefixTagText, { color: dec.color }]}>
76
77
  {dec.label}
77
78
  </react_native_1.Text>
@@ -99,67 +100,67 @@ exports.ConsoleLogCard = react_1.default.memo(function ConsoleLogCard({ item, se
99
100
  const method = (item.sourceMethod || type).toLowerCase();
100
101
  if (isAnalyticsError || type === 'error' || method === 'error') {
101
102
  return {
102
- border: '#EF4444',
103
- badgeBg: '#FEE2E2',
104
- badgeText: '#DC2626',
103
+ border: AppColors_1.AppColors.errorColor,
104
+ badgeBg: AppColors_1.AppColors.errorCardBg,
105
+ badgeText: AppColors_1.AppColors.rose600,
105
106
  label: 'ERROR',
106
- cardBg: '#FEF2F2',
107
- methodBorder: '#FECACA',
108
- methodBg: '#FEE2E2',
109
- methodText: '#DC2626',
110
- textColor: '#991B1B',
107
+ cardBg: AppColors_1.AppColors.errorCardBg,
108
+ methodBorder: AppColors_1.AppColors.errorBorder,
109
+ methodBg: AppColors_1.AppColors.errorCardBg,
110
+ methodText: AppColors_1.AppColors.rose600,
111
+ textColor: AppColors_1.AppColors.redErrorText,
111
112
  };
112
113
  }
113
114
  if (type === 'warn' || method === 'warn') {
114
115
  return {
115
- border: '#F59E0B',
116
- badgeBg: '#FEF3C7',
117
- badgeText: '#D97706',
116
+ border: AppColors_1.AppColors.amber600,
117
+ badgeBg: AppColors_1.AppColors.amberBg,
118
+ badgeText: AppColors_1.AppColors.amber700,
118
119
  label: 'WARN',
119
- cardBg: '#FFFBEB',
120
- methodBorder: '#FDE68A',
121
- methodBg: '#FEF3C7',
122
- methodText: '#D97706',
123
- textColor: '#92400E',
120
+ cardBg: AppColors_1.AppColors.amberWarmBg,
121
+ methodBorder: AppColors_1.AppColors.amberWarmBorder,
122
+ methodBg: AppColors_1.AppColors.amberBg,
123
+ methodText: AppColors_1.AppColors.amber700,
124
+ textColor: AppColors_1.AppColors.amberWarmText,
124
125
  };
125
126
  }
126
127
  if (type === 'debug' || method === 'debug') {
127
128
  return {
128
- border: '#8B5CF6',
129
- badgeBg: '#EDE9FE',
130
- badgeText: '#7C3AED',
129
+ border: AppColors_1.AppColors.purple500,
130
+ badgeBg: AppColors_1.AppColors.violetSoftBg,
131
+ badgeText: AppColors_1.AppColors.violetSoftText,
131
132
  label: 'DEBUG',
132
- cardBg: '#F5F3FF',
133
- methodBorder: '#DDD6FE',
134
- methodBg: '#EDE9FE',
135
- methodText: '#7C3AED',
136
- textColor: '#4C1D95',
133
+ cardBg: AppColors_1.AppColors.purpleShade50,
134
+ methodBorder: AppColors_1.AppColors.violetSoftBorder,
135
+ methodBg: AppColors_1.AppColors.violetSoftBg,
136
+ methodText: AppColors_1.AppColors.violetSoftText,
137
+ textColor: AppColors_1.AppColors.purpleText,
137
138
  };
138
139
  }
139
140
  if (type === 'info' || method === 'info') {
140
141
  return {
141
- border: '#0EA5E9',
142
- badgeBg: '#E0F2FE',
143
- badgeText: '#0284C7',
142
+ border: AppColors_1.AppColors.sky500,
143
+ badgeBg: AppColors_1.AppColors.skySoftBg,
144
+ badgeText: AppColors_1.AppColors.skySoftText,
144
145
  label: 'INFO',
145
- cardBg: '#F0F9FF',
146
- methodBorder: '#BAE6FD',
147
- methodBg: '#E0F2FE',
148
- methodText: '#0284C7',
149
- textColor: '#075985',
146
+ cardBg: AppColors_1.AppColors.blueBg,
147
+ methodBorder: AppColors_1.AppColors.skySoftBorder,
148
+ methodBg: AppColors_1.AppColors.skySoftBg,
149
+ methodText: AppColors_1.AppColors.skySoftText,
150
+ textColor: AppColors_1.AppColors.blue800,
150
151
  };
151
152
  }
152
153
  // Default / Standard console.log
153
154
  return {
154
- border: '#6366F1',
155
- badgeBg: '#EEF2FF',
156
- badgeText: '#4F46E5',
155
+ border: AppColors_1.AppColors.indigo500,
156
+ badgeBg: AppColors_1.AppColors.indigo50,
157
+ badgeText: AppColors_1.AppColors.indigo600Alt,
157
158
  label: 'LOG',
158
- cardBg: '#FFFFFF',
159
- methodBorder: '#E0E7FF',
160
- methodBg: '#EEF2FF',
161
- methodText: '#4F46E5',
162
- textColor: '#0F172A',
159
+ cardBg: AppColors_1.AppColors.primaryLight,
160
+ methodBorder: AppColors_1.AppColors.dividerColor,
161
+ methodBg: AppColors_1.AppColors.indigo50,
162
+ methodText: AppColors_1.AppColors.indigo600Alt,
163
+ textColor: AppColors_1.AppColors.primaryBlack,
163
164
  };
164
165
  };
165
166
  const colors = getLogColors();
@@ -204,11 +205,11 @@ exports.ConsoleLogCard = react_1.default.memo(function ConsoleLogCard({ item, se
204
205
  {jsonContent && (<react_native_1.View style={[
205
206
  styles.metaChip,
206
207
  {
207
- backgroundColor: '#ECFDF5',
208
- borderColor: '#A7F3D0',
208
+ backgroundColor: AppColors_1.AppColors.mintGreenBg,
209
+ borderColor: AppColors_1.AppColors.mintGreenBorder,
209
210
  },
210
211
  ]}>
211
- <react_native_1.Text style={[styles.metaChipText, { color: '#059669', fontFamily: AppFonts_1.AppFonts.interBold }]}>
212
+ <react_native_1.Text style={[styles.metaChipText, { color: AppColors_1.AppColors.mintGreenText, fontFamily: AppFonts_1.AppFonts.interBold }]}>
212
213
  {Array.isArray(jsonContent.data)
213
214
  ? `Array[${jsonContent.data.length}]`
214
215
  : `Object{${Object.keys(jsonContent.data).length}}`}
@@ -42,6 +42,7 @@ const react_native_1 = require("react-native");
42
42
  const TouchableScale_1 = __importDefault(require("./TouchableScale"));
43
43
  // Helpers
44
44
  const helpers_1 = require("../helpers");
45
+ const NativeInspector_1 = require("../native/NativeInspector");
45
46
  // Assets
46
47
  const NetworkIcons_1 = require("./NetworkIcons");
47
48
  // Stylesheet
@@ -50,6 +51,7 @@ const styles_1 = __importDefault(require("../styles"));
50
51
  const CopyButton = react_1.default.memo(({ value, label, iconType = 'copy' }) => {
51
52
  const [copied, setCopied] = (0, react_1.useState)(false);
52
53
  const handlePress = (0, react_1.useCallback)(() => {
54
+ (0, NativeInspector_1.triggerNativeHaptic)('success');
53
55
  const resolvedValue = typeof value === 'function' ? value() : value;
54
56
  (0, helpers_1.copyToClipboard)(resolvedValue, label);
55
57
  setCopied(true);
@@ -57,6 +59,7 @@ const CopyButton = react_1.default.memo(({ value, label, iconType = 'copy' }) =>
57
59
  }, [value, label]);
58
60
  const handleLongPress = (0, react_1.useCallback)(() => {
59
61
  try {
62
+ (0, NativeInspector_1.triggerNativeHaptic)('medium');
60
63
  const resolvedValue = typeof value === 'function' ? value() : value;
61
64
  const textToShare = typeof resolvedValue === 'string'
62
65
  ? resolvedValue
@@ -77,7 +80,13 @@ const CopyButton = react_1.default.memo(({ value, label, iconType = 'copy' }) =>
77
80
  : iconType === 'fetch'
78
81
  ? NetworkIcons_1.FetchIcon
79
82
  : NetworkIcons_1.CopyIcon;
80
- return (<TouchableScale_1.default onPress={handlePress} onLongPress={handleLongPress} hitSlop={12} style={containerStyle}>
83
+ return (<TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel={label
84
+ ? copied
85
+ ? `${label} copied`
86
+ : `Copy ${label}`
87
+ : copied
88
+ ? 'Copied to clipboard'
89
+ : 'Copy to clipboard'} accessibilityHint="Double tap to copy, long press to share" onPress={handlePress} onLongPress={handleLongPress} hitSlop={12} style={containerStyle}>
81
90
  {copied ? (<NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.greenColor} size={14}/>) : (<IconComponent color={AppColors_1.AppColors.grayTextWeak} size={14}/>)}
82
91
  </TouchableScale_1.default>);
83
92
  });
@@ -43,6 +43,7 @@ const i18n_1 = require("../i18n");
43
43
  const NetworkIcons_1 = require("./NetworkIcons");
44
44
  const crashHandler_1 = require("../customHooks/crashHandler");
45
45
  const enums_1 = require("../types/enums");
46
+ const NativeInspector_1 = require("../native/NativeInspector");
46
47
  function parseStackTrace(stack) {
47
48
  if (!stack)
48
49
  return { rootFrame: null, frames: [] };
@@ -145,6 +146,8 @@ ${error.stack || 'No stack trace available'}
145
146
  try {
146
147
  const stack = error?.stack || errorInfo?.componentStack || '';
147
148
  (0, crashHandler_1.handleInterceptedCrash)(error, stack, false, enums_1.CrashType.Render, errorInfo?.componentStack);
149
+ (0, NativeInspector_1.showNativeFloatingButton)();
150
+ (0, NativeInspector_1.setNativeFloatingButtonBadge)(true);
148
151
  }
149
152
  catch { }
150
153
  }
@@ -59,6 +59,10 @@ const AnalyticsHeader = react_1.default.memo(() => {
59
59
  const userProperties = (0, analyticsLogger_1.getCurrentUserProperties)();
60
60
  const defaultParams = (0, analyticsLogger_1.getDefaultEventParameters)();
61
61
  const isTrackingEnabled = (0, analyticsLogger_1.getCollectionEnabled)();
62
+ // If there are no analytics events in the session, hide the graph, category breakdown, and realtime card
63
+ if (analyticsEvents.length === 0) {
64
+ return null;
65
+ }
62
66
  const hasUserProps = Object.keys(userProperties).length > 0;
63
67
  const hasDefaultParams = Object.keys(defaultParams).length > 0;
64
68
  const totalEvents = filteredAnalyticsEvents.length;
@@ -628,8 +632,8 @@ const AnalyticsHeader = react_1.default.memo(() => {
628
632
  </react_native_1.View>
629
633
 
630
634
  {/* ── Crashlytics-Style Multi-Bar Histogram with Trendline Overlay ── */}
631
- <react_native_1.View style={{ height: chartHeight, position: 'relative' }}>
632
- <react_native_svg_1.default width="100%" height={chartHeight} viewBox={`0 0 ${svgWidth} ${chartHeight}`}>
635
+ <react_native_1.View style={{ height: chartHeight, position: 'relative', overflow: 'hidden', borderRadius: 8 }}>
636
+ <react_native_svg_1.default width="100%" height={chartHeight} viewBox={`0 0 ${svgWidth} ${chartHeight}`} preserveAspectRatio="none">
633
637
  <react_native_svg_1.Defs>
634
638
  <react_native_svg_1.LinearGradient id="crashlyticsBarGrad" x1="0" y1="0" x2="0" y2="1">
635
639
  <react_native_svg_1.Stop offset="0%" stopColor="#8B5CF6" stopOpacity="0.9"/>
@@ -993,7 +997,7 @@ const AnalyticsTab = react_1.default.memo(() => {
993
997
  <AnalyticsFilterModal_1.default visible={isFilterModalOpen} onClose={() => setIsFilterModalOpen(false)}/>
994
998
 
995
999
  <react_native_1.View style={{ flex: 1 }} onLayout={() => setIsAnalyticsLayoutReady(true)}>
996
- {selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : isAnalyticsLayoutReady ? (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={keyExtractor} ListHeaderComponent={AnalyticsHeader} renderItem={renderItem} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews={false} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1000
+ {selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : isAnalyticsLayoutReady ? (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={keyExtractor} ListHeaderComponent={AnalyticsHeader} renderItem={renderItem} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
997
1001
  <react_native_1.View style={styles_1.default.emptyIconWrap}>
998
1002
  <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
999
1003
  </react_native_1.View>
@@ -419,7 +419,7 @@ const BundleTreeNodeView = ({ node, level, search, totalBundleKb, expandedFolder
419
419
  const indentLeft = level * 16 + 10;
420
420
  if (node.isFolder) {
421
421
  return (<react_native_1.View style={bundleStyles.treeFolderBlock}>
422
- <TouchableScale_1.default onPress={() => toggleFolder(node.fullPath)} style={[
422
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel={`Folder ${node.name}, ${node.fileCount} ${node.fileCount === 1 ? 'file' : 'files'}, ${node.sizeKb >= 1024 ? `${(node.sizeKb / 1024).toFixed(2)} MB` : `${node.sizeKb} KB`}`} accessibilityState={{ expanded: isExpanded }} accessibilityHint="Double tap to expand or collapse folder" onPress={() => toggleFolder(node.fullPath)} style={[
423
423
  bundleStyles.treeFolderRow,
424
424
  { paddingLeft: indentLeft },
425
425
  ]}>
@@ -493,7 +493,7 @@ const BundleTreeNodeView = ({ node, level, search, totalBundleKb, expandedFolder
493
493
  </react_native_1.View>
494
494
 
495
495
  <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
496
- {onDownload && (<TouchableScale_1.default onPress={() => onDownload(file)} style={bundleStyles.treeActionBtn} hitSlop={8}>
496
+ {onDownload && (<TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel={`Download source code for ${file.name}`} accessibilityHint="Fetches module source code from Metro dev server" onPress={() => onDownload(file)} style={bundleStyles.treeActionBtn} hitSlop={8}>
497
497
  <NetworkIcons_1.DownloadIcon size={13} color={AppColors_1.AppColors.sky500}/>
498
498
  </TouchableScale_1.default>)}
499
499
 
@@ -786,7 +786,7 @@ const BundleTab = react_1.default.memo(() => {
786
786
  <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ flex: 1 }} contentContainerStyle={bundleStyles.subTabsScroll}>
787
787
  {subTabs.map(tab => {
788
788
  const isActive = activeSubTab === tab.key;
789
- return (<TouchableScale_1.default key={tab.key} onPress={() => setActiveSubTab(tab.key)} style={[
789
+ return (<TouchableScale_1.default key={tab.key} accessible={true} accessibilityRole="tab" accessibilityLabel={`${tab.label} tab`} accessibilityState={{ selected: isActive }} accessibilityHint={`Switches to ${tab.label} tab`} onPress={() => setActiveSubTab(tab.key)} style={[
790
790
  bundleStyles.subTabPill,
791
791
  isActive && bundleStyles.subTabPillActive,
792
792
  ]}>
@@ -800,7 +800,7 @@ const BundleTab = react_1.default.memo(() => {
800
800
  </TouchableScale_1.default>);
801
801
  })}
802
802
  </react_native_1.ScrollView>
803
- <TouchableScale_1.default onPress={refreshAnalysis} style={bundleStyles.reloadButton} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}>
803
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel={isAnalyzing ? "Analyzing Metro bundle" : "Reload bundle analysis"} accessibilityHint="Re-probes Metro dev server and refreshes bundle statistics" onPress={refreshAnalysis} style={bundleStyles.reloadButton} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}>
804
804
  {isAnalyzing ? (<react_native_1.ActivityIndicator size="small" color={AppColors_1.AppColors.brandPurple}/>) : (<NetworkIcons_1.RefreshCcwIcon color={AppColors_1.AppColors.brandPurple} size={14}/>)}
805
805
  </TouchableScale_1.default>
806
806
  </react_native_1.View>
@@ -822,7 +822,7 @@ const BundleTab = react_1.default.memo(() => {
822
822
  <react_native_1.Text style={bundleStyles.heroSubtitle}>
823
823
  {t('bundle.heroSubtitle')}
824
824
  </react_native_1.Text>
825
- <react_native_1.Pressable style={{
825
+ <react_native_1.Pressable accessible={true} accessibilityRole="link" accessibilityLabel={`Live Metro bundle URL: ${analysis.scriptURL}`} accessibilityHint="Opens Metro bundle script in browser" style={{
826
826
  backgroundColor: `${AppColors_1.AppColors.skyBlue}10`,
827
827
  borderColor: `${AppColors_1.AppColors.skyBlue}30`,
828
828
  borderWidth: 1,
@@ -856,7 +856,7 @@ const BundleTab = react_1.default.memo(() => {
856
856
  {analysis.scriptURL.length} chars
857
857
  </react_native_1.Text>
858
858
  </react_native_1.View>
859
- <react_native_1.Text selectable={true} style={{
859
+ <react_native_1.Text selectable={true} numberOfLines={1} ellipsizeMode="tail" style={{
860
860
  fontFamily: AppFonts_1.AppFonts.interMedium,
861
861
  fontSize: 11,
862
862
  color: AppColors_1.AppColors.skyBlue,
@@ -1032,7 +1032,7 @@ const BundleTab = react_1.default.memo(() => {
1032
1032
  <CopyButton_1.default value={() => summary} label={t('bundle.categoriesJson')}/>
1033
1033
  </react_native_1.View>
1034
1034
 
1035
- {summary.categories.map((cat, cIdx) => (<react_native_1.Pressable key={cIdx} style={({ pressed }) => [
1035
+ {summary.categories.map((cat, cIdx) => (<react_native_1.Pressable key={cIdx} accessible={true} accessibilityRole="button" accessibilityLabel={`${cat.title}, ${cat.sizeKb >= 1024 ? `${cat.sizeMb} MB` : `${cat.sizeKb} KB`}, ${cat.pct}% of bundle`} accessibilityHint={`Double tap to view ${cat.title} details`} style={({ pressed }) => [
1036
1036
  bundleStyles.catRowCard,
1037
1037
  pressed && { opacity: 0.85, transform: [{ scale: 0.99 }] },
1038
1038
  ]} onPress={() => setActiveSubTab(cat.targetTab)}>
@@ -1290,7 +1290,7 @@ const BundleTab = react_1.default.memo(() => {
1290
1290
  { key: 'androidApk', label: 'Universal APK (.apk)', badge: `${analysis?.production.androidApk.totalInstallMb || 364.0} MB` },
1291
1291
  ].map(tab => {
1292
1292
  const isSelected = prodPlatform === tab.key;
1293
- return (<TouchableScale_1.default key={tab.key} onPress={() => setProdPlatform(tab.key)} style={[
1293
+ return (<TouchableScale_1.default key={tab.key} accessible={true} accessibilityRole="tab" accessibilityLabel={`${tab.label}, ${tab.badge}`} accessibilityState={{ selected: isSelected }} accessibilityHint={`Switches production estimate to ${tab.label}`} onPress={() => setProdPlatform(tab.key)} style={[
1294
1294
  bundleStyles.prodPlatformBtn,
1295
1295
  isSelected && bundleStyles.prodPlatformBtnActive,
1296
1296
  ]}>
@@ -1540,8 +1540,8 @@ const BundleTab = react_1.default.memo(() => {
1540
1540
  <react_native_1.View style={bundleStyles.filterContainer}>
1541
1541
  <react_native_1.View style={bundleStyles.searchRow}>
1542
1542
  <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={15}/>
1543
- <react_native_1.TextInput placeholder={t('bundle.searchFilesPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={bundleStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
1544
- {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10}>
1543
+ <react_native_1.TextInput accessible={true} accessibilityRole="search" accessibilityLabel="Search files" accessibilityHint="Type a filename, path, or extension to filter" placeholder={t('bundle.searchFilesPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={bundleStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
1544
+ {search.length > 0 && (<react_native_1.Pressable accessible={true} accessibilityRole="button" accessibilityLabel="Clear search input" onPress={() => setSearch('')} hitSlop={10}>
1545
1545
  <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1546
1546
  </react_native_1.Pressable>)}
1547
1547
  <CopyButton_1.default value={() => filteredFiles} label={t('bundle.filteredFilesJson')}/>
@@ -1558,7 +1558,7 @@ const BundleTab = react_1.default.memo(() => {
1558
1558
  : tab.key === 'CONSUMED'
1559
1559
  ? bundleFiles.filter(f => f.isConsumed !== false).length
1560
1560
  : bundleFiles.filter(f => f.category === tab.key).length;
1561
- return (<TouchableScale_1.default key={tab.key} onPress={() => setActiveCategory(tab.key)} style={[
1561
+ return (<TouchableScale_1.default key={tab.key} accessible={true} accessibilityRole="button" accessibilityLabel={`Filter by ${t(tab.labelKey)}, ${count} items`} accessibilityState={{ selected: isActive }} accessibilityHint={`Filters files list to ${t(tab.labelKey)}`} onPress={() => setActiveCategory(tab.key)} style={[
1562
1562
  bundleStyles.catPill,
1563
1563
  isActive && bundleStyles.catPillActive,
1564
1564
  tab.key === 'UNUSED' && isActive && { backgroundColor: AppColors_1.AppColors.red500, borderColor: AppColors_1.AppColors.red600 },
@@ -1582,7 +1582,7 @@ const BundleTab = react_1.default.memo(() => {
1582
1582
  {/* View Mode Toggle Header Bar */}
1583
1583
  <react_native_1.View style={bundleStyles.treeHeaderRow}>
1584
1584
  <react_native_1.View style={bundleStyles.viewModeToggleGroup}>
1585
- <TouchableScale_1.default onPress={() => setFilesViewMode('tree')} style={[
1585
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel="Tree folder view" accessibilityState={{ selected: filesViewMode === 'tree' }} onPress={() => setFilesViewMode('tree')} style={[
1586
1586
  bundleStyles.viewModeBtn,
1587
1587
  filesViewMode === 'tree' && bundleStyles.viewModeBtnActive,
1588
1588
  ]}>
@@ -1593,7 +1593,7 @@ const BundleTab = react_1.default.memo(() => {
1593
1593
  {t('bundle.treeView')}
1594
1594
  </react_native_1.Text>
1595
1595
  </TouchableScale_1.default>
1596
- <TouchableScale_1.default onPress={() => setFilesViewMode('list')} style={[
1596
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel="Flat list view" accessibilityState={{ selected: filesViewMode === 'list' }} onPress={() => setFilesViewMode('list')} style={[
1597
1597
  bundleStyles.viewModeBtn,
1598
1598
  filesViewMode === 'list' && bundleStyles.viewModeBtnActive,
1599
1599
  ]}>
@@ -1607,11 +1607,11 @@ const BundleTab = react_1.default.memo(() => {
1607
1607
  </react_native_1.View>
1608
1608
 
1609
1609
  {filesViewMode === 'tree' ? (<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
1610
- <TouchableScale_1.default onPress={expandAllFolders}>
1610
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel="Expand all folders" onPress={expandAllFolders}>
1611
1611
  <react_native_1.Text style={bundleStyles.treeActionLink}>{t('bundle.expand')}</react_native_1.Text>
1612
1612
  </TouchableScale_1.default>
1613
1613
  <react_native_1.Text style={{ color: AppColors_1.AppColors.grayTextWeak, fontSize: 11 }}>•</react_native_1.Text>
1614
- <TouchableScale_1.default onPress={collapseAllFolders}>
1614
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel="Collapse all folders" onPress={collapseAllFolders}>
1615
1615
  <react_native_1.Text style={bundleStyles.treeActionLink}>{t('bundle.collapse')}</react_native_1.Text>
1616
1616
  </TouchableScale_1.default>
1617
1617
  </react_native_1.View>) : (<react_native_1.Text style={bundleStyles.listHeaderCount}>
@@ -1735,8 +1735,8 @@ const BundleTab = react_1.default.memo(() => {
1735
1735
  <react_native_1.View style={bundleStyles.filterContainer}>
1736
1736
  <react_native_1.View style={bundleStyles.searchRow}>
1737
1737
  <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={15}/>
1738
- <react_native_1.TextInput placeholder={t('bundle.searchPackagesPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={bundleStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
1739
- {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10}>
1738
+ <react_native_1.TextInput accessible={true} accessibilityRole="search" accessibilityLabel="Search packages" accessibilityHint="Type a package name or description to filter" placeholder={t('bundle.searchPackagesPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={bundleStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
1739
+ {search.length > 0 && (<react_native_1.Pressable accessible={true} accessibilityRole="button" accessibilityLabel="Clear search input" onPress={() => setSearch('')} hitSlop={10}>
1740
1740
  <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1741
1741
  </react_native_1.Pressable>)}
1742
1742
  <CopyButton_1.default value={() => filteredPackages} label={t('bundle.dependenciesJson')}/>
@@ -1751,7 +1751,7 @@ const BundleTab = react_1.default.memo(() => {
1751
1751
  const cleanInstalledVersion = pkg.version ? pkg.version.replace(/^\^/, '') : '';
1752
1752
  const hasUpdate = !!pkg.latestVersion && !!cleanInstalledVersion &&
1753
1753
  pkg.latestVersion !== cleanInstalledVersion;
1754
- return (<react_native_1.View key={pkg.id} style={[bundleStyles.fileCard, pkg.isDeprecated && { borderColor: AppColors_1.AppColors.errorBorder, backgroundColor: '#FFFDFD' }]}>
1754
+ return (<react_native_1.View key={pkg.id} style={[bundleStyles.fileCard, pkg.isDeprecated && { borderColor: AppColors_1.AppColors.errorBorder, backgroundColor: AppColors_1.AppColors.errorCardBg }]}>
1755
1755
  {/* Header Row: #s.no + Logo + Package Name + Version Pill + Update/Deprecated Badges + Size & Copy */}
1756
1756
  <react_native_1.View style={bundleStyles.fileCardTop}>
1757
1757
  <react_native_1.View style={bundleStyles.sNoBadge}>
@@ -1851,7 +1851,7 @@ const BundleTab = react_1.default.memo(() => {
1851
1851
  <react_native_1.Text style={bundleStyles.fileMetaText}>
1852
1852
  {t('bundle.minified', { size: pkg.sizeKb })}
1853
1853
  </react_native_1.Text>
1854
- <TouchableScale_1.default onPress={() => {
1854
+ <TouchableScale_1.default accessible={true} accessibilityRole="link" accessibilityLabel={`Open ${pkg.name} on NPM`} accessibilityHint="Opens NPM package page in browser" onPress={() => {
1855
1855
  const url = pkg.npmUrl || `https://www.npmjs.com/package/${pkg.name}`;
1856
1856
  react_native_1.Linking.openURL(url).catch(() => { });
1857
1857
  }} style={bundleStyles.npmLinkBtn}>
@@ -1930,7 +1930,7 @@ const BundleTab = react_1.default.memo(() => {
1930
1930
  {t('bundle.fileSizeKb', { size: file.sizeKb })}
1931
1931
  </react_native_1.Text>
1932
1932
  </react_native_1.View>
1933
- <TouchableScale_1.default onPress={() => (0, exports.downloadBundleFile)(file, analysis?.scriptURL)} style={bundleStyles.downloadFileBtn} hitSlop={8}>
1933
+ <TouchableScale_1.default accessible={true} accessibilityRole="button" accessibilityLabel={`Download ${file.name}`} accessibilityHint="Downloads media asset file" onPress={() => (0, exports.downloadBundleFile)(file, analysis?.scriptURL)} style={bundleStyles.downloadFileBtn} hitSlop={8}>
1934
1934
  <NetworkIcons_1.DownloadIcon size={14} color={AppColors_1.AppColors.sky500}/>
1935
1935
  </TouchableScale_1.default>
1936
1936
  <CopyButton_1.default value={() => file} label={t('bundle.mediaItemJson')}/>
@@ -507,7 +507,7 @@ const ConsoleTab = react_1.default.memo(() => {
507
507
  </react_native_1.ScrollView>
508
508
  </react_native_1.View>
509
509
 
510
- <react_native_1.FlatList data={filteredConsoleLogs} keyExtractor={keyExtractor} ListHeaderComponent={listHeader} renderItem={renderItem} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState_1.default isSearch={logSearch.length > 0 || logFilters.size > 0}/>} ListFooterComponent={filteredConsoleLogs.length > 0 ? (<EndOfListFooter_1.default count={filteredConsoleLogs.length} label="logs"/>) : null} contentContainerStyle={[
510
+ <react_native_1.FlatList data={filteredConsoleLogs} keyExtractor={keyExtractor} ListHeaderComponent={listHeader} renderItem={renderItem} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} ListEmptyComponent={<EmptyState_1.default isSearch={logSearch.length > 0 || logFilters.size > 0}/>} ListFooterComponent={filteredConsoleLogs.length > 0 ? (<EndOfListFooter_1.default count={filteredConsoleLogs.length} label="logs"/>) : null} contentContainerStyle={[
511
511
  styles_1.default.listContent,
512
512
  filteredConsoleLogs.length === 0 && { flexGrow: 1 },
513
513
  ]} keyboardShouldPersistTaps="handled"/>
@@ -135,23 +135,27 @@ const CrashDetail = react_1.default.memo(() => {
135
135
  localStyles.pillBadge,
136
136
  {
137
137
  backgroundColor: selectedCrash.isFatal
138
- ? '#FEE2E2'
139
- : '#FEF3C7',
140
- borderColor: selectedCrash.isFatal ? '#FCA5A5' : '#FCD34D',
138
+ ? AppColors_1.AppColors.errorCardBg
139
+ : AppColors_1.AppColors.amberBg,
140
+ borderColor: selectedCrash.isFatal
141
+ ? AppColors_1.AppColors.errorBorder
142
+ : AppColors_1.AppColors.amberWarmBorder,
141
143
  },
142
144
  ]}>
143
145
  <react_native_1.View style={[
144
146
  localStyles.statusDot,
145
147
  {
146
148
  backgroundColor: selectedCrash.isFatal
147
- ? '#DC2626'
148
- : '#D97706',
149
+ ? AppColors_1.AppColors.red600
150
+ : AppColors_1.AppColors.amber600,
149
151
  },
150
152
  ]}/>
151
153
  <react_native_1.Text style={[
152
154
  localStyles.pillBadgeText,
153
155
  {
154
- color: selectedCrash.isFatal ? '#991B1B' : '#92400E',
156
+ color: selectedCrash.isFatal
157
+ ? AppColors_1.AppColors.redErrorText
158
+ : AppColors_1.AppColors.amberWarmText,
155
159
  },
156
160
  ]}>
157
161
  {selectedCrash.isFatal ? t('crash.fatalCrash') : t('crash.handledException')}
@@ -162,11 +166,11 @@ const CrashDetail = react_1.default.memo(() => {
162
166
  <react_native_1.View style={[
163
167
  localStyles.pillBadge,
164
168
  {
165
- backgroundColor: '#EDE9FE',
166
- borderColor: '#C4B5FD',
169
+ backgroundColor: AppColors_1.AppColors.violetSoftBg,
170
+ borderColor: AppColors_1.AppColors.violetSoftBorder,
167
171
  },
168
172
  ]}>
169
- <react_native_1.Text style={[localStyles.pillBadgeText, { color: '#6D28D9' }]}>
173
+ <react_native_1.Text style={[localStyles.pillBadgeText, { color: AppColors_1.AppColors.purple700 }]}>
170
174
  {selectedCrash.type.toUpperCase()}
171
175
  </react_native_1.Text>
172
176
  </react_native_1.View>
@@ -176,12 +180,12 @@ const CrashDetail = react_1.default.memo(() => {
176
180
  {/* Copy Report Action */}
177
181
  <TouchableScale_1.default onPress={handleCopyReport} hitSlop={10} style={[
178
182
  localStyles.actionButton,
179
- copiedSuccess && { backgroundColor: '#ECFDF5', borderColor: '#6EE7B7' },
183
+ copiedSuccess && { backgroundColor: AppColors_1.AppColors.mintGreenBg, borderColor: AppColors_1.AppColors.mintGreenBorder },
180
184
  ]}>
181
- {copiedSuccess ? (<NetworkIcons_1.CircleCheckIcon color="#059669" size={12}/>) : (<NetworkIcons_1.CopyIcon color={AppColors_1.AppColors.purple} size={12}/>)}
185
+ {copiedSuccess ? (<NetworkIcons_1.CircleCheckIcon color={AppColors_1.AppColors.mintGreenText} size={12}/>) : (<NetworkIcons_1.CopyIcon color={AppColors_1.AppColors.purple} size={12}/>)}
182
186
  <react_native_1.Text style={[
183
187
  localStyles.actionButtonText,
184
- copiedSuccess && { color: '#059669' },
188
+ copiedSuccess && { color: AppColors_1.AppColors.mintGreenText },
185
189
  ]}>
186
190
  {copiedSuccess ? t('crash.copied') : t('crash.copyReport')}
187
191
  </react_native_1.Text>