react-native-inapp-inspector 1.0.8 → 1.0.10
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 +5 -6
- package/assets/social_preview.png +0 -0
- package/dist/commonjs/components/AnalyticsDetail.js +28 -23
- package/dist/commonjs/components/AnalyticsEventCard.js +9 -9
- package/dist/commonjs/components/BrandCircleIcon.d.ts +5 -0
- package/dist/commonjs/components/BrandCircleIcon.js +180 -0
- package/dist/commonjs/components/BrandSquareIcon.d.ts +5 -0
- package/dist/commonjs/components/BrandSquareIcon.js +180 -0
- package/dist/commonjs/components/CodeSnippet.js +32 -24
- package/dist/commonjs/components/ConsoleLogCard.js +127 -70
- package/dist/commonjs/components/JsonViewer.d.ts +2 -1
- package/dist/commonjs/components/JsonViewer.js +2 -2
- package/dist/commonjs/components/MetaAccordion.d.ts +1 -1
- package/dist/commonjs/components/MetaAccordion.js +45 -2
- package/dist/commonjs/components/NetworkIcons.d.ts +8 -0
- package/dist/commonjs/components/NetworkIcons.js +44 -1
- package/dist/commonjs/components/ReduxTreeView.d.ts +6 -0
- package/dist/commonjs/components/ReduxTreeView.js +403 -0
- package/dist/commonjs/components/TouchableScale.js +15 -1
- package/dist/commonjs/components/TreeNode.js +3 -3
- package/dist/commonjs/customHooks/reduxLogger.d.ts +4 -0
- package/dist/commonjs/customHooks/reduxLogger.js +48 -2
- package/dist/commonjs/index.js +1520 -506
- package/dist/commonjs/styles/index.d.ts +11 -1
- package/dist/commonjs/styles/index.js +19 -9
- package/dist/commonjs/types/index.d.ts +4 -0
- package/dist/esm/components/AnalyticsDetail.js +28 -23
- package/dist/esm/components/AnalyticsEventCard.js +9 -9
- package/dist/esm/components/BrandCircleIcon.d.ts +5 -0
- package/dist/esm/components/BrandCircleIcon.js +140 -0
- package/dist/esm/components/BrandSquareIcon.d.ts +5 -0
- package/dist/esm/components/BrandSquareIcon.js +140 -0
- package/dist/esm/components/CodeSnippet.js +32 -24
- package/dist/esm/components/ConsoleLogCard.js +127 -70
- package/dist/esm/components/JsonViewer.d.ts +2 -1
- package/dist/esm/components/JsonViewer.js +2 -2
- package/dist/esm/components/MetaAccordion.d.ts +1 -1
- package/dist/esm/components/MetaAccordion.js +46 -3
- package/dist/esm/components/NetworkIcons.d.ts +8 -0
- package/dist/esm/components/NetworkIcons.js +35 -0
- package/dist/esm/components/ReduxTreeView.d.ts +6 -0
- package/dist/esm/components/ReduxTreeView.js +366 -0
- package/dist/esm/components/TouchableScale.js +16 -2
- package/dist/esm/components/TreeNode.js +3 -3
- package/dist/esm/customHooks/reduxLogger.d.ts +4 -0
- package/dist/esm/customHooks/reduxLogger.js +43 -1
- package/dist/esm/index.js +1523 -509
- package/dist/esm/styles/index.d.ts +11 -1
- package/dist/esm/styles/index.js +19 -9
- package/dist/esm/types/index.d.ts +4 -0
- package/example/App.tsx +46 -0
- package/package.json +7 -5
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, Text, Pressable, StyleSheet } from 'react-native';
|
|
3
|
+
import { AppColors } from '../styles/AppColors';
|
|
4
|
+
import { AppFonts } from '../styles/AppFonts';
|
|
5
|
+
import { ChevronIcon } from './NetworkIcons';
|
|
6
|
+
import Svg, { Path } from 'react-native-svg';
|
|
7
|
+
// Custom icons
|
|
8
|
+
const DatabaseIcon = ({ color = AppColors.grayTextWeak, size = 12 }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
9
|
+
<Path d="M12 2C6.5 2 2 4.2 2 7v10c0 2.8 4.5 5 10 5s10-2.2 10-5V7c0-2.8-4.5-5-10-5z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
10
|
+
<Path d="M2 12c0 2.8 4.5 5 10 5s10-2.2 10-5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
11
|
+
<Path d="M2 7c0 2.8 4.5 5 10 5s10-2.2 10-5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
12
|
+
</Svg>);
|
|
13
|
+
const BoltIcon = ({ color = AppColors.grayTextWeak, size = 12 }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
14
|
+
<Path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill={color} stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
15
|
+
</Svg>);
|
|
16
|
+
const FolderIcon = ({ color = AppColors.grayTextWeak, size = 12 }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
17
|
+
<Path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
18
|
+
</Svg>);
|
|
19
|
+
const ReduxValueNode = ({ name, value, level, search }) => {
|
|
20
|
+
const [expanded, setExpanded] = useState(level < 1);
|
|
21
|
+
const isObject = typeof value === 'object' && value !== null;
|
|
22
|
+
const isArray = Array.isArray(value);
|
|
23
|
+
const nameStr = String(name);
|
|
24
|
+
// Filter check if search query matches key or value
|
|
25
|
+
const matchesSearch = (k, val) => {
|
|
26
|
+
if (!search)
|
|
27
|
+
return true;
|
|
28
|
+
const s = search.toLowerCase();
|
|
29
|
+
if (k.toLowerCase().includes(s))
|
|
30
|
+
return true;
|
|
31
|
+
if (typeof val !== 'object' && String(val).toLowerCase().includes(s))
|
|
32
|
+
return true;
|
|
33
|
+
if (typeof val === 'object' && val !== null) {
|
|
34
|
+
return Object.keys(val).some(key => matchesSearch(key, val[key]));
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
};
|
|
38
|
+
if (!matchesSearch(nameStr, value)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (!isObject) {
|
|
42
|
+
const valStr = value === null ? 'null' : value === undefined ? 'undefined' : String(value);
|
|
43
|
+
// Pick different colors for primitives
|
|
44
|
+
let valColor = '#0D9488'; // String
|
|
45
|
+
if (value === null || value === undefined) {
|
|
46
|
+
valColor = AppColors.grayTextWeak;
|
|
47
|
+
}
|
|
48
|
+
else if (typeof value === 'number') {
|
|
49
|
+
valColor = '#D97706';
|
|
50
|
+
}
|
|
51
|
+
else if (typeof value === 'boolean') {
|
|
52
|
+
valColor = '#4F46E5';
|
|
53
|
+
}
|
|
54
|
+
return (<View style={[reduxValueStyles.treeRow, { paddingLeft: 12 }]}>
|
|
55
|
+
<View style={reduxValueStyles.treeLeafConnector}/>
|
|
56
|
+
<Text style={reduxValueStyles.keyText} selectable={true}>
|
|
57
|
+
{nameStr}
|
|
58
|
+
<Text style={reduxValueStyles.colonText}>: </Text>
|
|
59
|
+
<Text style={[reduxValueStyles.valText, { color: valColor }]} selectable={true}>
|
|
60
|
+
{valStr}
|
|
61
|
+
</Text>
|
|
62
|
+
</Text>
|
|
63
|
+
</View>);
|
|
64
|
+
}
|
|
65
|
+
const keys = Object.keys(value);
|
|
66
|
+
const summaryText = isArray ? `Array [${keys.length}]` : `Object {${keys.length}}`;
|
|
67
|
+
return (<View style={reduxValueStyles.treeNodeBlock}>
|
|
68
|
+
<Pressable onPress={() => setExpanded(!expanded)} style={reduxValueStyles.treeRow}>
|
|
69
|
+
<View style={reduxValueStyles.treeLeafConnector}/>
|
|
70
|
+
<View style={[reduxValueStyles.chevronWrap, { transform: [{ rotate: expanded ? '90deg' : '0deg' }] }]}>
|
|
71
|
+
<ChevronIcon color={AppColors.grayTextWeak} size={10}/>
|
|
72
|
+
</View>
|
|
73
|
+
<Text style={reduxValueStyles.keyText} selectable={true}>
|
|
74
|
+
{nameStr}
|
|
75
|
+
<Text style={reduxValueStyles.colonText}>: </Text>
|
|
76
|
+
<Text style={reduxValueStyles.summaryText}>{summaryText}</Text>
|
|
77
|
+
</Text>
|
|
78
|
+
</Pressable>
|
|
79
|
+
{expanded && (<View style={reduxValueStyles.treeChildrenContainer}>
|
|
80
|
+
{keys.map(key => (<ReduxValueNode key={key} name={key} value={value[key]} level={level + 1} search={search}/>))}
|
|
81
|
+
</View>)}
|
|
82
|
+
</View>);
|
|
83
|
+
};
|
|
84
|
+
export const ReduxTreeView = ({ state, lastActionMap, search, }) => {
|
|
85
|
+
const [storeExpanded, setStoreExpanded] = useState(true);
|
|
86
|
+
const [reducerExpanded, setReducerExpanded] = useState({});
|
|
87
|
+
if (!state || typeof state !== 'object') {
|
|
88
|
+
return (<Text style={{ fontFamily: AppFonts.interRegular, fontSize: 12, color: AppColors.grayTextWeak, padding: 12 }}>
|
|
89
|
+
No state object to display.
|
|
90
|
+
</Text>);
|
|
91
|
+
}
|
|
92
|
+
const reducers = Object.keys(state);
|
|
93
|
+
const toggleReducer = (key) => {
|
|
94
|
+
setReducerExpanded(prev => ({
|
|
95
|
+
...prev,
|
|
96
|
+
[key]: !prev[key],
|
|
97
|
+
}));
|
|
98
|
+
};
|
|
99
|
+
return (<View style={styles.container}>
|
|
100
|
+
{/* Root Node: Store */}
|
|
101
|
+
<Pressable onPress={() => setStoreExpanded(!storeExpanded)} style={styles.storeHeader}>
|
|
102
|
+
<View style={[styles.chevronWrap, { transform: [{ rotate: storeExpanded ? '90deg' : '0deg' }] }]}>
|
|
103
|
+
<ChevronIcon color="#FFFFFF" size={12}/>
|
|
104
|
+
</View>
|
|
105
|
+
<Text style={styles.storeTitle}>🏪 Redux Store</Text>
|
|
106
|
+
<View style={styles.badge}>
|
|
107
|
+
<Text style={styles.badgeText}>{reducers.length} Reducers</Text>
|
|
108
|
+
</View>
|
|
109
|
+
</Pressable>
|
|
110
|
+
|
|
111
|
+
{storeExpanded && (<View style={styles.storeChildren}>
|
|
112
|
+
{reducers.map((reducerKey, index) => {
|
|
113
|
+
const isLastReducer = index === reducers.length - 1;
|
|
114
|
+
const isExpanded = !!reducerExpanded[reducerKey];
|
|
115
|
+
const sliceData = state[reducerKey];
|
|
116
|
+
const lastAction = lastActionMap[reducerKey];
|
|
117
|
+
return (<View key={reducerKey} style={styles.reducerContainer}>
|
|
118
|
+
{/* Visual Branch Line for Reducer */}
|
|
119
|
+
<View style={[styles.reducerVerticalLine, isLastReducer && { bottom: '50%' }]}/>
|
|
120
|
+
|
|
121
|
+
{/* Reducer Header */}
|
|
122
|
+
<Pressable onPress={() => toggleReducer(reducerKey)} style={styles.reducerHeader}>
|
|
123
|
+
<View style={styles.reducerHorizontalLine}/>
|
|
124
|
+
<View style={[styles.chevronWrap, { transform: [{ rotate: isExpanded ? '90deg' : '0deg' }] }]}>
|
|
125
|
+
<ChevronIcon color={AppColors.purple} size={10}/>
|
|
126
|
+
</View>
|
|
127
|
+
<View style={styles.iconWrap}>
|
|
128
|
+
<FolderIcon color={AppColors.purple} size={11}/>
|
|
129
|
+
</View>
|
|
130
|
+
<Text style={styles.reducerText}>{reducerKey}</Text>
|
|
131
|
+
</Pressable>
|
|
132
|
+
|
|
133
|
+
{isExpanded && (<View style={styles.reducerChildren}>
|
|
134
|
+
{/* Vertical line connecting children */}
|
|
135
|
+
<View style={styles.childrenVerticalLine}/>
|
|
136
|
+
|
|
137
|
+
{/* Node 1: Last Action */}
|
|
138
|
+
<View style={styles.childItem}>
|
|
139
|
+
<View style={styles.childHorizontalLine}/>
|
|
140
|
+
<View style={[styles.iconWrap, { backgroundColor: '#FDF2F8' }]}>
|
|
141
|
+
<BoltIcon color="#DB2777" size={11}/>
|
|
142
|
+
</View>
|
|
143
|
+
<View style={{ flex: 1 }}>
|
|
144
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', gap: 6 }}>
|
|
145
|
+
<Text style={styles.childLabel}>Last Action:</Text>
|
|
146
|
+
{lastAction ? (<View style={styles.actionTypeBadge}>
|
|
147
|
+
<Text style={styles.actionTypeText}>{lastAction.type}</Text>
|
|
148
|
+
</View>) : (<Text style={styles.noActionText}>None dispatched</Text>)}
|
|
149
|
+
</View>
|
|
150
|
+
{lastAction && (<Text style={styles.timestampText}>Dispatched: {lastAction.timestamp}</Text>)}
|
|
151
|
+
{lastAction && lastAction.payload !== null && (<View style={{ marginTop: 6 }}>
|
|
152
|
+
<ReduxValueNode name="payload" value={lastAction.payload} level={0} search={search}/>
|
|
153
|
+
</View>)}
|
|
154
|
+
</View>
|
|
155
|
+
</View>
|
|
156
|
+
|
|
157
|
+
{/* Node 2: State Data */}
|
|
158
|
+
<View style={styles.childItem}>
|
|
159
|
+
<View style={[styles.childHorizontalLine, { bottom: '50%' }]}/>
|
|
160
|
+
<View style={[styles.iconWrap, { backgroundColor: '#ECFDF5' }]}>
|
|
161
|
+
<DatabaseIcon color="#059669" size={11}/>
|
|
162
|
+
</View>
|
|
163
|
+
<View style={{ flex: 1 }}>
|
|
164
|
+
<Text style={styles.childLabel}>State Slice Data</Text>
|
|
165
|
+
<View style={{ marginTop: 6 }}>
|
|
166
|
+
<ReduxValueNode name="state" value={sliceData} level={0} search={search}/>
|
|
167
|
+
</View>
|
|
168
|
+
</View>
|
|
169
|
+
</View>
|
|
170
|
+
</View>)}
|
|
171
|
+
</View>);
|
|
172
|
+
})}
|
|
173
|
+
</View>)}
|
|
174
|
+
</View>);
|
|
175
|
+
};
|
|
176
|
+
const reduxValueStyles = StyleSheet.create({
|
|
177
|
+
treeNodeBlock: {
|
|
178
|
+
marginTop: 4,
|
|
179
|
+
},
|
|
180
|
+
treeRow: {
|
|
181
|
+
flexDirection: 'row',
|
|
182
|
+
alignItems: 'center',
|
|
183
|
+
paddingVertical: 3,
|
|
184
|
+
gap: 4,
|
|
185
|
+
position: 'relative',
|
|
186
|
+
},
|
|
187
|
+
treeLeafConnector: {
|
|
188
|
+
position: 'absolute',
|
|
189
|
+
left: -12,
|
|
190
|
+
top: '50%',
|
|
191
|
+
width: 8,
|
|
192
|
+
height: 1,
|
|
193
|
+
borderBottomWidth: 1,
|
|
194
|
+
borderBottomColor: AppColors.dividerColor,
|
|
195
|
+
opacity: 0.5,
|
|
196
|
+
},
|
|
197
|
+
treeChildrenContainer: {
|
|
198
|
+
paddingLeft: 14,
|
|
199
|
+
borderLeftWidth: 1,
|
|
200
|
+
borderLeftColor: AppColors.dividerColor,
|
|
201
|
+
marginLeft: 6,
|
|
202
|
+
},
|
|
203
|
+
chevronWrap: {
|
|
204
|
+
width: 10,
|
|
205
|
+
height: 10,
|
|
206
|
+
alignItems: 'center',
|
|
207
|
+
justifyContent: 'center',
|
|
208
|
+
},
|
|
209
|
+
keyText: {
|
|
210
|
+
fontFamily: AppFonts.interMedium,
|
|
211
|
+
fontSize: 11.5,
|
|
212
|
+
color: AppColors.grayTextStrong,
|
|
213
|
+
},
|
|
214
|
+
colonText: {
|
|
215
|
+
color: AppColors.grayTextWeak,
|
|
216
|
+
},
|
|
217
|
+
valText: {
|
|
218
|
+
fontFamily: AppFonts.interRegular,
|
|
219
|
+
fontSize: 11.5,
|
|
220
|
+
},
|
|
221
|
+
summaryText: {
|
|
222
|
+
fontFamily: AppFonts.interRegular,
|
|
223
|
+
fontSize: 11,
|
|
224
|
+
color: AppColors.grayTextWeak,
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
const styles = StyleSheet.create({
|
|
228
|
+
container: {
|
|
229
|
+
flex: 1,
|
|
230
|
+
},
|
|
231
|
+
storeHeader: {
|
|
232
|
+
flexDirection: 'row',
|
|
233
|
+
alignItems: 'center',
|
|
234
|
+
backgroundColor: AppColors.purple,
|
|
235
|
+
borderRadius: 8,
|
|
236
|
+
paddingVertical: 10,
|
|
237
|
+
paddingHorizontal: 12,
|
|
238
|
+
gap: 8,
|
|
239
|
+
},
|
|
240
|
+
chevronWrap: {
|
|
241
|
+
width: 12,
|
|
242
|
+
height: 12,
|
|
243
|
+
alignItems: 'center',
|
|
244
|
+
justifyContent: 'center',
|
|
245
|
+
},
|
|
246
|
+
storeTitle: {
|
|
247
|
+
fontFamily: AppFonts.interBold,
|
|
248
|
+
fontSize: 14,
|
|
249
|
+
color: '#FFFFFF',
|
|
250
|
+
},
|
|
251
|
+
badge: {
|
|
252
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
253
|
+
paddingHorizontal: 8,
|
|
254
|
+
paddingVertical: 2,
|
|
255
|
+
borderRadius: 12,
|
|
256
|
+
marginLeft: 'auto',
|
|
257
|
+
},
|
|
258
|
+
badgeText: {
|
|
259
|
+
fontFamily: AppFonts.interBold,
|
|
260
|
+
fontSize: 10,
|
|
261
|
+
color: '#FFFFFF',
|
|
262
|
+
},
|
|
263
|
+
storeChildren: {
|
|
264
|
+
paddingLeft: 12,
|
|
265
|
+
marginTop: 4,
|
|
266
|
+
},
|
|
267
|
+
reducerContainer: {
|
|
268
|
+
position: 'relative',
|
|
269
|
+
paddingLeft: 16,
|
|
270
|
+
paddingVertical: 4,
|
|
271
|
+
},
|
|
272
|
+
reducerVerticalLine: {
|
|
273
|
+
position: 'absolute',
|
|
274
|
+
left: 0,
|
|
275
|
+
top: 0,
|
|
276
|
+
bottom: 0,
|
|
277
|
+
width: 1,
|
|
278
|
+
backgroundColor: AppColors.dividerColor,
|
|
279
|
+
},
|
|
280
|
+
reducerHorizontalLine: {
|
|
281
|
+
position: 'absolute',
|
|
282
|
+
left: -16,
|
|
283
|
+
top: '50%',
|
|
284
|
+
width: 16,
|
|
285
|
+
height: 1,
|
|
286
|
+
backgroundColor: AppColors.dividerColor,
|
|
287
|
+
},
|
|
288
|
+
reducerHeader: {
|
|
289
|
+
flexDirection: 'row',
|
|
290
|
+
alignItems: 'center',
|
|
291
|
+
paddingVertical: 6,
|
|
292
|
+
gap: 6,
|
|
293
|
+
},
|
|
294
|
+
iconWrap: {
|
|
295
|
+
width: 18,
|
|
296
|
+
height: 18,
|
|
297
|
+
borderRadius: 4,
|
|
298
|
+
backgroundColor: AppColors.purpleShade50,
|
|
299
|
+
alignItems: 'center',
|
|
300
|
+
justifyContent: 'center',
|
|
301
|
+
},
|
|
302
|
+
reducerText: {
|
|
303
|
+
fontFamily: AppFonts.interBold,
|
|
304
|
+
fontSize: 13,
|
|
305
|
+
color: AppColors.primaryBlack,
|
|
306
|
+
},
|
|
307
|
+
reducerChildren: {
|
|
308
|
+
paddingLeft: 20,
|
|
309
|
+
position: 'relative',
|
|
310
|
+
marginTop: 4,
|
|
311
|
+
gap: 10,
|
|
312
|
+
},
|
|
313
|
+
childrenVerticalLine: {
|
|
314
|
+
position: 'absolute',
|
|
315
|
+
left: 8,
|
|
316
|
+
top: 0,
|
|
317
|
+
bottom: 16,
|
|
318
|
+
width: 1,
|
|
319
|
+
backgroundColor: AppColors.dividerColor,
|
|
320
|
+
},
|
|
321
|
+
childItem: {
|
|
322
|
+
flexDirection: 'row',
|
|
323
|
+
alignItems: 'flex-start',
|
|
324
|
+
gap: 8,
|
|
325
|
+
position: 'relative',
|
|
326
|
+
paddingLeft: 12,
|
|
327
|
+
},
|
|
328
|
+
childHorizontalLine: {
|
|
329
|
+
position: 'absolute',
|
|
330
|
+
left: -12,
|
|
331
|
+
top: 10,
|
|
332
|
+
width: 12,
|
|
333
|
+
height: 1,
|
|
334
|
+
backgroundColor: AppColors.dividerColor,
|
|
335
|
+
},
|
|
336
|
+
childLabel: {
|
|
337
|
+
fontFamily: AppFonts.interBold,
|
|
338
|
+
fontSize: 11.5,
|
|
339
|
+
color: AppColors.grayText,
|
|
340
|
+
marginTop: 2,
|
|
341
|
+
},
|
|
342
|
+
actionTypeBadge: {
|
|
343
|
+
backgroundColor: '#FCE7F3',
|
|
344
|
+
borderColor: '#FBCFE8',
|
|
345
|
+
borderWidth: 1,
|
|
346
|
+
borderRadius: 6,
|
|
347
|
+
paddingHorizontal: 6,
|
|
348
|
+
paddingVertical: 2,
|
|
349
|
+
},
|
|
350
|
+
actionTypeText: {
|
|
351
|
+
fontFamily: AppFonts.interBold,
|
|
352
|
+
fontSize: 10.5,
|
|
353
|
+
color: '#BE185D',
|
|
354
|
+
},
|
|
355
|
+
noActionText: {
|
|
356
|
+
fontFamily: AppFonts.interRegular,
|
|
357
|
+
fontSize: 11,
|
|
358
|
+
color: AppColors.grayTextWeak,
|
|
359
|
+
},
|
|
360
|
+
timestampText: {
|
|
361
|
+
fontFamily: AppFonts.interRegular,
|
|
362
|
+
fontSize: 9.5,
|
|
363
|
+
color: AppColors.grayTextWeak,
|
|
364
|
+
marginTop: 2,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import React, { useRef } from 'react';
|
|
2
|
-
import { Animated, Pressable } from 'react-native';
|
|
2
|
+
import { Animated, Pressable, StyleSheet } from 'react-native';
|
|
3
3
|
const TouchableScale = ({ onPress, style, children, hitSlop, disabled, }) => {
|
|
4
4
|
const scale = useRef(new Animated.Value(1)).current;
|
|
5
|
+
const flattenedStyle = StyleSheet.flatten(style) || {};
|
|
6
|
+
const layoutStyle = {
|
|
7
|
+
flex: flattenedStyle.flex,
|
|
8
|
+
flexDirection: flattenedStyle.flexDirection,
|
|
9
|
+
alignItems: flattenedStyle.alignItems,
|
|
10
|
+
justifyContent: flattenedStyle.justifyContent,
|
|
11
|
+
flexWrap: flattenedStyle.flexWrap,
|
|
12
|
+
alignSelf: flattenedStyle.alignSelf,
|
|
13
|
+
flexGrow: flattenedStyle.flexGrow,
|
|
14
|
+
flexShrink: flattenedStyle.flexShrink,
|
|
15
|
+
gap: flattenedStyle.gap,
|
|
16
|
+
};
|
|
5
17
|
return (<Pressable disabled={disabled} style={style} onPressIn={() => Animated.spring(scale, { toValue: 0.94, useNativeDriver: true }).start()} onPressOut={() => Animated.spring(scale, { toValue: 1, useNativeDriver: true }).start()} onPress={onPress} hitSlop={hitSlop}>
|
|
6
|
-
<Animated.View style={{ transform: [{ scale }] }}>
|
|
18
|
+
<Animated.View style={[{ transform: [{ scale }] }, layoutStyle]}>
|
|
19
|
+
{children}
|
|
20
|
+
</Animated.View>
|
|
7
21
|
</Pressable>);
|
|
8
22
|
};
|
|
9
23
|
export default TouchableScale;
|
|
@@ -7,8 +7,8 @@ import { ChevronIcon } from './NetworkIcons';
|
|
|
7
7
|
// Stylesheet
|
|
8
8
|
import { AppColors } from '../styles/AppColors';
|
|
9
9
|
import styles from '../styles';
|
|
10
|
-
const TreeNode = React.memo(function TreeNode({ data, name, level = 0, search, forceOpen, }) {
|
|
11
|
-
const [localOpen, setLocalOpen] = useState(level < 1);
|
|
10
|
+
const TreeNode = React.memo(function TreeNode({ data, name, level = 0, search, forceOpen, defaultExpandDepth, }) {
|
|
11
|
+
const [localOpen, setLocalOpen] = useState(level < (defaultExpandDepth ?? 1));
|
|
12
12
|
const open = forceOpen !== undefined ? forceOpen : localOpen;
|
|
13
13
|
const isObject = typeof data === 'object' && data !== null;
|
|
14
14
|
const isArray = Array.isArray(data);
|
|
@@ -94,7 +94,7 @@ const TreeNode = React.memo(function TreeNode({ data, name, level = 0, search, f
|
|
|
94
94
|
</Pressable>
|
|
95
95
|
|
|
96
96
|
{open &&
|
|
97
|
-
entries.map(([k, v]) => (<TreeNode key={String(k)} name={k} data={v} level={level + 1} search={search} forceOpen={forceOpen}/>))}
|
|
97
|
+
entries.map(([k, v]) => (<TreeNode key={String(k)} name={k} data={v} level={level + 1} search={search} forceOpen={forceOpen} defaultExpandDepth={defaultExpandDepth}/>))}
|
|
98
98
|
|
|
99
99
|
{open && <Text style={styles.codeSyntax}>{isArray ? ']' : '}'}</Text>}
|
|
100
100
|
</View>);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export declare const getReduxState: () => any;
|
|
2
|
+
export declare const setReduxAutoRefresh: (val: boolean) => void;
|
|
3
|
+
export declare const getReduxAutoRefresh: () => boolean;
|
|
4
|
+
export declare const getLastActionForReducer: () => Record<string, any>;
|
|
5
|
+
export declare const clearLastActionForReducer: () => void;
|
|
2
6
|
export declare const setReduxState: (state: any) => void;
|
|
3
7
|
export declare const subscribeReduxState: (cb: () => void) => () => void;
|
|
4
8
|
export declare const connectReduxStore: (store: any) => void;
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
let currentReduxState = null;
|
|
2
2
|
const listeners = new Set();
|
|
3
|
+
let globalReduxAutoRefresh = true;
|
|
4
|
+
let lastActionForReducer = {};
|
|
3
5
|
export const getReduxState = () => currentReduxState;
|
|
6
|
+
export const setReduxAutoRefresh = (val) => {
|
|
7
|
+
globalReduxAutoRefresh = val;
|
|
8
|
+
};
|
|
9
|
+
export const getReduxAutoRefresh = () => globalReduxAutoRefresh;
|
|
10
|
+
export const getLastActionForReducer = () => lastActionForReducer;
|
|
11
|
+
export const clearLastActionForReducer = () => {
|
|
12
|
+
lastActionForReducer = {};
|
|
13
|
+
listeners.forEach(cb => cb());
|
|
14
|
+
};
|
|
4
15
|
export const setReduxState = (state) => {
|
|
5
16
|
currentReduxState = state;
|
|
6
17
|
listeners.forEach(cb => cb());
|
|
@@ -16,8 +27,39 @@ export const connectReduxStore = (store) => {
|
|
|
16
27
|
console.warn('[NetworkInspector] Invalid Redux store passed to connectReduxStore.');
|
|
17
28
|
return;
|
|
18
29
|
}
|
|
30
|
+
// Intercept dispatch calls to log actions and tie them to modified state slices
|
|
31
|
+
const originalDispatch = store.dispatch.bind(store);
|
|
32
|
+
store.dispatch = (action) => {
|
|
33
|
+
const prevState = store.getState();
|
|
34
|
+
const result = originalDispatch(action);
|
|
35
|
+
const nextState = store.getState();
|
|
36
|
+
// Map the dispatched action to state slices that actually changed
|
|
37
|
+
if (prevState &&
|
|
38
|
+
nextState &&
|
|
39
|
+
typeof prevState === 'object' &&
|
|
40
|
+
typeof nextState === 'object' &&
|
|
41
|
+
action &&
|
|
42
|
+
typeof action === 'object') {
|
|
43
|
+
Object.keys(nextState).forEach(key => {
|
|
44
|
+
if (prevState[key] !== nextState[key]) {
|
|
45
|
+
lastActionForReducer[key] = {
|
|
46
|
+
type: action.type || 'UNKNOWN_ACTION',
|
|
47
|
+
payload: action.payload !== undefined ? action.payload : null,
|
|
48
|
+
timestamp: new Date().toLocaleTimeString(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (globalReduxAutoRefresh) {
|
|
54
|
+
setReduxState(nextState);
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
19
58
|
setReduxState(store.getState());
|
|
59
|
+
// Listen to subscription for devtools updates or any other state changes
|
|
20
60
|
store.subscribe(() => {
|
|
21
|
-
|
|
61
|
+
if (globalReduxAutoRefresh) {
|
|
62
|
+
setReduxState(store.getState());
|
|
63
|
+
}
|
|
22
64
|
});
|
|
23
65
|
};
|