react-native-inapp-inspector 1.1.32 → 1.1.34
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/dist/commonjs/components/Inspector/BundleTab.js +282 -39
- package/dist/commonjs/components/Inspector/ReduxDetail.js +574 -75
- package/dist/commonjs/components/Inspector/ReduxTab.js +59 -180
- package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
- package/dist/commonjs/components/NetworkIcons.js +14 -1
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +5 -2
- package/dist/commonjs/customHooks/bundleAnalyzer.js +229 -216
- package/dist/commonjs/customHooks/consoleLogger.js +7 -2
- package/dist/commonjs/helpers/index.js +19 -2
- package/dist/esm/components/Inspector/BundleTab.js +283 -40
- package/dist/esm/components/Inspector/ReduxDetail.js +575 -76
- package/dist/esm/components/Inspector/ReduxTab.js +60 -181
- package/dist/esm/components/NetworkIcons.d.ts +2 -0
- package/dist/esm/components/NetworkIcons.js +11 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/bundleAnalyzer.d.ts +5 -2
- package/dist/esm/customHooks/bundleAnalyzer.js +227 -215
- package/dist/esm/customHooks/consoleLogger.js +7 -2
- package/dist/esm/helpers/index.js +19 -2
- package/package.json +1 -1
|
@@ -14,13 +14,13 @@ import { getSize, openInVSCode, parseStackLine } from '../../helpers';
|
|
|
14
14
|
import { getCustomStorage } from '../../helpers/settingsStore';
|
|
15
15
|
import { AppColors } from '../../styles/AppColors';
|
|
16
16
|
import { AppFonts } from '../../styles/AppFonts';
|
|
17
|
-
import { SearchIcon, ClearIcon, ClockIcon, LayersIcon, TrashIcon, ForwardChevronIcon, LiveStateIcon, TimelineIcon, StorageIcon, MetadataIcon, BoltIcon, ExternalLinkIcon, } from '../NetworkIcons';
|
|
17
|
+
import { TerminalIcon, SearchIcon, ClearIcon, ClockIcon, LayersIcon, TrashIcon, ForwardChevronIcon, LiveStateIcon, TimelineIcon, StorageIcon, MetadataIcon, BoltIcon, AtomIcon, ScreenIcon, ListenerIcon, DocIcon, ExternalLinkIcon, CodeBracketsIcon, } from '../NetworkIcons';
|
|
18
18
|
const getOriginBadge = (originType) => {
|
|
19
19
|
switch (originType) {
|
|
20
20
|
case 'saga':
|
|
21
21
|
return {
|
|
22
22
|
label: 'SAGA',
|
|
23
|
-
|
|
23
|
+
renderIcon: (color, size = 9) => (<BoltIcon color={color} size={size}/>),
|
|
24
24
|
bg: AppColors.purple100,
|
|
25
25
|
text: AppColors.brandPurple,
|
|
26
26
|
border: AppColors.purple200,
|
|
@@ -28,7 +28,7 @@ const getOriginBadge = (originType) => {
|
|
|
28
28
|
case 'thunk':
|
|
29
29
|
return {
|
|
30
30
|
label: 'THUNK',
|
|
31
|
-
|
|
31
|
+
renderIcon: (color, size = 9) => (<AtomIcon color={color} size={size}/>),
|
|
32
32
|
bg: AppColors.amber100,
|
|
33
33
|
text: AppColors.amber800Warm,
|
|
34
34
|
border: AppColors.amber200,
|
|
@@ -36,7 +36,7 @@ const getOriginBadge = (originType) => {
|
|
|
36
36
|
case 'ui':
|
|
37
37
|
return {
|
|
38
38
|
label: 'UI',
|
|
39
|
-
|
|
39
|
+
renderIcon: (color, size = 9) => (<ScreenIcon color={color} size={size}/>),
|
|
40
40
|
bg: AppColors.sky100,
|
|
41
41
|
text: AppColors.sky600,
|
|
42
42
|
border: AppColors.sky400,
|
|
@@ -44,7 +44,7 @@ const getOriginBadge = (originType) => {
|
|
|
44
44
|
case 'listener':
|
|
45
45
|
return {
|
|
46
46
|
label: 'LISTENER',
|
|
47
|
-
|
|
47
|
+
renderIcon: (color, size = 9) => (<ListenerIcon color={color} size={size}/>),
|
|
48
48
|
bg: AppColors.teal100,
|
|
49
49
|
text: AppColors.teal700,
|
|
50
50
|
border: AppColors.teal400,
|
|
@@ -52,7 +52,7 @@ const getOriginBadge = (originType) => {
|
|
|
52
52
|
default:
|
|
53
53
|
return {
|
|
54
54
|
label: 'DIRECT',
|
|
55
|
-
|
|
55
|
+
renderIcon: (color, size = 9) => (<BoltIcon color={color} size={size}/>),
|
|
56
56
|
bg: AppColors.slate100,
|
|
57
57
|
text: AppColors.slate700,
|
|
58
58
|
border: AppColors.slate200,
|
|
@@ -61,11 +61,12 @@ const getOriginBadge = (originType) => {
|
|
|
61
61
|
};
|
|
62
62
|
const ReduxDetail = React.memo(() => {
|
|
63
63
|
const { t } = useTranslation();
|
|
64
|
-
const { reduxState, reduxLastActionMap, selectedReduxSlice, selectedReduxAction, setSelectedReduxSlice,
|
|
64
|
+
const { reduxState, reduxLastActionMap, selectedReduxSlice, selectedReduxAction, setSelectedReduxSlice, } = useInspector();
|
|
65
65
|
// Search filter within details
|
|
66
66
|
const [detailSearch, setDetailSearch] = useState('');
|
|
67
|
-
// Sub-tabs for Slice
|
|
67
|
+
// Sub-tabs for Slice & Action
|
|
68
68
|
const [sliceTab, setSliceTab] = useState('live');
|
|
69
|
+
const [actionTab, setActionTab] = useState('payload');
|
|
69
70
|
const [viewMode, setViewMode] = useState('pretty');
|
|
70
71
|
// Selected Action inside Timeline
|
|
71
72
|
const [expandedActionId, setExpandedActionId] = useState(null);
|
|
@@ -86,6 +87,18 @@ const ReduxDetail = React.memo(() => {
|
|
|
86
87
|
return action.affectedSlices.includes(selectedReduxSlice);
|
|
87
88
|
});
|
|
88
89
|
}, [allActionHistory, selectedReduxSlice]);
|
|
90
|
+
// Filtered slice actions by search query in timeline tab
|
|
91
|
+
const filteredTimelineActions = useMemo(() => {
|
|
92
|
+
if (!detailSearch.trim())
|
|
93
|
+
return sliceActions;
|
|
94
|
+
const q = detailSearch.toLowerCase();
|
|
95
|
+
return sliceActions.filter(action => {
|
|
96
|
+
return (action.type.toLowerCase().includes(q) ||
|
|
97
|
+
(action.callerFile && action.callerFile.toLowerCase().includes(q)) ||
|
|
98
|
+
(action.payload &&
|
|
99
|
+
JSON.stringify(action.payload).toLowerCase().includes(q)));
|
|
100
|
+
});
|
|
101
|
+
}, [sliceActions, detailSearch]);
|
|
89
102
|
useEffect(() => {
|
|
90
103
|
if (!selectedReduxSlice)
|
|
91
104
|
return;
|
|
@@ -182,22 +195,24 @@ const ReduxDetail = React.memo(() => {
|
|
|
182
195
|
const sliceTabs = [
|
|
183
196
|
{
|
|
184
197
|
key: 'live',
|
|
185
|
-
label: t('redux.liveState'),
|
|
198
|
+
label: t('redux.liveState', 'Live State'),
|
|
186
199
|
icon: (isActive) => (<LiveStateIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
187
200
|
},
|
|
188
201
|
{
|
|
189
202
|
key: 'timeline',
|
|
190
|
-
label: `${t('redux.timeline')} (${sliceActions.length})`,
|
|
203
|
+
label: `${t('redux.timeline', 'Timeline')} (${sliceActions.length})`,
|
|
191
204
|
icon: (isActive) => (<TimelineIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
192
205
|
},
|
|
193
206
|
{
|
|
194
207
|
key: 'persisted',
|
|
195
|
-
label: isPersisted
|
|
208
|
+
label: isPersisted
|
|
209
|
+
? t('redux.persisted', 'Persisted')
|
|
210
|
+
: t('redux.storage', 'Storage'),
|
|
196
211
|
icon: (isActive) => (<StorageIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
197
212
|
},
|
|
198
213
|
{
|
|
199
214
|
key: 'metadata',
|
|
200
|
-
label: t('redux.metadata'),
|
|
215
|
+
label: t('redux.metadata', 'Metadata'),
|
|
201
216
|
icon: (isActive) => (<MetadataIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
202
217
|
},
|
|
203
218
|
];
|
|
@@ -205,18 +220,34 @@ const ReduxDetail = React.memo(() => {
|
|
|
205
220
|
{/* Info Header Bar */}
|
|
206
221
|
<View style={reduxDetailStyles.infoBar}>
|
|
207
222
|
<View style={reduxDetailStyles.infoTopRow}>
|
|
208
|
-
<View style={{
|
|
209
|
-
|
|
210
|
-
|
|
223
|
+
<View style={{
|
|
224
|
+
flexDirection: 'row',
|
|
225
|
+
alignItems: 'center',
|
|
226
|
+
gap: 6,
|
|
227
|
+
flexWrap: 'wrap',
|
|
228
|
+
flex: 1,
|
|
229
|
+
minWidth: 0,
|
|
230
|
+
}}>
|
|
231
|
+
<View style={[
|
|
232
|
+
reduxDetailStyles.methodBadge,
|
|
233
|
+
{ backgroundColor: AppColors.indigo600Alt },
|
|
234
|
+
]}>
|
|
235
|
+
<Text style={reduxDetailStyles.methodBadgeText}>
|
|
236
|
+
{t('redux.slice', 'SLICE')}
|
|
237
|
+
</Text>
|
|
211
238
|
</View>
|
|
212
|
-
<Text style={reduxDetailStyles.sliceNameText}>
|
|
239
|
+
<Text style={reduxDetailStyles.sliceNameText} numberOfLines={1}>
|
|
213
240
|
{selectedReduxSlice}
|
|
214
241
|
</Text>
|
|
215
242
|
{isPersisted ? (<View style={reduxDetailStyles.persistedChip}>
|
|
216
243
|
<StorageIcon color={AppColors.emerald700} size={10}/>
|
|
217
|
-
<Text style={reduxDetailStyles.persistedChipText}>
|
|
244
|
+
<Text style={reduxDetailStyles.persistedChipText}>
|
|
245
|
+
{t('redux.persisted', 'Persisted').toUpperCase()}
|
|
246
|
+
</Text>
|
|
218
247
|
</View>) : (<View style={reduxDetailStyles.inMemoryChip}>
|
|
219
|
-
<Text style={reduxDetailStyles.inMemoryChipText}>
|
|
248
|
+
<Text style={reduxDetailStyles.inMemoryChipText}>
|
|
249
|
+
{t('redux.inMemory', 'In-Memory').toUpperCase()}
|
|
250
|
+
</Text>
|
|
220
251
|
</View>)}
|
|
221
252
|
{lastAction?.timestamp && (<View style={reduxDetailStyles.timePill}>
|
|
222
253
|
<ClockIcon color={AppColors.violet600} size={10}/>
|
|
@@ -227,29 +258,93 @@ const ReduxDetail = React.memo(() => {
|
|
|
227
258
|
</View>
|
|
228
259
|
|
|
229
260
|
{/* Copy Button */}
|
|
230
|
-
<CopyButton value={() => (sliceTab === 'live' ? sliceData : persistedData)} label={t('redux.sliceJson')}/>
|
|
261
|
+
<CopyButton value={() => (sliceTab === 'live' ? sliceData : persistedData)} label={t('redux.sliceJson', 'Slice JSON')}/>
|
|
231
262
|
</View>
|
|
232
263
|
|
|
233
264
|
{/* Sub Stats Row */}
|
|
234
265
|
<View style={reduxDetailStyles.subStatsRow}>
|
|
235
|
-
<View style={[
|
|
266
|
+
<View style={[
|
|
267
|
+
reduxDetailStyles.statPill,
|
|
268
|
+
{
|
|
269
|
+
backgroundColor: AppColors.indigo50,
|
|
270
|
+
borderColor: AppColors.indigo400,
|
|
271
|
+
},
|
|
272
|
+
]}>
|
|
236
273
|
<LayersIcon color={AppColors.indigo600Alt} size={11}/>
|
|
237
|
-
<Text style={[
|
|
238
|
-
|
|
274
|
+
<Text style={[
|
|
275
|
+
reduxDetailStyles.statLabel,
|
|
276
|
+
{ color: AppColors.indigo600Alt },
|
|
277
|
+
]}>
|
|
278
|
+
{t('redux.keys', 'Keys')}:
|
|
279
|
+
</Text>
|
|
280
|
+
<Text style={[
|
|
281
|
+
reduxDetailStyles.statValue,
|
|
282
|
+
{ color: AppColors.indigo600Alt },
|
|
283
|
+
]}>
|
|
284
|
+
{fieldsCount}
|
|
285
|
+
</Text>
|
|
239
286
|
</View>
|
|
240
|
-
<View style={[
|
|
241
|
-
|
|
242
|
-
|
|
287
|
+
<View style={[
|
|
288
|
+
reduxDetailStyles.statPill,
|
|
289
|
+
{
|
|
290
|
+
backgroundColor: AppColors.sky100,
|
|
291
|
+
borderColor: AppColors.sky400,
|
|
292
|
+
},
|
|
293
|
+
]}>
|
|
294
|
+
<Text style={[
|
|
295
|
+
reduxDetailStyles.statLabel,
|
|
296
|
+
{ color: AppColors.sky600 },
|
|
297
|
+
]}>
|
|
298
|
+
{t('redux.size', 'Size')}:
|
|
299
|
+
</Text>
|
|
300
|
+
<Text style={[
|
|
301
|
+
reduxDetailStyles.statValue,
|
|
302
|
+
{ color: AppColors.sky600 },
|
|
303
|
+
]}>
|
|
304
|
+
{getSize(sliceData)}
|
|
305
|
+
</Text>
|
|
243
306
|
</View>
|
|
244
|
-
<View style={[
|
|
307
|
+
<View style={[
|
|
308
|
+
reduxDetailStyles.statPill,
|
|
309
|
+
{
|
|
310
|
+
backgroundColor: AppColors.purple100,
|
|
311
|
+
borderColor: AppColors.purple200,
|
|
312
|
+
},
|
|
313
|
+
]}>
|
|
245
314
|
<TimelineIcon color={AppColors.violet600} size={11}/>
|
|
246
|
-
<Text style={[
|
|
247
|
-
|
|
315
|
+
<Text style={[
|
|
316
|
+
reduxDetailStyles.statLabel,
|
|
317
|
+
{ color: AppColors.brandPurple },
|
|
318
|
+
]}>
|
|
319
|
+
{t('redux.timeline', 'Timeline')}:
|
|
320
|
+
</Text>
|
|
321
|
+
<Text style={[
|
|
322
|
+
reduxDetailStyles.statValue,
|
|
323
|
+
{ color: AppColors.brandPurple },
|
|
324
|
+
]}>
|
|
325
|
+
{sliceActions.length}
|
|
326
|
+
</Text>
|
|
248
327
|
</View>
|
|
249
|
-
{lastAction && (<View style={[
|
|
328
|
+
{lastAction && (<View style={[
|
|
329
|
+
reduxDetailStyles.statPill,
|
|
330
|
+
{
|
|
331
|
+
backgroundColor: AppColors.amber100,
|
|
332
|
+
borderColor: AppColors.amber200,
|
|
333
|
+
flexShrink: 1,
|
|
334
|
+
maxWidth: 160,
|
|
335
|
+
},
|
|
336
|
+
]}>
|
|
250
337
|
<BoltIcon color={AppColors.amber800Warm} size={11}/>
|
|
251
|
-
<Text style={[
|
|
252
|
-
|
|
338
|
+
<Text style={[
|
|
339
|
+
reduxDetailStyles.statLabel,
|
|
340
|
+
{ color: AppColors.amber800Warm },
|
|
341
|
+
]}>
|
|
342
|
+
{t('redux.last', 'Last')}:
|
|
343
|
+
</Text>
|
|
344
|
+
<Text style={[
|
|
345
|
+
reduxDetailStyles.statValue,
|
|
346
|
+
{ color: AppColors.amber800Warm, flexShrink: 1 },
|
|
347
|
+
]} numberOfLines={1}>
|
|
253
348
|
{lastAction.type}
|
|
254
349
|
</Text>
|
|
255
350
|
</View>)}
|
|
@@ -259,10 +354,12 @@ const ReduxDetail = React.memo(() => {
|
|
|
259
354
|
<SegmentedTabs tabs={sliceTabs} activeKey={sliceTab} onChange={key => setSliceTab(key)} style={{ marginTop: 10 }}/>
|
|
260
355
|
</View>
|
|
261
356
|
|
|
262
|
-
{/* Search Bar within slice */}
|
|
357
|
+
{/* Search Bar within slice (for Live, Timeline, Persisted) */}
|
|
263
358
|
{sliceTab !== 'metadata' && (<View style={reduxDetailStyles.searchContainer}>
|
|
264
359
|
<SearchIcon color={AppColors.grayTextWeak} size={14}/>
|
|
265
|
-
<TextInput placeholder=
|
|
360
|
+
<TextInput placeholder={sliceTab === 'timeline'
|
|
361
|
+
? 'Search action type, file, or payload...'
|
|
362
|
+
: 'Search keys or values...'} placeholderTextColor={AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={reduxDetailStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
266
363
|
{detailSearch.length > 0 && (<Pressable onPress={() => setDetailSearch('')} hitSlop={10}>
|
|
267
364
|
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
268
365
|
</Pressable>)}
|
|
@@ -270,11 +367,14 @@ const ReduxDetail = React.memo(() => {
|
|
|
270
367
|
|
|
271
368
|
{/* Content Body */}
|
|
272
369
|
{sliceTab === 'timeline' ? (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 12, paddingBottom: 40 }} keyboardShouldPersistTaps="handled">
|
|
273
|
-
{
|
|
370
|
+
{filteredTimelineActions.length === 0 ? (<View style={reduxDetailStyles.emptyBox}>
|
|
371
|
+
<TimelineIcon color={AppColors.grayTextWeak} size={28}/>
|
|
274
372
|
<Text style={reduxDetailStyles.emptyBoxText}>
|
|
275
|
-
|
|
373
|
+
{detailSearch.trim()
|
|
374
|
+
? 'No actions matching your search query.'
|
|
375
|
+
: 'No dispatched actions recorded for this slice yet.'}
|
|
276
376
|
</Text>
|
|
277
|
-
</View>) : (
|
|
377
|
+
</View>) : (filteredTimelineActions.map((action, aIdx) => {
|
|
278
378
|
const isExpanded = expandedActionId === action.id;
|
|
279
379
|
const originMeta = getOriginBadge(action.originType);
|
|
280
380
|
const callerBasename = action.callerFile
|
|
@@ -283,7 +383,14 @@ const ReduxDetail = React.memo(() => {
|
|
|
283
383
|
return (<AnimatedEntrance key={action.id} index={aIdx} distance={6}>
|
|
284
384
|
<TouchableScale onPress={() => setExpandedActionId(isExpanded ? null : action.id)} style={reduxDetailStyles.timelineCard}>
|
|
285
385
|
<View style={reduxDetailStyles.timelineHeader}>
|
|
286
|
-
<View style={{
|
|
386
|
+
<View style={{
|
|
387
|
+
flexDirection: 'row',
|
|
388
|
+
alignItems: 'center',
|
|
389
|
+
gap: 6,
|
|
390
|
+
flex: 1,
|
|
391
|
+
minWidth: 0,
|
|
392
|
+
flexWrap: 'wrap',
|
|
393
|
+
}}>
|
|
287
394
|
<View style={reduxDetailStyles.actionBadge}>
|
|
288
395
|
<Text style={reduxDetailStyles.actionBadgeText}>
|
|
289
396
|
#{action.id}
|
|
@@ -295,13 +402,13 @@ const ReduxDetail = React.memo(() => {
|
|
|
295
402
|
alignItems: 'center',
|
|
296
403
|
gap: 3,
|
|
297
404
|
backgroundColor: originMeta.bg,
|
|
298
|
-
paddingHorizontal:
|
|
405
|
+
paddingHorizontal: 5,
|
|
299
406
|
paddingVertical: 2,
|
|
300
407
|
borderRadius: 4,
|
|
301
408
|
borderWidth: 1,
|
|
302
409
|
borderColor: originMeta.border,
|
|
303
410
|
}}>
|
|
304
|
-
|
|
411
|
+
{originMeta.renderIcon(originMeta.text, 8.5)}
|
|
305
412
|
<Text style={{
|
|
306
413
|
fontFamily: AppFonts.interBold,
|
|
307
414
|
fontSize: 8.5,
|
|
@@ -328,18 +435,29 @@ const ReduxDetail = React.memo(() => {
|
|
|
328
435
|
flexDirection: 'row',
|
|
329
436
|
alignItems: 'center',
|
|
330
437
|
justifyContent: 'space-between',
|
|
331
|
-
marginTop:
|
|
438
|
+
marginTop: 6,
|
|
332
439
|
marginBottom: 2,
|
|
333
|
-
paddingHorizontal:
|
|
334
|
-
paddingVertical:
|
|
440
|
+
paddingHorizontal: 8,
|
|
441
|
+
paddingVertical: 4,
|
|
335
442
|
backgroundColor: AppColors.grayBackground,
|
|
336
|
-
borderRadius:
|
|
443
|
+
borderRadius: 6,
|
|
337
444
|
borderWidth: 1,
|
|
338
445
|
borderColor: AppColors.dividerColor,
|
|
339
446
|
}}>
|
|
340
|
-
<View style={{
|
|
341
|
-
|
|
342
|
-
|
|
447
|
+
<View style={{
|
|
448
|
+
flexDirection: 'row',
|
|
449
|
+
alignItems: 'center',
|
|
450
|
+
gap: 5,
|
|
451
|
+
flex: 1,
|
|
452
|
+
minWidth: 0,
|
|
453
|
+
}}>
|
|
454
|
+
<DocIcon color={AppColors.sky600} size={10}/>
|
|
455
|
+
<Text style={{
|
|
456
|
+
fontFamily: AppFonts.interMedium,
|
|
457
|
+
fontSize: 9.5,
|
|
458
|
+
color: AppColors.grayTextWeak,
|
|
459
|
+
}}>
|
|
460
|
+
{t('redux.triggeredFrom', 'Triggered From:')}
|
|
343
461
|
</Text>
|
|
344
462
|
<Text style={{
|
|
345
463
|
fontFamily: AppFonts.interBold,
|
|
@@ -356,12 +474,16 @@ const ReduxDetail = React.memo(() => {
|
|
|
356
474
|
gap: 3,
|
|
357
475
|
backgroundColor: AppColors.sky100,
|
|
358
476
|
paddingHorizontal: 5,
|
|
359
|
-
paddingVertical:
|
|
360
|
-
borderRadius:
|
|
477
|
+
paddingVertical: 2,
|
|
478
|
+
borderRadius: 4,
|
|
361
479
|
}}>
|
|
362
480
|
<ExternalLinkIcon color={AppColors.sky600} size={9}/>
|
|
363
|
-
<Text style={{
|
|
364
|
-
|
|
481
|
+
<Text style={{
|
|
482
|
+
fontFamily: AppFonts.interBold,
|
|
483
|
+
fontSize: 8.5,
|
|
484
|
+
color: AppColors.sky600,
|
|
485
|
+
}}>
|
|
486
|
+
{t('redux.openInEditor', 'Open in Editor')}
|
|
365
487
|
</Text>
|
|
366
488
|
</Pressable>
|
|
367
489
|
</View>)}
|
|
@@ -369,9 +491,9 @@ const ReduxDetail = React.memo(() => {
|
|
|
369
491
|
{/* Expanded Payload, Diff Viewer & Call Stack */}
|
|
370
492
|
{isExpanded ? (<View style={reduxDetailStyles.expandedContent}>
|
|
371
493
|
{/* Call Stack Trace Box */}
|
|
372
|
-
{action.stack ? (<View style={{ marginBottom:
|
|
494
|
+
{action.stack ? (<View style={{ marginBottom: 12 }}>
|
|
373
495
|
<Text style={reduxDetailStyles.expandedSectionTitle}>
|
|
374
|
-
{t('redux.callStack')}:
|
|
496
|
+
{t('redux.callStack', 'Call Stack Trace')}:
|
|
375
497
|
</Text>
|
|
376
498
|
<View style={{
|
|
377
499
|
backgroundColor: AppColors.grayBackground,
|
|
@@ -384,37 +506,48 @@ const ReduxDetail = React.memo(() => {
|
|
|
384
506
|
{action.stack
|
|
385
507
|
.split('\n')
|
|
386
508
|
.map(l => l.trim())
|
|
387
|
-
.filter(l => l.length > 0 &&
|
|
509
|
+
.filter(l => l.length > 0 &&
|
|
510
|
+
!l.includes('reduxLogger') &&
|
|
511
|
+
!l.includes('inspectorReduxMiddleware'))
|
|
388
512
|
.slice(0, 8)
|
|
389
513
|
.map((frameLine, fIdx) => {
|
|
390
514
|
const parsed = parseStackLine(frameLine, fIdx === 0);
|
|
391
515
|
const isApp = parsed.frameType === 'app';
|
|
392
516
|
return (<Pressable key={fIdx} onPress={() => {
|
|
393
517
|
if (parsed.fileName !== 'Unknown') {
|
|
394
|
-
openInVSCode(parsed.fullPath ||
|
|
518
|
+
openInVSCode(parsed.fullPath ||
|
|
519
|
+
parsed.fileName, parsed.lineNumber, parsed.columnNumber);
|
|
395
520
|
}
|
|
396
521
|
}} style={{
|
|
397
522
|
flexDirection: 'row',
|
|
398
523
|
alignItems: 'center',
|
|
399
524
|
justifyContent: 'space-between',
|
|
400
|
-
paddingVertical:
|
|
525
|
+
paddingVertical: 3,
|
|
401
526
|
borderBottomWidth: fIdx < 7 ? 0.5 : 0,
|
|
402
527
|
borderBottomColor: AppColors.dividerColor,
|
|
403
528
|
}}>
|
|
404
529
|
<View style={{ flex: 1, minWidth: 0 }}>
|
|
405
530
|
<Text style={{
|
|
406
|
-
fontFamily: isApp
|
|
531
|
+
fontFamily: isApp
|
|
532
|
+
? AppFonts.interBold
|
|
533
|
+
: AppFonts.interRegular,
|
|
407
534
|
fontSize: 9.5,
|
|
408
|
-
color: isApp
|
|
535
|
+
color: isApp
|
|
536
|
+
? AppColors.primaryBlack
|
|
537
|
+
: AppColors.grayTextWeak,
|
|
409
538
|
}} numberOfLines={1}>
|
|
410
539
|
{parsed.functionName || 'anonymous'}
|
|
411
540
|
</Text>
|
|
412
541
|
<Text style={{
|
|
413
542
|
fontFamily: AppFonts.interRegular,
|
|
414
543
|
fontSize: 8.5,
|
|
415
|
-
color: isApp
|
|
544
|
+
color: isApp
|
|
545
|
+
? AppColors.sky600
|
|
546
|
+
: AppColors.grayTextWeak,
|
|
416
547
|
}} numberOfLines={1}>
|
|
417
|
-
{parsed.fileName}:
|
|
548
|
+
{parsed.fileName}:
|
|
549
|
+
{parsed.lineNumber || 1}:
|
|
550
|
+
{parsed.columnNumber || 1}
|
|
418
551
|
</Text>
|
|
419
552
|
</View>
|
|
420
553
|
{isApp && (<ExternalLinkIcon color={AppColors.sky600} size={10}/>)}
|
|
@@ -423,20 +556,20 @@ const ReduxDetail = React.memo(() => {
|
|
|
423
556
|
</View>
|
|
424
557
|
</View>) : null}
|
|
425
558
|
|
|
426
|
-
{action.payload !== undefined && (<View style={{ marginBottom:
|
|
559
|
+
{action.payload !== undefined && (<View style={{ marginBottom: 12 }}>
|
|
427
560
|
<Text style={reduxDetailStyles.expandedSectionTitle}>
|
|
428
|
-
{t('redux.actionPayload')}
|
|
561
|
+
{t('redux.actionPayload', 'Action Payload:')}
|
|
429
562
|
</Text>
|
|
430
|
-
<JsonViewer data={action.payload} search={detailSearch} forceOpen={true}/>
|
|
563
|
+
<JsonViewer data={action.payload} search={detailSearch} forceOpen={true} wrap={true}/>
|
|
431
564
|
</View>)}
|
|
432
565
|
|
|
433
566
|
<Text style={reduxDetailStyles.expandedSectionTitle}>
|
|
434
|
-
{t('redux.stateChangesDiff')}
|
|
567
|
+
{t('redux.stateChangesDiff', 'State Changes (Diff):')}
|
|
435
568
|
</Text>
|
|
436
569
|
<DiffViewer oldData={action.prevState?.[selectedReduxSlice] || {}} newData={action.nextState?.[selectedReduxSlice] || {}} forceOpen={true}/>
|
|
437
570
|
</View>) : (<View style={reduxDetailStyles.collapsedPrompt}>
|
|
438
571
|
<Text style={reduxDetailStyles.collapsedPromptText}>
|
|
439
|
-
{t('redux.tapToInspectAction')}
|
|
572
|
+
{t('redux.tapToInspectAction', 'Tap to inspect action payload & diff changes')}
|
|
440
573
|
</Text>
|
|
441
574
|
<ForwardChevronIcon color={AppColors.grayTextWeak} size={12}/>
|
|
442
575
|
</View>)}
|
|
@@ -451,7 +584,9 @@ const ReduxDetail = React.memo(() => {
|
|
|
451
584
|
{ label: 'In-Memory State Size', value: getSize(sliceData) },
|
|
452
585
|
{
|
|
453
586
|
label: 'Persistence Status',
|
|
454
|
-
value: isPersisted
|
|
587
|
+
value: isPersisted
|
|
588
|
+
? `Persisted (${getSize(persistedData)})`
|
|
589
|
+
: 'Not Persisted (In-Memory)',
|
|
455
590
|
},
|
|
456
591
|
{
|
|
457
592
|
label: 'Dispatched Actions History',
|
|
@@ -482,12 +617,330 @@ const ReduxDetail = React.memo(() => {
|
|
|
482
617
|
</Text>
|
|
483
618
|
</TouchableOpacity>)}
|
|
484
619
|
</View>
|
|
485
|
-
</ScrollView>) : (<
|
|
486
|
-
|
|
487
|
-
|
|
620
|
+
</ScrollView>) : sliceTab === 'persisted' ? (<View style={{ flex: 1, padding: 10 }}>
|
|
621
|
+
{isPersisted ? (<View style={{ flex: 1 }}>
|
|
622
|
+
<View style={reduxDetailStyles.persistedInfoCard}>
|
|
623
|
+
<View style={{
|
|
624
|
+
flexDirection: 'row',
|
|
625
|
+
alignItems: 'center',
|
|
626
|
+
justifyContent: 'space-between',
|
|
627
|
+
}}>
|
|
628
|
+
<View style={{
|
|
629
|
+
flexDirection: 'row',
|
|
630
|
+
alignItems: 'center',
|
|
631
|
+
gap: 6,
|
|
632
|
+
}}>
|
|
633
|
+
<StorageIcon color={AppColors.emerald700} size={14}/>
|
|
634
|
+
<Text style={reduxDetailStyles.persistedInfoTitle}>
|
|
635
|
+
Stored in persistent storage ({getSize(persistedData)})
|
|
636
|
+
</Text>
|
|
637
|
+
</View>
|
|
638
|
+
<TouchableOpacity style={reduxDetailStyles.clearPersistMiniBtn} onPress={handleClearPersistence}>
|
|
639
|
+
<TrashIcon color={AppColors.errorColor} size={12}/>
|
|
640
|
+
<Text style={reduxDetailStyles.clearPersistMiniText}>
|
|
641
|
+
Clear
|
|
642
|
+
</Text>
|
|
643
|
+
</TouchableOpacity>
|
|
644
|
+
</View>
|
|
645
|
+
</View>
|
|
646
|
+
<View style={{ flex: 1, marginTop: 8 }}>
|
|
647
|
+
<JsonViewer data={persistedData} search={detailSearch} forceOpen={detailSearch.length > 0 ? true : undefined} mode={viewMode} onModeChange={setViewMode} fullHeight={true} wrap={true}/>
|
|
648
|
+
</View>
|
|
649
|
+
</View>) : (<View style={reduxDetailStyles.emptyBox}>
|
|
650
|
+
<StorageIcon color={AppColors.grayTextWeak} size={32}/>
|
|
651
|
+
<Text style={reduxDetailStyles.emptyBoxTitle}>
|
|
652
|
+
Not Persisted in Storage
|
|
653
|
+
</Text>
|
|
654
|
+
<Text style={reduxDetailStyles.emptyBoxText}>
|
|
655
|
+
This slice is not stored in AsyncStorage or redux-persist.
|
|
656
|
+
State exists purely in active JavaScript memory.
|
|
657
|
+
</Text>
|
|
658
|
+
</View>)}
|
|
659
|
+
</View>) : (
|
|
660
|
+
/* Live State JsonViewer: Direct flex: 1 with fullHeight to prevent nested scroll conflicts */
|
|
661
|
+
<View style={{ flex: 1, padding: 10 }}>
|
|
662
|
+
<JsonViewer data={sliceData} search={detailSearch} forceOpen={detailSearch.length > 0 ? true : undefined} mode={viewMode} onModeChange={setViewMode} fullHeight={true} wrap={true}/>
|
|
663
|
+
</View>)}
|
|
664
|
+
</View>);
|
|
665
|
+
}
|
|
666
|
+
// ══════════════════════════════════════════════════════════════════════════
|
|
667
|
+
// ── 2. RENDER ACTION DETAIL VIEW (when an action is selected directly) ────
|
|
668
|
+
// ══════════════════════════════════════════════════════════════════════════
|
|
669
|
+
if (selectedReduxAction != null) {
|
|
670
|
+
const originMeta = getOriginBadge(selectedReduxAction.originType);
|
|
671
|
+
const callerBasename = selectedReduxAction.callerFile
|
|
672
|
+
? selectedReduxAction.callerFile.split('/').pop()
|
|
673
|
+
: null;
|
|
674
|
+
const actionTabs = [
|
|
675
|
+
{
|
|
676
|
+
key: 'payload',
|
|
677
|
+
label: t('redux.payload', 'Payload'),
|
|
678
|
+
icon: (isActive) => (<CodeBracketsIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
key: 'diff',
|
|
682
|
+
label: t('redux.diff', 'State Diff'),
|
|
683
|
+
icon: (isActive) => (<TimelineIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
key: 'stack',
|
|
687
|
+
label: t('redux.callStack', 'Call Stack'),
|
|
688
|
+
icon: (isActive) => (<DocIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
key: 'raw',
|
|
692
|
+
label: 'Raw Action',
|
|
693
|
+
icon: (isActive) => (<LiveStateIcon color={isActive ? AppColors.white : AppColors.grayText} size={12}/>),
|
|
694
|
+
},
|
|
695
|
+
];
|
|
696
|
+
return (<View style={{ flex: 1, backgroundColor: AppColors.grayBackground }}>
|
|
697
|
+
{/* Top Info Bar */}
|
|
698
|
+
<View style={reduxDetailStyles.infoBar}>
|
|
699
|
+
<View style={reduxDetailStyles.infoTopRow}>
|
|
700
|
+
<View style={{
|
|
701
|
+
flexDirection: 'row',
|
|
702
|
+
alignItems: 'center',
|
|
703
|
+
gap: 6,
|
|
704
|
+
flexWrap: 'wrap',
|
|
705
|
+
flex: 1,
|
|
706
|
+
minWidth: 0,
|
|
707
|
+
}}>
|
|
708
|
+
<View style={reduxDetailStyles.actionBadge}>
|
|
709
|
+
<Text style={reduxDetailStyles.actionBadgeText}>
|
|
710
|
+
#{selectedReduxAction.id}
|
|
711
|
+
</Text>
|
|
712
|
+
</View>
|
|
713
|
+
{/* Origin Badge */}
|
|
714
|
+
<View style={{
|
|
715
|
+
flexDirection: 'row',
|
|
716
|
+
alignItems: 'center',
|
|
717
|
+
gap: 3,
|
|
718
|
+
backgroundColor: originMeta.bg,
|
|
719
|
+
paddingHorizontal: 5,
|
|
720
|
+
paddingVertical: 2,
|
|
721
|
+
borderRadius: 4,
|
|
722
|
+
borderWidth: 1,
|
|
723
|
+
borderColor: originMeta.border,
|
|
724
|
+
}}>
|
|
725
|
+
{originMeta.renderIcon(originMeta.text, 8.5)}
|
|
726
|
+
<Text style={{
|
|
727
|
+
fontFamily: AppFonts.interBold,
|
|
728
|
+
fontSize: 8.5,
|
|
729
|
+
color: originMeta.text,
|
|
730
|
+
letterSpacing: 0.3,
|
|
731
|
+
}}>
|
|
732
|
+
{originMeta.label}
|
|
733
|
+
</Text>
|
|
734
|
+
</View>
|
|
735
|
+
<Text style={reduxDetailStyles.sliceNameText} numberOfLines={1}>
|
|
736
|
+
{selectedReduxAction.type}
|
|
737
|
+
</Text>
|
|
738
|
+
{selectedReduxAction.timestamp && (<View style={reduxDetailStyles.timePill}>
|
|
739
|
+
<ClockIcon color={AppColors.purple} size={10}/>
|
|
740
|
+
<Text style={reduxDetailStyles.timeText}>
|
|
741
|
+
{selectedReduxAction.timestamp}
|
|
742
|
+
</Text>
|
|
743
|
+
</View>)}
|
|
744
|
+
</View>
|
|
745
|
+
|
|
746
|
+
{/* Copy Button */}
|
|
747
|
+
<CopyButton value={() => selectedReduxAction} label="Copy Action"/>
|
|
748
|
+
</View>
|
|
749
|
+
|
|
750
|
+
{/* Sub Stats Row */}
|
|
751
|
+
<View style={reduxDetailStyles.subStatsRow}>
|
|
752
|
+
{selectedReduxAction.affectedSlices &&
|
|
753
|
+
selectedReduxAction.affectedSlices.length > 0 && (<View style={[
|
|
754
|
+
reduxDetailStyles.statPill,
|
|
755
|
+
{
|
|
756
|
+
backgroundColor: AppColors.indigo50,
|
|
757
|
+
borderColor: AppColors.indigo400,
|
|
758
|
+
},
|
|
759
|
+
]}>
|
|
760
|
+
<LayersIcon color={AppColors.indigo600Alt} size={11}/>
|
|
761
|
+
<Text style={[
|
|
762
|
+
reduxDetailStyles.statLabel,
|
|
763
|
+
{ color: AppColors.indigo600Alt },
|
|
764
|
+
]}>
|
|
765
|
+
Slices:
|
|
766
|
+
</Text>
|
|
767
|
+
<Text style={[
|
|
768
|
+
reduxDetailStyles.statValue,
|
|
769
|
+
{ color: AppColors.indigo600Alt },
|
|
770
|
+
]}>
|
|
771
|
+
{selectedReduxAction.affectedSlices.join(', ')}
|
|
772
|
+
</Text>
|
|
773
|
+
</View>)}
|
|
774
|
+
<View style={[
|
|
775
|
+
reduxDetailStyles.statPill,
|
|
776
|
+
{
|
|
777
|
+
backgroundColor: AppColors.sky100,
|
|
778
|
+
borderColor: AppColors.sky400,
|
|
779
|
+
},
|
|
780
|
+
]}>
|
|
781
|
+
<Text style={[
|
|
782
|
+
reduxDetailStyles.statLabel,
|
|
783
|
+
{ color: AppColors.sky600 },
|
|
784
|
+
]}>
|
|
785
|
+
Payload Size:
|
|
786
|
+
</Text>
|
|
787
|
+
<Text style={[
|
|
788
|
+
reduxDetailStyles.statValue,
|
|
789
|
+
{ color: AppColors.sky600 },
|
|
790
|
+
]}>
|
|
791
|
+
{getSize(selectedReduxAction.payload)}
|
|
792
|
+
</Text>
|
|
793
|
+
</View>
|
|
794
|
+
</View>
|
|
795
|
+
|
|
796
|
+
{/* Triggered from caller preview row */}
|
|
797
|
+
{selectedReduxAction.callerFile && (<View style={{
|
|
798
|
+
flexDirection: 'row',
|
|
799
|
+
alignItems: 'center',
|
|
800
|
+
justifyContent: 'space-between',
|
|
801
|
+
marginTop: 8,
|
|
802
|
+
paddingHorizontal: 8,
|
|
803
|
+
paddingVertical: 4,
|
|
804
|
+
backgroundColor: AppColors.grayBackground,
|
|
805
|
+
borderRadius: 6,
|
|
806
|
+
borderWidth: 1,
|
|
807
|
+
borderColor: AppColors.dividerColor,
|
|
808
|
+
}}>
|
|
809
|
+
<View style={{
|
|
810
|
+
flexDirection: 'row',
|
|
811
|
+
alignItems: 'center',
|
|
812
|
+
gap: 5,
|
|
813
|
+
flex: 1,
|
|
814
|
+
minWidth: 0,
|
|
815
|
+
}}>
|
|
816
|
+
<DocIcon color={AppColors.sky600} size={10}/>
|
|
817
|
+
<Text style={{
|
|
818
|
+
fontFamily: AppFonts.interMedium,
|
|
819
|
+
fontSize: 9.5,
|
|
820
|
+
color: AppColors.grayTextWeak,
|
|
821
|
+
}}>
|
|
822
|
+
Triggered from:
|
|
823
|
+
</Text>
|
|
824
|
+
<Text style={{
|
|
825
|
+
fontFamily: AppFonts.interBold,
|
|
826
|
+
fontSize: 9.5,
|
|
827
|
+
color: AppColors.sky600,
|
|
828
|
+
}} numberOfLines={1}>
|
|
829
|
+
{callerBasename}:{selectedReduxAction.callerLine || 1}
|
|
830
|
+
</Text>
|
|
831
|
+
</View>
|
|
832
|
+
|
|
833
|
+
<Pressable onPress={() => openInVSCode(selectedReduxAction.callerFile, selectedReduxAction.callerLine, selectedReduxAction.callerCol)} hitSlop={8} style={{
|
|
834
|
+
flexDirection: 'row',
|
|
835
|
+
alignItems: 'center',
|
|
836
|
+
gap: 3,
|
|
837
|
+
backgroundColor: AppColors.sky100,
|
|
838
|
+
paddingHorizontal: 5,
|
|
839
|
+
paddingVertical: 2,
|
|
840
|
+
borderRadius: 4,
|
|
841
|
+
}}>
|
|
842
|
+
<ExternalLinkIcon color={AppColors.sky600} size={9}/>
|
|
843
|
+
<Text style={{
|
|
844
|
+
fontFamily: AppFonts.interBold,
|
|
845
|
+
fontSize: 8.5,
|
|
846
|
+
color: AppColors.sky600,
|
|
847
|
+
}}>
|
|
848
|
+
Open in Editor
|
|
849
|
+
</Text>
|
|
850
|
+
</Pressable>
|
|
851
|
+
</View>)}
|
|
852
|
+
|
|
853
|
+
{/* Sub-Tabs */}
|
|
854
|
+
<SegmentedTabs tabs={actionTabs} activeKey={actionTab} onChange={key => setActionTab(key)} style={{ marginTop: 10 }}/>
|
|
855
|
+
</View>
|
|
856
|
+
|
|
857
|
+
{/* Content Body */}
|
|
858
|
+
{actionTab === 'payload' ? (<View style={{ flex: 1, padding: 10 }}>
|
|
859
|
+
{selectedReduxAction.payload !== undefined ? (<JsonViewer data={selectedReduxAction.payload} search={detailSearch} forceOpen={true} fullHeight={true} wrap={true}/>) : (<View style={reduxDetailStyles.emptyBox}>
|
|
860
|
+
<Text style={reduxDetailStyles.emptyBoxText}>
|
|
861
|
+
This action has no payload dispatched.
|
|
862
|
+
</Text>
|
|
863
|
+
</View>)}
|
|
864
|
+
</View>) : actionTab === 'diff' ? (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 12, paddingBottom: 40 }} keyboardShouldPersistTaps="handled">
|
|
865
|
+
<DiffViewer oldData={selectedReduxAction.prevState || {}} newData={selectedReduxAction.nextState || {}} forceOpen={true}/>
|
|
866
|
+
</ScrollView>) : actionTab === 'stack' ? (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 12, paddingBottom: 40 }} keyboardShouldPersistTaps="handled">
|
|
867
|
+
{selectedReduxAction.stack ? (<View style={{
|
|
868
|
+
backgroundColor: AppColors.white,
|
|
869
|
+
borderRadius: 10,
|
|
870
|
+
padding: 10,
|
|
871
|
+
borderWidth: 1,
|
|
872
|
+
borderColor: AppColors.dividerColor,
|
|
873
|
+
}}>
|
|
874
|
+
<Text style={reduxDetailStyles.expandedSectionTitle}>
|
|
875
|
+
Dispatched from call stack:
|
|
876
|
+
</Text>
|
|
877
|
+
{selectedReduxAction.stack
|
|
878
|
+
.split('\n')
|
|
879
|
+
.map(l => l.trim())
|
|
880
|
+
.filter(l => l.length > 0 &&
|
|
881
|
+
!l.includes('reduxLogger') &&
|
|
882
|
+
!l.includes('inspectorReduxMiddleware'))
|
|
883
|
+
.map((frameLine, fIdx) => {
|
|
884
|
+
const parsed = parseStackLine(frameLine, fIdx === 0);
|
|
885
|
+
const isApp = parsed.frameType === 'app';
|
|
886
|
+
return (<Pressable key={fIdx} onPress={() => {
|
|
887
|
+
if (parsed.fileName !== 'Unknown') {
|
|
888
|
+
openInVSCode(parsed.fullPath || parsed.fileName, parsed.lineNumber, parsed.columnNumber);
|
|
889
|
+
}
|
|
890
|
+
}} style={{
|
|
891
|
+
flexDirection: 'row',
|
|
892
|
+
alignItems: 'center',
|
|
893
|
+
justifyContent: 'space-between',
|
|
894
|
+
paddingVertical: 5,
|
|
895
|
+
borderBottomWidth: 0.5,
|
|
896
|
+
borderBottomColor: AppColors.dividerColor,
|
|
897
|
+
}}>
|
|
898
|
+
<View style={{ flex: 1, minWidth: 0 }}>
|
|
899
|
+
<Text style={{
|
|
900
|
+
fontFamily: isApp
|
|
901
|
+
? AppFonts.interBold
|
|
902
|
+
: AppFonts.interRegular,
|
|
903
|
+
fontSize: 10.5,
|
|
904
|
+
color: isApp
|
|
905
|
+
? AppColors.primaryBlack
|
|
906
|
+
: AppColors.grayTextWeak,
|
|
907
|
+
}} numberOfLines={1}>
|
|
908
|
+
{parsed.functionName || 'anonymous'}
|
|
909
|
+
</Text>
|
|
910
|
+
<Text style={{
|
|
911
|
+
fontFamily: AppFonts.interRegular,
|
|
912
|
+
fontSize: 9,
|
|
913
|
+
color: isApp
|
|
914
|
+
? AppColors.sky600
|
|
915
|
+
: AppColors.grayTextWeak,
|
|
916
|
+
}} numberOfLines={1}>
|
|
917
|
+
{parsed.fileName}:{parsed.lineNumber || 1}:
|
|
918
|
+
{parsed.columnNumber || 1}
|
|
919
|
+
</Text>
|
|
920
|
+
</View>
|
|
921
|
+
{isApp && (<ExternalLinkIcon color={AppColors.sky600} size={11}/>)}
|
|
922
|
+
</Pressable>);
|
|
923
|
+
})}
|
|
924
|
+
</View>) : (<View style={reduxDetailStyles.emptyBox}>
|
|
925
|
+
<Text style={reduxDetailStyles.emptyBoxText}>
|
|
926
|
+
No call stack trace captured for this action.
|
|
927
|
+
</Text>
|
|
928
|
+
</View>)}
|
|
929
|
+
</ScrollView>) : (<View style={{ flex: 1, padding: 10 }}>
|
|
930
|
+
<JsonViewer data={selectedReduxAction} forceOpen={true} fullHeight={true} wrap={true}/>
|
|
931
|
+
</View>)}
|
|
488
932
|
</View>);
|
|
489
933
|
}
|
|
490
|
-
return
|
|
934
|
+
return (<View style={reduxDetailStyles.emptyBox}>
|
|
935
|
+
<TerminalIcon color={AppColors.purple} size={32}/>
|
|
936
|
+
<Text style={reduxDetailStyles.emptyBoxTitle}>
|
|
937
|
+
No Redux Slice Selected
|
|
938
|
+
</Text>
|
|
939
|
+
<Text style={reduxDetailStyles.emptyBoxText}>
|
|
940
|
+
Select a slice from the Redux tab to inspect its state and dispatched
|
|
941
|
+
actions.
|
|
942
|
+
</Text>
|
|
943
|
+
</View>);
|
|
491
944
|
});
|
|
492
945
|
const reduxDetailStyles = StyleSheet.create({
|
|
493
946
|
infoBar: {
|
|
@@ -503,20 +956,21 @@ const reduxDetailStyles = StyleSheet.create({
|
|
|
503
956
|
marginBottom: 8,
|
|
504
957
|
},
|
|
505
958
|
methodBadge: {
|
|
506
|
-
paddingHorizontal:
|
|
507
|
-
paddingVertical:
|
|
508
|
-
borderRadius:
|
|
959
|
+
paddingHorizontal: 7,
|
|
960
|
+
paddingVertical: 2.5,
|
|
961
|
+
borderRadius: 5,
|
|
509
962
|
},
|
|
510
963
|
methodBadgeText: {
|
|
511
964
|
fontFamily: AppFonts.interBold,
|
|
512
|
-
fontSize:
|
|
965
|
+
fontSize: 9.5,
|
|
513
966
|
color: AppColors.white,
|
|
514
|
-
letterSpacing: 0.
|
|
967
|
+
letterSpacing: 0.4,
|
|
515
968
|
},
|
|
516
969
|
sliceNameText: {
|
|
517
970
|
fontFamily: AppFonts.interBold,
|
|
518
971
|
fontSize: 14,
|
|
519
972
|
color: AppColors.primaryBlack,
|
|
973
|
+
flexShrink: 1,
|
|
520
974
|
},
|
|
521
975
|
persistedChip: {
|
|
522
976
|
flexDirection: 'row',
|
|
@@ -601,6 +1055,11 @@ const reduxDetailStyles = StyleSheet.create({
|
|
|
601
1055
|
marginBottom: 8,
|
|
602
1056
|
borderWidth: 1,
|
|
603
1057
|
borderColor: AppColors.dividerColor,
|
|
1058
|
+
shadowColor: AppColors.primaryBlack,
|
|
1059
|
+
shadowOffset: { width: 0, height: 1 },
|
|
1060
|
+
shadowOpacity: 0.03,
|
|
1061
|
+
shadowRadius: 3,
|
|
1062
|
+
elevation: 1,
|
|
604
1063
|
},
|
|
605
1064
|
timelineHeader: {
|
|
606
1065
|
flexDirection: 'row',
|
|
@@ -664,7 +1123,7 @@ const reduxDetailStyles = StyleSheet.create({
|
|
|
664
1123
|
fontFamily: AppFonts.interBold,
|
|
665
1124
|
fontSize: 11,
|
|
666
1125
|
color: AppColors.grayTextStrong,
|
|
667
|
-
marginBottom:
|
|
1126
|
+
marginBottom: 6,
|
|
668
1127
|
},
|
|
669
1128
|
metadataCard: {
|
|
670
1129
|
backgroundColor: AppColors.white,
|
|
@@ -672,6 +1131,11 @@ const reduxDetailStyles = StyleSheet.create({
|
|
|
672
1131
|
padding: 12,
|
|
673
1132
|
borderWidth: 1,
|
|
674
1133
|
borderColor: AppColors.dividerColor,
|
|
1134
|
+
shadowColor: AppColors.primaryBlack,
|
|
1135
|
+
shadowOffset: { width: 0, height: 1 },
|
|
1136
|
+
shadowOpacity: 0.03,
|
|
1137
|
+
shadowRadius: 3,
|
|
1138
|
+
elevation: 1,
|
|
675
1139
|
},
|
|
676
1140
|
metaRow: {
|
|
677
1141
|
flexDirection: 'row',
|
|
@@ -693,6 +1157,32 @@ const reduxDetailStyles = StyleSheet.create({
|
|
|
693
1157
|
maxWidth: '60%',
|
|
694
1158
|
textAlign: 'right',
|
|
695
1159
|
},
|
|
1160
|
+
persistedInfoCard: {
|
|
1161
|
+
backgroundColor: '#ECFDF5',
|
|
1162
|
+
borderRadius: 8,
|
|
1163
|
+
borderWidth: 1,
|
|
1164
|
+
borderColor: '#A7F3D0',
|
|
1165
|
+
padding: 10,
|
|
1166
|
+
},
|
|
1167
|
+
persistedInfoTitle: {
|
|
1168
|
+
fontFamily: AppFonts.interBold,
|
|
1169
|
+
fontSize: 11,
|
|
1170
|
+
color: '#047857',
|
|
1171
|
+
},
|
|
1172
|
+
clearPersistMiniBtn: {
|
|
1173
|
+
flexDirection: 'row',
|
|
1174
|
+
alignItems: 'center',
|
|
1175
|
+
gap: 3,
|
|
1176
|
+
backgroundColor: '#FEE2E2',
|
|
1177
|
+
paddingHorizontal: 6,
|
|
1178
|
+
paddingVertical: 2.5,
|
|
1179
|
+
borderRadius: 4,
|
|
1180
|
+
},
|
|
1181
|
+
clearPersistMiniText: {
|
|
1182
|
+
fontFamily: AppFonts.interBold,
|
|
1183
|
+
fontSize: 9.5,
|
|
1184
|
+
color: AppColors.errorColor,
|
|
1185
|
+
},
|
|
696
1186
|
clearPersistBtn: {
|
|
697
1187
|
flexDirection: 'row',
|
|
698
1188
|
alignItems: 'center',
|
|
@@ -718,11 +1208,20 @@ const reduxDetailStyles = StyleSheet.create({
|
|
|
718
1208
|
justifyContent: 'center',
|
|
719
1209
|
borderWidth: 1,
|
|
720
1210
|
borderColor: AppColors.dividerColor,
|
|
1211
|
+
margin: 12,
|
|
1212
|
+
gap: 8,
|
|
1213
|
+
},
|
|
1214
|
+
emptyBoxTitle: {
|
|
1215
|
+
fontFamily: AppFonts.interBold,
|
|
1216
|
+
fontSize: 14,
|
|
1217
|
+
color: AppColors.primaryBlack,
|
|
721
1218
|
},
|
|
722
1219
|
emptyBoxText: {
|
|
723
1220
|
fontFamily: AppFonts.interMedium,
|
|
724
|
-
fontSize: 12
|
|
1221
|
+
fontSize: 12,
|
|
725
1222
|
color: AppColors.grayTextWeak,
|
|
1223
|
+
textAlign: 'center',
|
|
1224
|
+
lineHeight: 18,
|
|
726
1225
|
},
|
|
727
1226
|
highlight: {
|
|
728
1227
|
backgroundColor: '#FEF08A',
|