react-native-inapp-inspector 2.0.0 → 2.0.2

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 (95) hide show
  1. package/README.md +10 -0
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
  4. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  5. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  6. package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  8. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  9. package/android/.gradle/8.9/gc.properties +0 -0
  10. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  11. package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
  12. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  13. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  14. package/android/.gradle/9.2.0/gc.properties +0 -0
  15. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  16. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  17. package/android/.gradle/vcs-1/gc.properties +0 -0
  18. package/android/build/reports/problems/problems-report.html +659 -0
  19. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +33 -24
  20. package/dist/commonjs/components/ConsoleLogCard.js +5 -5
  21. package/dist/commonjs/components/EndOfListFooter.js +1 -1
  22. package/dist/commonjs/components/Inspector/AnalyticsTab.js +19 -71
  23. package/dist/commonjs/components/Inspector/BundleTab.js +670 -188
  24. package/dist/commonjs/components/Inspector/ConsoleTab.js +109 -98
  25. package/dist/commonjs/components/Inspector/CrashTab.js +2 -1
  26. package/dist/commonjs/components/Inspector/InspectorHeader.js +102 -19
  27. package/dist/commonjs/components/Inspector/MainScreen.js +151 -17
  28. package/dist/commonjs/components/Inspector/NetworkTab.js +104 -20
  29. package/dist/commonjs/components/Inspector/SettingsPanel.js +1111 -1385
  30. package/dist/commonjs/components/Inspector/TabBar.js +3 -4
  31. package/dist/commonjs/components/Inspector/TelemetryConsentModal.d.ts +3 -0
  32. package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +212 -0
  33. package/dist/commonjs/components/JsonViewer.js +9 -4
  34. package/dist/commonjs/components/LogCard.js +31 -1
  35. package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
  36. package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
  37. package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
  38. package/dist/commonjs/components/NetworkIcons.js +10 -1
  39. package/dist/commonjs/components/Slider.d.ts +13 -0
  40. package/dist/commonjs/components/Slider.js +261 -0
  41. package/dist/commonjs/constants/version.d.ts +1 -1
  42. package/dist/commonjs/constants/version.js +1 -1
  43. package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
  44. package/dist/commonjs/customHooks/crashHandler.js +1 -1
  45. package/dist/commonjs/helpers/index.d.ts +2 -0
  46. package/dist/commonjs/helpers/index.js +16 -0
  47. package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
  48. package/dist/commonjs/helpers/searchQueryParser.js +236 -0
  49. package/dist/commonjs/helpers/settingsStore.js +13 -13
  50. package/dist/commonjs/helpers/telemetry.d.ts +99 -0
  51. package/dist/commonjs/helpers/telemetry.js +398 -0
  52. package/dist/commonjs/index.d.ts +2 -0
  53. package/dist/commonjs/index.js +30 -21
  54. package/dist/commonjs/native/NativeInspector.d.ts +5 -0
  55. package/dist/commonjs/native/NativeInspector.js +3 -2
  56. package/dist/commonjs/styles/index.js +35 -35
  57. package/dist/esm/components/ConsoleLogCard.js +5 -5
  58. package/dist/esm/components/EndOfListFooter.js +2 -2
  59. package/dist/esm/components/Inspector/AnalyticsTab.js +21 -73
  60. package/dist/esm/components/Inspector/BundleTab.js +670 -188
  61. package/dist/esm/components/Inspector/ConsoleTab.js +110 -99
  62. package/dist/esm/components/Inspector/CrashTab.js +2 -1
  63. package/dist/esm/components/Inspector/InspectorHeader.js +103 -20
  64. package/dist/esm/components/Inspector/MainScreen.js +119 -18
  65. package/dist/esm/components/Inspector/NetworkTab.js +105 -21
  66. package/dist/esm/components/Inspector/SettingsPanel.js +1114 -1388
  67. package/dist/esm/components/Inspector/TabBar.js +4 -5
  68. package/dist/esm/components/Inspector/TelemetryConsentModal.d.ts +3 -0
  69. package/dist/esm/components/Inspector/TelemetryConsentModal.js +175 -0
  70. package/dist/esm/components/JsonViewer.js +9 -4
  71. package/dist/esm/components/LogCard.js +32 -2
  72. package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
  73. package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
  74. package/dist/esm/components/NetworkIcons.d.ts +2 -0
  75. package/dist/esm/components/NetworkIcons.js +7 -0
  76. package/dist/esm/components/Slider.d.ts +13 -0
  77. package/dist/esm/components/Slider.js +222 -0
  78. package/dist/esm/constants/version.d.ts +1 -1
  79. package/dist/esm/constants/version.js +1 -1
  80. package/dist/esm/customHooks/analyticsLogger.js +1 -1
  81. package/dist/esm/customHooks/crashHandler.js +1 -1
  82. package/dist/esm/helpers/index.d.ts +2 -0
  83. package/dist/esm/helpers/index.js +2 -0
  84. package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
  85. package/dist/esm/helpers/searchQueryParser.js +233 -0
  86. package/dist/esm/helpers/settingsStore.js +13 -13
  87. package/dist/esm/helpers/telemetry.d.ts +99 -0
  88. package/dist/esm/helpers/telemetry.js +380 -0
  89. package/dist/esm/index.d.ts +2 -0
  90. package/dist/esm/index.js +20 -21
  91. package/dist/esm/native/NativeInspector.d.ts +5 -0
  92. package/dist/esm/native/NativeInspector.js +3 -2
  93. package/dist/esm/styles/index.js +35 -35
  94. package/ios/{NetworkInspectorModule.m → NetworkInspectorModule.mm} +193 -97
  95. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { ActivityIndicator, Modal, Platform, Pressable, StatusBar, Text, View, } from 'react-native';
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { ActivityIndicator, Animated, Modal, Platform, Pressable, StatusBar, StyleSheet, Text, View, } from 'react-native';
3
3
  import { useInspector } from './InspectorContext';
4
4
  import ErrorBoundary from '../ErrorBoundary';
5
5
  import FabLauncher from './FabLauncher';
@@ -18,6 +18,7 @@ import PerformanceTab from './PerformanceTab';
18
18
  import CrashTab from './CrashTab';
19
19
  import CrashDetail from './CrashDetail';
20
20
  import SettingsPanel from './SettingsPanel';
21
+ import TelemetryConsentModal from './TelemetryConsentModal';
21
22
  import Toast from '../Toast';
22
23
  import styles from '../../styles';
23
24
  import { AppColors } from '../../styles/AppColors';
@@ -29,6 +30,40 @@ const MainScreen = () => {
29
30
  (activeTab === 'logs' && selectedLog != null) ||
30
31
  (activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null)) ||
31
32
  (activeTab === 'crash' && selectedCrash != null);
33
+ // ─── 60 FPS Transition Animations ──────────────────────────────────────────
34
+ const detailAnim = useRef(new Animated.Value(0)).current;
35
+ useEffect(() => {
36
+ if (isDetailActive) {
37
+ detailAnim.setValue(0);
38
+ Animated.spring(detailAnim, {
39
+ toValue: 1,
40
+ friction: 8,
41
+ tension: 65,
42
+ useNativeDriver: true,
43
+ }).start();
44
+ }
45
+ }, [isDetailActive]);
46
+ const settingsAnim = useRef(new Animated.Value(0)).current;
47
+ useEffect(() => {
48
+ if (settingsPage !== null) {
49
+ settingsAnim.setValue(0);
50
+ Animated.spring(settingsAnim, {
51
+ toValue: 1,
52
+ friction: 8,
53
+ tension: 65,
54
+ useNativeDriver: true,
55
+ }).start();
56
+ }
57
+ }, [settingsPage !== null]);
58
+ const tabAnim = useRef(new Animated.Value(1)).current;
59
+ useEffect(() => {
60
+ tabAnim.setValue(0);
61
+ Animated.timing(tabAnim, {
62
+ toValue: 1,
63
+ duration: 150,
64
+ useNativeDriver: true,
65
+ }).start();
66
+ }, [activeTab]);
32
67
  return (<>
33
68
  {(Platform.OS === 'ios' || Platform.OS === 'android') &&
34
69
  isEnabled &&
@@ -49,26 +84,92 @@ const MainScreen = () => {
49
84
 
50
85
  <InspectorHeader />
51
86
 
52
- {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
53
- {!isDetailActive && settingsPage === null ? (<TabBar />) : null}
87
+ <View style={{ flex: 1 }}>
88
+ {isReady ? (<View style={{ flex: 1 }}>
89
+ {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
90
+ {!isDetailActive && <TabBar />}
54
91
 
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}>
64
- <ActivityIndicator size="large" color={AppColors.purple}/>
65
- <Text style={[styles.emptySub, { marginTop: 12 }]}>
66
- Loading logs...
67
- </Text>
68
- </View>)}
92
+ {/* Persistent List Layer - Never unmounted, preserves 100% native scroll with smooth tab transition */}
93
+ <Animated.View style={[
94
+ {
95
+ flex: 1,
96
+ opacity: tabAnim,
97
+ transform: [
98
+ {
99
+ translateY: tabAnim.interpolate({
100
+ inputRange: [0, 1],
101
+ outputRange: [6, 0],
102
+ }),
103
+ },
104
+ ],
105
+ },
106
+ (isDetailActive || settingsPage !== null) && {
107
+ pointerEvents: 'none',
108
+ },
109
+ ]}>
110
+ {activeTab === 'apis' && <NetworkTab />}
111
+ {activeTab === 'logs' && <ConsoleTab />}
112
+ {activeTab === 'analytics' && <AnalyticsTab />}
113
+ {activeTab === 'redux' && <ReduxTab />}
114
+ {activeTab === 'bundle' && <BundleTab />}
115
+ {activeTab === 'performance' && <PerformanceTab />}
116
+ {activeTab === 'crash' && <CrashTab />}
117
+ </Animated.View>
118
+
119
+ {/* Detail View Layer - Rendered on top with smooth slide & spring transition */}
120
+ {isDetailActive && (<Animated.View style={[
121
+ StyleSheet.absoluteFill,
122
+ {
123
+ backgroundColor: AppColors.contentBg,
124
+ opacity: detailAnim,
125
+ transform: [
126
+ {
127
+ translateX: detailAnim.interpolate({
128
+ inputRange: [0, 1],
129
+ outputRange: [32, 0],
130
+ }),
131
+ },
132
+ ],
133
+ },
134
+ ]}>
135
+ {activeTab === 'apis' && selected != null && (<NetworkDetail />)}
136
+ {activeTab === 'analytics' && selectedEvent != null && (<AnalyticsDetail event={selectedEvent}/>)}
137
+ {activeTab === 'logs' && selectedLog != null && (<LogDetail />)}
138
+ {activeTab === 'redux' && <ReduxDetail />}
139
+ {activeTab === 'crash' && selectedCrash != null && (<CrashDetail />)}
140
+ </Animated.View>)}
141
+ </View>) : (<View style={styles.empty}>
142
+ <ActivityIndicator size="large" color={AppColors.purple}/>
143
+ <Text style={[styles.emptySub, { marginTop: 12 }]}>
144
+ Loading logs...
145
+ </Text>
146
+ </View>)}
147
+
148
+ {/* Settings Panel Layer - Rendered on top with smooth slide & spring transition */}
149
+ {settingsPage !== null && (<Animated.View style={[
150
+ StyleSheet.absoluteFill,
151
+ {
152
+ backgroundColor: AppColors.grayBackground,
153
+ opacity: settingsAnim,
154
+ transform: [
155
+ {
156
+ translateY: settingsAnim.interpolate({
157
+ inputRange: [0, 1],
158
+ outputRange: [24, 0],
159
+ }),
160
+ },
161
+ ],
162
+ },
163
+ ]}>
164
+ <SettingsPanel />
165
+ </Animated.View>)}
166
+ </View>
69
167
 
70
168
  {/* Bottom floating toast notification */}
71
169
  <Toast />
170
+
171
+ {/* Anonymous Telemetry Consent Dialog */}
172
+ <TelemetryConsentModal />
72
173
  </View>
73
174
  </View>
74
175
  </ErrorBoundary>)}
@@ -13,7 +13,7 @@ import { AppColors } from '../../styles/AppColors';
13
13
  import { AppFonts } from '../../styles/AppFonts';
14
14
  import { STATUS_FILTERS, METHOD_COLORS } from '../../constants';
15
15
  import { useTranslation } from '../../i18n';
16
- import { SearchIcon, ClearIcon, TrashIcon, SortArrowIcon, FilterIcon, ChevronIcon, CheckIcon, CircleCheckIcon, CircleXIcon, CircleAlertIcon, LayersIcon, HeaderPauseIcon, ClockIcon, } from '../NetworkIcons';
16
+ import { SearchIcon, ClearIcon, TrashIcon, SortArrowIcon, FilterIcon, ChevronIcon, CircleCheckIcon, CircleXIcon, CircleAlertIcon, LayersIcon, HeaderPauseIcon, ClockIcon, } from '../NetworkIcons';
17
17
  const STATUS_META = {
18
18
  ALL: { color: AppColors.grayText, Icon: LayersIcon },
19
19
  '2xx': { color: AppColors.greenColor, Icon: CircleCheckIcon },
@@ -56,29 +56,31 @@ const FilterChip = React.memo(({ label, color, Icon, badge, active, onPress, })
56
56
  return (<TouchableScale style={styles.statusFilterWrap} onPress={onPress} hitSlop={10}>
57
57
  <View style={[
58
58
  styles.statusFilterChip,
59
+ {
60
+ paddingHorizontal: 9,
61
+ paddingVertical: 5,
62
+ borderRadius: 7,
63
+ borderWidth: 1,
64
+ borderColor: active ? color : `${AppColors.grayBorderSecondary}`,
65
+ backgroundColor: active ? `${color}14` : AppColors.grayBackground,
66
+ },
59
67
  active && {
60
- borderColor: color,
61
- backgroundColor: `${color}12`,
68
+ shadowColor: color,
69
+ shadowOffset: { width: 0, height: 1 },
70
+ shadowOpacity: 0.2,
71
+ shadowRadius: 2,
72
+ elevation: 1.5,
62
73
  },
63
74
  ]}>
64
- <View style={[
65
- styles.filterCheckbox,
66
- active && [
67
- styles.filterCheckboxActive,
68
- { backgroundColor: color },
69
- ],
70
- ]}>
71
- {active && (<CheckIcon color={AppColors.white} size={10}/>)}
72
- </View>
73
75
  {badge != null ? (<View style={[
74
76
  styles.methodBadgeMini,
75
77
  { backgroundColor: badge },
76
78
  ]}/>) : (Icon && (<Icon color={iconColor} size={13}/>))}
77
79
  <Text numberOfLines={1} style={[
78
80
  styles.statusFilterText,
79
- active && {
80
- color,
81
- fontFamily: AppFonts.interBold,
81
+ {
82
+ color: active ? color : AppColors.grayText,
83
+ fontFamily: active ? AppFonts.interBold : AppFonts.interMedium,
82
84
  },
83
85
  ]}>
84
86
  {label}
@@ -91,6 +93,19 @@ const NetworkTab = React.memo(() => {
91
93
  const { t } = useTranslation();
92
94
  const filtersAccordion = useAccordion(false, 300, 260);
93
95
  const apisListRef = useRef(null);
96
+ const [isSearchFocused, setIsSearchFocused] = React.useState(false);
97
+ const QUICK_API_QUERY_TAGS = useMemo(() => [
98
+ { label: '⚠️ Failed', query: 'is:error' },
99
+ { label: '🐢 Slow >1s', query: 'slow:>1s' },
100
+ { label: 'POST', query: 'm:POST' },
101
+ { label: 'GET', query: 'm:GET' },
102
+ { label: 'GraphQL', query: 'is:graphql' },
103
+ { label: 'Axios', query: 'client:axios' },
104
+ { label: '200 OK', query: 'status:200' },
105
+ { label: '404', query: 'status:404' },
106
+ { label: '500', query: 'status:500' },
107
+ { label: '🔒 HTTPS', query: 'is:https' },
108
+ ], []);
94
109
  const networkMetrics = useMemo(() => {
95
110
  if (!logs || logs.length === 0)
96
111
  return null;
@@ -225,12 +240,38 @@ const NetworkTab = React.memo(() => {
225
240
  </View>)}
226
241
 
227
242
  <View style={styles.toolbarRow}>
228
- <View style={styles.searchContainer}>
229
- <SearchIcon color={AppColors.grayTextWeak} size={16}/>
230
- <TextInput placeholder="Search endpoints..." placeholderTextColor={AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
231
- {search.length > 0 && (<Pressable onPress={() => setSearch('')} hitSlop={10} style={styles.clearBtn}>
232
- <ClearIcon color={AppColors.grayTextWeak} size={14}/>
233
- </Pressable>)}
243
+ <View style={[
244
+ styles.searchContainer,
245
+ isSearchFocused && {
246
+ borderColor: AppColors.purple,
247
+ borderWidth: 1.5,
248
+ },
249
+ ]}>
250
+ <SearchIcon color={isSearchFocused ? AppColors.purple : AppColors.grayTextWeak} size={16}/>
251
+ <TextInput placeholder="Search url, body, is:error, slow:>1s..." placeholderTextColor={AppColors.grayTextWeak} value={search} onChangeText={setSearch} onFocus={() => setIsSearchFocused(true)} onBlur={() => setIsSearchFocused(false)} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
252
+ {search.length > 0 && (<View style={{
253
+ flexDirection: 'row',
254
+ alignItems: 'center',
255
+ gap: 4,
256
+ }}>
257
+ <View style={{
258
+ backgroundColor: `${AppColors.purple}20`,
259
+ borderRadius: 10,
260
+ paddingHorizontal: 6,
261
+ paddingVertical: 2,
262
+ }}>
263
+ <Text style={{
264
+ color: AppColors.purple,
265
+ fontSize: 10,
266
+ fontFamily: AppFonts.interBold,
267
+ }}>
268
+ {filteredLogs.length}
269
+ </Text>
270
+ </View>
271
+ <Pressable onPress={() => setSearch('')} hitSlop={10} style={styles.clearBtn}>
272
+ <ClearIcon color={AppColors.grayTextWeak} size={14}/>
273
+ </Pressable>
274
+ </View>)}
234
275
  </View>
235
276
 
236
277
  <View style={styles.toolbarRight}>
@@ -277,6 +318,49 @@ const NetworkTab = React.memo(() => {
277
318
  </View>
278
319
  </View>
279
320
 
321
+ {/* Advanced Search Quick Query Suggestions Bar */}
322
+ {(isSearchFocused || search.length > 0) && (<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginBottom: 6, maxHeight: 30 }} contentContainerStyle={{
323
+ paddingHorizontal: 12,
324
+ flexDirection: 'row',
325
+ alignItems: 'center',
326
+ gap: 6,
327
+ }}>
328
+ {QUICK_API_QUERY_TAGS.map(item => {
329
+ const isSelected = search.includes(item.query);
330
+ return (<TouchableScale key={item.query} onPress={() => {
331
+ if (isSelected) {
332
+ setSearch(prev => prev.replace(item.query, '').trim());
333
+ }
334
+ else {
335
+ setSearch(prev => prev ? `${prev} ${item.query}`.trim() : item.query);
336
+ }
337
+ }}>
338
+ <View style={{
339
+ paddingHorizontal: 8,
340
+ paddingVertical: 3.5,
341
+ borderRadius: 6,
342
+ backgroundColor: isSelected
343
+ ? AppColors.purple
344
+ : `${AppColors.purple}14`,
345
+ borderWidth: 1,
346
+ borderColor: isSelected
347
+ ? AppColors.purple
348
+ : `${AppColors.purple}30`,
349
+ }}>
350
+ <Text style={{
351
+ fontFamily: AppFonts.interBold,
352
+ fontSize: 10,
353
+ color: isSelected
354
+ ? AppColors.white
355
+ : AppColors.purple,
356
+ }}>
357
+ {item.label}
358
+ </Text>
359
+ </View>
360
+ </TouchableScale>);
361
+ })}
362
+ </ScrollView>)}
363
+
280
364
  <Animated.View style={[
281
365
  filtersAccordion.bodyStyle,
282
366
  { overflow: 'hidden' },