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,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { ScrollView, View, Text, StyleSheet } from 'react-native';
|
|
2
|
+
import { ScrollView, View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
// Components
|
|
5
5
|
import TreeNode from './TreeNode';
|
|
@@ -10,10 +10,63 @@ import { PrettyIcon, RawIcon, TableIcon } from './NetworkIcons';
|
|
|
10
10
|
import { AppColors } from '../styles/AppColors';
|
|
11
11
|
import { AppFonts } from '../styles/AppFonts';
|
|
12
12
|
import styles from '../styles';
|
|
13
|
+
// ── Table Row Component with 3-Line Clamp & Show More/Less ───────────────────
|
|
14
|
+
const JsonTableRow = React.memo(({ itemKey, val, search, }) => {
|
|
15
|
+
const [expanded, setExpanded] = useState(false);
|
|
16
|
+
const isObject = val !== null && typeof val === 'object';
|
|
17
|
+
let rawStr = '';
|
|
18
|
+
if (val === null) {
|
|
19
|
+
rawStr = 'null';
|
|
20
|
+
}
|
|
21
|
+
else if (val === undefined) {
|
|
22
|
+
rawStr = 'undefined';
|
|
23
|
+
}
|
|
24
|
+
else if (isObject) {
|
|
25
|
+
try {
|
|
26
|
+
rawStr = JSON.stringify(val, null, 2);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
rawStr = String(val);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
rawStr = String(val);
|
|
34
|
+
}
|
|
35
|
+
const isMultiline = rawStr.includes('\n') || rawStr.length > 90;
|
|
36
|
+
return (<View style={localStyles.tableRow}>
|
|
37
|
+
<View style={{ flex: 2, paddingRight: 8 }}>
|
|
38
|
+
<HighlightText text={itemKey} search={search} style={localStyles.tableCellKey} highlightStyle={localStyles.highlight}/>
|
|
39
|
+
{isObject && (<Text style={localStyles.tableTypeBadge}>
|
|
40
|
+
{Array.isArray(val) ? `Array(${val.length})` : 'Object'}
|
|
41
|
+
</Text>)}
|
|
42
|
+
</View>
|
|
43
|
+
|
|
44
|
+
<View style={{ flex: 3 }}>
|
|
45
|
+
<HighlightText text={rawStr} search={search} style={[
|
|
46
|
+
localStyles.tableCellValue,
|
|
47
|
+
isObject && localStyles.tableCellRawCode,
|
|
48
|
+
]} highlightStyle={localStyles.highlight} numberOfLines={expanded ? undefined : 3} selectable={true}/>
|
|
49
|
+
{isMultiline && (<TouchableOpacity onPress={() => setExpanded(prev => !prev)} hitSlop={6} style={localStyles.showMoreBtn}>
|
|
50
|
+
<Text style={localStyles.showMoreText}>
|
|
51
|
+
{expanded ? 'Show less ▲' : 'Show more ▼'}
|
|
52
|
+
</Text>
|
|
53
|
+
</TouchableOpacity>)}
|
|
54
|
+
</View>
|
|
55
|
+
</View>);
|
|
56
|
+
});
|
|
13
57
|
// ── JsonViewer Component ─────────────────────────────────────────────────────
|
|
14
58
|
const JsonViewer = React.memo(({ data, search, forceOpen, defaultExpandDepth, wrap, fullHeight = false, maxHeight, mode: externalMode, onModeChange, hideTabs = false, }) => {
|
|
15
59
|
const { t } = useTranslation();
|
|
16
|
-
const [
|
|
60
|
+
const [internalMode, setInternalMode] = useState('pretty');
|
|
61
|
+
const mode = externalMode ?? internalMode;
|
|
62
|
+
const setMode = (newMode) => {
|
|
63
|
+
if (onModeChange) {
|
|
64
|
+
onModeChange(newMode);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
setInternalMode(newMode);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
17
70
|
const rawText = React.useMemo(() => {
|
|
18
71
|
if (typeof data === 'string') {
|
|
19
72
|
return data;
|
|
@@ -27,12 +80,9 @@ const JsonViewer = React.memo(({ data, search, forceOpen, defaultExpandDepth, wr
|
|
|
27
80
|
}, [data]);
|
|
28
81
|
useEffect(() => {
|
|
29
82
|
if (externalMode) {
|
|
30
|
-
|
|
83
|
+
setInternalMode(externalMode);
|
|
31
84
|
}
|
|
32
85
|
}, [externalMode]);
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
onModeChange?.(mode);
|
|
35
|
-
}, [mode, onModeChange]);
|
|
36
86
|
const contentWrapperStyle = [
|
|
37
87
|
localStyles.contentWrapper,
|
|
38
88
|
{ backgroundColor: AppColors.contentBg },
|
|
@@ -45,7 +95,9 @@ const JsonViewer = React.memo(({ data, search, forceOpen, defaultExpandDepth, wr
|
|
|
45
95
|
];
|
|
46
96
|
// Determine type and size details
|
|
47
97
|
const isObject = typeof data === 'object' && data !== null;
|
|
48
|
-
const isEmpty =
|
|
98
|
+
const isEmpty = data === null ||
|
|
99
|
+
data === undefined ||
|
|
100
|
+
(isObject && Object.keys(data).length === 0);
|
|
49
101
|
// Render Table view (Key-Value flat table for root keys)
|
|
50
102
|
const renderTableMode = () => {
|
|
51
103
|
if (!isObject) {
|
|
@@ -65,28 +117,7 @@ const JsonViewer = React.memo(({ data, search, forceOpen, defaultExpandDepth, wr
|
|
|
65
117
|
<Text style={[localStyles.tableHeaderCell, { flex: 2 }]}>{t('network.jsonViewer.key')}</Text>
|
|
66
118
|
<Text style={[localStyles.tableHeaderCell, { flex: 3 }]}>{t('network.jsonViewer.value')}</Text>
|
|
67
119
|
</View>
|
|
68
|
-
{keys.map((key) => {
|
|
69
|
-
const val = data[key];
|
|
70
|
-
let displayVal = '';
|
|
71
|
-
if (val === null) {
|
|
72
|
-
displayVal = 'null';
|
|
73
|
-
}
|
|
74
|
-
else if (val === undefined) {
|
|
75
|
-
displayVal = 'undefined';
|
|
76
|
-
}
|
|
77
|
-
else if (typeof val === 'object') {
|
|
78
|
-
displayVal = Array.isArray(val) ? `[Array(${val.length})]` : '{Object}';
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
displayVal = String(val);
|
|
82
|
-
}
|
|
83
|
-
return (<View key={key} style={localStyles.tableRow}>
|
|
84
|
-
<Text style={[localStyles.tableCellKey, { flex: 2 }]}>{key}</Text>
|
|
85
|
-
<Text style={[localStyles.tableCellValue, { flex: 3 }]} numberOfLines={2}>
|
|
86
|
-
{displayVal}
|
|
87
|
-
</Text>
|
|
88
|
-
</View>);
|
|
89
|
-
})}
|
|
120
|
+
{keys.map((key) => (<JsonTableRow key={key} itemKey={key} val={data[key]} search={search}/>))}
|
|
90
121
|
</View>);
|
|
91
122
|
};
|
|
92
123
|
// Tree View Content
|
|
@@ -220,11 +251,36 @@ const localStyles = StyleSheet.create({
|
|
|
220
251
|
fontSize: 12.5,
|
|
221
252
|
color: AppColors.purple,
|
|
222
253
|
},
|
|
254
|
+
tableTypeBadge: {
|
|
255
|
+
fontFamily: AppFonts.interMedium,
|
|
256
|
+
fontSize: 9.5,
|
|
257
|
+
color: AppColors.slate400,
|
|
258
|
+
marginTop: 2,
|
|
259
|
+
},
|
|
223
260
|
tableCellValue: {
|
|
224
261
|
fontFamily: AppFonts.interRegular,
|
|
225
|
-
fontSize: 12
|
|
262
|
+
fontSize: 12,
|
|
226
263
|
color: AppColors.primaryBlack,
|
|
227
|
-
lineHeight:
|
|
264
|
+
lineHeight: 17,
|
|
265
|
+
},
|
|
266
|
+
tableCellRawCode: {
|
|
267
|
+
fontFamily: AppFonts.interRegular,
|
|
268
|
+
fontSize: 11.5,
|
|
269
|
+
color: AppColors.slate700,
|
|
270
|
+
backgroundColor: `${AppColors.slate100}80`,
|
|
271
|
+
padding: 6,
|
|
272
|
+
borderRadius: 6,
|
|
273
|
+
},
|
|
274
|
+
showMoreBtn: {
|
|
275
|
+
alignSelf: 'flex-start',
|
|
276
|
+
marginTop: 4,
|
|
277
|
+
paddingVertical: 2,
|
|
278
|
+
paddingHorizontal: 4,
|
|
279
|
+
},
|
|
280
|
+
showMoreText: {
|
|
281
|
+
fontFamily: AppFonts.interBold,
|
|
282
|
+
fontSize: 11,
|
|
283
|
+
color: AppColors.purple,
|
|
228
284
|
},
|
|
229
285
|
emptyTable: {
|
|
230
286
|
padding: 24,
|
|
@@ -236,5 +292,10 @@ const localStyles = StyleSheet.create({
|
|
|
236
292
|
fontSize: 12.5,
|
|
237
293
|
color: AppColors.slate400,
|
|
238
294
|
},
|
|
295
|
+
highlight: {
|
|
296
|
+
backgroundColor: '#FEF08A',
|
|
297
|
+
color: '#854D0E',
|
|
298
|
+
fontFamily: AppFonts.interBold,
|
|
299
|
+
},
|
|
239
300
|
});
|
|
240
301
|
export default JsonViewer;
|
|
@@ -39,9 +39,8 @@ const LogCard = React.memo(function LogCard({ item, onPress, timelineMinStart, t
|
|
|
39
39
|
}, [isNew]);
|
|
40
40
|
const path = getPath(item.url);
|
|
41
41
|
const baseUrl = getBaseUrl(item.url) || item.url;
|
|
42
|
-
const cleanHost = baseUrl.replace(/^https?:\/\//, '');
|
|
43
42
|
const slug = path && path !== '/' ? path : item.url;
|
|
44
|
-
const showSlug = slug !==
|
|
43
|
+
const showSlug = slug !== baseUrl && slug !== item.url;
|
|
45
44
|
const triggeredAt = formatDateTime(item.startTime);
|
|
46
45
|
const isJson = item.url.split('?')[0].toLowerCase().endsWith('.json');
|
|
47
46
|
return (<TouchableScale onPress={onPress} style={[
|
|
@@ -52,7 +51,7 @@ const LogCard = React.memo(function LogCard({ item, onPress, timelineMinStart, t
|
|
|
52
51
|
},
|
|
53
52
|
]}>
|
|
54
53
|
<View style={styles.cardBody}>
|
|
55
|
-
{/* Row 1: Header (Checkbox, Serial, Method Badge, Base URL / Host, Status Pill) */}
|
|
54
|
+
{/* Row 1: Header (Checkbox, Serial, Method Badge, Base URL / Host with HTTPS, Status Pill) */}
|
|
56
55
|
<View style={styles.cardHeaderRow}>
|
|
57
56
|
<View style={styles.cardHeaderLeft}>
|
|
58
57
|
<Pressable onPress={() => onToggleSelect(item.id)} hitSlop={12} style={[
|
|
@@ -72,7 +71,7 @@ const LogCard = React.memo(function LogCard({ item, onPress, timelineMinStart, t
|
|
|
72
71
|
</Text>
|
|
73
72
|
</View>
|
|
74
73
|
|
|
75
|
-
<HighlightText text={
|
|
74
|
+
<HighlightText text={baseUrl || item.url} search={searchStr} style={styles.cardHostText} highlightStyle={styles.highlight} numberOfLines={1} ellipsizeMode="tail"/>
|
|
76
75
|
</View>
|
|
77
76
|
|
|
78
77
|
<View style={[
|
|
@@ -57,3 +57,12 @@ export declare const SortIcon: ({ ascending, color, size, }: any) => React.JSX.E
|
|
|
57
57
|
export declare const PrettyIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
58
58
|
export declare const RawIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
59
59
|
export declare const TableIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
60
|
+
export declare const PackageIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
61
|
+
export declare const ForwardChevronIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
62
|
+
export declare const BundleIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
63
|
+
export declare const LiveStateIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
64
|
+
export declare const TimelineIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
65
|
+
export declare const StorageIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
66
|
+
export declare const MetadataIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
67
|
+
export declare const ReduxIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
68
|
+
export declare const PerformanceIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Svg, { Circle, Line, Path, Rect } from 'react-native-svg';
|
|
2
|
+
import Svg, { Circle, Ellipse, Line, Path, Rect } from 'react-native-svg';
|
|
3
3
|
// Stylesheet
|
|
4
4
|
import { AppColors } from '../styles/AppColors';
|
|
5
5
|
export const EmptyRadarIcon = ({ color = AppColors.purple, size = 32 }) => {
|
|
@@ -348,3 +348,57 @@ export const TableIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
|
|
|
348
348
|
<Rect x="3" y="14" width="7" height="7" rx="1.5" stroke={color} strokeWidth="2"/>
|
|
349
349
|
</Svg>);
|
|
350
350
|
};
|
|
351
|
+
export const PackageIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
|
|
352
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
353
|
+
<Path d="M16.5 9.4 7.55 4.24a1.78 1.78 0 0 0-2.5 1.55v12.42a1.78 1.78 0 0 0 .86 1.52l8.95 5.16a1.78 1.78 0 0 0 1.78 0l8.95-5.16a1.78 1.78 0 0 0 .86-1.52V5.79a1.78 1.78 0 0 0-2.5-1.55L16.5 9.4z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
|
|
354
|
+
<Path d="M3.29 7 12 12.01 20.71 7M12 22.08V12" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
|
|
355
|
+
</Svg>);
|
|
356
|
+
};
|
|
357
|
+
export const ForwardChevronIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
|
|
358
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
359
|
+
<Path d="M9 18l6-6-6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
360
|
+
</Svg>);
|
|
361
|
+
};
|
|
362
|
+
export const BundleIcon = PackageIcon;
|
|
363
|
+
export const LiveStateIcon = ({ color = AppColors.purple, size = 14, }) => {
|
|
364
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
365
|
+
<Path d="M12 3v3M12 18v3M3 12h3M18 12h3" stroke={color} strokeWidth="2" strokeLinecap="round"/>
|
|
366
|
+
<Circle cx="12" cy="12" r="3.5" stroke={color} strokeWidth="1.8" fill={`${color}22`}/>
|
|
367
|
+
<Circle cx="12" cy="12" r="1.5" fill={color}/>
|
|
368
|
+
</Svg>);
|
|
369
|
+
};
|
|
370
|
+
export const TimelineIcon = ({ color = AppColors.purple, size = 14, }) => {
|
|
371
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
372
|
+
<Circle cx="12" cy="12" r="8.5" stroke={color} strokeWidth="1.8"/>
|
|
373
|
+
<Path d="M12 7.5v4.5l3 2" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
|
|
374
|
+
</Svg>);
|
|
375
|
+
};
|
|
376
|
+
export const StorageIcon = ({ color = AppColors.purple, size = 14, }) => {
|
|
377
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
378
|
+
<Ellipse cx="12" cy="6" rx="8" ry="2.8" stroke={color} strokeWidth="1.8"/>
|
|
379
|
+
<Path d="M20 12c0 1.55-3.58 2.8-8 2.8s-8-1.25-8-2.8" stroke={color} strokeWidth="1.8" strokeLinecap="round"/>
|
|
380
|
+
<Path d="M4 6v12c0 1.55 3.58 2.8 8 2.8s8-1.25 8-2.8V6" stroke={color} strokeWidth="1.8" strokeLinecap="round"/>
|
|
381
|
+
</Svg>);
|
|
382
|
+
};
|
|
383
|
+
export const MetadataIcon = ({ color = AppColors.purple, size = 14, }) => {
|
|
384
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
385
|
+
<Circle cx="12" cy="12" r="8.5" stroke={color} strokeWidth="1.8"/>
|
|
386
|
+
<Path d="M12 16v-4M12 8.2h.01" stroke={color} strokeWidth="2" strokeLinecap="round"/>
|
|
387
|
+
</Svg>);
|
|
388
|
+
};
|
|
389
|
+
export const ReduxIcon = ({ color = AppColors.purple, size = 14, }) => {
|
|
390
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
391
|
+
<Circle cx="12" cy="12" r="4" stroke={color} strokeWidth="1.8"/>
|
|
392
|
+
<Path d="M12 3a9 9 0 0 1 9 9M12 21a9 9 0 0 1-9-9" stroke={color} strokeWidth="1.8" strokeLinecap="round"/>
|
|
393
|
+
<Circle cx="21" cy="12" r="1.5" fill={color}/>
|
|
394
|
+
<Circle cx="3" cy="12" r="1.5" fill={color}/>
|
|
395
|
+
</Svg>);
|
|
396
|
+
};
|
|
397
|
+
export const PerformanceIcon = ({ color = AppColors.purple, size = 14, }) => {
|
|
398
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
399
|
+
<Path d="M12 3v2M5.636 5.636l1.414 1.414M18.364 5.636l-1.414 1.414M3 12h2M19 12h2" stroke={color} strokeWidth="1.8" strokeLinecap="round"/>
|
|
400
|
+
<Path d="M12 19a7 7 0 1 0-7-7c0 1.93.784 3.68 2.05 4.95" stroke={color} strokeWidth="1.8" strokeLinecap="round"/>
|
|
401
|
+
<Path d="M12 12l3.5-3.5" stroke={color} strokeWidth="2" strokeLinecap="round"/>
|
|
402
|
+
<Circle cx="12" cy="12" r="1.5" fill={color}/>
|
|
403
|
+
</Svg>);
|
|
404
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "1.1.
|
|
1
|
+
export declare const LIB_VERSION = "1.1.18";
|
|
@@ -63,6 +63,16 @@ const symbolicateStack = async (stackString) => {
|
|
|
63
63
|
catch { }
|
|
64
64
|
return null;
|
|
65
65
|
};
|
|
66
|
+
const isLoggerInternal = (line) => {
|
|
67
|
+
const l = line.toLowerCase();
|
|
68
|
+
return (l.includes('getstackdetails') ||
|
|
69
|
+
l.includes('addlog') ||
|
|
70
|
+
l.includes('consolelogger') ||
|
|
71
|
+
l.includes('setupconsolelogger') ||
|
|
72
|
+
l.includes('formatargs') ||
|
|
73
|
+
l.includes('react-native-inapp-inspector') ||
|
|
74
|
+
l.trim() === 'error');
|
|
75
|
+
};
|
|
66
76
|
const getStackDetails = (args) => {
|
|
67
77
|
try {
|
|
68
78
|
let errorStack;
|
|
@@ -89,11 +99,7 @@ const getStackDetails = (args) => {
|
|
|
89
99
|
let fallbackCaller;
|
|
90
100
|
for (let i = 0; i < lines.length; i++) {
|
|
91
101
|
const line = lines[i];
|
|
92
|
-
if (!line ||
|
|
93
|
-
line.includes('consoleLogger') ||
|
|
94
|
-
line.includes('setupConsoleLogger') ||
|
|
95
|
-
line.includes('react-native-inapp-inspector') ||
|
|
96
|
-
line.trim() === 'Error') {
|
|
102
|
+
if (!line || isLoggerInternal(line)) {
|
|
97
103
|
continue;
|
|
98
104
|
}
|
|
99
105
|
const isInternal = line.includes('react-native/Libraries') ||
|
|
@@ -110,10 +116,7 @@ const getStackDetails = (args) => {
|
|
|
110
116
|
break;
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
|
-
const cleanedStack = lines
|
|
114
|
-
.filter(l => !l.includes('consoleLogger') &&
|
|
115
|
-
!l.includes('setupConsoleLogger'))
|
|
116
|
-
.join('\n');
|
|
119
|
+
const cleanedStack = lines.filter(l => !isLoggerInternal(l)).join('\n');
|
|
117
120
|
const caller = userCaller || fallbackCaller || 'Unknown';
|
|
118
121
|
return { caller, stack: cleanedStack || stackToUse, errorStack, stackToUse };
|
|
119
122
|
}
|
|
@@ -159,6 +162,31 @@ const addLog = (type, args, sourceMethod) => {
|
|
|
159
162
|
logs.unshift(newLog);
|
|
160
163
|
logs = logs.slice(0, MAX_LOGS);
|
|
161
164
|
notify();
|
|
165
|
+
// Asynchronously symbolicate stack trace via Metro in development
|
|
166
|
+
if (newLog.stack && typeof __DEV__ !== 'undefined' && __DEV__) {
|
|
167
|
+
symbolicateStack(newLog.stack)
|
|
168
|
+
.then(symbolicatedFrames => {
|
|
169
|
+
if (symbolicatedFrames && symbolicatedFrames.length > 0) {
|
|
170
|
+
const validFrames = symbolicatedFrames.filter(f => f.file &&
|
|
171
|
+
!f.file.includes('react-native/Libraries') &&
|
|
172
|
+
!f.file.includes('node_modules') &&
|
|
173
|
+
!isLoggerInternal(f.file) &&
|
|
174
|
+
!isLoggerInternal(f.methodName || ''));
|
|
175
|
+
const topFrame = validFrames[0] || symbolicatedFrames[0];
|
|
176
|
+
if (topFrame) {
|
|
177
|
+
const cleanMethod = topFrame.methodName || 'anonymous';
|
|
178
|
+
const cleanFile = topFrame.file.split('/').pop() || topFrame.file;
|
|
179
|
+
newLog.caller = `${cleanMethod} (${cleanFile}:${topFrame.lineNumber || 1}:${topFrame.column || 1})`;
|
|
180
|
+
}
|
|
181
|
+
newLog.stack = symbolicatedFrames
|
|
182
|
+
.filter(f => !isLoggerInternal(f.file || '') && !isLoggerInternal(f.methodName || ''))
|
|
183
|
+
.map(f => ` at ${f.methodName || 'anonymous'} (${f.file}:${f.lineNumber || 1}:${f.column || 1})`)
|
|
184
|
+
.join('\n');
|
|
185
|
+
notify();
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
.catch(() => { });
|
|
189
|
+
}
|
|
162
190
|
// Asynchronously symbolicate stack trace using Metro in DEV mode
|
|
163
191
|
if (stackToUse && typeof __DEV__ !== 'undefined' && __DEV__) {
|
|
164
192
|
const currentLogId = newLog.id;
|
|
@@ -67,7 +67,8 @@ function recordAction(action, prevState, nextState) {
|
|
|
67
67
|
const payload = action && typeof action === 'object' && action.payload !== undefined
|
|
68
68
|
? action.payload
|
|
69
69
|
: null;
|
|
70
|
-
const
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const timestamp = new Date(now).toLocaleTimeString();
|
|
71
72
|
const affectedSlices = [];
|
|
72
73
|
if (prevState &&
|
|
73
74
|
nextState &&
|
|
@@ -75,7 +76,7 @@ function recordAction(action, prevState, nextState) {
|
|
|
75
76
|
typeof nextState === 'object') {
|
|
76
77
|
Object.keys(nextState).forEach(key => {
|
|
77
78
|
if (prevState[key] !== nextState[key]) {
|
|
78
|
-
lastActionForReducer[key] = { type, payload, timestamp };
|
|
79
|
+
lastActionForReducer[key] = { type, payload, timestamp, updatedAt: now };
|
|
79
80
|
affectedSlices.push(key);
|
|
80
81
|
}
|
|
81
82
|
});
|
|
@@ -85,6 +86,7 @@ function recordAction(action, prevState, nextState) {
|
|
|
85
86
|
type,
|
|
86
87
|
payload,
|
|
87
88
|
timestamp,
|
|
89
|
+
updatedAt: now,
|
|
88
90
|
affectedSlices,
|
|
89
91
|
prevState,
|
|
90
92
|
nextState,
|
|
@@ -458,10 +458,14 @@ export const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
458
458
|
columnNumber = locMatch[3];
|
|
459
459
|
}
|
|
460
460
|
// Clean file name (remove query strings, packager urls, and parent paths)
|
|
461
|
-
let cleanPath = fullPath
|
|
461
|
+
let cleanPath = fullPath
|
|
462
|
+
.split('?')[0]
|
|
463
|
+
.split('&')[0]
|
|
464
|
+
.replace(/[)]+$/, '')
|
|
465
|
+
.replace(/\/\/+$/, '');
|
|
462
466
|
// Remove protocol prefixes
|
|
463
467
|
cleanPath = cleanPath.replace(/^(?:https?:\/\/[^\/]+\/|file:\/\/\/|webpack:\/\/\/?)/, '');
|
|
464
|
-
const fileName = cleanPath.split('/').pop() || cleanPath;
|
|
468
|
+
const fileName = cleanPath.split('/').filter(Boolean).pop() || cleanPath;
|
|
465
469
|
// Determine file extension (.tsx, .jsx, .ts, .js)
|
|
466
470
|
const extMatch = fileName.match(/\.([a-z0-9]+)$/i);
|
|
467
471
|
const ext = extMatch ? extMatch[1].toLowerCase() : '';
|
package/dist/esm/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import { getReduxState, subscribeReduxState, setReduxAutoRefresh, getLastActionF
|
|
|
22
22
|
import { LIB_VERSION } from './constants';
|
|
23
23
|
// Stylesheet
|
|
24
24
|
import { toggleGlobalTheme } from './styles';
|
|
25
|
-
const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigationRef, }) => {
|
|
25
|
+
const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigationRef, appIcon, environment, }) => {
|
|
26
26
|
// Set custom storage synchronously during render phase
|
|
27
27
|
setCustomStorage(storage || null);
|
|
28
28
|
const [isDark, setIsDark] = useState(false);
|
|
@@ -41,6 +41,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
41
41
|
const [search, setSearch] = useState('');
|
|
42
42
|
const [detailSearch, setDetailSearch] = useState('');
|
|
43
43
|
const [reduxSearch, setReduxSearch] = useState('');
|
|
44
|
+
const [selectedReduxSlice, setSelectedReduxSlice] = useState(null);
|
|
45
|
+
const [selectedReduxAction, setSelectedReduxAction] = useState(null);
|
|
46
|
+
const [reduxActiveSubTab, setReduxActiveSubTab] = useState('state');
|
|
44
47
|
const [apiDetailActiveTab, setApiDetailActiveTab] = useState('response');
|
|
45
48
|
useEffect(() => {
|
|
46
49
|
LogBox.ignoreAllLogs(enabled);
|
|
@@ -147,6 +150,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
147
150
|
logs: true,
|
|
148
151
|
analytics: true,
|
|
149
152
|
redux: false,
|
|
153
|
+
bundle: false,
|
|
154
|
+
performance: false,
|
|
150
155
|
});
|
|
151
156
|
const [maxNetworkLogs, setMaxNetworkLogs] = useState(100);
|
|
152
157
|
const [reduxAutoRefresh, setReduxAutoRefreshState] = useState(true);
|
|
@@ -165,6 +170,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
165
170
|
logs: true,
|
|
166
171
|
analytics: true,
|
|
167
172
|
redux: false,
|
|
173
|
+
bundle: false,
|
|
174
|
+
performance: false,
|
|
168
175
|
});
|
|
169
176
|
setDefaultTab('apis');
|
|
170
177
|
setMaxNetworkLogs(100);
|
|
@@ -222,6 +229,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
222
229
|
logs: true,
|
|
223
230
|
analytics: true,
|
|
224
231
|
redux: false,
|
|
232
|
+
bundle: false,
|
|
233
|
+
performance: false,
|
|
225
234
|
},
|
|
226
235
|
...(saved.tabVisibility || {}),
|
|
227
236
|
apis: true,
|
|
@@ -1089,6 +1098,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1089
1098
|
closeModal,
|
|
1090
1099
|
isReady,
|
|
1091
1100
|
isEnabled,
|
|
1101
|
+
appIcon,
|
|
1102
|
+
environment,
|
|
1092
1103
|
modalHeightPercent,
|
|
1093
1104
|
setModalHeightPercent,
|
|
1094
1105
|
modalAnimationType,
|
|
@@ -1197,6 +1208,12 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1197
1208
|
reduxLastActionMap,
|
|
1198
1209
|
reduxSearch,
|
|
1199
1210
|
setReduxSearch,
|
|
1211
|
+
selectedReduxSlice,
|
|
1212
|
+
setSelectedReduxSlice,
|
|
1213
|
+
selectedReduxAction,
|
|
1214
|
+
setSelectedReduxAction,
|
|
1215
|
+
reduxActiveSubTab,
|
|
1216
|
+
setReduxActiveSubTab,
|
|
1200
1217
|
// ─── Settings ───────────────────────────────────────────────────────
|
|
1201
1218
|
settingsActiveSubTab,
|
|
1202
1219
|
setSettingsActiveSubTab,
|