react-native-inapp-inspector 1.1.16 → 1.1.18
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 +46 -0
- package/dist/commonjs/components/Inspector/BundleTab.js +2439 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +185 -52
- package/dist/commonjs/components/Inspector/MainScreen.js +93 -7
- package/dist/commonjs/components/Inspector/PerformanceTab.d.ts +22 -0
- package/dist/commonjs/components/Inspector/PerformanceTab.js +1143 -0
- 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 +13 -2
- package/dist/commonjs/components/Inspector/TabBar.js +16 -6
- package/dist/commonjs/components/JsonViewer.js +91 -30
- package/dist/commonjs/components/LogCard.js +3 -4
- package/dist/commonjs/components/NetworkIcons.d.ts +9 -0
- package/dist/commonjs/components/NetworkIcons.js +63 -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 +18 -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 +46 -0
- package/dist/esm/components/Inspector/BundleTab.js +2401 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +151 -51
- package/dist/esm/components/Inspector/MainScreen.js +60 -7
- package/dist/esm/components/Inspector/PerformanceTab.d.ts +22 -0
- package/dist/esm/components/Inspector/PerformanceTab.js +1105 -0
- 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 +14 -3
- package/dist/esm/components/Inspector/TabBar.js +17 -7
- package/dist/esm/components/JsonViewer.js +92 -31
- package/dist/esm/components/LogCard.js +3 -4
- package/dist/esm/components/NetworkIcons.d.ts +9 -0
- package/dist/esm/components/NetworkIcons.js +55 -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 +18 -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,70 +1,421 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Pressable,
|
|
1
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import { FlatList, Pressable, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native';
|
|
3
3
|
import { useInspector } from './InspectorContext';
|
|
4
|
-
import
|
|
4
|
+
import TouchableScale from '../TouchableScale';
|
|
5
|
+
import AnimatedEntrance from '../AnimatedEntrance';
|
|
6
|
+
import EmptyState from '../EmptyState';
|
|
7
|
+
import EndOfListFooter from '../EndOfListFooter';
|
|
8
|
+
import HighlightText from '../HighlightText';
|
|
9
|
+
import { getSize } from '../../helpers';
|
|
5
10
|
import styles from '../../styles';
|
|
6
11
|
import { AppColors } from '../../styles/AppColors';
|
|
7
12
|
import { AppFonts } from '../../styles/AppFonts';
|
|
8
|
-
import { TerminalIcon, ClearIcon } from '../NetworkIcons';
|
|
13
|
+
import { TerminalIcon, SearchIcon, ClearIcon, ClockIcon, ForwardChevronIcon, SortArrowIcon, } from '../NetworkIcons';
|
|
9
14
|
const ReduxTab = React.memo(() => {
|
|
10
|
-
const { reduxState, reduxLastActionMap, reduxSearch, setReduxSearch, } = useInspector();
|
|
15
|
+
const { reduxState, reduxLastActionMap, reduxSearch, setReduxSearch, setSelectedReduxSlice, } = useInspector();
|
|
16
|
+
// Sort mode: 'latest' (newest updated first) vs 'alpha' (A-Z)
|
|
17
|
+
const [sortMode, setSortMode] = useState('latest');
|
|
18
|
+
// Total state size calculation
|
|
19
|
+
const totalStateSize = useMemo(() => {
|
|
20
|
+
return getSize(reduxState);
|
|
21
|
+
}, [reduxState]);
|
|
22
|
+
// Compute slice items with exact timestamps
|
|
23
|
+
const sliceItems = useMemo(() => {
|
|
24
|
+
if (!reduxState || typeof reduxState !== 'object')
|
|
25
|
+
return [];
|
|
26
|
+
const keys = Object.keys(reduxState);
|
|
27
|
+
return keys.map(key => {
|
|
28
|
+
const sliceVal = reduxState[key];
|
|
29
|
+
const keysCount = sliceVal && typeof sliceVal === 'object'
|
|
30
|
+
? Object.keys(sliceVal).length
|
|
31
|
+
: typeof sliceVal !== 'undefined'
|
|
32
|
+
? 1
|
|
33
|
+
: 0;
|
|
34
|
+
const lastAction = reduxLastActionMap[key];
|
|
35
|
+
const updatedAt = lastAction?.updatedAt || 0;
|
|
36
|
+
return {
|
|
37
|
+
id: `slice-${key}`,
|
|
38
|
+
name: key,
|
|
39
|
+
keysCount,
|
|
40
|
+
sizeStr: getSize(sliceVal),
|
|
41
|
+
lastAction,
|
|
42
|
+
updatedAt,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}, [reduxState, reduxLastActionMap]);
|
|
46
|
+
// Filter & Sort slices: by default, the most recently updated item is at the FIRST position
|
|
47
|
+
const filteredSlices = useMemo(() => {
|
|
48
|
+
let list = sliceItems;
|
|
49
|
+
if (reduxSearch.trim().length > 0) {
|
|
50
|
+
const q = reduxSearch.toLowerCase();
|
|
51
|
+
list = list.filter(item => item.name.toLowerCase().includes(q) ||
|
|
52
|
+
(item.lastAction && item.lastAction.type.toLowerCase().includes(q)));
|
|
53
|
+
}
|
|
54
|
+
return [...list].sort((a, b) => {
|
|
55
|
+
if (sortMode === 'latest') {
|
|
56
|
+
// Most recently updated item first
|
|
57
|
+
if (b.updatedAt !== a.updatedAt) {
|
|
58
|
+
return b.updatedAt - a.updatedAt;
|
|
59
|
+
}
|
|
60
|
+
return a.name.localeCompare(b.name);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Alphabetical A-Z
|
|
64
|
+
return a.name.localeCompare(b.name);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}, [sliceItems, reduxSearch, sortMode]);
|
|
68
|
+
const lastGlobalAction = useMemo(() => {
|
|
69
|
+
const actions = Object.values(reduxLastActionMap);
|
|
70
|
+
if (actions.length === 0)
|
|
71
|
+
return null;
|
|
72
|
+
return actions.reduce((latest, curr) => {
|
|
73
|
+
if (!latest)
|
|
74
|
+
return curr;
|
|
75
|
+
return (curr.updatedAt || 0) > (latest.updatedAt || 0) ? curr : latest;
|
|
76
|
+
}, null);
|
|
77
|
+
}, [reduxLastActionMap]);
|
|
78
|
+
const renderSliceItem = useCallback(({ item, index }) => {
|
|
79
|
+
const isRecentlyUpdated = item.updatedAt > 0 && Date.now() - item.updatedAt < 5000;
|
|
80
|
+
return (<AnimatedEntrance index={index} distance={8}>
|
|
81
|
+
<TouchableScale onPress={() => setSelectedReduxSlice(item.name)} style={[
|
|
82
|
+
reduxTabStyles.card,
|
|
83
|
+
isRecentlyUpdated && reduxTabStyles.cardRecentlyUpdated,
|
|
84
|
+
]}>
|
|
85
|
+
{/* Top row: Badge + Slice Name + Timestamp + Chevron */}
|
|
86
|
+
<View style={reduxTabStyles.cardHeader}>
|
|
87
|
+
<View style={reduxTabStyles.sliceBadge}>
|
|
88
|
+
<Text style={reduxTabStyles.sliceBadgeText}>SLICE</Text>
|
|
89
|
+
</View>
|
|
90
|
+
|
|
91
|
+
<HighlightText text={item.name} search={reduxSearch} style={reduxTabStyles.sliceName} highlightStyle={reduxTabStyles.highlight}/>
|
|
92
|
+
|
|
93
|
+
{item.lastAction?.timestamp && (<View style={reduxTabStyles.timePill}>
|
|
94
|
+
<ClockIcon color={AppColors.purple} size={10}/>
|
|
95
|
+
<Text style={reduxTabStyles.timeText}>
|
|
96
|
+
{item.lastAction.timestamp}
|
|
97
|
+
</Text>
|
|
98
|
+
</View>)}
|
|
99
|
+
|
|
100
|
+
<ForwardChevronIcon color={AppColors.grayTextWeak} size={13}/>
|
|
101
|
+
</View>
|
|
102
|
+
|
|
103
|
+
{/* Middle row: Stats pills */}
|
|
104
|
+
<View style={reduxTabStyles.statsRow}>
|
|
105
|
+
<View style={reduxTabStyles.pill}>
|
|
106
|
+
<Text style={reduxTabStyles.pillLabel}>Keys:</Text>
|
|
107
|
+
<Text style={reduxTabStyles.pillValue}>{item.keysCount}</Text>
|
|
108
|
+
</View>
|
|
109
|
+
<View style={reduxTabStyles.pill}>
|
|
110
|
+
<Text style={reduxTabStyles.pillLabel}>Size:</Text>
|
|
111
|
+
<Text style={reduxTabStyles.pillValue}>{item.sizeStr}</Text>
|
|
112
|
+
</View>
|
|
113
|
+
<View style={reduxTabStyles.livePill}>
|
|
114
|
+
<View style={reduxTabStyles.liveDot}/>
|
|
115
|
+
<Text style={reduxTabStyles.livePillText}>Live</Text>
|
|
116
|
+
</View>
|
|
117
|
+
</View>
|
|
118
|
+
|
|
119
|
+
{/* Bottom row: Last Dispatched Action */}
|
|
120
|
+
{item.lastAction && (<View style={reduxTabStyles.lastActionRow}>
|
|
121
|
+
<Text style={reduxTabStyles.lastActionLabel}>Last Action:</Text>
|
|
122
|
+
<HighlightText text={item.lastAction.type} search={reduxSearch} style={reduxTabStyles.lastActionValue} highlightStyle={reduxTabStyles.highlight} numberOfLines={1}/>
|
|
123
|
+
</View>)}
|
|
124
|
+
</TouchableScale>
|
|
125
|
+
</AnimatedEntrance>);
|
|
126
|
+
}, [reduxSearch, setSelectedReduxSlice]);
|
|
11
127
|
if (!reduxState) {
|
|
12
128
|
return (<View style={styles.emptyContainer}>
|
|
13
129
|
<View style={styles.emptyIconWrap}>
|
|
14
130
|
<TerminalIcon color={AppColors.purple} size={32}/>
|
|
15
131
|
</View>
|
|
16
|
-
<Text style={styles.emptyTitle}>No Redux Store</Text>
|
|
132
|
+
<Text style={styles.emptyTitle}>No Redux Store Connected</Text>
|
|
17
133
|
<Text style={styles.emptySub}>
|
|
18
|
-
|
|
134
|
+
Call connectReduxStore(store) or use inspectorReduxMiddleware at app initialization.
|
|
19
135
|
</Text>
|
|
20
136
|
</View>);
|
|
21
137
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}}>
|
|
45
|
-
<TextInput placeholder="Search Redux keys or values..." placeholderTextColor={AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
|
|
46
|
-
flex: 1,
|
|
47
|
-
fontFamily: AppFonts.interRegular,
|
|
48
|
-
fontSize: 12,
|
|
49
|
-
color: AppColors.grayTextStrong,
|
|
50
|
-
padding: 0,
|
|
51
|
-
}} autoCorrect={false} autoCapitalize="none"/>
|
|
52
|
-
{reduxSearch.length > 0 && (<Pressable onPress={() => setReduxSearch('')} hitSlop={10}>
|
|
53
|
-
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
54
|
-
</Pressable>)}
|
|
138
|
+
return (<View style={{ flex: 1, backgroundColor: AppColors.grayBackground }}>
|
|
139
|
+
{/* ─── Top Stats Overview Card ─── */}
|
|
140
|
+
<View style={reduxTabStyles.overviewCard}>
|
|
141
|
+
<View style={reduxTabStyles.statCol}>
|
|
142
|
+
<Text style={reduxTabStyles.statHeading}>ACTIVE SLICES</Text>
|
|
143
|
+
<Text style={reduxTabStyles.statBigVal}>{sliceItems.length}</Text>
|
|
144
|
+
</View>
|
|
145
|
+
<View style={reduxTabStyles.statDivider}/>
|
|
146
|
+
<View style={reduxTabStyles.statCol}>
|
|
147
|
+
<Text style={reduxTabStyles.statHeading}>TOTAL STATE</Text>
|
|
148
|
+
<Text style={reduxTabStyles.statBigVal}>{totalStateSize}</Text>
|
|
149
|
+
</View>
|
|
150
|
+
<View style={reduxTabStyles.statDivider}/>
|
|
151
|
+
<View style={[reduxTabStyles.statCol, { flex: 1.5 }]}>
|
|
152
|
+
<Text style={reduxTabStyles.statHeading}>LAST ACTION</Text>
|
|
153
|
+
<Text style={reduxTabStyles.statLastAction} numberOfLines={1}>
|
|
154
|
+
{lastGlobalAction ? lastGlobalAction.type : 'Initial'}
|
|
155
|
+
</Text>
|
|
156
|
+
{lastGlobalAction?.timestamp && (<Text style={reduxTabStyles.statLastTime}>
|
|
157
|
+
{lastGlobalAction.timestamp}
|
|
158
|
+
</Text>)}
|
|
159
|
+
</View>
|
|
55
160
|
</View>
|
|
56
161
|
|
|
57
|
-
{/*
|
|
58
|
-
<View style={
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
162
|
+
{/* ─── Search & Sort Bar ─── */}
|
|
163
|
+
<View style={reduxTabStyles.toolbarContainer}>
|
|
164
|
+
<View style={reduxTabStyles.searchRow}>
|
|
165
|
+
<View style={styles.searchContainer}>
|
|
166
|
+
<SearchIcon color={AppColors.grayTextWeak} size={15}/>
|
|
167
|
+
<TextInput placeholder="Search Redux slices or actions..." placeholderTextColor={AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
168
|
+
{reduxSearch.length > 0 && (<Pressable onPress={() => setReduxSearch('')} hitSlop={10}>
|
|
169
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
170
|
+
</Pressable>)}
|
|
171
|
+
</View>
|
|
172
|
+
|
|
173
|
+
{/* Sort Button */}
|
|
174
|
+
<TouchableOpacity style={[
|
|
175
|
+
styles.toolbarBtn,
|
|
176
|
+
sortMode === 'latest' && { backgroundColor: `${AppColors.brandPurple}1F`, borderColor: AppColors.brandPurple },
|
|
177
|
+
]} onPress={() => setSortMode(prev => (prev === 'latest' ? 'alpha' : 'latest'))} hitSlop={6}>
|
|
178
|
+
<SortArrowIcon color={sortMode === 'latest' ? AppColors.brandPurple : AppColors.grayTextStrong} size={16}/>
|
|
179
|
+
</TouchableOpacity>
|
|
180
|
+
</View>
|
|
181
|
+
|
|
182
|
+
<View style={reduxTabStyles.headerSubRow}>
|
|
183
|
+
<Text style={reduxTabStyles.resultCount}>
|
|
184
|
+
Showing {filteredSlices.length} of {sliceItems.length} state slices
|
|
185
|
+
</Text>
|
|
186
|
+
<Text style={reduxTabStyles.sortLabel}>
|
|
187
|
+
{sortMode === 'latest' ? '⚡ Newest Updates First' : '🔤 Alphabetical (A-Z)'}
|
|
188
|
+
</Text>
|
|
189
|
+
</View>
|
|
67
190
|
</View>
|
|
68
|
-
|
|
191
|
+
|
|
192
|
+
{/* ─── FlatList of Slices ─── */}
|
|
193
|
+
<FlatList data={filteredSlices} keyExtractor={item => item.id} renderItem={renderSliceItem} initialNumToRender={15} maxToRenderPerBatch={10} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState isSearch={reduxSearch.length > 0}/>} ListFooterComponent={filteredSlices.length > 0 ? (<EndOfListFooter count={filteredSlices.length} label="slices"/>) : null} contentContainerStyle={[
|
|
194
|
+
reduxTabStyles.listContent,
|
|
195
|
+
filteredSlices.length === 0 && { flexGrow: 1 },
|
|
196
|
+
]} keyboardShouldPersistTaps="handled"/>
|
|
197
|
+
</View>);
|
|
198
|
+
});
|
|
199
|
+
const reduxTabStyles = StyleSheet.create({
|
|
200
|
+
overviewCard: {
|
|
201
|
+
flexDirection: 'row',
|
|
202
|
+
alignItems: 'center',
|
|
203
|
+
backgroundColor: AppColors.white,
|
|
204
|
+
marginHorizontal: 12,
|
|
205
|
+
marginTop: 10,
|
|
206
|
+
borderRadius: 12,
|
|
207
|
+
padding: 12,
|
|
208
|
+
borderWidth: 1,
|
|
209
|
+
borderColor: AppColors.dividerColor,
|
|
210
|
+
shadowColor: AppColors.primaryBlack,
|
|
211
|
+
shadowOffset: { width: 0, height: 1 },
|
|
212
|
+
shadowOpacity: 0.03,
|
|
213
|
+
shadowRadius: 3,
|
|
214
|
+
elevation: 1,
|
|
215
|
+
},
|
|
216
|
+
statCol: {
|
|
217
|
+
flex: 1,
|
|
218
|
+
},
|
|
219
|
+
statDivider: {
|
|
220
|
+
width: 1,
|
|
221
|
+
height: 28,
|
|
222
|
+
backgroundColor: AppColors.dividerColor,
|
|
223
|
+
marginHorizontal: 8,
|
|
224
|
+
},
|
|
225
|
+
statHeading: {
|
|
226
|
+
fontFamily: AppFonts.interBold,
|
|
227
|
+
fontSize: 9,
|
|
228
|
+
color: AppColors.grayTextWeak,
|
|
229
|
+
letterSpacing: 0.5,
|
|
230
|
+
},
|
|
231
|
+
statBigVal: {
|
|
232
|
+
fontFamily: AppFonts.interBold,
|
|
233
|
+
fontSize: 14,
|
|
234
|
+
color: AppColors.primaryBlack,
|
|
235
|
+
marginTop: 2,
|
|
236
|
+
},
|
|
237
|
+
statLastAction: {
|
|
238
|
+
fontFamily: AppFonts.interBold,
|
|
239
|
+
fontSize: 11,
|
|
240
|
+
color: AppColors.purple,
|
|
241
|
+
marginTop: 2,
|
|
242
|
+
},
|
|
243
|
+
statLastTime: {
|
|
244
|
+
fontFamily: AppFonts.interRegular,
|
|
245
|
+
fontSize: 9.5,
|
|
246
|
+
color: AppColors.grayTextWeak,
|
|
247
|
+
},
|
|
248
|
+
toolbarContainer: {
|
|
249
|
+
backgroundColor: AppColors.white,
|
|
250
|
+
borderBottomWidth: 1,
|
|
251
|
+
borderBottomColor: AppColors.dividerColor,
|
|
252
|
+
paddingHorizontal: 12,
|
|
253
|
+
paddingTop: 8,
|
|
254
|
+
paddingBottom: 6,
|
|
255
|
+
marginTop: 8,
|
|
256
|
+
},
|
|
257
|
+
searchRow: {
|
|
258
|
+
flexDirection: 'row',
|
|
259
|
+
alignItems: 'center',
|
|
260
|
+
gap: 8,
|
|
261
|
+
},
|
|
262
|
+
headerSubRow: {
|
|
263
|
+
flexDirection: 'row',
|
|
264
|
+
justifyContent: 'space-between',
|
|
265
|
+
alignItems: 'center',
|
|
266
|
+
marginTop: 6,
|
|
267
|
+
paddingHorizontal: 2,
|
|
268
|
+
},
|
|
269
|
+
resultCount: {
|
|
270
|
+
fontFamily: AppFonts.interMedium,
|
|
271
|
+
fontSize: 11,
|
|
272
|
+
color: AppColors.grayTextWeak,
|
|
273
|
+
},
|
|
274
|
+
sortLabel: {
|
|
275
|
+
fontFamily: AppFonts.interMedium,
|
|
276
|
+
fontSize: 10.5,
|
|
277
|
+
color: AppColors.brandPurple,
|
|
278
|
+
},
|
|
279
|
+
listContent: {
|
|
280
|
+
padding: 12,
|
|
281
|
+
paddingBottom: 36,
|
|
282
|
+
},
|
|
283
|
+
card: {
|
|
284
|
+
backgroundColor: AppColors.white,
|
|
285
|
+
borderRadius: 12,
|
|
286
|
+
padding: 12,
|
|
287
|
+
marginBottom: 10,
|
|
288
|
+
borderWidth: 1,
|
|
289
|
+
borderColor: AppColors.dividerColor,
|
|
290
|
+
shadowColor: AppColors.primaryBlack,
|
|
291
|
+
shadowOffset: { width: 0, height: 1 },
|
|
292
|
+
shadowOpacity: 0.04,
|
|
293
|
+
shadowRadius: 4,
|
|
294
|
+
elevation: 2,
|
|
295
|
+
},
|
|
296
|
+
cardRecentlyUpdated: {
|
|
297
|
+
borderColor: `${AppColors.brandPurple}66`,
|
|
298
|
+
backgroundColor: '#FAFAFF',
|
|
299
|
+
},
|
|
300
|
+
cardHeader: {
|
|
301
|
+
flexDirection: 'row',
|
|
302
|
+
alignItems: 'center',
|
|
303
|
+
gap: 8,
|
|
304
|
+
marginBottom: 8,
|
|
305
|
+
},
|
|
306
|
+
sliceBadge: {
|
|
307
|
+
backgroundColor: '#EDE9FE',
|
|
308
|
+
paddingHorizontal: 6,
|
|
309
|
+
paddingVertical: 3,
|
|
310
|
+
borderRadius: 5,
|
|
311
|
+
borderWidth: 1,
|
|
312
|
+
borderColor: '#DDD6FE',
|
|
313
|
+
},
|
|
314
|
+
sliceBadgeText: {
|
|
315
|
+
fontFamily: AppFonts.interBold,
|
|
316
|
+
fontSize: 9.5,
|
|
317
|
+
color: '#6D28D9',
|
|
318
|
+
letterSpacing: 0.4,
|
|
319
|
+
},
|
|
320
|
+
sliceName: {
|
|
321
|
+
flex: 1,
|
|
322
|
+
fontFamily: AppFonts.interBold,
|
|
323
|
+
fontSize: 13.5,
|
|
324
|
+
color: AppColors.primaryBlack,
|
|
325
|
+
},
|
|
326
|
+
timePill: {
|
|
327
|
+
flexDirection: 'row',
|
|
328
|
+
alignItems: 'center',
|
|
329
|
+
gap: 3,
|
|
330
|
+
backgroundColor: `${AppColors.purple}14`,
|
|
331
|
+
paddingHorizontal: 6,
|
|
332
|
+
paddingVertical: 2,
|
|
333
|
+
borderRadius: 4,
|
|
334
|
+
borderWidth: 1,
|
|
335
|
+
borderColor: `${AppColors.purple}2E`,
|
|
336
|
+
},
|
|
337
|
+
timeText: {
|
|
338
|
+
fontFamily: AppFonts.interMedium,
|
|
339
|
+
fontSize: 10,
|
|
340
|
+
color: AppColors.purple,
|
|
341
|
+
},
|
|
342
|
+
statsRow: {
|
|
343
|
+
flexDirection: 'row',
|
|
344
|
+
alignItems: 'center',
|
|
345
|
+
gap: 6,
|
|
346
|
+
flexWrap: 'wrap',
|
|
347
|
+
marginBottom: 6,
|
|
348
|
+
},
|
|
349
|
+
pill: {
|
|
350
|
+
flexDirection: 'row',
|
|
351
|
+
alignItems: 'center',
|
|
352
|
+
gap: 4,
|
|
353
|
+
backgroundColor: AppColors.grayBackground,
|
|
354
|
+
paddingHorizontal: 7,
|
|
355
|
+
paddingVertical: 3,
|
|
356
|
+
borderRadius: 5,
|
|
357
|
+
borderWidth: 1,
|
|
358
|
+
borderColor: AppColors.dividerColor,
|
|
359
|
+
},
|
|
360
|
+
pillLabel: {
|
|
361
|
+
fontFamily: AppFonts.interMedium,
|
|
362
|
+
fontSize: 10.5,
|
|
363
|
+
color: AppColors.grayTextWeak,
|
|
364
|
+
},
|
|
365
|
+
pillValue: {
|
|
366
|
+
fontFamily: AppFonts.interBold,
|
|
367
|
+
fontSize: 10.5,
|
|
368
|
+
color: AppColors.primaryBlack,
|
|
369
|
+
},
|
|
370
|
+
livePill: {
|
|
371
|
+
flexDirection: 'row',
|
|
372
|
+
alignItems: 'center',
|
|
373
|
+
gap: 4,
|
|
374
|
+
backgroundColor: '#ECFDF5',
|
|
375
|
+
paddingHorizontal: 6,
|
|
376
|
+
paddingVertical: 3,
|
|
377
|
+
borderRadius: 5,
|
|
378
|
+
borderWidth: 1,
|
|
379
|
+
borderColor: '#A7F3D0',
|
|
380
|
+
},
|
|
381
|
+
liveDot: {
|
|
382
|
+
width: 6,
|
|
383
|
+
height: 6,
|
|
384
|
+
borderRadius: 3,
|
|
385
|
+
backgroundColor: '#10B981',
|
|
386
|
+
},
|
|
387
|
+
livePillText: {
|
|
388
|
+
fontFamily: AppFonts.interBold,
|
|
389
|
+
fontSize: 10,
|
|
390
|
+
color: '#047857',
|
|
391
|
+
},
|
|
392
|
+
lastActionRow: {
|
|
393
|
+
flexDirection: 'row',
|
|
394
|
+
alignItems: 'center',
|
|
395
|
+
gap: 6,
|
|
396
|
+
backgroundColor: AppColors.grayBackground,
|
|
397
|
+
borderRadius: 6,
|
|
398
|
+
paddingHorizontal: 8,
|
|
399
|
+
paddingVertical: 4,
|
|
400
|
+
marginTop: 2,
|
|
401
|
+
borderWidth: 1,
|
|
402
|
+
borderColor: AppColors.dividerColor,
|
|
403
|
+
},
|
|
404
|
+
lastActionLabel: {
|
|
405
|
+
fontFamily: AppFonts.interMedium,
|
|
406
|
+
fontSize: 10.5,
|
|
407
|
+
color: AppColors.grayTextWeak,
|
|
408
|
+
},
|
|
409
|
+
lastActionValue: {
|
|
410
|
+
flex: 1,
|
|
411
|
+
fontFamily: AppFonts.interBold,
|
|
412
|
+
fontSize: 11,
|
|
413
|
+
color: AppColors.primaryBlack,
|
|
414
|
+
},
|
|
415
|
+
highlight: {
|
|
416
|
+
backgroundColor: '#FEF08A',
|
|
417
|
+
color: '#854D0E',
|
|
418
|
+
fontFamily: AppFonts.interBold,
|
|
419
|
+
},
|
|
69
420
|
});
|
|
70
421
|
export default ReduxTab;
|
|
@@ -12,9 +12,10 @@ import { isPersistentStorageAvailable } from '../../helpers/settingsStore';
|
|
|
12
12
|
import { clearNetworkLogs } from '../../customHooks/networkLogger';
|
|
13
13
|
import { clearConsoleLogs } from '../../customHooks/consoleLogger';
|
|
14
14
|
import { clearAnalyticsEvents } from '../../customHooks/analyticsLogger';
|
|
15
|
-
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon, WhiteBackNavigation, } from '../NetworkIcons';
|
|
15
|
+
import { SignalIcon, TerminalIcon, AnalyticsIcon, SettingsIcon, SunIcon, MoonIcon, ScreenIcon, MotionIcon, LayersIcon, EyeIcon, CheckIcon, TrashIcon, WhiteBackNavigation, PackageIcon, ReduxIcon, PerformanceIcon, } from '../NetworkIcons';
|
|
16
16
|
const SettingsPanel = () => {
|
|
17
17
|
const { settingsPage, setSettingsPage, settingsActiveSubTab, setSettingsActiveSubTab, tabVisibility, toggleTabVisibility, defaultTab, setDefaultTab, isDark, setIsDark, modalHeightPercent, setModalHeightPercent, modalAnimationType, setModalAnimationType, showDuplicateLogs, setShowDuplicateLogs, showConsoleLevels, setShowConsoleLevels, resetToDefaults, storage, logs, consoleLogs, analyticsEvents, reduxState, maxNetworkLogs, setMaxNetworkLogs, maxConsoleLogs, setMaxConsoleLogs, reduxAutoRefresh, setReduxAutoRefreshState, reduxExpandDepth, setReduxExpandDepth, switchActiveTab, setSelected, setSelectedEvent, setReduxState, } = useInspector();
|
|
18
|
+
const isPersistent = isPersistentStorageAvailable();
|
|
18
19
|
const headerTopPadding = Platform.OS === 'ios' && modalHeightPercent >= 95 ? 44 : 0;
|
|
19
20
|
if (settingsPage === 'main') {
|
|
20
21
|
const settingsTabs = [
|
|
@@ -22,6 +23,8 @@ const SettingsPanel = () => {
|
|
|
22
23
|
{ key: 'logs', label: 'Logs', icon: 'logs' },
|
|
23
24
|
{ key: 'analytics', label: 'Analytics', icon: 'analytics' },
|
|
24
25
|
{ key: 'redux', label: 'Redux', icon: 'redux' },
|
|
26
|
+
{ key: 'bundle', label: 'Bundle', icon: 'bundle' },
|
|
27
|
+
{ key: 'performance', label: 'Performance', icon: 'performance' },
|
|
25
28
|
];
|
|
26
29
|
return (<View style={{ flex: 1, backgroundColor: AppColors.grayBackground }}>
|
|
27
30
|
{/* Settings Header with back button */}
|
|
@@ -223,7 +226,13 @@ const SettingsPanel = () => {
|
|
|
223
226
|
{tab.icon === 'analytics' && (<AnalyticsIcon color={isLocked
|
|
224
227
|
? AppColors.grayTextWeak
|
|
225
228
|
: AppColors.purple} size={11}/>)}
|
|
226
|
-
{tab.icon === 'redux' && (<
|
|
229
|
+
{tab.icon === 'redux' && (<ReduxIcon color={isLocked
|
|
230
|
+
? AppColors.grayTextWeak
|
|
231
|
+
: AppColors.purple} size={11}/>)}
|
|
232
|
+
{tab.icon === 'bundle' && (<PackageIcon color={isLocked
|
|
233
|
+
? AppColors.grayTextWeak
|
|
234
|
+
: AppColors.purple} size={11}/>)}
|
|
235
|
+
{tab.icon === 'performance' && (<PerformanceIcon color={isLocked
|
|
227
236
|
? AppColors.grayTextWeak
|
|
228
237
|
: AppColors.purple} size={11}/>)}
|
|
229
238
|
</View>
|
|
@@ -662,7 +671,9 @@ const SettingsPanel = () => {
|
|
|
662
671
|
{tab.icon === 'apis' && (<SignalIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
663
672
|
{tab.icon === 'logs' && (<TerminalIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
664
673
|
{tab.icon === 'analytics' && (<AnalyticsIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
665
|
-
{tab.icon === 'redux' && (<
|
|
674
|
+
{tab.icon === 'redux' && (<ReduxIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
675
|
+
{tab.icon === 'bundle' && (<PackageIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
676
|
+
{tab.icon === 'performance' && (<PerformanceIcon color={isActive ? AppColors.white : AppColors.purple} size={11}/>)}
|
|
666
677
|
</View>
|
|
667
678
|
<Text style={{
|
|
668
679
|
fontFamily: AppFonts.interBold,
|
|
@@ -4,7 +4,7 @@ import { useInspector } from './InspectorContext';
|
|
|
4
4
|
import TouchableScale from '../TouchableScale';
|
|
5
5
|
import styles from '../../styles';
|
|
6
6
|
import { AppColors } from '../../styles/AppColors';
|
|
7
|
-
import { SignalIcon, TerminalIcon, AnalyticsIcon, } from '../NetworkIcons';
|
|
7
|
+
import { SignalIcon, TerminalIcon, AnalyticsIcon, PackageIcon, ReduxIcon, PerformanceIcon, } from '../NetworkIcons';
|
|
8
8
|
const TabBar = React.memo(() => {
|
|
9
9
|
const { activeTab, switchActiveTab, tabVisibility, logs, consoleLogs, analyticsEvents, lastReadApisCount, lastReadLogsCount, unreadPulseAnim, } = useInspector();
|
|
10
10
|
return (<View style={styles.tabBarContainer}>
|
|
@@ -34,6 +34,18 @@ const TabBar = React.memo(() => {
|
|
|
34
34
|
count: 0,
|
|
35
35
|
icon: 'redux',
|
|
36
36
|
},
|
|
37
|
+
{
|
|
38
|
+
key: 'bundle',
|
|
39
|
+
label: 'Bundle',
|
|
40
|
+
count: 0,
|
|
41
|
+
icon: 'bundle',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 'performance',
|
|
45
|
+
label: 'Performance',
|
|
46
|
+
count: 0,
|
|
47
|
+
icon: 'performance',
|
|
48
|
+
},
|
|
37
49
|
]
|
|
38
50
|
.filter(tab => tabVisibility?.[tab.key])
|
|
39
51
|
.map(tab => {
|
|
@@ -46,11 +58,7 @@ const TabBar = React.memo(() => {
|
|
|
46
58
|
logs.length > lastReadApisCount;
|
|
47
59
|
const hasUnreadLogs = activeTab !== 'logs' &&
|
|
48
60
|
consoleLogs.length > lastReadLogsCount;
|
|
49
|
-
return (<TouchableScale key={tab.key} onPress={() => {
|
|
50
|
-
requestAnimationFrame(() => {
|
|
51
|
-
switchActiveTab(tab.key);
|
|
52
|
-
});
|
|
53
|
-
}} style={[
|
|
61
|
+
return (<TouchableScale key={tab.key} onPress={() => switchActiveTab(tab.key)} style={[
|
|
54
62
|
styles.contentTabButton,
|
|
55
63
|
isActive && styles.contentTabButtonActive,
|
|
56
64
|
]}>
|
|
@@ -62,7 +70,9 @@ const TabBar = React.memo(() => {
|
|
|
62
70
|
{tab.icon === 'apis' && (<SignalIcon color={iconColor} size={14}/>)}
|
|
63
71
|
{tab.icon === 'logs' && (<TerminalIcon color={iconColor} size={14}/>)}
|
|
64
72
|
{tab.icon === 'analytics' && (<AnalyticsIcon color={iconColor} size={14}/>)}
|
|
65
|
-
{tab.icon === 'redux' && (<
|
|
73
|
+
{tab.icon === 'redux' && (<ReduxIcon color={iconColor} size={14}/>)}
|
|
74
|
+
{tab.icon === 'bundle' && (<PackageIcon color={iconColor} size={14}/>)}
|
|
75
|
+
{tab.icon === 'performance' && (<PerformanceIcon color={iconColor} size={14}/>)}
|
|
66
76
|
<Text numberOfLines={1} ellipsizeMode="tail" style={[
|
|
67
77
|
styles.contentTabButtonText,
|
|
68
78
|
isActive &&
|