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
@@ -109,11 +109,16 @@ const CrashTab = React.memo(() => {
109
109
  }
110
110
  // Search filter
111
111
  if (searchQuery.trim().length > 0) {
112
- const q = searchQuery.toLowerCase();
113
- const msg = (item.message || '').toLowerCase();
114
- const name = (item.name || '').toLowerCase();
115
- const stack = (item.stack || '').toLowerCase();
116
- return msg.includes(q) || name.includes(q) || stack.includes(q);
112
+ const queryTokens = searchQuery.trim().toLowerCase().split(/\s+/).filter(Boolean);
113
+ const searchTarget = [
114
+ item.message || '',
115
+ item.name || '',
116
+ item.stack || '',
117
+ item.type || '',
118
+ item.deviceInfo?.platform || '',
119
+ ...(item.breadcrumbs || []).map(b => `${b.type || ''} ${b.message || ''}`),
120
+ ].join(' ').toLowerCase();
121
+ return queryTokens.every(token => searchTarget.includes(token));
117
122
  }
118
123
  return true;
119
124
  });
@@ -250,74 +255,75 @@ const CrashTab = React.memo(() => {
250
255
  </AnimatedEntrance>);
251
256
  }, [searchQuery, setSelectedCrash]);
252
257
  return (<View style={localStyles.container}>
253
- {/* ─── Top Stats Bar ─── */}
254
- <View style={localStyles.statsBar}>
255
- <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.statsScrollContent}>
256
- <View style={[localStyles.statChip, localStyles.statChipActive]}>
257
- <Text style={localStyles.statChipValue}>{stats.total}</Text>
258
- <Text style={localStyles.statChipLabel}>{t('crash.statCrashes')}</Text>
259
- </View>
258
+ {crashRecords.length > 0 && (<>
259
+ {/* ─── Top Stats Bar ─── */}
260
+ <View style={localStyles.statsBar}>
261
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.statsScrollContent}>
262
+ <View style={[localStyles.statChip, localStyles.statChipActive]}>
263
+ <Text style={localStyles.statChipValue}>{stats.total}</Text>
264
+ <Text style={localStyles.statChipLabel}>{t('crash.statCrashes')}</Text>
265
+ </View>
260
266
 
261
- <View style={localStyles.statChip}>
262
- <Text style={[localStyles.statChipValue, { color: AppColors.errorColor }]}>
263
- {stats.fatalCount}
264
- </Text>
265
- <Text style={localStyles.statChipLabel}>{t('crash.statFatal')}</Text>
266
- </View>
267
+ <View style={localStyles.statChip}>
268
+ <Text style={[localStyles.statChipValue, { color: AppColors.errorColor }]}>
269
+ {stats.fatalCount}
270
+ </Text>
271
+ <Text style={localStyles.statChipLabel}>{t('crash.statFatal')}</Text>
272
+ </View>
267
273
 
268
- <View style={localStyles.statChip}>
269
- <Text style={[localStyles.statChipValue, { color: AppColors.offerPurple }]}>
270
- {stats.jsCount}
271
- </Text>
272
- <Text style={localStyles.statChipLabel}>{t('crash.statJsErrors')}</Text>
273
- </View>
274
+ <View style={localStyles.statChip}>
275
+ <Text style={[localStyles.statChipValue, { color: AppColors.offerPurple }]}>
276
+ {stats.jsCount}
277
+ </Text>
278
+ <Text style={localStyles.statChipLabel}>{t('crash.statJsErrors')}</Text>
279
+ </View>
274
280
 
275
- <View style={localStyles.statChip}>
276
- <Text style={[localStyles.statChipValue, { color: AppColors.darkOrange }]}>
277
- {stats.promiseCount}
278
- </Text>
279
- <Text style={localStyles.statChipLabel}>{t('crash.statPromises')}</Text>
280
- </View>
281
+ <View style={localStyles.statChip}>
282
+ <Text style={[localStyles.statChipValue, { color: AppColors.darkOrange }]}>
283
+ {stats.promiseCount}
284
+ </Text>
285
+ <Text style={localStyles.statChipLabel}>{t('crash.statPromises')}</Text>
286
+ </View>
281
287
 
282
- <View style={localStyles.statChip}>
283
- <Text style={[localStyles.statChipValue, { color: AppColors.purple }]}>
284
- {stats.renderCount}
285
- </Text>
286
- <Text style={localStyles.statChipLabel}>{t('crash.statRender')}</Text>
287
- </View>
288
+ <View style={localStyles.statChip}>
289
+ <Text style={[localStyles.statChipValue, { color: AppColors.purple }]}>
290
+ {stats.renderCount}
291
+ </Text>
292
+ <Text style={localStyles.statChipLabel}>{t('crash.statRender')}</Text>
293
+ </View>
288
294
 
289
- <View style={localStyles.statChip}>
290
- <Text style={[localStyles.statChipValue, { color: AppColors.skyBlue }]}>
291
- {stats.nativeCount}
292
- </Text>
293
- <Text style={localStyles.statChipLabel}>{t('crash.statNative')}</Text>
295
+ <View style={localStyles.statChip}>
296
+ <Text style={[localStyles.statChipValue, { color: AppColors.skyBlue }]}>
297
+ {stats.nativeCount}
298
+ </Text>
299
+ <Text style={localStyles.statChipLabel}>{t('crash.statNative')}</Text>
300
+ </View>
301
+ </ScrollView>
294
302
  </View>
295
- </ScrollView>
296
- </View>
297
303
 
298
- {/* ─── Search & Controls ─── */}
299
- <View style={localStyles.controlsContainer}>
300
- <View style={localStyles.searchRow}>
301
- <View style={localStyles.searchInputWrapper}>
302
- <SearchIcon color={AppColors.grayTextWeak} size={14}/>
303
- <TextInput value={searchQuery} onChangeText={setSearchQuery} placeholder={t('crash.searchPlaceholder')} placeholderTextColor={AppColors.grayTextWeak} style={localStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
304
- {searchQuery.length > 0 && (<TouchableOpacity onPress={() => setSearchQuery('')} hitSlop={8}>
305
- <ClearIcon color={AppColors.grayTextWeak} size={14}/>
306
- </TouchableOpacity>)}
307
- </View>
304
+ {/* ─── Search & Controls ─── */}
305
+ <View style={localStyles.controlsContainer}>
306
+ <View style={localStyles.searchRow}>
307
+ <View style={localStyles.searchInputWrapper}>
308
+ <SearchIcon color={AppColors.grayTextWeak} size={14}/>
309
+ <TextInput value={searchQuery} onChangeText={setSearchQuery} placeholder={t('crash.searchPlaceholder')} placeholderTextColor={AppColors.grayTextWeak} style={localStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
310
+ {searchQuery.length > 0 && (<TouchableOpacity onPress={() => setSearchQuery('')} hitSlop={8}>
311
+ <ClearIcon color={AppColors.grayTextWeak} size={14}/>
312
+ </TouchableOpacity>)}
313
+ </View>
308
314
 
309
- {/* Crash Filters */}
310
- {crashRecords.length > 0 && (<TouchableScale onPress={() => setIsFilterModalOpen(true)} style={[
315
+ {/* Crash Filters */}
316
+ <TouchableScale onPress={() => setIsFilterModalOpen(true)} style={[
311
317
  localStyles.filterButton,
312
318
  !isCrashFiltersDefault(crashFilters) && {
313
319
  borderColor: `${AppColors.brandPurple}60`,
314
320
  backgroundColor: `${AppColors.brandPurple}15`,
315
321
  },
316
322
  ]}>
317
- <FilterIcon size={14} color={isCrashFiltersDefault(crashFilters)
323
+ <FilterIcon size={14} color={isCrashFiltersDefault(crashFilters)
318
324
  ? AppColors.grayTextStrong
319
325
  : AppColors.brandPurple}/>
320
- {!isCrashFiltersDefault(crashFilters) && (<View style={{
326
+ {!isCrashFiltersDefault(crashFilters) && (<View style={{
321
327
  position: 'absolute',
322
328
  top: 2,
323
329
  right: 2,
@@ -328,40 +334,41 @@ const CrashTab = React.memo(() => {
328
334
  borderWidth: 1,
329
335
  borderColor: AppColors.white,
330
336
  }}/>)}
331
- </TouchableScale>)}
337
+ </TouchableScale>
332
338
 
333
- {/* Clear Crashes */}
334
- {crashRecords.length > 0 && (<TouchableScale onPress={handleClearAll} style={localStyles.clearButton}>
335
- <TrashIcon size={14} color={AppColors.errorColor}/>
336
- </TouchableScale>)}
337
- </View>
339
+ {/* Clear Crashes */}
340
+ <TouchableScale onPress={handleClearAll} style={localStyles.clearButton}>
341
+ <TrashIcon size={14} color={AppColors.errorColor}/>
342
+ </TouchableScale>
343
+ </View>
338
344
 
339
- {/* ─── Filter Chips ─── */}
340
- <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.filterScrollContent}>
341
- {[
342
- { key: 'all', label: t('crash.filterAll'), Icon: LayersIcon },
343
- { key: 'fatal', label: t('crash.filterFatal'), Icon: SkullIcon },
344
- { key: 'js', label: t('crash.filterJsError'), Icon: JsIcon },
345
- { key: 'promise', label: t('crash.filterPromise'), Icon: HourglassIcon },
346
- { key: 'render', label: t('crash.filterRender'), Icon: LayoutIcon },
347
- { key: 'native', label: t('crash.filterNative'), Icon: ChipIcon },
348
- ].map(chip => {
349
- const isActive = filterType === chip.key;
350
- return (<TouchableOpacity key={chip.key} onPress={() => setFilterType(chip.key)} style={[
351
- localStyles.filterChip,
352
- isActive && localStyles.filterChipActive,
353
- ]}>
354
- <chip.Icon size={12} color={isActive ? AppColors.white : AppColors.grayTextStrong}/>
355
- <Text style={[
356
- localStyles.filterChipText,
357
- isActive && localStyles.filterChipTextActive,
358
- ]}>
359
- {chip.label}
360
- </Text>
361
- </TouchableOpacity>);
362
- })}
363
- </ScrollView>
364
- </View>
345
+ {/* ─── Filter Chips ─── */}
346
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.filterScrollContent}>
347
+ {[
348
+ { key: 'all', label: t('crash.filterAll'), Icon: LayersIcon },
349
+ { key: 'fatal', label: t('crash.filterFatal'), Icon: SkullIcon },
350
+ { key: 'js', label: t('crash.filterJsError'), Icon: JsIcon },
351
+ { key: 'promise', label: t('crash.filterPromise'), Icon: HourglassIcon },
352
+ { key: 'render', label: t('crash.filterRender'), Icon: LayoutIcon },
353
+ { key: 'native', label: t('crash.filterNative'), Icon: ChipIcon },
354
+ ].map(chip => {
355
+ const isActive = filterType === chip.key;
356
+ return (<TouchableOpacity key={chip.key} onPress={() => setFilterType(chip.key)} style={[
357
+ localStyles.filterChip,
358
+ isActive && localStyles.filterChipActive,
359
+ ]}>
360
+ <chip.Icon size={12} color={isActive ? AppColors.white : AppColors.grayTextStrong}/>
361
+ <Text style={[
362
+ localStyles.filterChipText,
363
+ isActive && localStyles.filterChipTextActive,
364
+ ]}>
365
+ {chip.label}
366
+ </Text>
367
+ </TouchableOpacity>);
368
+ })}
369
+ </ScrollView>
370
+ </View>
371
+ </>)}
365
372
 
366
373
  {/* ─── Crash List or Empty State ─── */}
367
374
  {filteredList.length === 0 ? (<ScrollView contentContainerStyle={localStyles.emptyContainer} showsVerticalScrollIndicator={false}>
@@ -374,7 +381,7 @@ const CrashTab = React.memo(() => {
374
381
  ? t('crash.emptySearchSubtitle')
375
382
  : t('crash.emptySubtitle')}
376
383
  </Text>
377
- </ScrollView>) : (<FlatList data={filteredList} keyExtractor={item => item.id} renderItem={renderCard} contentContainerStyle={localStyles.listContent} showsVerticalScrollIndicator={false} ListFooterComponent={<EndOfListFooter />}/>)}
384
+ </ScrollView>) : (<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 />}/>)}
378
385
 
379
386
  {/* Filter Modal */}
380
387
  <CrashFilterModal visible={isFilterModalOpen} onClose={() => setIsFilterModalOpen(false)} filters={crashFilters} onApply={setCrashFilters} searchQuery={searchQuery}/>
@@ -10,7 +10,7 @@ import { AppFonts } from '../../styles/AppFonts';
10
10
  import { METHOD_COLORS } from '../../constants';
11
11
  import { LIB_VERSION } from '../../constants';
12
12
  import { getStatusColor, getAppName, getBundleIdentifier, formatTime, getSize } from '../../helpers';
13
- import { WhiteBackNavigation, TrashIcon, SettingsIcon, CloseWhite, ClockIcon, SizeIcon, AppleIcon, AndroidIcon, } from '../NetworkIcons';
13
+ import { WhiteBackNavigation, TrashIcon, SettingsIcon, CloseWhite, ClockIcon, SizeIcon, AppleIcon, AndroidIcon, NpmIcon, } from '../NetworkIcons';
14
14
  const InspectorHeader = React.memo(() => {
15
15
  const { modalHeightPercent, appIcon, selected, setSelected, selectedEvent, setSelectedEvent, selectedLog, setSelectedLog, selectedReduxSlice, setSelectedReduxSlice, selectedReduxAction, setSelectedReduxAction, reduxState, reduxLastActionMap, showHeaderInfo, setShowHeaderInfo, updateAvailable, latestNpmVersion, clearAnim, activePulseAnim, unreadPulseAnim, runClearAllWithAnimation, setSettingsPage, closeModal, detailTitle, activeTab, environment, selectedCrash, setSelectedCrash, } = useInspector();
16
16
  const envConfig = useMemo(() => {
@@ -19,33 +19,33 @@ const InspectorHeader = React.memo(() => {
19
19
  if (clean === 'DEV' || clean.includes('DEV') || clean === 'LOCAL') {
20
20
  return {
21
21
  label: rawEnv,
22
- bg: 'rgba(16, 185, 129, 0.25)', // emerald
23
- border: 'rgba(110, 231, 183, 0.55)',
24
- text: '#A7F3D0',
22
+ bg: `${AppColors.emerald500}40`, // emerald
23
+ border: `${AppColors.emerald400}8C`,
24
+ text: AppColors.mintGreenBorder,
25
25
  };
26
26
  }
27
27
  if (clean === 'UAT' || clean === 'QA' || clean === 'TEST') {
28
28
  return {
29
29
  label: rawEnv,
30
- bg: 'rgba(245, 158, 11, 0.28)', // amber
31
- border: 'rgba(252, 211, 77, 0.6)',
32
- text: '#FDE68A',
30
+ bg: `${AppColors.amber500}47`, // amber
31
+ border: `${AppColors.amber400}99`,
32
+ text: AppColors.amberWarmBorder,
33
33
  };
34
34
  }
35
35
  if (clean === 'PREPROD' || clean === 'STAGE' || clean === 'STAGING') {
36
36
  return {
37
37
  label: rawEnv,
38
- bg: 'rgba(139, 92, 246, 0.28)', // purple
39
- border: 'rgba(196, 181, 253, 0.6)',
40
- text: '#DDD6FE',
38
+ bg: `${AppColors.purple500}47`, // purple
39
+ border: `${AppColors.purple400}99`,
40
+ text: AppColors.violetSoftBorder,
41
41
  };
42
42
  }
43
43
  // PROD / Live
44
44
  return {
45
45
  label: rawEnv,
46
- bg: 'rgba(244, 63, 94, 0.25)', // rose
47
- border: 'rgba(253, 164, 175, 0.55)',
48
- text: '#FECDD3',
46
+ bg: `${AppColors.rose500}40`, // rose
47
+ border: `${AppColors.roseBorder}8C`,
48
+ text: AppColors.errorBorder,
49
49
  };
50
50
  }, [environment]);
51
51
  const isDetailView = (activeTab === 'apis' && selected != null) ||
@@ -188,23 +188,27 @@ const InspectorHeader = React.memo(() => {
188
188
  </Text>
189
189
  </View>
190
190
 
191
- <View style={{
192
- backgroundColor: `${AppColors.white}14`,
191
+ <Pressable onPress={() => Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { })} style={{
192
+ backgroundColor: '#CB383726',
193
193
  borderRadius: 4,
194
- paddingHorizontal: 4.5,
194
+ paddingHorizontal: 5,
195
195
  paddingVertical: 1.5,
196
196
  borderWidth: 1,
197
- borderColor: `${AppColors.white}20`,
197
+ borderColor: '#CB383780',
198
+ flexDirection: 'row',
199
+ alignItems: 'center',
200
+ gap: 3.5,
198
201
  flexShrink: 0,
199
202
  }}>
203
+ <NpmIcon size={11} color="#FF6B6B"/>
200
204
  <Text style={{
201
- fontFamily: AppFonts.interMedium,
202
- fontSize: 8.5,
203
- color: `${AppColors.white}B3`,
205
+ fontFamily: AppFonts.interBold,
206
+ fontSize: 9,
207
+ color: '#FF6B6B',
204
208
  }} numberOfLines={1}>
205
209
  v{LIB_VERSION}
206
210
  </Text>
207
- </View>
211
+ </Pressable>
208
212
  </View>
209
213
  </View>
210
214
  </View>) : null}
@@ -446,8 +450,8 @@ const InspectorHeader = React.memo(() => {
446
450
  styles.headerMethodBadge,
447
451
  {
448
452
  backgroundColor: selectedCrash.isFatal
449
- ? '#DC2626'
450
- : '#D97706',
453
+ ? AppColors.red600
454
+ : AppColors.amber600,
451
455
  },
452
456
  ]}>
453
457
  <Text style={styles.headerMethodText}>
@@ -463,8 +467,8 @@ const InspectorHeader = React.memo(() => {
463
467
  styles.headerStatusDot,
464
468
  {
465
469
  backgroundColor: selectedCrash.isFatal
466
- ? '#DC2626'
467
- : '#F59E0B',
470
+ ? AppColors.red600
471
+ : AppColors.amber500,
468
472
  },
469
473
  ]}/>
470
474
  <Text style={styles.headerSubTitle}>
@@ -1,5 +1,5 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { ActivityIndicator, Modal, Platform, Pressable, StatusBar, StyleSheet, Text, View, } from 'react-native';
1
+ import React from 'react';
2
+ import { ActivityIndicator, Modal, Platform, Pressable, StatusBar, Text, View, } from 'react-native';
3
3
  import { useInspector } from './InspectorContext';
4
4
  import ErrorBoundary from '../ErrorBoundary';
5
5
  import FabLauncher from './FabLauncher';
@@ -23,32 +23,27 @@ import styles from '../../styles';
23
23
  import { AppColors } from '../../styles/AppColors';
24
24
  import NavigationTracker from './NavigationTracker';
25
25
  const MainScreen = () => {
26
- const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, selectedCrash, settingsPage, activeTab, isReady, isEnabled, hasNavigationContext, setNavState, } = useInspector();
27
- // Lazy-mount each tab on first visit and cache it in memory for 0ms instantaneous switching
28
- const [mountedTabs, setMountedTabs] = useState({
29
- [activeTab]: true,
30
- });
31
- useEffect(() => {
32
- setMountedTabs(prev => {
33
- if (prev[activeTab])
34
- return prev;
35
- return { ...prev, [activeTab]: true };
36
- });
37
- }, [activeTab]);
26
+ const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, selectedCrash, settingsPage, activeTab, isReady, isEnabled, useNativeFab, hasNavigationContext, setNavState, } = useInspector();
38
27
  const isDetailActive = (activeTab === 'apis' && selected != null) ||
39
28
  (activeTab === 'analytics' && selectedEvent != null) ||
40
29
  (activeTab === 'logs' && selectedLog != null) ||
41
30
  (activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null)) ||
42
31
  (activeTab === 'crash' && selectedCrash != null);
43
32
  return (<>
44
- {(Platform.OS === 'ios' || Platform.OS === 'android') && isEnabled && <FabLauncher />}
45
- <Modal visible={visible} animationType={modalAnimationType} transparent>
33
+ {(Platform.OS === 'ios' || Platform.OS === 'android') &&
34
+ isEnabled &&
35
+ !useNativeFab && <FabLauncher />}
36
+ <Modal visible={visible} animationType={modalAnimationType} transparent statusBarTranslucent={true}>
46
37
  {visible && (<ErrorBoundary onClose={closeModal}>
47
38
  <View style={styles.modalBackdrop}>
48
39
  <Pressable style={styles.modalBackdropPressable} onPress={closeModal}/>
49
40
  <View style={[
50
41
  styles.modalContentCard,
51
- { height: `${modalHeightPercent}%` },
42
+ {
43
+ height: `${modalHeightPercent}%`,
44
+ borderTopLeftRadius: modalHeightPercent >= 100 ? 0 : 20,
45
+ borderTopRightRadius: modalHeightPercent >= 100 ? 0 : 20,
46
+ },
52
47
  ]}>
53
48
  <StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
54
49
 
@@ -57,66 +52,21 @@ const MainScreen = () => {
57
52
  {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
58
53
  {!isDetailActive && settingsPage === null ? (<TabBar />) : null}
59
54
 
60
- {isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail />) : activeTab === 'redux' ? (<ReduxDetail />) : activeTab === 'crash' && selectedCrash != null ? (<CrashDetail />) : null) : (<>
61
- <View style={{
62
- flex: 1,
63
- display: activeTab === 'apis' ? 'flex' : 'none',
64
- }}>
65
- {mountedTabs.apis && <NetworkTab />}
66
- </View>
67
- <View style={{
68
- flex: 1,
69
- display: activeTab === 'logs' ? 'flex' : 'none',
70
- }}>
71
- {mountedTabs.logs && <ConsoleTab />}
72
- </View>
73
- <View style={{
74
- flex: 1,
75
- display: activeTab === 'analytics' ? 'flex' : 'none',
76
- }}>
77
- {mountedTabs.analytics && <AnalyticsTab />}
78
- </View>
79
- <View style={{
80
- flex: 1,
81
- display: activeTab === 'redux' ? 'flex' : 'none',
82
- }}>
83
- {mountedTabs.redux && <ReduxTab />}
84
- </View>
85
- <View style={{
86
- flex: 1,
87
- display: activeTab === 'bundle' ? 'flex' : 'none',
88
- }}>
89
- {mountedTabs.bundle && <BundleTab />}
90
- </View>
91
- <View style={{
92
- flex: 1,
93
- display: activeTab === 'performance' ? 'flex' : 'none',
94
- }}>
95
- {mountedTabs.performance && <PerformanceTab />}
96
- </View>
97
- <View style={{
98
- flex: 1,
99
- display: activeTab === 'crash' ? 'flex' : 'none',
100
- }}>
101
- {mountedTabs.crash && <CrashTab />}
102
- </View>
103
- </>)) : (<View style={styles.empty}>
55
+ {settingsPage !== null ? (<SettingsPanel />) : isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail />) : activeTab === 'redux' ? (<ReduxDetail />) : activeTab === 'crash' && selectedCrash != null ? (<CrashDetail />) : null) : (<View style={{ flex: 1 }}>
56
+ {activeTab === 'apis' && <NetworkTab />}
57
+ {activeTab === 'logs' && <ConsoleTab />}
58
+ {activeTab === 'analytics' && <AnalyticsTab />}
59
+ {activeTab === 'redux' && <ReduxTab />}
60
+ {activeTab === 'bundle' && <BundleTab />}
61
+ {activeTab === 'performance' && <PerformanceTab />}
62
+ {activeTab === 'crash' && <CrashTab />}
63
+ </View>)) : (<View style={styles.empty}>
104
64
  <ActivityIndicator size="large" color={AppColors.purple}/>
105
65
  <Text style={[styles.emptySub, { marginTop: 12 }]}>
106
66
  Loading logs...
107
67
  </Text>
108
68
  </View>)}
109
69
 
110
- {settingsPage !== null && (<View style={[
111
- StyleSheet.absoluteFill,
112
- {
113
- backgroundColor: AppColors.grayBackground,
114
- zIndex: 99999,
115
- },
116
- ]}>
117
- <SettingsPanel />
118
- </View>)}
119
-
120
70
  {/* Bottom floating toast notification */}
121
71
  <Toast />
122
72
  </View>