react-native-inapp-inspector 1.1.35 → 2.0.1

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 (104) 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 +890 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
  5. package/dist/commonjs/components/ConsoleLogCard.js +5 -5
  6. package/dist/commonjs/components/CopyButton.js +3 -0
  7. package/dist/commonjs/components/EndOfListFooter.js +1 -1
  8. package/dist/commonjs/components/ErrorBoundary.js +3 -0
  9. package/dist/commonjs/components/Inspector/AnalyticsTab.js +25 -73
  10. package/dist/commonjs/components/Inspector/BundleTab.js +671 -189
  11. package/dist/commonjs/components/Inspector/ConsoleTab.js +110 -99
  12. package/dist/commonjs/components/Inspector/CrashTab.js +99 -91
  13. package/dist/commonjs/components/Inspector/InspectorHeader.js +107 -20
  14. package/dist/commonjs/components/Inspector/MainScreen.js +111 -68
  15. package/dist/commonjs/components/Inspector/NetworkTab.js +151 -30
  16. package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
  17. package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
  18. package/dist/commonjs/components/Inspector/SettingsPanel.js +1218 -1238
  19. package/dist/commonjs/components/Inspector/TabBar.js +4 -2
  20. package/dist/commonjs/components/JsonViewer.js +9 -4
  21. package/dist/commonjs/components/LogCard.js +31 -1
  22. package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
  23. package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
  24. package/dist/commonjs/components/NetworkIcons.d.ts +3 -0
  25. package/dist/commonjs/components/NetworkIcons.js +15 -1
  26. package/dist/commonjs/components/Slider.d.ts +13 -0
  27. package/dist/commonjs/components/Slider.js +261 -0
  28. package/dist/commonjs/components/TouchableScale.d.ts +1 -0
  29. package/dist/commonjs/components/TouchableScale.js +30 -32
  30. package/dist/commonjs/constants/index.d.ts +1 -2
  31. package/dist/commonjs/constants/index.js +4 -0
  32. package/dist/commonjs/constants/version.d.ts +1 -1
  33. package/dist/commonjs/constants/version.js +1 -1
  34. package/dist/commonjs/customHooks/analyticsLogger.d.ts +4 -0
  35. package/dist/commonjs/customHooks/analyticsLogger.js +8 -6
  36. package/dist/commonjs/customHooks/crashHandler.js +8 -1
  37. package/dist/commonjs/helpers/index.d.ts +1 -0
  38. package/dist/commonjs/helpers/index.js +25 -1
  39. package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
  40. package/dist/commonjs/helpers/searchQueryParser.js +236 -0
  41. package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
  42. package/dist/commonjs/helpers/settingsStore.js +59 -3
  43. package/dist/commonjs/index.d.ts +1 -0
  44. package/dist/commonjs/index.js +220 -43
  45. package/dist/commonjs/native/NativeInspector.d.ts +125 -0
  46. package/dist/commonjs/native/NativeInspector.js +313 -0
  47. package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
  48. package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
  49. package/dist/commonjs/styles/index.js +41 -41
  50. package/dist/commonjs/types/enums.d.ts +1 -1
  51. package/dist/commonjs/types/interfaces.d.ts +9 -0
  52. package/dist/esm/components/ConsoleLogCard.js +5 -5
  53. package/dist/esm/components/CopyButton.js +3 -0
  54. package/dist/esm/components/EndOfListFooter.js +2 -2
  55. package/dist/esm/components/ErrorBoundary.js +3 -0
  56. package/dist/esm/components/Inspector/AnalyticsTab.js +27 -75
  57. package/dist/esm/components/Inspector/BundleTab.js +671 -189
  58. package/dist/esm/components/Inspector/ConsoleTab.js +111 -100
  59. package/dist/esm/components/Inspector/CrashTab.js +99 -91
  60. package/dist/esm/components/Inspector/InspectorHeader.js +108 -21
  61. package/dist/esm/components/Inspector/MainScreen.js +113 -70
  62. package/dist/esm/components/Inspector/NetworkTab.js +152 -31
  63. package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
  64. package/dist/esm/components/Inspector/ReduxTab.js +18 -10
  65. package/dist/esm/components/Inspector/SettingsPanel.js +1222 -1242
  66. package/dist/esm/components/Inspector/TabBar.js +4 -2
  67. package/dist/esm/components/JsonViewer.js +9 -4
  68. package/dist/esm/components/LogCard.js +32 -2
  69. package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
  70. package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
  71. package/dist/esm/components/NetworkIcons.d.ts +3 -0
  72. package/dist/esm/components/NetworkIcons.js +11 -0
  73. package/dist/esm/components/Slider.d.ts +13 -0
  74. package/dist/esm/components/Slider.js +222 -0
  75. package/dist/esm/components/TouchableScale.d.ts +1 -0
  76. package/dist/esm/components/TouchableScale.js +31 -33
  77. package/dist/esm/constants/index.d.ts +1 -2
  78. package/dist/esm/constants/index.js +4 -0
  79. package/dist/esm/constants/version.d.ts +1 -1
  80. package/dist/esm/constants/version.js +1 -1
  81. package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
  82. package/dist/esm/customHooks/analyticsLogger.js +6 -5
  83. package/dist/esm/customHooks/crashHandler.js +8 -1
  84. package/dist/esm/helpers/index.d.ts +1 -0
  85. package/dist/esm/helpers/index.js +11 -1
  86. package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
  87. package/dist/esm/helpers/searchQueryParser.js +233 -0
  88. package/dist/esm/helpers/settingsStore.d.ts +9 -0
  89. package/dist/esm/helpers/settingsStore.js +58 -3
  90. package/dist/esm/index.d.ts +1 -0
  91. package/dist/esm/index.js +207 -44
  92. package/dist/esm/native/NativeInspector.d.ts +125 -0
  93. package/dist/esm/native/NativeInspector.js +289 -0
  94. package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
  95. package/dist/esm/native/NativeNetworkInspector.js +2 -0
  96. package/dist/esm/styles/index.js +41 -41
  97. package/dist/esm/types/enums.d.ts +1 -1
  98. package/dist/esm/types/interfaces.d.ts +9 -0
  99. package/ios/NetworkInspectorModule.h +6 -0
  100. package/ios/NetworkInspectorModule.m +760 -5
  101. package/package.json +13 -2
  102. package/react-native-inapp-inspector.podspec +7 -2
  103. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
  104. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +0 -28
@@ -89,6 +89,8 @@ const ConsoleTab = react_1.default.memo(() => {
89
89
  </react_native_1.Text>);
90
90
  }
91
91
  }, [visibleConsoleLogs.length, filteredConsoleLogs.length, logFilters]);
92
+ const [isSearchFocused, setIsSearchFocused] = react_1.default.useState(false);
93
+ const QUICK_TAG_SUGGESTIONS = (0, react_1.useMemo)(() => ['[AXIOS]', '[API]', '[REDUX]', '[ANALYTICS]', '[AUTH]', '[WARN]', '[ERROR]'], []);
92
94
  return (<react_native_1.View style={{ flex: 1 }}>
93
95
  <react_native_1.View style={{
94
96
  backgroundColor: AppColors_1.AppColors.white,
@@ -100,12 +102,38 @@ const ConsoleTab = react_1.default.memo(() => {
100
102
  styles_1.default.toolbarRow,
101
103
  { marginTop: 12, marginBottom: 8 },
102
104
  ]}>
103
- <react_native_1.View style={styles_1.default.searchContainer}>
104
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
105
- <react_native_1.TextInput placeholder={t('console.searchPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={logSearch} onChangeText={setLogSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
106
- {logSearch.length > 0 && (<react_native_1.Pressable onPress={() => setLogSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
107
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
108
- </react_native_1.Pressable>)}
105
+ <react_native_1.View style={[
106
+ styles_1.default.searchContainer,
107
+ isSearchFocused && {
108
+ borderColor: AppColors_1.AppColors.purple,
109
+ borderWidth: 1.5,
110
+ },
111
+ ]}>
112
+ <NetworkIcons_1.SearchIcon color={isSearchFocused ? AppColors_1.AppColors.purple : AppColors_1.AppColors.grayTextWeak} size={16}/>
113
+ <react_native_1.TextInput placeholder={t('console.searchPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={logSearch} onChangeText={setLogSearch} onFocus={() => setIsSearchFocused(true)} onBlur={() => setIsSearchFocused(false)} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
114
+ {logSearch.length > 0 && (<react_native_1.View style={{
115
+ flexDirection: 'row',
116
+ alignItems: 'center',
117
+ gap: 4,
118
+ }}>
119
+ <react_native_1.View style={{
120
+ backgroundColor: `${AppColors_1.AppColors.purple}20`,
121
+ borderRadius: 10,
122
+ paddingHorizontal: 6,
123
+ paddingVertical: 2,
124
+ }}>
125
+ <react_native_1.Text style={{
126
+ color: AppColors_1.AppColors.purple,
127
+ fontSize: 10,
128
+ fontFamily: AppFonts_1.AppFonts.interBold,
129
+ }}>
130
+ {filteredConsoleLogs.length}
131
+ </react_native_1.Text>
132
+ </react_native_1.View>
133
+ <react_native_1.Pressable onPress={() => setLogSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
134
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
135
+ </react_native_1.Pressable>
136
+ </react_native_1.View>)}
109
137
  </react_native_1.View>
110
138
 
111
139
  <react_native_1.View style={styles_1.default.toolbarRight}>
@@ -135,6 +163,49 @@ const ConsoleTab = react_1.default.memo(() => {
135
163
  </react_native_1.View>
136
164
  </react_native_1.View>
137
165
 
166
+ {/* Quick Tag Search Suggestions Bar */}
167
+ {(isSearchFocused || logSearch.length > 0) && (<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginBottom: 6, maxHeight: 30 }} contentContainerStyle={{
168
+ paddingHorizontal: 16,
169
+ flexDirection: 'row',
170
+ alignItems: 'center',
171
+ gap: 6,
172
+ }}>
173
+ {QUICK_TAG_SUGGESTIONS.map(tag => {
174
+ const isSelected = logSearch.includes(tag);
175
+ return (<TouchableScale_1.default key={tag} onPress={() => {
176
+ if (isSelected) {
177
+ setLogSearch(prev => prev.replace(tag, '').trim());
178
+ }
179
+ else {
180
+ setLogSearch(prev => prev ? `${prev} ${tag}`.trim() : tag);
181
+ }
182
+ }}>
183
+ <react_native_1.View style={{
184
+ paddingHorizontal: 8,
185
+ paddingVertical: 3,
186
+ borderRadius: 6,
187
+ backgroundColor: isSelected
188
+ ? AppColors_1.AppColors.purple
189
+ : `${AppColors_1.AppColors.purple}14`,
190
+ borderWidth: 1,
191
+ borderColor: isSelected
192
+ ? AppColors_1.AppColors.purple
193
+ : `${AppColors_1.AppColors.purple}30`,
194
+ }}>
195
+ <react_native_1.Text style={{
196
+ fontFamily: AppFonts_1.AppFonts.interBold,
197
+ fontSize: 10,
198
+ color: isSelected
199
+ ? AppColors_1.AppColors.white
200
+ : AppColors_1.AppColors.purple,
201
+ }}>
202
+ {tag}
203
+ </react_native_1.Text>
204
+ </react_native_1.View>
205
+ </TouchableScale_1.default>);
206
+ })}
207
+ </react_native_1.ScrollView>)}
208
+
138
209
  <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginVertical: 4, maxHeight: 46 }} contentContainerStyle={{
139
210
  paddingHorizontal: 16,
140
211
  paddingBottom: 4,
@@ -153,7 +224,9 @@ const ConsoleTab = react_1.default.memo(() => {
153
224
  {
154
225
  backgroundColor: active ? AppColors_1.AppColors.indigo600Alt : AppColors_1.AppColors.indigo50,
155
226
  borderColor: active ? AppColors_1.AppColors.indigo600 : AppColors_1.AppColors.indigo400,
156
- borderRadius: 7,
227
+ borderRadius: 8,
228
+ paddingHorizontal: 10,
229
+ paddingVertical: 6,
157
230
  },
158
231
  active && {
159
232
  shadowColor: AppColors_1.AppColors.indigo600Alt,
@@ -166,21 +239,9 @@ const ConsoleTab = react_1.default.memo(() => {
166
239
  <react_native_1.View style={{
167
240
  flexDirection: 'row',
168
241
  alignItems: 'center',
169
- gap: 5,
170
- }}>
171
- <react_native_1.View style={{
172
- width: 12,
173
- height: 12,
174
- borderRadius: 3,
175
- borderWidth: 1.2,
176
- borderColor: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.indigo400,
177
- backgroundColor: active ? AppColors_1.AppColors.white : 'transparent',
178
- alignItems: 'center',
179
- justifyContent: 'center',
242
+ gap: 6,
180
243
  }}>
181
- {active && <NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.indigo600Alt} size={8}/>}
182
- </react_native_1.View>
183
- <NetworkIcons_1.LayersIcon size={12} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.indigo600Alt}/>
244
+ <NetworkIcons_1.LayersIcon size={13} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.indigo600Alt}/>
184
245
  <react_native_1.Text numberOfLines={1} style={[
185
246
  styles_1.default.statusFilterText,
186
247
  {
@@ -215,7 +276,9 @@ const ConsoleTab = react_1.default.memo(() => {
215
276
  {
216
277
  backgroundColor: active ? AppColors_1.AppColors.teal600 : AppColors_1.AppColors.teal100,
217
278
  borderColor: active ? AppColors_1.AppColors.teal600 : AppColors_1.AppColors.teal400,
218
- borderRadius: 7,
279
+ borderRadius: 8,
280
+ paddingHorizontal: 10,
281
+ paddingVertical: 6,
219
282
  },
220
283
  active && {
221
284
  shadowColor: AppColors_1.AppColors.teal600,
@@ -228,21 +291,9 @@ const ConsoleTab = react_1.default.memo(() => {
228
291
  <react_native_1.View style={{
229
292
  flexDirection: 'row',
230
293
  alignItems: 'center',
231
- gap: 5,
294
+ gap: 6,
232
295
  }}>
233
- <react_native_1.View style={{
234
- width: 12,
235
- height: 12,
236
- borderRadius: 3,
237
- borderWidth: 1.2,
238
- borderColor: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.teal400,
239
- backgroundColor: active ? AppColors_1.AppColors.white : 'transparent',
240
- alignItems: 'center',
241
- justifyContent: 'center',
242
- }}>
243
- {active && <NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.teal600} size={8}/>}
244
- </react_native_1.View>
245
- <NetworkIcons_1.UserIcon size={12} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.teal600}/>
296
+ <NetworkIcons_1.UserIcon size={13} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.teal600}/>
246
297
  <react_native_1.Text numberOfLines={1} style={[
247
298
  styles_1.default.statusFilterText,
248
299
  {
@@ -277,7 +328,9 @@ const ConsoleTab = react_1.default.memo(() => {
277
328
  {
278
329
  backgroundColor: active ? AppColors_1.AppColors.sky600 : AppColors_1.AppColors.sky100,
279
330
  borderColor: active ? AppColors_1.AppColors.blue700 : AppColors_1.AppColors.sky400,
280
- borderRadius: 7,
331
+ borderRadius: 8,
332
+ paddingHorizontal: 10,
333
+ paddingVertical: 6,
281
334
  },
282
335
  active && {
283
336
  shadowColor: AppColors_1.AppColors.sky600,
@@ -290,21 +343,9 @@ const ConsoleTab = react_1.default.memo(() => {
290
343
  <react_native_1.View style={{
291
344
  flexDirection: 'row',
292
345
  alignItems: 'center',
293
- gap: 5,
346
+ gap: 6,
294
347
  }}>
295
- <react_native_1.View style={{
296
- width: 12,
297
- height: 12,
298
- borderRadius: 3,
299
- borderWidth: 1.2,
300
- borderColor: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.sky400,
301
- backgroundColor: active ? AppColors_1.AppColors.white : 'transparent',
302
- alignItems: 'center',
303
- justifyContent: 'center',
304
- }}>
305
- {active && <NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.sky600} size={8}/>}
306
- </react_native_1.View>
307
- <NetworkIcons_1.InfoCircleIcon size={12} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.sky600}/>
348
+ <NetworkIcons_1.InfoCircleIcon size={13} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.sky600}/>
308
349
  <react_native_1.Text numberOfLines={1} style={[
309
350
  styles_1.default.statusFilterText,
310
351
  {
@@ -339,7 +380,9 @@ const ConsoleTab = react_1.default.memo(() => {
339
380
  {
340
381
  backgroundColor: active ? AppColors_1.AppColors.amber600 : AppColors_1.AppColors.amber100,
341
382
  borderColor: active ? AppColors_1.AppColors.amber700 : AppColors_1.AppColors.amber200,
342
- borderRadius: 7,
383
+ borderRadius: 8,
384
+ paddingHorizontal: 10,
385
+ paddingVertical: 6,
343
386
  },
344
387
  active && {
345
388
  shadowColor: AppColors_1.AppColors.amber600,
@@ -352,21 +395,9 @@ const ConsoleTab = react_1.default.memo(() => {
352
395
  <react_native_1.View style={{
353
396
  flexDirection: 'row',
354
397
  alignItems: 'center',
355
- gap: 5,
356
- }}>
357
- <react_native_1.View style={{
358
- width: 12,
359
- height: 12,
360
- borderRadius: 3,
361
- borderWidth: 1.2,
362
- borderColor: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.amber500,
363
- backgroundColor: active ? AppColors_1.AppColors.white : 'transparent',
364
- alignItems: 'center',
365
- justifyContent: 'center',
398
+ gap: 6,
366
399
  }}>
367
- {active && <NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.amber600} size={8}/>}
368
- </react_native_1.View>
369
- <NetworkIcons_1.WarningTriangleIcon size={12} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.amber700}/>
400
+ <NetworkIcons_1.WarningTriangleIcon size={13} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.amber700}/>
370
401
  <react_native_1.Text numberOfLines={1} style={[
371
402
  styles_1.default.statusFilterText,
372
403
  {
@@ -401,7 +432,9 @@ const ConsoleTab = react_1.default.memo(() => {
401
432
  {
402
433
  backgroundColor: active ? AppColors_1.AppColors.red500 : AppColors_1.AppColors.red100,
403
434
  borderColor: active ? AppColors_1.AppColors.red600 : AppColors_1.AppColors.errorBorder,
404
- borderRadius: 7,
435
+ borderRadius: 8,
436
+ paddingHorizontal: 10,
437
+ paddingVertical: 6,
405
438
  },
406
439
  active && {
407
440
  shadowColor: AppColors_1.AppColors.red500,
@@ -414,21 +447,9 @@ const ConsoleTab = react_1.default.memo(() => {
414
447
  <react_native_1.View style={{
415
448
  flexDirection: 'row',
416
449
  alignItems: 'center',
417
- gap: 5,
418
- }}>
419
- <react_native_1.View style={{
420
- width: 12,
421
- height: 12,
422
- borderRadius: 3,
423
- borderWidth: 1.2,
424
- borderColor: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.red500,
425
- backgroundColor: active ? AppColors_1.AppColors.white : 'transparent',
426
- alignItems: 'center',
427
- justifyContent: 'center',
450
+ gap: 6,
428
451
  }}>
429
- {active && <NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.red500} size={8}/>}
430
- </react_native_1.View>
431
- <NetworkIcons_1.ErrorCircleIcon size={12} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.red500}/>
452
+ <NetworkIcons_1.ErrorCircleIcon size={13} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.red500}/>
432
453
  <react_native_1.Text numberOfLines={1} style={[
433
454
  styles_1.default.statusFilterText,
434
455
  {
@@ -463,7 +484,9 @@ const ConsoleTab = react_1.default.memo(() => {
463
484
  {
464
485
  backgroundColor: active ? AppColors_1.AppColors.violet600 : AppColors_1.AppColors.purple100,
465
486
  borderColor: active ? AppColors_1.AppColors.purple700 : AppColors_1.AppColors.purple200,
466
- borderRadius: 7,
487
+ borderRadius: 8,
488
+ paddingHorizontal: 10,
489
+ paddingVertical: 6,
467
490
  },
468
491
  active && {
469
492
  shadowColor: AppColors_1.AppColors.violet600,
@@ -476,29 +499,17 @@ const ConsoleTab = react_1.default.memo(() => {
476
499
  <react_native_1.View style={{
477
500
  flexDirection: 'row',
478
501
  alignItems: 'center',
479
- gap: 5,
480
- }}>
481
- <react_native_1.View style={{
482
- width: 12,
483
- height: 12,
484
- borderRadius: 3,
485
- borderWidth: 1.2,
486
- borderColor: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple400,
487
- backgroundColor: active ? AppColors_1.AppColors.white : 'transparent',
488
- alignItems: 'center',
489
- justifyContent: 'center',
502
+ gap: 6,
490
503
  }}>
491
- {active && <NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.violet600} size={8}/>}
492
- </react_native_1.View>
493
- <NetworkIcons_1.AnalyticsIcon size={12} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple}/>
504
+ <NetworkIcons_1.AnalyticsIcon size={13} color={active ? AppColors_1.AppColors.white : AppColors_1.AppColors.violet600}/>
494
505
  <react_native_1.Text numberOfLines={1} style={[
495
506
  styles_1.default.statusFilterText,
496
507
  {
497
- color: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.brandPurple,
508
+ color: active ? AppColors_1.AppColors.white : AppColors_1.AppColors.purpleText,
498
509
  fontFamily: AppFonts_1.AppFonts.interBold,
499
510
  },
500
511
  ]}>
501
- {t('tabs.analytics', 'Analytics')} ({logCounts.analytics})
512
+ {t('console.analytics', 'Analytics')} ({logCounts.analytics})
502
513
  </react_native_1.Text>
503
514
  </react_native_1.View>
504
515
  </react_native_1.View>
@@ -507,7 +518,7 @@ const ConsoleTab = react_1.default.memo(() => {
507
518
  </react_native_1.ScrollView>
508
519
  </react_native_1.View>
509
520
 
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={[
521
+ <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
522
  styles_1.default.listContent,
512
523
  filteredConsoleLogs.length === 0 && { flexGrow: 1 },
513
524
  ]} keyboardShouldPersistTaps="handled"/>
@@ -147,11 +147,16 @@ const CrashTab = react_1.default.memo(() => {
147
147
  }
148
148
  // Search filter
149
149
  if (searchQuery.trim().length > 0) {
150
- const q = searchQuery.toLowerCase();
151
- const msg = (item.message || '').toLowerCase();
152
- const name = (item.name || '').toLowerCase();
153
- const stack = (item.stack || '').toLowerCase();
154
- return msg.includes(q) || name.includes(q) || stack.includes(q);
150
+ const queryTokens = searchQuery.trim().toLowerCase().split(/\s+/).filter(Boolean);
151
+ const searchTarget = [
152
+ item.message || '',
153
+ item.name || '',
154
+ item.stack || '',
155
+ item.type || '',
156
+ item.deviceInfo?.platform || '',
157
+ ...(item.breadcrumbs || []).map(b => `${b.type || ''} ${b.message || ''}`),
158
+ ].join(' ').toLowerCase();
159
+ return queryTokens.every(token => searchTarget.includes(token));
155
160
  }
156
161
  return true;
157
162
  });
@@ -288,74 +293,75 @@ const CrashTab = react_1.default.memo(() => {
288
293
  </AnimatedEntrance_1.default>);
289
294
  }, [searchQuery, setSelectedCrash]);
290
295
  return (<react_native_1.View style={localStyles.container}>
291
- {/* ─── Top Stats Bar ─── */}
292
- <react_native_1.View style={localStyles.statsBar}>
293
- <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.statsScrollContent}>
294
- <react_native_1.View style={[localStyles.statChip, localStyles.statChipActive]}>
295
- <react_native_1.Text style={localStyles.statChipValue}>{stats.total}</react_native_1.Text>
296
- <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statCrashes')}</react_native_1.Text>
297
- </react_native_1.View>
296
+ {crashRecords.length > 0 && (<>
297
+ {/* ─── Top Stats Bar ─── */}
298
+ <react_native_1.View style={localStyles.statsBar}>
299
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.statsScrollContent}>
300
+ <react_native_1.View style={[localStyles.statChip, localStyles.statChipActive]}>
301
+ <react_native_1.Text style={localStyles.statChipValue}>{stats.total}</react_native_1.Text>
302
+ <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statCrashes')}</react_native_1.Text>
303
+ </react_native_1.View>
298
304
 
299
- <react_native_1.View style={localStyles.statChip}>
300
- <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.errorColor }]}>
301
- {stats.fatalCount}
302
- </react_native_1.Text>
303
- <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statFatal')}</react_native_1.Text>
304
- </react_native_1.View>
305
+ <react_native_1.View style={localStyles.statChip}>
306
+ <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.errorColor }]}>
307
+ {stats.fatalCount}
308
+ </react_native_1.Text>
309
+ <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statFatal')}</react_native_1.Text>
310
+ </react_native_1.View>
305
311
 
306
- <react_native_1.View style={localStyles.statChip}>
307
- <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.offerPurple }]}>
308
- {stats.jsCount}
309
- </react_native_1.Text>
310
- <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statJsErrors')}</react_native_1.Text>
311
- </react_native_1.View>
312
+ <react_native_1.View style={localStyles.statChip}>
313
+ <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.offerPurple }]}>
314
+ {stats.jsCount}
315
+ </react_native_1.Text>
316
+ <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statJsErrors')}</react_native_1.Text>
317
+ </react_native_1.View>
312
318
 
313
- <react_native_1.View style={localStyles.statChip}>
314
- <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.darkOrange }]}>
315
- {stats.promiseCount}
316
- </react_native_1.Text>
317
- <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statPromises')}</react_native_1.Text>
318
- </react_native_1.View>
319
+ <react_native_1.View style={localStyles.statChip}>
320
+ <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.darkOrange }]}>
321
+ {stats.promiseCount}
322
+ </react_native_1.Text>
323
+ <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statPromises')}</react_native_1.Text>
324
+ </react_native_1.View>
319
325
 
320
- <react_native_1.View style={localStyles.statChip}>
321
- <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.purple }]}>
322
- {stats.renderCount}
323
- </react_native_1.Text>
324
- <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statRender')}</react_native_1.Text>
325
- </react_native_1.View>
326
+ <react_native_1.View style={localStyles.statChip}>
327
+ <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.purple }]}>
328
+ {stats.renderCount}
329
+ </react_native_1.Text>
330
+ <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statRender')}</react_native_1.Text>
331
+ </react_native_1.View>
326
332
 
327
- <react_native_1.View style={localStyles.statChip}>
328
- <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.skyBlue }]}>
329
- {stats.nativeCount}
330
- </react_native_1.Text>
331
- <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statNative')}</react_native_1.Text>
333
+ <react_native_1.View style={localStyles.statChip}>
334
+ <react_native_1.Text style={[localStyles.statChipValue, { color: AppColors_1.AppColors.skyBlue }]}>
335
+ {stats.nativeCount}
336
+ </react_native_1.Text>
337
+ <react_native_1.Text style={localStyles.statChipLabel}>{t('crash.statNative')}</react_native_1.Text>
338
+ </react_native_1.View>
339
+ </react_native_1.ScrollView>
332
340
  </react_native_1.View>
333
- </react_native_1.ScrollView>
334
- </react_native_1.View>
335
341
 
336
- {/* ─── Search & Controls ─── */}
337
- <react_native_1.View style={localStyles.controlsContainer}>
338
- <react_native_1.View style={localStyles.searchRow}>
339
- <react_native_1.View style={localStyles.searchInputWrapper}>
340
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
341
- <react_native_1.TextInput value={searchQuery} onChangeText={setSearchQuery} placeholder={t('crash.searchPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} style={localStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
342
- {searchQuery.length > 0 && (<react_native_1.TouchableOpacity onPress={() => setSearchQuery('')} hitSlop={8}>
343
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
344
- </react_native_1.TouchableOpacity>)}
345
- </react_native_1.View>
342
+ {/* ─── Search & Controls ─── */}
343
+ <react_native_1.View style={localStyles.controlsContainer}>
344
+ <react_native_1.View style={localStyles.searchRow}>
345
+ <react_native_1.View style={localStyles.searchInputWrapper}>
346
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
347
+ <react_native_1.TextInput value={searchQuery} onChangeText={setSearchQuery} placeholder={t('crash.searchPlaceholder')} placeholderTextColor={AppColors_1.AppColors.grayTextWeak} style={localStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
348
+ {searchQuery.length > 0 && (<react_native_1.TouchableOpacity onPress={() => setSearchQuery('')} hitSlop={8}>
349
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
350
+ </react_native_1.TouchableOpacity>)}
351
+ </react_native_1.View>
346
352
 
347
- {/* Crash Filters */}
348
- {crashRecords.length > 0 && (<TouchableScale_1.default onPress={() => setIsFilterModalOpen(true)} style={[
353
+ {/* Crash Filters */}
354
+ <TouchableScale_1.default onPress={() => setIsFilterModalOpen(true)} style={[
349
355
  localStyles.filterButton,
350
356
  !(0, CrashFilterModal_1.isCrashFiltersDefault)(crashFilters) && {
351
357
  borderColor: `${AppColors_1.AppColors.brandPurple}60`,
352
358
  backgroundColor: `${AppColors_1.AppColors.brandPurple}15`,
353
359
  },
354
360
  ]}>
355
- <NetworkIcons_1.FilterIcon size={14} color={(0, CrashFilterModal_1.isCrashFiltersDefault)(crashFilters)
361
+ <NetworkIcons_1.FilterIcon size={14} color={(0, CrashFilterModal_1.isCrashFiltersDefault)(crashFilters)
356
362
  ? AppColors_1.AppColors.grayTextStrong
357
363
  : AppColors_1.AppColors.brandPurple}/>
358
- {!(0, CrashFilterModal_1.isCrashFiltersDefault)(crashFilters) && (<react_native_1.View style={{
364
+ {!(0, CrashFilterModal_1.isCrashFiltersDefault)(crashFilters) && (<react_native_1.View style={{
359
365
  position: 'absolute',
360
366
  top: 2,
361
367
  right: 2,
@@ -366,40 +372,41 @@ const CrashTab = react_1.default.memo(() => {
366
372
  borderWidth: 1,
367
373
  borderColor: AppColors_1.AppColors.white,
368
374
  }}/>)}
369
- </TouchableScale_1.default>)}
375
+ </TouchableScale_1.default>
370
376
 
371
- {/* Clear Crashes */}
372
- {crashRecords.length > 0 && (<TouchableScale_1.default onPress={handleClearAll} style={localStyles.clearButton}>
373
- <NetworkIcons_1.TrashIcon size={14} color={AppColors_1.AppColors.errorColor}/>
374
- </TouchableScale_1.default>)}
375
- </react_native_1.View>
377
+ {/* Clear Crashes */}
378
+ <TouchableScale_1.default onPress={handleClearAll} style={localStyles.clearButton}>
379
+ <NetworkIcons_1.TrashIcon size={14} color={AppColors_1.AppColors.errorColor}/>
380
+ </TouchableScale_1.default>
381
+ </react_native_1.View>
376
382
 
377
- {/* ─── Filter Chips ─── */}
378
- <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.filterScrollContent}>
379
- {[
380
- { key: 'all', label: t('crash.filterAll'), Icon: NetworkIcons_1.LayersIcon },
381
- { key: 'fatal', label: t('crash.filterFatal'), Icon: NetworkIcons_1.SkullIcon },
382
- { key: 'js', label: t('crash.filterJsError'), Icon: NetworkIcons_1.JsIcon },
383
- { key: 'promise', label: t('crash.filterPromise'), Icon: NetworkIcons_1.HourglassIcon },
384
- { key: 'render', label: t('crash.filterRender'), Icon: NetworkIcons_1.LayoutIcon },
385
- { key: 'native', label: t('crash.filterNative'), Icon: NetworkIcons_1.ChipIcon },
386
- ].map(chip => {
387
- const isActive = filterType === chip.key;
388
- return (<react_native_1.TouchableOpacity key={chip.key} onPress={() => setFilterType(chip.key)} style={[
389
- localStyles.filterChip,
390
- isActive && localStyles.filterChipActive,
391
- ]}>
392
- <chip.Icon size={12} color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextStrong}/>
393
- <react_native_1.Text style={[
394
- localStyles.filterChipText,
395
- isActive && localStyles.filterChipTextActive,
396
- ]}>
397
- {chip.label}
398
- </react_native_1.Text>
399
- </react_native_1.TouchableOpacity>);
400
- })}
401
- </react_native_1.ScrollView>
402
- </react_native_1.View>
383
+ {/* ─── Filter Chips ─── */}
384
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.filterScrollContent}>
385
+ {[
386
+ { key: 'all', label: t('crash.filterAll'), Icon: NetworkIcons_1.LayersIcon },
387
+ { key: 'fatal', label: t('crash.filterFatal'), Icon: NetworkIcons_1.SkullIcon },
388
+ { key: 'js', label: t('crash.filterJsError'), Icon: NetworkIcons_1.JsIcon },
389
+ { key: 'promise', label: t('crash.filterPromise'), Icon: NetworkIcons_1.HourglassIcon },
390
+ { key: 'render', label: t('crash.filterRender'), Icon: NetworkIcons_1.LayoutIcon },
391
+ { key: 'native', label: t('crash.filterNative'), Icon: NetworkIcons_1.ChipIcon },
392
+ ].map(chip => {
393
+ const isActive = filterType === chip.key;
394
+ return (<react_native_1.TouchableOpacity key={chip.key} onPress={() => setFilterType(chip.key)} style={[
395
+ localStyles.filterChip,
396
+ isActive && localStyles.filterChipActive,
397
+ ]}>
398
+ <chip.Icon size={12} color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.grayTextStrong}/>
399
+ <react_native_1.Text style={[
400
+ localStyles.filterChipText,
401
+ isActive && localStyles.filterChipTextActive,
402
+ ]}>
403
+ {chip.label}
404
+ </react_native_1.Text>
405
+ </react_native_1.TouchableOpacity>);
406
+ })}
407
+ </react_native_1.ScrollView>
408
+ </react_native_1.View>
409
+ </>)}
403
410
 
404
411
  {/* ─── Crash List or Empty State ─── */}
405
412
  {filteredList.length === 0 ? (<react_native_1.ScrollView contentContainerStyle={localStyles.emptyContainer} showsVerticalScrollIndicator={false}>
@@ -412,7 +419,7 @@ const CrashTab = react_1.default.memo(() => {
412
419
  ? t('crash.emptySearchSubtitle')
413
420
  : t('crash.emptySubtitle')}
414
421
  </react_native_1.Text>
415
- </react_native_1.ScrollView>) : (<react_native_1.FlatList data={filteredList} keyExtractor={item => item.id} renderItem={renderCard} contentContainerStyle={localStyles.listContent} showsVerticalScrollIndicator={false} ListFooterComponent={<EndOfListFooter_1.default />}/>)}
422
+ </react_native_1.ScrollView>) : (<react_native_1.FlatList data={filteredList} keyExtractor={item => item.id} renderItem={renderCard} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} contentContainerStyle={localStyles.listContent} showsVerticalScrollIndicator={false} ListFooterComponent={<EndOfListFooter_1.default />}/>)}
416
423
 
417
424
  {/* Filter Modal */}
418
425
  <CrashFilterModal_1.default visible={isFilterModalOpen} onClose={() => setIsFilterModalOpen(false)} filters={crashFilters} onApply={setCrashFilters} searchQuery={searchQuery}/>
@@ -688,10 +695,11 @@ const localStyles = react_native_1.StyleSheet.create({
688
695
  color: AppColors_1.AppColors.grayTextWeak,
689
696
  },
690
697
  emptyContainer: {
698
+ flexGrow: 1,
691
699
  alignItems: 'center',
692
700
  justifyContent: 'center',
693
701
  padding: 32,
694
- marginTop: 40,
702
+ paddingBottom: 80,
695
703
  },
696
704
  emptyIconCircle: {
697
705
  width: 72,