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.
- package/README.md +123 -101
- package/android/build.gradle +13 -1
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +890 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
- package/dist/commonjs/components/ConsoleLogCard.js +5 -5
- package/dist/commonjs/components/CopyButton.js +3 -0
- package/dist/commonjs/components/EndOfListFooter.js +1 -1
- package/dist/commonjs/components/ErrorBoundary.js +3 -0
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +25 -73
- package/dist/commonjs/components/Inspector/BundleTab.js +671 -189
- package/dist/commonjs/components/Inspector/ConsoleTab.js +110 -99
- package/dist/commonjs/components/Inspector/CrashTab.js +99 -91
- package/dist/commonjs/components/Inspector/InspectorHeader.js +107 -20
- package/dist/commonjs/components/Inspector/MainScreen.js +111 -68
- package/dist/commonjs/components/Inspector/NetworkTab.js +151 -30
- package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
- package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
- package/dist/commonjs/components/Inspector/SettingsPanel.js +1218 -1238
- package/dist/commonjs/components/Inspector/TabBar.js +4 -2
- package/dist/commonjs/components/JsonViewer.js +9 -4
- package/dist/commonjs/components/LogCard.js +31 -1
- package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
- package/dist/commonjs/components/NetworkIcons.d.ts +3 -0
- package/dist/commonjs/components/NetworkIcons.js +15 -1
- package/dist/commonjs/components/Slider.d.ts +13 -0
- package/dist/commonjs/components/Slider.js +261 -0
- package/dist/commonjs/components/TouchableScale.d.ts +1 -0
- package/dist/commonjs/components/TouchableScale.js +30 -32
- package/dist/commonjs/constants/index.d.ts +1 -2
- package/dist/commonjs/constants/index.js +4 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +4 -0
- package/dist/commonjs/customHooks/analyticsLogger.js +8 -6
- package/dist/commonjs/customHooks/crashHandler.js +8 -1
- package/dist/commonjs/helpers/index.d.ts +1 -0
- package/dist/commonjs/helpers/index.js +25 -1
- package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
- package/dist/commonjs/helpers/searchQueryParser.js +236 -0
- package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
- package/dist/commonjs/helpers/settingsStore.js +59 -3
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +220 -43
- package/dist/commonjs/native/NativeInspector.d.ts +125 -0
- package/dist/commonjs/native/NativeInspector.js +313 -0
- package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
- package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
- package/dist/commonjs/styles/index.js +41 -41
- package/dist/commonjs/types/enums.d.ts +1 -1
- package/dist/commonjs/types/interfaces.d.ts +9 -0
- package/dist/esm/components/ConsoleLogCard.js +5 -5
- package/dist/esm/components/CopyButton.js +3 -0
- package/dist/esm/components/EndOfListFooter.js +2 -2
- package/dist/esm/components/ErrorBoundary.js +3 -0
- package/dist/esm/components/Inspector/AnalyticsTab.js +27 -75
- package/dist/esm/components/Inspector/BundleTab.js +671 -189
- package/dist/esm/components/Inspector/ConsoleTab.js +111 -100
- package/dist/esm/components/Inspector/CrashTab.js +99 -91
- package/dist/esm/components/Inspector/InspectorHeader.js +108 -21
- package/dist/esm/components/Inspector/MainScreen.js +113 -70
- package/dist/esm/components/Inspector/NetworkTab.js +152 -31
- package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
- package/dist/esm/components/Inspector/ReduxTab.js +18 -10
- package/dist/esm/components/Inspector/SettingsPanel.js +1222 -1242
- package/dist/esm/components/Inspector/TabBar.js +4 -2
- package/dist/esm/components/JsonViewer.js +9 -4
- package/dist/esm/components/LogCard.js +32 -2
- package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
- package/dist/esm/components/NetworkIcons.d.ts +3 -0
- package/dist/esm/components/NetworkIcons.js +11 -0
- package/dist/esm/components/Slider.d.ts +13 -0
- package/dist/esm/components/Slider.js +222 -0
- package/dist/esm/components/TouchableScale.d.ts +1 -0
- package/dist/esm/components/TouchableScale.js +31 -33
- package/dist/esm/constants/index.d.ts +1 -2
- package/dist/esm/constants/index.js +4 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
- package/dist/esm/customHooks/analyticsLogger.js +6 -5
- package/dist/esm/customHooks/crashHandler.js +8 -1
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +11 -1
- package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
- package/dist/esm/helpers/searchQueryParser.js +233 -0
- package/dist/esm/helpers/settingsStore.d.ts +9 -0
- package/dist/esm/helpers/settingsStore.js +58 -3
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +207 -44
- package/dist/esm/native/NativeInspector.d.ts +125 -0
- package/dist/esm/native/NativeInspector.js +289 -0
- package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
- package/dist/esm/native/NativeNetworkInspector.js +2 -0
- package/dist/esm/styles/index.js +41 -41
- package/dist/esm/types/enums.d.ts +1 -1
- package/dist/esm/types/interfaces.d.ts +9 -0
- package/ios/NetworkInspectorModule.h +6 -0
- package/ios/NetworkInspectorModule.m +760 -5
- package/package.json +13 -2
- package/react-native-inapp-inspector.podspec +7 -2
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
- 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
|
|
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={[
|
|
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:
|
|
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
|
-
{
|
|
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={
|
|
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
|
-
<
|
|
192
|
-
backgroundColor:
|
|
193
|
-
borderRadius:
|
|
194
|
-
paddingHorizontal:
|
|
195
|
-
paddingVertical:
|
|
196
|
-
|
|
197
|
-
|
|
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.
|
|
202
|
-
fontSize:
|
|
203
|
-
color:
|
|
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
|
-
</
|
|
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={
|
|
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={
|
|
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={
|
|
615
|
+
<CloseWhite size={14}/>
|
|
529
616
|
</TouchableScale>
|
|
530
617
|
</View>
|
|
531
618
|
</View>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import 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') &&
|
|
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
|
-
{
|
|
62
|
-
|
|
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
|
-
|
|
65
|
-
<View style={
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
122
|
-
|
|
163
|
+
<SettingsPanel />
|
|
164
|
+
</Animated.View>)}
|
|
165
|
+
</View>
|
|
123
166
|
|
|
124
167
|
{/* Bottom floating toast notification */}
|
|
125
168
|
<Toast />
|