react-native-inapp-inspector 1.1.16 → 1.1.17
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 +13 -0
- package/dist/commonjs/components/AnimatedEntrance.js +3 -0
- package/dist/commonjs/components/AppHeaderLogo.d.ts +8 -0
- package/dist/commonjs/components/AppHeaderLogo.js +85 -0
- package/dist/commonjs/components/Inspector/BundleTab.d.ts +41 -0
- package/dist/commonjs/components/Inspector/BundleTab.js +2309 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +185 -52
- package/dist/commonjs/components/Inspector/MainScreen.js +86 -7
- package/dist/commonjs/components/Inspector/ReduxDetail.d.ts +3 -0
- package/dist/commonjs/components/Inspector/ReduxDetail.js +576 -0
- package/dist/commonjs/components/Inspector/ReduxTab.js +433 -49
- package/dist/commonjs/components/Inspector/SettingsPanel.js +8 -2
- package/dist/commonjs/components/Inspector/TabBar.js +9 -6
- package/dist/commonjs/components/JsonViewer.js +91 -30
- package/dist/commonjs/components/LogCard.js +3 -4
- package/dist/commonjs/components/NetworkIcons.d.ts +8 -0
- package/dist/commonjs/components/NetworkIcons.js +54 -1
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/consoleLogger.js +37 -9
- package/dist/commonjs/customHooks/reduxLogger.js +4 -2
- package/dist/commonjs/helpers/index.js +6 -2
- package/dist/commonjs/index.js +15 -1
- package/dist/commonjs/styles/AppColors.js +163 -163
- package/dist/commonjs/styles/index.d.ts +14 -0
- package/dist/commonjs/styles/index.js +14 -0
- package/dist/commonjs/types/enums.d.ts +2 -2
- package/dist/commonjs/types/interfaces.d.ts +11 -0
- package/dist/esm/components/AnimatedEntrance.js +4 -1
- package/dist/esm/components/AppHeaderLogo.d.ts +8 -0
- package/dist/esm/components/AppHeaderLogo.js +45 -0
- package/dist/esm/components/Inspector/BundleTab.d.ts +41 -0
- package/dist/esm/components/Inspector/BundleTab.js +2271 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +151 -51
- package/dist/esm/components/Inspector/MainScreen.js +53 -7
- package/dist/esm/components/Inspector/ReduxDetail.d.ts +3 -0
- package/dist/esm/components/Inspector/ReduxDetail.js +538 -0
- package/dist/esm/components/Inspector/ReduxTab.js +402 -51
- package/dist/esm/components/Inspector/SettingsPanel.js +9 -3
- package/dist/esm/components/Inspector/TabBar.js +10 -7
- package/dist/esm/components/JsonViewer.js +92 -31
- package/dist/esm/components/LogCard.js +3 -4
- package/dist/esm/components/NetworkIcons.d.ts +8 -0
- package/dist/esm/components/NetworkIcons.js +47 -1
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/consoleLogger.js +37 -9
- package/dist/esm/customHooks/reduxLogger.js +4 -2
- package/dist/esm/helpers/index.js +6 -2
- package/dist/esm/index.js +15 -1
- package/dist/esm/styles/AppColors.js +163 -163
- package/dist/esm/styles/index.d.ts +14 -0
- package/dist/esm/styles/index.js +14 -0
- package/dist/esm/types/enums.d.ts +2 -2
- package/dist/esm/types/interfaces.d.ts +11 -0
- package/example/App.tsx +5 -1
- package/example/assets/app_icon.png +0 -0
- package/example/ios/Podfile.lock +3 -3
- package/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json +18 -9
- package/example/ios/example/Images.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/example/package-lock.json +824 -10
- package/example/package.json +6 -2
- package/package.json +4 -2
|
@@ -1,21 +1,58 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { Alert, Animated, Linking, Platform, Pressable, Text, View, } from 'react-native';
|
|
3
3
|
import LinearGradient from 'react-native-linear-gradient';
|
|
4
4
|
import { useInspector } from './InspectorContext';
|
|
5
5
|
import TouchableScale from '../TouchableScale';
|
|
6
|
-
import
|
|
6
|
+
import AppHeaderLogo from '../AppHeaderLogo';
|
|
7
7
|
import styles from '../../styles';
|
|
8
8
|
import { AppColors } from '../../styles/AppColors';
|
|
9
9
|
import { AppFonts } from '../../styles/AppFonts';
|
|
10
10
|
import { METHOD_COLORS } from '../../constants';
|
|
11
11
|
import { LIB_VERSION } from '../../constants';
|
|
12
|
-
import { getStatusColor } from '../../helpers';
|
|
13
|
-
import { getAppName } from '../../helpers';
|
|
14
|
-
import { getBundleIdentifier } from '../../helpers';
|
|
15
|
-
import { formatTime } from '../../helpers';
|
|
12
|
+
import { getStatusColor, getAppName, getBundleIdentifier, formatTime, getSize } from '../../helpers';
|
|
16
13
|
import { WhiteBackNavigation, TrashIcon, SettingsIcon, CloseWhite, ChevronIcon, ClockIcon, } from '../NetworkIcons';
|
|
17
14
|
const InspectorHeader = React.memo(() => {
|
|
18
|
-
const { modalHeightPercent, selected, setSelected, selectedEvent, setSelectedEvent, selectedLog, setSelectedLog, showHeaderInfo, setShowHeaderInfo, updateAvailable, latestNpmVersion, clearAnim, activePulseAnim, unreadPulseAnim, runClearAllWithAnimation, setSettingsPage, closeModal, detailTitle, } = 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, setSettingsPage, closeModal, detailTitle, activeTab, environment, } = useInspector();
|
|
16
|
+
const envConfig = useMemo(() => {
|
|
17
|
+
const rawEnv = (environment || (__DEV__ ? 'DEV' : 'PROD')).trim();
|
|
18
|
+
const clean = rawEnv.toUpperCase();
|
|
19
|
+
if (clean === 'DEV' || clean.includes('DEV') || clean === 'LOCAL') {
|
|
20
|
+
return {
|
|
21
|
+
label: rawEnv,
|
|
22
|
+
bg: 'rgba(16, 185, 129, 0.25)', // emerald
|
|
23
|
+
border: 'rgba(110, 231, 183, 0.55)',
|
|
24
|
+
text: '#A7F3D0',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (clean === 'UAT' || clean === 'QA' || clean === 'TEST') {
|
|
28
|
+
return {
|
|
29
|
+
label: rawEnv,
|
|
30
|
+
bg: 'rgba(245, 158, 11, 0.28)', // amber
|
|
31
|
+
border: 'rgba(252, 211, 77, 0.6)',
|
|
32
|
+
text: '#FDE68A',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (clean === 'PREPROD' || clean === 'STAGE' || clean === 'STAGING') {
|
|
36
|
+
return {
|
|
37
|
+
label: rawEnv,
|
|
38
|
+
bg: 'rgba(139, 92, 246, 0.28)', // purple
|
|
39
|
+
border: 'rgba(196, 181, 253, 0.6)',
|
|
40
|
+
text: '#DDD6FE',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// PROD / Live
|
|
44
|
+
return {
|
|
45
|
+
label: rawEnv,
|
|
46
|
+
bg: 'rgba(244, 63, 94, 0.25)', // rose
|
|
47
|
+
border: 'rgba(253, 164, 175, 0.55)',
|
|
48
|
+
text: '#FECDD3',
|
|
49
|
+
};
|
|
50
|
+
}, [environment]);
|
|
51
|
+
const isDetailView = (activeTab === 'apis' && selected != null) ||
|
|
52
|
+
(activeTab === 'analytics' && selectedEvent != null) ||
|
|
53
|
+
(activeTab === 'logs' && selectedLog != null) ||
|
|
54
|
+
(activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null));
|
|
55
|
+
const isAnySelected = isDetailView;
|
|
19
56
|
const headerTopPadding = Platform.OS === 'ios' && modalHeightPercent >= 95 ? 44 : 0;
|
|
20
57
|
return (<LinearGradient colors={[AppColors.purple, AppColors.brandPurple]} style={styles.headerGradient}>
|
|
21
58
|
<View style={{ paddingTop: headerTopPadding, width: '100%' }}>
|
|
@@ -26,11 +63,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
26
63
|
flexDirection: 'row',
|
|
27
64
|
alignItems: 'center',
|
|
28
65
|
gap: 16,
|
|
29
|
-
flex:
|
|
30
|
-
selectedEvent == null &&
|
|
31
|
-
selectedLog == null
|
|
32
|
-
? 5
|
|
33
|
-
: 1,
|
|
66
|
+
flex: !isDetailView ? 5 : 1,
|
|
34
67
|
},
|
|
35
68
|
]}>
|
|
36
69
|
<TouchableScale onPress={() => {
|
|
@@ -38,6 +71,8 @@ const InspectorHeader = React.memo(() => {
|
|
|
38
71
|
setSelected(null);
|
|
39
72
|
setSelectedEvent(null);
|
|
40
73
|
setSelectedLog(null);
|
|
74
|
+
setSelectedReduxSlice(null);
|
|
75
|
+
setSelectedReduxAction(null);
|
|
41
76
|
});
|
|
42
77
|
}} hitSlop={15} style={[
|
|
43
78
|
{
|
|
@@ -50,9 +85,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
50
85
|
borderWidth: 1,
|
|
51
86
|
borderColor: `${AppColors.white}4D`,
|
|
52
87
|
},
|
|
53
|
-
|
|
54
|
-
selectedEvent == null &&
|
|
55
|
-
selectedLog == null && { display: 'none' },
|
|
88
|
+
!isAnySelected && { display: 'none' },
|
|
56
89
|
]}>
|
|
57
90
|
{/* Soft outer glow to fake a blurred circle */}
|
|
58
91
|
<View style={{
|
|
@@ -65,36 +98,32 @@ const InspectorHeader = React.memo(() => {
|
|
|
65
98
|
<WhiteBackNavigation />
|
|
66
99
|
</TouchableScale>
|
|
67
100
|
|
|
68
|
-
{
|
|
69
|
-
selectedEvent == null &&
|
|
70
|
-
selectedLog == null ? (<TouchableScale onPress={() => setShowHeaderInfo(prev => !prev)} style={{
|
|
101
|
+
{!isAnySelected ? (<TouchableScale onPress={() => setShowHeaderInfo(prev => !prev)} style={{
|
|
71
102
|
flexDirection: 'row',
|
|
72
103
|
alignItems: 'flex-start',
|
|
73
104
|
gap: 10,
|
|
74
105
|
flex: 1,
|
|
75
106
|
}}>
|
|
76
|
-
<
|
|
77
|
-
width: 46,
|
|
78
|
-
height: 46,
|
|
79
|
-
borderRadius: 12,
|
|
80
|
-
alignItems: 'center',
|
|
81
|
-
justifyContent: 'center',
|
|
82
|
-
backgroundColor: `${AppColors.white}21`,
|
|
83
|
-
borderWidth: 1.5,
|
|
84
|
-
borderColor: `${AppColors.white}40`,
|
|
85
|
-
shadowColor: AppColors.black,
|
|
86
|
-
shadowOpacity: 0.15,
|
|
87
|
-
shadowRadius: 4,
|
|
88
|
-
shadowOffset: { width: 0, height: 2 },
|
|
89
|
-
flexShrink: 0,
|
|
90
|
-
}}>
|
|
91
|
-
<BrandSquareIcon size={42}/>
|
|
92
|
-
</View>
|
|
107
|
+
<AppHeaderLogo size={46} customIcon={appIcon}/>
|
|
93
108
|
<View style={{ gap: 2, flex: 1 }}>
|
|
94
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
109
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
95
110
|
<Text style={[styles.headerTitle]} numberOfLines={1}>
|
|
96
111
|
{getAppName()}
|
|
97
112
|
</Text>
|
|
113
|
+
<View style={[
|
|
114
|
+
styles.envBadge,
|
|
115
|
+
{
|
|
116
|
+
backgroundColor: envConfig.bg,
|
|
117
|
+
borderColor: envConfig.border,
|
|
118
|
+
},
|
|
119
|
+
]}>
|
|
120
|
+
<Text style={[
|
|
121
|
+
styles.envBadgeText,
|
|
122
|
+
{ color: envConfig.text },
|
|
123
|
+
]}>
|
|
124
|
+
{envConfig.label}
|
|
125
|
+
</Text>
|
|
126
|
+
</View>
|
|
98
127
|
{updateAvailable && (<Pressable hitSlop={10} onPress={() => Alert.alert('Update Available', `react-native-inapp-inspector v${latestNpmVersion} is available on NPM (installed: v${LIB_VERSION}).`, [
|
|
99
128
|
{ text: 'Later', style: 'cancel' },
|
|
100
129
|
{
|
|
@@ -233,10 +262,8 @@ const InspectorHeader = React.memo(() => {
|
|
|
233
262
|
</TouchableScale>) : null}
|
|
234
263
|
</View>
|
|
235
264
|
|
|
236
|
-
{
|
|
237
|
-
|
|
238
|
-
selectedLog != null) && (<View style={styles.headerCenter}>
|
|
239
|
-
{selected != null ? (<View style={styles.headerDetailCenter}>
|
|
265
|
+
{isDetailView && (<View style={styles.headerCenter}>
|
|
266
|
+
{activeTab === 'apis' && selected != null ? (<View style={styles.headerDetailCenter}>
|
|
240
267
|
<View style={styles.headerDetailRow}>
|
|
241
268
|
<View style={[
|
|
242
269
|
styles.headerMethodBadge,
|
|
@@ -297,7 +324,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
297
324
|
</Text>
|
|
298
325
|
</View>
|
|
299
326
|
</View>
|
|
300
|
-
</View>) : selectedEvent != null ? (<View style={styles.headerDetailCenter}>
|
|
327
|
+
</View>) : activeTab === 'analytics' && selectedEvent != null ? (<View style={styles.headerDetailCenter}>
|
|
301
328
|
<View style={styles.headerDetailRow}>
|
|
302
329
|
<View style={[
|
|
303
330
|
styles.headerMethodBadge,
|
|
@@ -335,7 +362,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
335
362
|
{selectedEvent.source}
|
|
336
363
|
</Text>
|
|
337
364
|
</View>
|
|
338
|
-
</View>) : selectedLog != null ? (<View style={styles.headerDetailCenter}>
|
|
365
|
+
</View>) : activeTab === 'logs' && selectedLog != null ? (<View style={styles.headerDetailCenter}>
|
|
339
366
|
<View style={styles.headerDetailRow}>
|
|
340
367
|
<View style={[
|
|
341
368
|
styles.headerMethodBadge,
|
|
@@ -368,27 +395,100 @@ const InspectorHeader = React.memo(() => {
|
|
|
368
395
|
borderRadius: 20,
|
|
369
396
|
backgroundColor: `${AppColors.white}29`,
|
|
370
397
|
}}>
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
398
|
+
<ClockIcon color={AppColors.white} size={11}/>
|
|
399
|
+
<Text style={styles.headerSubTitle}>
|
|
400
|
+
{formatTime(selectedLog.timestamp)}
|
|
401
|
+
</Text>
|
|
402
|
+
</View>
|
|
403
|
+
</View>
|
|
404
|
+
</View>) : activeTab === 'redux' && selectedReduxSlice != null ? ((() => {
|
|
405
|
+
const sliceData = reduxState?.[selectedReduxSlice];
|
|
406
|
+
const keyCount = sliceData && typeof sliceData === 'object'
|
|
407
|
+
? Object.keys(sliceData).length
|
|
408
|
+
: typeof sliceData !== 'undefined'
|
|
409
|
+
? 1
|
|
410
|
+
: 0;
|
|
411
|
+
const sliceSize = getSize(sliceData);
|
|
412
|
+
const lastAction = reduxLastActionMap[selectedReduxSlice];
|
|
413
|
+
return (<View style={styles.headerDetailCenter}>
|
|
414
|
+
<View style={styles.headerDetailRow}>
|
|
415
|
+
<View style={[
|
|
416
|
+
styles.headerMethodBadge,
|
|
417
|
+
{
|
|
418
|
+
backgroundColor: `${AppColors.purple}4D`,
|
|
419
|
+
},
|
|
420
|
+
]}>
|
|
421
|
+
<Text style={styles.headerMethodText}>
|
|
422
|
+
SLICE
|
|
423
|
+
</Text>
|
|
424
|
+
</View>
|
|
425
|
+
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
426
|
+
{selectedReduxSlice}
|
|
427
|
+
</Text>
|
|
428
|
+
</View>
|
|
429
|
+
<View style={styles.headerDetailSubRow}>
|
|
430
|
+
<View style={[
|
|
431
|
+
styles.headerStatusDot,
|
|
432
|
+
{ backgroundColor: AppColors.liveGreen },
|
|
433
|
+
]}/>
|
|
434
|
+
<Text style={styles.headerSubTitle}>
|
|
435
|
+
Live
|
|
436
|
+
</Text>
|
|
437
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>•</Text>
|
|
438
|
+
<Text style={styles.headerSubTitle}>
|
|
439
|
+
{keyCount} keys
|
|
440
|
+
</Text>
|
|
441
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>•</Text>
|
|
442
|
+
<Text style={styles.headerSubTitle}>
|
|
443
|
+
{sliceSize}
|
|
444
|
+
</Text>
|
|
445
|
+
{lastAction?.timestamp && (<>
|
|
446
|
+
<Text style={[styles.headerSubTitle, { opacity: 0.6 }]}>•</Text>
|
|
447
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 3 }}>
|
|
448
|
+
<ClockIcon color={AppColors.white} size={10}/>
|
|
449
|
+
<Text style={styles.headerSubTitle}>
|
|
450
|
+
{lastAction.timestamp}
|
|
451
|
+
</Text>
|
|
452
|
+
</View>
|
|
453
|
+
</>)}
|
|
454
|
+
</View>
|
|
455
|
+
</View>);
|
|
456
|
+
})()) : activeTab === 'redux' && selectedReduxAction != null ? (<View style={styles.headerDetailCenter}>
|
|
457
|
+
<View style={styles.headerDetailRow}>
|
|
458
|
+
<View style={[
|
|
459
|
+
styles.headerMethodBadge,
|
|
460
|
+
{
|
|
461
|
+
backgroundColor: `${AppColors.brandPurple}4D`,
|
|
462
|
+
},
|
|
463
|
+
]}>
|
|
464
|
+
<Text style={styles.headerMethodText}>
|
|
465
|
+
ACTION
|
|
374
466
|
</Text>
|
|
375
467
|
</View>
|
|
468
|
+
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
469
|
+
{selectedReduxAction.type}
|
|
470
|
+
</Text>
|
|
471
|
+
</View>
|
|
472
|
+
<View style={styles.headerDetailSubRow}>
|
|
473
|
+
<View style={[
|
|
474
|
+
styles.headerStatusDot,
|
|
475
|
+
{ backgroundColor: AppColors.purple },
|
|
476
|
+
]}/>
|
|
477
|
+
<Text style={styles.headerSubTitle}>
|
|
478
|
+
{selectedReduxAction.timestamp || 'Dispatched'}
|
|
479
|
+
</Text>
|
|
376
480
|
</View>
|
|
377
481
|
</View>) : null}
|
|
378
482
|
</View>)}
|
|
379
483
|
|
|
380
484
|
<View style={[
|
|
381
485
|
styles.headerRight,
|
|
382
|
-
|
|
383
|
-
selectedEvent == null &&
|
|
384
|
-
selectedLog == null && {
|
|
486
|
+
!isAnySelected && {
|
|
385
487
|
flexShrink: 0,
|
|
386
488
|
minWidth: 116,
|
|
387
489
|
},
|
|
388
490
|
]}>
|
|
389
|
-
{
|
|
390
|
-
selectedEvent == null &&
|
|
391
|
-
selectedLog == null && (<TouchableScale onPress={() => {
|
|
491
|
+
{!isAnySelected && (<TouchableScale onPress={() => {
|
|
392
492
|
Alert.alert('Clear Everything', 'This clears all tabs — APIs, Logs, Analytics and Redux timeline. Continue?', [
|
|
393
493
|
{ text: 'Cancel', style: 'cancel' },
|
|
394
494
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
2
|
import { ActivityIndicator, Modal, Pressable, StatusBar, StyleSheet, Text, View, } from 'react-native';
|
|
3
3
|
import { useInspector } from './InspectorContext';
|
|
4
4
|
import ErrorBoundary from '../ErrorBoundary';
|
|
@@ -10,13 +10,31 @@ import NetworkDetail from './NetworkDetail';
|
|
|
10
10
|
import LogDetail from './LogDetail';
|
|
11
11
|
import ConsoleTab from './ConsoleTab';
|
|
12
12
|
import AnalyticsTab from './AnalyticsTab';
|
|
13
|
+
import AnalyticsDetail from '../AnalyticsDetail';
|
|
13
14
|
import ReduxTab from './ReduxTab';
|
|
15
|
+
import ReduxDetail from './ReduxDetail';
|
|
16
|
+
import BundleTab from './BundleTab';
|
|
14
17
|
import SettingsPanel from './SettingsPanel';
|
|
15
18
|
import styles from '../../styles';
|
|
16
19
|
import { AppColors } from '../../styles/AppColors';
|
|
17
20
|
import NavigationTracker from './NavigationTracker';
|
|
18
21
|
const MainScreen = () => {
|
|
19
|
-
const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, settingsPage, activeTab, isReady, isEnabled, hasNavigationContext, setNavState, } = useInspector();
|
|
22
|
+
const { visible, modalAnimationType, closeModal, modalHeightPercent, selected, selectedEvent, selectedLog, selectedReduxSlice, selectedReduxAction, settingsPage, activeTab, isReady, isEnabled, hasNavigationContext, setNavState, } = useInspector();
|
|
23
|
+
// Lazy-mount each tab on first visit and cache it in memory for 0ms instantaneous switching
|
|
24
|
+
const [mountedTabs, setMountedTabs] = useState({
|
|
25
|
+
[activeTab]: true,
|
|
26
|
+
});
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setMountedTabs(prev => {
|
|
29
|
+
if (prev[activeTab])
|
|
30
|
+
return prev;
|
|
31
|
+
return { ...prev, [activeTab]: true };
|
|
32
|
+
});
|
|
33
|
+
}, [activeTab]);
|
|
34
|
+
const isDetailActive = (activeTab === 'apis' && selected != null) ||
|
|
35
|
+
(activeTab === 'analytics' && selectedEvent != null) ||
|
|
36
|
+
(activeTab === 'logs' && selectedLog != null) ||
|
|
37
|
+
(activeTab === 'redux' && (selectedReduxSlice != null || selectedReduxAction != null));
|
|
20
38
|
return (<>
|
|
21
39
|
{isEnabled && <FabLauncher />}
|
|
22
40
|
<Modal visible={visible} animationType={modalAnimationType} transparent>
|
|
@@ -32,12 +50,40 @@ const MainScreen = () => {
|
|
|
32
50
|
<InspectorHeader />
|
|
33
51
|
|
|
34
52
|
{/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
|
|
35
|
-
{
|
|
36
|
-
selectedEvent == null &&
|
|
37
|
-
selectedLog == null &&
|
|
38
|
-
settingsPage === null ? (<TabBar />) : null}
|
|
53
|
+
{!isDetailActive && settingsPage === null ? (<TabBar />) : null}
|
|
39
54
|
|
|
40
|
-
{isReady ? (
|
|
55
|
+
{isReady ? (isDetailActive ? (activeTab === 'apis' && selected != null ? (<NetworkDetail />) : activeTab === 'analytics' && selectedEvent != null ? (<AnalyticsDetail event={selectedEvent}/>) : activeTab === 'logs' && selectedLog != null ? (<LogDetail />) : activeTab === 'redux' ? (<ReduxDetail />) : null) : (<>
|
|
56
|
+
<View style={{
|
|
57
|
+
flex: 1,
|
|
58
|
+
display: activeTab === 'apis' ? 'flex' : 'none',
|
|
59
|
+
}}>
|
|
60
|
+
{mountedTabs.apis && <NetworkTab />}
|
|
61
|
+
</View>
|
|
62
|
+
<View style={{
|
|
63
|
+
flex: 1,
|
|
64
|
+
display: activeTab === 'logs' ? 'flex' : 'none',
|
|
65
|
+
}}>
|
|
66
|
+
{mountedTabs.logs && <ConsoleTab />}
|
|
67
|
+
</View>
|
|
68
|
+
<View style={{
|
|
69
|
+
flex: 1,
|
|
70
|
+
display: activeTab === 'analytics' ? 'flex' : 'none',
|
|
71
|
+
}}>
|
|
72
|
+
{mountedTabs.analytics && <AnalyticsTab />}
|
|
73
|
+
</View>
|
|
74
|
+
<View style={{
|
|
75
|
+
flex: 1,
|
|
76
|
+
display: activeTab === 'redux' ? 'flex' : 'none',
|
|
77
|
+
}}>
|
|
78
|
+
{mountedTabs.redux && <ReduxTab />}
|
|
79
|
+
</View>
|
|
80
|
+
<View style={{
|
|
81
|
+
flex: 1,
|
|
82
|
+
display: activeTab === 'bundle' ? 'flex' : 'none',
|
|
83
|
+
}}>
|
|
84
|
+
{mountedTabs.bundle && <BundleTab />}
|
|
85
|
+
</View>
|
|
86
|
+
</>)) : (<View style={styles.empty}>
|
|
41
87
|
<ActivityIndicator size="large" color={AppColors.purple}/>
|
|
42
88
|
<Text style={[styles.emptySub, { marginTop: 12 }]}>
|
|
43
89
|
Loading logs...
|