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
@@ -10,9 +10,9 @@ 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, ResetIcon, } from '../NetworkIcons';
14
14
  const InspectorHeader = React.memo(() => {
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();
15
+ const { modalHeightPercent, appIcon, selected, setSelected, selectedEvent, setSelectedEvent, selectedLog, setSelectedLog, selectedReduxSlice, setSelectedReduxSlice, selectedReduxAction, setSelectedReduxAction, reduxState, reduxLastActionMap, showHeaderInfo, setShowHeaderInfo, updateAvailable, latestNpmVersion, clearAnim, activePulseAnim, unreadPulseAnim, runClearAllWithAnimation, settingsPage, setSettingsPage, resetToDefaults, closeModal, detailTitle, activeTab, environment, selectedCrash, setSelectedCrash, } = useInspector();
16
16
  const envConfig = useMemo(() => {
17
17
  const rawEnv = (environment || (__DEV__ ? 'DEV' : 'PROD')).trim();
18
18
  const clean = rawEnv.toUpperCase();
@@ -53,9 +53,30 @@ const InspectorHeader = React.memo(() => {
53
53
  (activeTab === 'logs' && selectedLog != null) ||
54
54
  (activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null)) ||
55
55
  (activeTab === 'crash' && selectedCrash != null);
56
- const isAnySelected = isDetailView;
56
+ const isSettingsView = settingsPage !== null;
57
+ const isAnySelected = isDetailView || isSettingsView;
58
+ const settingsModuleTitle = useMemo(() => {
59
+ switch (settingsPage) {
60
+ case 'apis':
61
+ return 'APIs (Network)';
62
+ case 'logs':
63
+ return 'Console Logs';
64
+ case 'performance':
65
+ return 'Performance Tracker';
66
+ case 'bundle':
67
+ return 'Bundle Analyzer';
68
+ case 'crash':
69
+ return 'Crash Protection';
70
+ case 'analytics':
71
+ return 'Analytics Logger';
72
+ case 'redux':
73
+ return 'Redux Inspector';
74
+ default:
75
+ return 'Settings & Modules';
76
+ }
77
+ }, [settingsPage]);
57
78
  const headerTopPadding = Platform.OS === 'ios' && modalHeightPercent >= 95 ? 44 : 0;
58
- return (<LinearGradient colors={[AppColors.purple, AppColors.brandPurple]} style={styles.headerGradient}>
79
+ return (<LinearGradient colors={['#4F46E5', '#7C3AED']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={styles.headerGradient}>
59
80
  <View style={{ paddingTop: headerTopPadding, width: '100%' }}>
60
81
  <View style={styles.header}>
61
82
  <View style={[
@@ -63,12 +84,21 @@ const InspectorHeader = React.memo(() => {
63
84
  {
64
85
  flexDirection: 'row',
65
86
  alignItems: 'center',
66
- gap: 12,
87
+ gap: 8,
67
88
  flex: !isDetailView ? 1 : 0,
68
89
  minWidth: 0,
69
90
  },
70
91
  ]}>
71
92
  <TouchableScale onPress={() => {
93
+ if (isSettingsView) {
94
+ if (settingsPage === 'main') {
95
+ setSettingsPage(null);
96
+ }
97
+ else {
98
+ setSettingsPage('main');
99
+ }
100
+ return;
101
+ }
72
102
  requestAnimationFrame(() => {
73
103
  setSelected(null);
74
104
  setSelectedEvent(null);
@@ -101,7 +131,43 @@ const InspectorHeader = React.memo(() => {
101
131
  <WhiteBackNavigation />
102
132
  </TouchableScale>
103
133
 
104
- {!isAnySelected ? (<View style={{
134
+ {isSettingsView ? (<View style={{ gap: 2, flex: 1, minWidth: 0 }}>
135
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
136
+ <Text style={{
137
+ fontFamily: AppFonts.interBold,
138
+ fontSize: 16,
139
+ color: AppColors.white,
140
+ letterSpacing: -0.2,
141
+ }} numberOfLines={1}>
142
+ {settingsModuleTitle}
143
+ </Text>
144
+ {settingsPage === 'main' && (<View style={{
145
+ backgroundColor: `${AppColors.white}26`,
146
+ paddingHorizontal: 6,
147
+ paddingVertical: 1.5,
148
+ borderRadius: 10,
149
+ borderWidth: 1,
150
+ borderColor: `${AppColors.white}20`,
151
+ }}>
152
+ <Text style={{
153
+ fontFamily: AppFonts.interBold,
154
+ fontSize: 9,
155
+ color: AppColors.white,
156
+ }}>
157
+ v{LIB_VERSION}
158
+ </Text>
159
+ </View>)}
160
+ </View>
161
+ <Text style={{
162
+ fontFamily: AppFonts.interRegular,
163
+ fontSize: 10.5,
164
+ color: `${AppColors.white}CC`,
165
+ }} numberOfLines={1}>
166
+ {settingsPage === 'main'
167
+ ? 'Manage modules and preferences'
168
+ : 'Configure module parameters'}
169
+ </Text>
170
+ </View>) : !isAnySelected ? (<View style={{
105
171
  flexDirection: 'row',
106
172
  alignItems: 'center',
107
173
  gap: 8,
@@ -109,7 +175,7 @@ const InspectorHeader = React.memo(() => {
109
175
  minWidth: 0,
110
176
  marginRight: 6,
111
177
  }}>
112
- <AppHeaderLogo size={38} customIcon={appIcon}/>
178
+ <AppHeaderLogo size={30} customIcon={appIcon}/>
113
179
  <View style={{ gap: 2.5, flex: 1, minWidth: 0 }}>
114
180
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, minWidth: 0 }}>
115
181
  <Text style={[styles.headerTitle, { flexShrink: 1 }]} numberOfLines={1} ellipsizeMode="tail">
@@ -188,23 +254,31 @@ const InspectorHeader = React.memo(() => {
188
254
  </Text>
189
255
  </View>
190
256
 
191
- <View style={{
192
- backgroundColor: `${AppColors.white}14`,
193
- borderRadius: 4,
194
- paddingHorizontal: 4.5,
195
- paddingVertical: 1.5,
196
- borderWidth: 1,
197
- borderColor: `${AppColors.white}20`,
257
+ <Pressable onPress={() => Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { })} style={{
258
+ backgroundColor: '#FFFFFF',
259
+ borderRadius: 5,
260
+ paddingHorizontal: 6,
261
+ paddingVertical: 2,
262
+ flexDirection: 'row',
263
+ alignItems: 'center',
264
+ gap: 4,
198
265
  flexShrink: 0,
266
+ shadowColor: '#000000',
267
+ shadowOffset: { width: 0, height: 1 },
268
+ shadowOpacity: 0.15,
269
+ shadowRadius: 2,
270
+ elevation: 2,
199
271
  }}>
272
+ <NpmIcon size={11} color="#CB3837"/>
200
273
  <Text style={{
201
- fontFamily: AppFonts.interMedium,
202
- fontSize: 8.5,
203
- color: `${AppColors.white}B3`,
274
+ fontFamily: AppFonts.interBold,
275
+ fontSize: 9.5,
276
+ color: '#CB3837',
277
+ letterSpacing: 0.2,
204
278
  }} numberOfLines={1}>
205
279
  v{LIB_VERSION}
206
280
  </Text>
207
- </View>
281
+ </Pressable>
208
282
  </View>
209
283
  </View>
210
284
  </View>) : null}
@@ -490,6 +564,19 @@ const InspectorHeader = React.memo(() => {
490
564
  gap: 8,
491
565
  },
492
566
  ]}>
567
+ {isSettingsView && (<TouchableScale onPress={() => {
568
+ Alert.alert('Reset All Settings', 'This restores all module visibility and UI preferences to defaults. Continue?', [
569
+ { text: 'Cancel', style: 'cancel' },
570
+ {
571
+ text: 'Reset',
572
+ style: 'destructive',
573
+ onPress: resetToDefaults,
574
+ },
575
+ ]);
576
+ }} hitSlop={15} style={styles.closeButtonSquare}>
577
+ <ResetIcon color={AppColors.white} size={14}/>
578
+ </TouchableScale>)}
579
+
493
580
  {!isAnySelected && (<TouchableScale onPress={() => {
494
581
  Alert.alert('Clear Everything', 'This clears all tabs — APIs, Logs, Analytics, Redux timeline and Crash history. Continue?', [
495
582
  { text: 'Cancel', style: 'cancel' },
@@ -516,16 +603,16 @@ const InspectorHeader = React.memo(() => {
516
603
  },
517
604
  ],
518
605
  }}>
519
- <TrashIcon color={AppColors.white} size={16}/>
606
+ <TrashIcon color={AppColors.white} size={14}/>
520
607
  </Animated.View>
521
608
  </TouchableScale>)}
522
609
 
523
610
  {!isAnySelected && (<TouchableScale onPress={() => setSettingsPage('main')} hitSlop={15} style={styles.closeButtonSquare}>
524
- <SettingsIcon color={AppColors.white} size={16}/>
611
+ <SettingsIcon color={AppColors.white} size={14}/>
525
612
  </TouchableScale>)}
526
613
 
527
614
  <TouchableScale onPress={closeModal} hitSlop={15} style={styles.closeButtonSquare}>
528
- <CloseWhite size={16}/>
615
+ <CloseWhite size={14}/>
529
616
  </TouchableScale>
530
617
  </View>
531
618
  </View>
@@ -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, { 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';
@@ -23,25 +23,50 @@ 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);
32
+ // ─── 60 FPS Transition Animations ──────────────────────────────────────────
33
+ const detailAnim = useRef(new Animated.Value(0)).current;
34
+ useEffect(() => {
35
+ if (isDetailActive) {
36
+ detailAnim.setValue(0);
37
+ Animated.spring(detailAnim, {
38
+ toValue: 1,
39
+ friction: 8,
40
+ tension: 65,
41
+ useNativeDriver: true,
42
+ }).start();
43
+ }
44
+ }, [isDetailActive]);
45
+ const settingsAnim = useRef(new Animated.Value(0)).current;
46
+ useEffect(() => {
47
+ if (settingsPage !== null) {
48
+ settingsAnim.setValue(0);
49
+ Animated.spring(settingsAnim, {
50
+ toValue: 1,
51
+ friction: 8,
52
+ tension: 65,
53
+ useNativeDriver: true,
54
+ }).start();
55
+ }
56
+ }, [settingsPage !== null]);
57
+ const tabAnim = useRef(new Animated.Value(1)).current;
58
+ useEffect(() => {
59
+ tabAnim.setValue(0);
60
+ Animated.timing(tabAnim, {
61
+ toValue: 1,
62
+ duration: 150,
63
+ useNativeDriver: true,
64
+ }).start();
65
+ }, [activeTab]);
43
66
  return (<>
44
- {(Platform.OS === 'ios' || Platform.OS === 'android') && isEnabled && <FabLauncher />}
67
+ {(Platform.OS === 'ios' || Platform.OS === 'android') &&
68
+ isEnabled &&
69
+ !useNativeFab && <FabLauncher />}
45
70
  <Modal visible={visible} animationType={modalAnimationType} transparent statusBarTranslucent={true}>
46
71
  {visible && (<ErrorBoundary onClose={closeModal}>
47
72
  <View style={styles.modalBackdrop}>
@@ -58,68 +83,86 @@ const MainScreen = () => {
58
83
 
59
84
  <InspectorHeader />
60
85
 
61
- {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
62
- {!isDetailActive && settingsPage === null ? (<TabBar />) : null}
86
+ <View style={{ flex: 1 }}>
87
+ {isReady ? (<View style={{ flex: 1 }}>
88
+ {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
89
+ {!isDetailActive && <TabBar />}
90
+
91
+ {/* Persistent List Layer - Never unmounted, preserves 100% native scroll with smooth tab transition */}
92
+ <Animated.View style={[
93
+ {
94
+ flex: 1,
95
+ opacity: tabAnim,
96
+ transform: [
97
+ {
98
+ translateY: tabAnim.interpolate({
99
+ inputRange: [0, 1],
100
+ outputRange: [6, 0],
101
+ }),
102
+ },
103
+ ],
104
+ },
105
+ (isDetailActive || settingsPage !== null) && {
106
+ pointerEvents: 'none',
107
+ },
108
+ ]}>
109
+ {activeTab === 'apis' && <NetworkTab />}
110
+ {activeTab === 'logs' && <ConsoleTab />}
111
+ {activeTab === 'analytics' && <AnalyticsTab />}
112
+ {activeTab === 'redux' && <ReduxTab />}
113
+ {activeTab === 'bundle' && <BundleTab />}
114
+ {activeTab === 'performance' && <PerformanceTab />}
115
+ {activeTab === 'crash' && <CrashTab />}
116
+ </Animated.View>
63
117
 
64
- {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) : (<>
65
- <View style={{
66
- flex: 1,
67
- display: activeTab === 'apis' ? 'flex' : 'none',
68
- }}>
69
- {mountedTabs.apis && <NetworkTab />}
70
- </View>
71
- <View style={{
72
- flex: 1,
73
- display: activeTab === 'logs' ? 'flex' : 'none',
74
- }}>
75
- {mountedTabs.logs && <ConsoleTab />}
76
- </View>
77
- <View style={{
78
- flex: 1,
79
- display: activeTab === 'analytics' ? 'flex' : 'none',
80
- }}>
81
- {mountedTabs.analytics && <AnalyticsTab />}
82
- </View>
83
- <View style={{
84
- flex: 1,
85
- display: activeTab === 'redux' ? 'flex' : 'none',
86
- }}>
87
- {mountedTabs.redux && <ReduxTab />}
88
- </View>
89
- <View style={{
90
- flex: 1,
91
- display: activeTab === 'bundle' ? 'flex' : 'none',
92
- }}>
93
- {mountedTabs.bundle && <BundleTab />}
94
- </View>
95
- <View style={{
96
- flex: 1,
97
- display: activeTab === 'performance' ? 'flex' : 'none',
98
- }}>
99
- {mountedTabs.performance && <PerformanceTab />}
100
- </View>
101
- <View style={{
102
- flex: 1,
103
- display: activeTab === 'crash' ? 'flex' : 'none',
104
- }}>
105
- {mountedTabs.crash && <CrashTab />}
106
- </View>
107
- </>)) : (<View style={styles.empty}>
108
- <ActivityIndicator size="large" color={AppColors.purple}/>
109
- <Text style={[styles.emptySub, { marginTop: 12 }]}>
110
- Loading logs...
111
- </Text>
112
- </View>)}
118
+ {/* Detail View Layer - Rendered on top with smooth slide & spring transition */}
119
+ {isDetailActive && (<Animated.View style={[
120
+ StyleSheet.absoluteFill,
121
+ {
122
+ backgroundColor: AppColors.contentBg,
123
+ opacity: detailAnim,
124
+ transform: [
125
+ {
126
+ translateX: detailAnim.interpolate({
127
+ inputRange: [0, 1],
128
+ outputRange: [32, 0],
129
+ }),
130
+ },
131
+ ],
132
+ },
133
+ ]}>
134
+ {activeTab === 'apis' && selected != null && (<NetworkDetail />)}
135
+ {activeTab === 'analytics' && selectedEvent != null && (<AnalyticsDetail event={selectedEvent}/>)}
136
+ {activeTab === 'logs' && selectedLog != null && (<LogDetail />)}
137
+ {activeTab === 'redux' && <ReduxDetail />}
138
+ {activeTab === 'crash' && selectedCrash != null && (<CrashDetail />)}
139
+ </Animated.View>)}
140
+ </View>) : (<View style={styles.empty}>
141
+ <ActivityIndicator size="large" color={AppColors.purple}/>
142
+ <Text style={[styles.emptySub, { marginTop: 12 }]}>
143
+ Loading logs...
144
+ </Text>
145
+ </View>)}
113
146
 
114
- {settingsPage !== null && (<View style={[
147
+ {/* Settings Panel Layer - Rendered on top with smooth slide & spring transition */}
148
+ {settingsPage !== null && (<Animated.View style={[
115
149
  StyleSheet.absoluteFill,
116
150
  {
117
151
  backgroundColor: AppColors.grayBackground,
118
- zIndex: 99999,
152
+ opacity: settingsAnim,
153
+ transform: [
154
+ {
155
+ translateY: settingsAnim.interpolate({
156
+ inputRange: [0, 1],
157
+ outputRange: [24, 0],
158
+ }),
159
+ },
160
+ ],
119
161
  },
120
162
  ]}>
121
- <SettingsPanel />
122
- </View>)}
163
+ <SettingsPanel />
164
+ </Animated.View>)}
165
+ </View>
123
166
 
124
167
  {/* Bottom floating toast notification */}
125
168
  <Toast />