react-native-inapp-inspector 1.1.35 → 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 (82) 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/CopyButton.js +3 -0
  6. package/dist/commonjs/components/ErrorBoundary.js +3 -0
  7. package/dist/commonjs/components/Inspector/AnalyticsTab.js +7 -3
  8. package/dist/commonjs/components/Inspector/BundleTab.js +1 -1
  9. package/dist/commonjs/components/Inspector/ConsoleTab.js +1 -1
  10. package/dist/commonjs/components/Inspector/CrashTab.js +97 -90
  11. package/dist/commonjs/components/Inspector/InspectorHeader.js +12 -8
  12. package/dist/commonjs/components/Inspector/MainScreen.js +14 -101
  13. package/dist/commonjs/components/Inspector/NetworkTab.js +47 -10
  14. package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
  15. package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
  16. package/dist/commonjs/components/Inspector/SettingsPanel.js +342 -88
  17. package/dist/commonjs/components/Inspector/TabBar.js +6 -3
  18. package/dist/commonjs/components/NetworkIcons.d.ts +1 -0
  19. package/dist/commonjs/components/NetworkIcons.js +6 -1
  20. package/dist/commonjs/components/TouchableScale.d.ts +1 -0
  21. package/dist/commonjs/components/TouchableScale.js +30 -32
  22. package/dist/commonjs/constants/index.d.ts +1 -2
  23. package/dist/commonjs/constants/index.js +4 -0
  24. package/dist/commonjs/constants/version.d.ts +1 -1
  25. package/dist/commonjs/constants/version.js +1 -1
  26. package/dist/commonjs/customHooks/analyticsLogger.d.ts +4 -0
  27. package/dist/commonjs/customHooks/analyticsLogger.js +7 -5
  28. package/dist/commonjs/customHooks/crashHandler.js +7 -0
  29. package/dist/commonjs/helpers/index.js +10 -1
  30. package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
  31. package/dist/commonjs/helpers/settingsStore.js +59 -3
  32. package/dist/commonjs/index.d.ts +1 -0
  33. package/dist/commonjs/index.js +229 -39
  34. package/dist/commonjs/native/NativeInspector.d.ts +125 -0
  35. package/dist/commonjs/native/NativeInspector.js +313 -0
  36. package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
  37. package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
  38. package/dist/commonjs/styles/index.js +6 -6
  39. package/dist/commonjs/types/enums.d.ts +1 -1
  40. package/dist/commonjs/types/interfaces.d.ts +9 -0
  41. package/dist/esm/components/CopyButton.js +3 -0
  42. package/dist/esm/components/ErrorBoundary.js +3 -0
  43. package/dist/esm/components/Inspector/AnalyticsTab.js +7 -3
  44. package/dist/esm/components/Inspector/BundleTab.js +1 -1
  45. package/dist/esm/components/Inspector/ConsoleTab.js +1 -1
  46. package/dist/esm/components/Inspector/CrashTab.js +97 -90
  47. package/dist/esm/components/Inspector/InspectorHeader.js +13 -9
  48. package/dist/esm/components/Inspector/MainScreen.js +15 -69
  49. package/dist/esm/components/Inspector/NetworkTab.js +47 -10
  50. package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
  51. package/dist/esm/components/Inspector/ReduxTab.js +18 -10
  52. package/dist/esm/components/Inspector/SettingsPanel.js +344 -90
  53. package/dist/esm/components/Inspector/TabBar.js +7 -4
  54. package/dist/esm/components/NetworkIcons.d.ts +1 -0
  55. package/dist/esm/components/NetworkIcons.js +4 -0
  56. package/dist/esm/components/TouchableScale.d.ts +1 -0
  57. package/dist/esm/components/TouchableScale.js +31 -33
  58. package/dist/esm/constants/index.d.ts +1 -2
  59. package/dist/esm/constants/index.js +4 -0
  60. package/dist/esm/constants/version.d.ts +1 -1
  61. package/dist/esm/constants/version.js +1 -1
  62. package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
  63. package/dist/esm/customHooks/analyticsLogger.js +5 -4
  64. package/dist/esm/customHooks/crashHandler.js +7 -0
  65. package/dist/esm/helpers/index.js +10 -1
  66. package/dist/esm/helpers/settingsStore.d.ts +9 -0
  67. package/dist/esm/helpers/settingsStore.js +58 -3
  68. package/dist/esm/index.d.ts +1 -0
  69. package/dist/esm/index.js +215 -39
  70. package/dist/esm/native/NativeInspector.d.ts +125 -0
  71. package/dist/esm/native/NativeInspector.js +289 -0
  72. package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
  73. package/dist/esm/native/NativeNetworkInspector.js +2 -0
  74. package/dist/esm/styles/index.js +6 -6
  75. package/dist/esm/types/enums.d.ts +1 -1
  76. package/dist/esm/types/interfaces.d.ts +9 -0
  77. package/ios/NetworkInspectorModule.h +6 -0
  78. package/ios/NetworkInspectorModule.m +720 -5
  79. package/package.json +13 -2
  80. package/react-native-inapp-inspector.podspec +7 -2
  81. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
  82. 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
+ }
@@ -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
@@ -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>
@@ -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,
@@ -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"/>
@@ -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}/>
@@ -226,23 +226,27 @@ const InspectorHeader = react_1.default.memo(() => {
226
226
  </react_native_1.Text>
227
227
  </react_native_1.View>
228
228
 
229
- <react_native_1.View style={{
230
- backgroundColor: `${AppColors_1.AppColors.white}14`,
229
+ <react_native_1.Pressable onPress={() => react_native_1.Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { })} style={{
230
+ backgroundColor: '#CB383726',
231
231
  borderRadius: 4,
232
- paddingHorizontal: 4.5,
232
+ paddingHorizontal: 5,
233
233
  paddingVertical: 1.5,
234
234
  borderWidth: 1,
235
- borderColor: `${AppColors_1.AppColors.white}20`,
235
+ borderColor: '#CB383780',
236
+ flexDirection: 'row',
237
+ alignItems: 'center',
238
+ gap: 3.5,
236
239
  flexShrink: 0,
237
240
  }}>
241
+ <NetworkIcons_1.NpmIcon size={11} color="#FF6B6B"/>
238
242
  <react_native_1.Text style={{
239
- fontFamily: AppFonts_1.AppFonts.interMedium,
240
- fontSize: 8.5,
241
- color: `${AppColors_1.AppColors.white}B3`,
243
+ fontFamily: AppFonts_1.AppFonts.interBold,
244
+ fontSize: 9,
245
+ color: '#FF6B6B',
242
246
  }} numberOfLines={1}>
243
247
  v{constants_2.LIB_VERSION}
244
248
  </react_native_1.Text>
245
- </react_native_1.View>
249
+ </react_native_1.Pressable>
246
250
  </react_native_1.View>
247
251
  </react_native_1.View>
248
252
  </react_native_1.View>) : null}
@@ -1,42 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
38
5
  Object.defineProperty(exports, "__esModule", { value: true });
39
- const react_1 = __importStar(require("react"));
6
+ const react_1 = __importDefault(require("react"));
40
7
  const react_native_1 = require("react-native");
41
8
  const InspectorContext_1 = require("./InspectorContext");
42
9
  const ErrorBoundary_1 = __importDefault(require("../ErrorBoundary"));
@@ -61,25 +28,16 @@ const styles_1 = __importDefault(require("../../styles"));
61
28
  const AppColors_1 = require("../../styles/AppColors");
62
29
  const NavigationTracker_1 = __importDefault(require("./NavigationTracker"));
63
30
  const MainScreen = () => {
64
- const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, selectedCrash, settingsPage, activeTab, isReady, isEnabled, hasNavigationContext, setNavState, } = (0, InspectorContext_1.useInspector)();
65
- // Lazy-mount each tab on first visit and cache it in memory for 0ms instantaneous switching
66
- const [mountedTabs, setMountedTabs] = (0, react_1.useState)({
67
- [activeTab]: true,
68
- });
69
- (0, react_1.useEffect)(() => {
70
- setMountedTabs(prev => {
71
- if (prev[activeTab])
72
- return prev;
73
- return { ...prev, [activeTab]: true };
74
- });
75
- }, [activeTab]);
31
+ const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, selectedCrash, settingsPage, activeTab, isReady, isEnabled, useNativeFab, hasNavigationContext, setNavState, } = (0, InspectorContext_1.useInspector)();
76
32
  const isDetailActive = (activeTab === 'apis' && selected != null) ||
77
33
  (activeTab === 'analytics' && selectedEvent != null) ||
78
34
  (activeTab === 'logs' && selectedLog != null) ||
79
35
  (activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null)) ||
80
36
  (activeTab === 'crash' && selectedCrash != null);
81
37
  return (<>
82
- {(react_native_1.Platform.OS === 'ios' || react_native_1.Platform.OS === 'android') && isEnabled && <FabLauncher_1.default />}
38
+ {(react_native_1.Platform.OS === 'ios' || react_native_1.Platform.OS === 'android') &&
39
+ isEnabled &&
40
+ !useNativeFab && <FabLauncher_1.default />}
83
41
  <react_native_1.Modal visible={visible} animationType={modalAnimationType} transparent statusBarTranslucent={true}>
84
42
  {visible && (<ErrorBoundary_1.default onClose={closeModal}>
85
43
  <react_native_1.View style={styles_1.default.modalBackdrop}>
@@ -99,66 +57,21 @@ const MainScreen = () => {
99
57
  {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
100
58
  {!isDetailActive && settingsPage === null ? (<TabBar_1.default />) : null}
101
59
 
102
- {isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail_1.default />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail_1.default />) : activeTab === 'redux' ? (<ReduxDetail_1.default />) : activeTab === 'crash' && selectedCrash != null ? (<CrashDetail_1.default />) : null) : (<>
103
- <react_native_1.View style={{
104
- flex: 1,
105
- display: activeTab === 'apis' ? 'flex' : 'none',
106
- }}>
107
- {mountedTabs.apis && <NetworkTab_1.default />}
108
- </react_native_1.View>
109
- <react_native_1.View style={{
110
- flex: 1,
111
- display: activeTab === 'logs' ? 'flex' : 'none',
112
- }}>
113
- {mountedTabs.logs && <ConsoleTab_1.default />}
114
- </react_native_1.View>
115
- <react_native_1.View style={{
116
- flex: 1,
117
- display: activeTab === 'analytics' ? 'flex' : 'none',
118
- }}>
119
- {mountedTabs.analytics && <AnalyticsTab_1.default />}
120
- </react_native_1.View>
121
- <react_native_1.View style={{
122
- flex: 1,
123
- display: activeTab === 'redux' ? 'flex' : 'none',
124
- }}>
125
- {mountedTabs.redux && <ReduxTab_1.default />}
126
- </react_native_1.View>
127
- <react_native_1.View style={{
128
- flex: 1,
129
- display: activeTab === 'bundle' ? 'flex' : 'none',
130
- }}>
131
- {mountedTabs.bundle && <BundleTab_1.default />}
132
- </react_native_1.View>
133
- <react_native_1.View style={{
134
- flex: 1,
135
- display: activeTab === 'performance' ? 'flex' : 'none',
136
- }}>
137
- {mountedTabs.performance && <PerformanceTab_1.default />}
138
- </react_native_1.View>
139
- <react_native_1.View style={{
140
- flex: 1,
141
- display: activeTab === 'crash' ? 'flex' : 'none',
142
- }}>
143
- {mountedTabs.crash && <CrashTab_1.default />}
144
- </react_native_1.View>
145
- </>)) : (<react_native_1.View style={styles_1.default.empty}>
60
+ {settingsPage !== null ? (<SettingsPanel_1.default />) : isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail_1.default />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail_1.default />) : activeTab === 'redux' ? (<ReduxDetail_1.default />) : activeTab === 'crash' && selectedCrash != null ? (<CrashDetail_1.default />) : null) : (<react_native_1.View style={{ flex: 1 }}>
61
+ {activeTab === 'apis' && <NetworkTab_1.default />}
62
+ {activeTab === 'logs' && <ConsoleTab_1.default />}
63
+ {activeTab === 'analytics' && <AnalyticsTab_1.default />}
64
+ {activeTab === 'redux' && <ReduxTab_1.default />}
65
+ {activeTab === 'bundle' && <BundleTab_1.default />}
66
+ {activeTab === 'performance' && <PerformanceTab_1.default />}
67
+ {activeTab === 'crash' && <CrashTab_1.default />}
68
+ </react_native_1.View>)) : (<react_native_1.View style={styles_1.default.empty}>
146
69
  <react_native_1.ActivityIndicator size="large" color={AppColors_1.AppColors.purple}/>
147
70
  <react_native_1.Text style={[styles_1.default.emptySub, { marginTop: 12 }]}>
148
71
  Loading logs...
149
72
  </react_native_1.Text>
150
73
  </react_native_1.View>)}
151
74
 
152
- {settingsPage !== null && (<react_native_1.View style={[
153
- react_native_1.StyleSheet.absoluteFill,
154
- {
155
- backgroundColor: AppColors_1.AppColors.grayBackground,
156
- zIndex: 99999,
157
- },
158
- ]}>
159
- <SettingsPanel_1.default />
160
- </react_native_1.View>)}
161
-
162
75
  {/* Bottom floating toast notification */}
163
76
  <Toast_1.default />
164
77
  </react_native_1.View>