react-native-inapp-inspector 2.2.2 → 2.2.3
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/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/package.json +2 -1
- package/src/analytics.ts +35 -0
- package/src/bundle.ts +25 -0
- package/src/components/AnalyticsDetail.tsx +865 -0
- package/src/components/AnalyticsEventCard.tsx +441 -0
- package/src/components/AnalyticsGraph.tsx +583 -0
- package/src/components/AnimatedEntrance.tsx +64 -0
- package/src/components/AppHeaderLogo.tsx +109 -0
- package/src/components/BrandCircleIcon.tsx +144 -0
- package/src/components/BrandSquareIcon.tsx +144 -0
- package/src/components/CodeSnippet.tsx +725 -0
- package/src/components/ConsoleLogCard.tsx +628 -0
- package/src/components/CopyButton.tsx +87 -0
- package/src/components/DiffViewer.tsx +82 -0
- package/src/components/DomainHeader.tsx +237 -0
- package/src/components/EmptyState.tsx +73 -0
- package/src/components/EndOfListFooter.tsx +100 -0
- package/src/components/ErrorBoundary.tsx +688 -0
- package/src/components/HeadersSection.tsx +192 -0
- package/src/components/HighlightText.tsx +100 -0
- package/src/components/Inspector/AnalyticsFilterModal.tsx +1250 -0
- package/src/components/Inspector/AnalyticsTab.tsx +1336 -0
- package/src/components/Inspector/BundleTab.tsx +4731 -0
- package/src/components/Inspector/ConsoleTab.tsx +702 -0
- package/src/components/Inspector/CrashDetail.tsx +941 -0
- package/src/components/Inspector/CrashFilterModal.tsx +721 -0
- package/src/components/Inspector/CrashTab.tsx +871 -0
- package/src/components/Inspector/FabLauncher.tsx +80 -0
- package/src/components/Inspector/InspectorContext.tsx +28 -0
- package/src/components/Inspector/InspectorHeader.tsx +973 -0
- package/src/components/Inspector/LogDetail.tsx +1427 -0
- package/src/components/Inspector/MainScreen.tsx +258 -0
- package/src/components/Inspector/NavigationTracker.tsx +13 -0
- package/src/components/Inspector/NetworkDetail.tsx +794 -0
- package/src/components/Inspector/NetworkTab.tsx +1095 -0
- package/src/components/Inspector/NpmUpdateToast.tsx +392 -0
- package/src/components/Inspector/PerformanceTab.tsx +1894 -0
- package/src/components/Inspector/ReduxDetail.tsx +1651 -0
- package/src/components/Inspector/ReduxTab.tsx +954 -0
- package/src/components/Inspector/SettingsPanel.tsx +3181 -0
- package/src/components/Inspector/TabBar.tsx +187 -0
- package/src/components/Inspector/TelemetryConsentModal.tsx +392 -0
- package/src/components/Inspector/UpdateAvailableModal.tsx +545 -0
- package/src/components/JsonViewer.tsx +486 -0
- package/src/components/LogCard.tsx +491 -0
- package/src/components/LogSyntaxHighlighter.tsx +178 -0
- package/src/components/MetaAccordion.tsx +340 -0
- package/src/components/MiniBarChart.tsx +42 -0
- package/src/components/MiniLineChart.tsx +33 -0
- package/src/components/NetworkIcons.tsx +2118 -0
- package/src/components/SectionHeader.tsx +113 -0
- package/src/components/SegmentedTabs.tsx +83 -0
- package/src/components/Slider.tsx +300 -0
- package/src/components/SourcePageCard.tsx +148 -0
- package/src/components/Toast.tsx +131 -0
- package/src/components/TouchableScale.tsx +91 -0
- package/src/components/TreeNode.tsx +186 -0
- package/src/console.ts +24 -0
- package/src/constants/index.ts +38 -0
- package/src/constants/version.ts +3 -0
- package/src/crash.ts +32 -0
- package/src/customHooks/analyticsLogger.ts +336 -0
- package/src/customHooks/bundleAnalyzer.ts +1231 -0
- package/src/customHooks/consoleLogger.ts +497 -0
- package/src/customHooks/crashHandler.ts +944 -0
- package/src/customHooks/logFilters.ts +32 -0
- package/src/customHooks/networkLogger.ts +419 -0
- package/src/customHooks/performanceTracker.ts +1014 -0
- package/src/customHooks/reduxLogger.ts +406 -0
- package/src/customHooks/useAccordion.tsx +60 -0
- package/src/decorators/index.ts +184 -0
- package/src/helpers/gaAnalyticsRegistry.ts +204 -0
- package/src/helpers/index.ts +860 -0
- package/src/helpers/memoryManager.ts +138 -0
- package/src/helpers/searchQueryParser.ts +283 -0
- package/src/helpers/settingsStore.ts +171 -0
- package/src/helpers/telemetry.ts +505 -0
- package/src/helpers/toast.ts +17 -0
- package/src/i18n/index.ts +69 -0
- package/src/i18n/locales/en.json +1052 -0
- package/src/index.tsx +2336 -0
- package/src/native/NativeInspector.ts +397 -0
- package/src/native/NativeNetworkInspector.ts +24 -0
- package/src/network.ts +22 -0
- package/src/performance.ts +38 -0
- package/src/redux.ts +23 -0
- package/src/styles/AppColors.ts +408 -0
- package/src/styles/AppFonts.ts +8 -0
- package/src/styles/common.ts +209 -0
- package/src/styles/index.ts +1570 -0
- package/src/types/enums.ts +194 -0
- package/src/types/index.ts +34 -0
- package/src/types/interfaces.ts +515 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
|
2
|
+
import {useTranslation} from '../i18n';
|
|
3
|
+
import {View, Pressable, Text, Animated} from 'react-native';
|
|
4
|
+
|
|
5
|
+
// Components
|
|
6
|
+
import CopyButton from './CopyButton';
|
|
7
|
+
import TouchableScale from './TouchableScale';
|
|
8
|
+
|
|
9
|
+
// Helpers
|
|
10
|
+
import {copyToClipboard} from '../helpers';
|
|
11
|
+
|
|
12
|
+
// Custom Hooks
|
|
13
|
+
import useAccordion from '../customHooks/useAccordion';
|
|
14
|
+
|
|
15
|
+
// Assets
|
|
16
|
+
import {HeadersIcon, ChevronIcon, CopyIcon} from './NetworkIcons';
|
|
17
|
+
|
|
18
|
+
// Stylesheet
|
|
19
|
+
import {AppColors} from '../styles/AppColors';
|
|
20
|
+
import styles from '../styles';
|
|
21
|
+
|
|
22
|
+
// Type Definition
|
|
23
|
+
import {HeadersSectionProps} from '../types';
|
|
24
|
+
|
|
25
|
+
const HeaderRow = React.memo(function HeaderRow({
|
|
26
|
+
headerKey,
|
|
27
|
+
value,
|
|
28
|
+
isLast,
|
|
29
|
+
index,
|
|
30
|
+
}: {
|
|
31
|
+
headerKey: string;
|
|
32
|
+
value: string;
|
|
33
|
+
isLast: boolean;
|
|
34
|
+
index: number;
|
|
35
|
+
}) {
|
|
36
|
+
const [expanded, setExpanded] = useState(false);
|
|
37
|
+
const isLong = value.length > 35;
|
|
38
|
+
|
|
39
|
+
const entryAnim = useRef(new Animated.Value(0)).current;
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
Animated.timing(entryAnim, {
|
|
43
|
+
toValue: 1,
|
|
44
|
+
duration: 220,
|
|
45
|
+
delay: index * 30,
|
|
46
|
+
useNativeDriver: true,
|
|
47
|
+
}).start();
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
const rowAnimStyle = {
|
|
51
|
+
opacity: entryAnim,
|
|
52
|
+
transform: [
|
|
53
|
+
{
|
|
54
|
+
translateY: entryAnim.interpolate({
|
|
55
|
+
inputRange: [0, 1],
|
|
56
|
+
outputRange: [8, 0],
|
|
57
|
+
}),
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Animated.View
|
|
64
|
+
style={[styles.htRow, !isLast && styles.htRowBorder, rowAnimStyle]}>
|
|
65
|
+
<View style={styles.htKeyCell}>
|
|
66
|
+
<Text style={styles.htKey} numberOfLines={2}>
|
|
67
|
+
{headerKey}
|
|
68
|
+
</Text>
|
|
69
|
+
</View>
|
|
70
|
+
<View style={styles.htCellDivider} />
|
|
71
|
+
<Pressable
|
|
72
|
+
style={styles.htValueCell}
|
|
73
|
+
onPress={() => isLong && setExpanded(v => !v)}
|
|
74
|
+
hitSlop={8}>
|
|
75
|
+
<Text
|
|
76
|
+
style={styles.htValue}
|
|
77
|
+
selectable
|
|
78
|
+
numberOfLines={expanded ? undefined : 3}>
|
|
79
|
+
{value}
|
|
80
|
+
</Text>
|
|
81
|
+
{isLong && (
|
|
82
|
+
<View style={styles.htExpandRow}>
|
|
83
|
+
<Text style={styles.htExpandText}>
|
|
84
|
+
{expanded ? '▲ less' : '▼ more'}
|
|
85
|
+
</Text>
|
|
86
|
+
</View>
|
|
87
|
+
)}
|
|
88
|
+
</Pressable>
|
|
89
|
+
<TouchableScale
|
|
90
|
+
onPress={() => copyToClipboard(value, headerKey)}
|
|
91
|
+
hitSlop={8}
|
|
92
|
+
style={styles.htCopyBtn}>
|
|
93
|
+
<CopyIcon color={AppColors.grayTextWeak} size={14} />
|
|
94
|
+
</TouchableScale>
|
|
95
|
+
</Animated.View>
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const HeadersSection = ({
|
|
100
|
+
title,
|
|
101
|
+
headers,
|
|
102
|
+
search,
|
|
103
|
+
resetKey,
|
|
104
|
+
}: HeadersSectionProps) => {
|
|
105
|
+
const {t} = useTranslation();
|
|
106
|
+
const {toggleOpen, forceOpen, chevronStyle, bodyStyle} = useAccordion(
|
|
107
|
+
false,
|
|
108
|
+
2400,
|
|
109
|
+
300,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
forceOpen(false);
|
|
114
|
+
}, [resetKey]);
|
|
115
|
+
|
|
116
|
+
const entries = useMemo(
|
|
117
|
+
() => (headers ? Object.entries(headers) : []),
|
|
118
|
+
[headers],
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const filtered = useMemo(() => {
|
|
122
|
+
if (!search) return entries;
|
|
123
|
+
const q = search.toLowerCase();
|
|
124
|
+
return entries.filter(
|
|
125
|
+
([k, v]) => k.toLowerCase().includes(q) || v.toLowerCase().includes(q),
|
|
126
|
+
);
|
|
127
|
+
}, [entries, search]);
|
|
128
|
+
|
|
129
|
+
if (entries.length === 0) return null;
|
|
130
|
+
|
|
131
|
+
const isRequest =
|
|
132
|
+
title.toLowerCase().includes('request') ||
|
|
133
|
+
title.toLowerCase().includes('api');
|
|
134
|
+
const accentColor = isRequest ? AppColors.offerPurple : AppColors.greenColor;
|
|
135
|
+
const accentBg = isRequest
|
|
136
|
+
? `${AppColors.offerPurple}10`
|
|
137
|
+
: `${AppColors.greenColor}10`;
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<View style={[styles.htCard, {borderLeftColor: accentColor}]}>
|
|
141
|
+
<Pressable onPress={toggleOpen} hitSlop={10}>
|
|
142
|
+
<View style={styles.htCardHeader}>
|
|
143
|
+
<View style={[styles.htIconWrap, {backgroundColor: accentBg}]}>
|
|
144
|
+
<HeadersIcon color={accentColor} />
|
|
145
|
+
</View>
|
|
146
|
+
<Text style={styles.htTitle}>{title}</Text>
|
|
147
|
+
<View
|
|
148
|
+
style={[
|
|
149
|
+
styles.htBadge,
|
|
150
|
+
{backgroundColor: accentBg, borderColor: accentColor},
|
|
151
|
+
]}>
|
|
152
|
+
<Text style={[styles.htBadgeText, {color: accentColor}]}>
|
|
153
|
+
{entries.length}
|
|
154
|
+
</Text>
|
|
155
|
+
</View>
|
|
156
|
+
<View style={styles.htHeaderSpacer} />
|
|
157
|
+
<CopyButton value={headers} label={title} />
|
|
158
|
+
<View style={styles.htChevronBtn}>
|
|
159
|
+
<Animated.View style={chevronStyle}>
|
|
160
|
+
<ChevronIcon color={AppColors.grayTextStrong} size={14} />
|
|
161
|
+
</Animated.View>
|
|
162
|
+
</View>
|
|
163
|
+
</View>
|
|
164
|
+
</Pressable>
|
|
165
|
+
|
|
166
|
+
<Animated.View style={bodyStyle}>
|
|
167
|
+
<View style={styles.htColHeadRow}>
|
|
168
|
+
<Text style={[styles.htColHead, {width: '30%'}]}>{t('network.jsonViewer.key')}</Text>
|
|
169
|
+
<Text style={[styles.htColHead, {flex: 1}]}>{t('network.jsonViewer.value')}</Text>
|
|
170
|
+
</View>
|
|
171
|
+
|
|
172
|
+
{filtered.length > 0 ? (
|
|
173
|
+
filtered.map(([k, v], i) => (
|
|
174
|
+
<HeaderRow
|
|
175
|
+
key={k}
|
|
176
|
+
headerKey={k}
|
|
177
|
+
value={v}
|
|
178
|
+
isLast={i === filtered.length - 1}
|
|
179
|
+
index={i}
|
|
180
|
+
/>
|
|
181
|
+
))
|
|
182
|
+
) : (
|
|
183
|
+
<View style={styles.htEmpty}>
|
|
184
|
+
<Text style={styles.htEmptyText}>{t('network.noMatchingHeaders')}</Text>
|
|
185
|
+
</View>
|
|
186
|
+
)}
|
|
187
|
+
</Animated.View>
|
|
188
|
+
</View>
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export default HeadersSection;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {Text, Linking} from 'react-native';
|
|
3
|
+
|
|
4
|
+
// Helpers
|
|
5
|
+
import {escapeRegex, handleOpenExternalLink} from '../helpers';
|
|
6
|
+
|
|
7
|
+
const HighlightText = React.memo(function HighlightText({
|
|
8
|
+
text,
|
|
9
|
+
search,
|
|
10
|
+
style,
|
|
11
|
+
highlightStyle,
|
|
12
|
+
detectLinks,
|
|
13
|
+
numberOfLines,
|
|
14
|
+
...rest
|
|
15
|
+
}: any) {
|
|
16
|
+
// Optimization: For huge strings (> 20KB) with no active search, bypass all splitting/regex overhead
|
|
17
|
+
if (!text || (text.length > 20000 && !search && !detectLinks)) {
|
|
18
|
+
return (
|
|
19
|
+
<Text style={style} numberOfLines={numberOfLines} {...rest}>
|
|
20
|
+
{text}
|
|
21
|
+
</Text>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Regex to detect absolute URLs
|
|
26
|
+
const URL_REGEX = /(https?:\/\/[^\s]+)/g;
|
|
27
|
+
|
|
28
|
+
const renderNormalOrHighlighted = (subText: string, keyPrefix: string) => {
|
|
29
|
+
if (!search) {
|
|
30
|
+
return <Text key={keyPrefix}>{subText}</Text>;
|
|
31
|
+
}
|
|
32
|
+
const regex = new RegExp(`(${escapeRegex(search)})`, 'gi');
|
|
33
|
+
const parts = subText.split(regex);
|
|
34
|
+
return (
|
|
35
|
+
<Text key={keyPrefix}>
|
|
36
|
+
{parts.map((part: any, i: number) =>
|
|
37
|
+
part.toLowerCase() === search.toLowerCase() ? (
|
|
38
|
+
<Text key={i} style={highlightStyle}>
|
|
39
|
+
{part}
|
|
40
|
+
</Text>
|
|
41
|
+
) : (
|
|
42
|
+
<Text key={i}>{part}</Text>
|
|
43
|
+
),
|
|
44
|
+
)}
|
|
45
|
+
</Text>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (detectLinks && text && text.length < 20000) {
|
|
50
|
+
const parts = text.split(URL_REGEX);
|
|
51
|
+
return (
|
|
52
|
+
<Text style={style} numberOfLines={numberOfLines} {...rest}>
|
|
53
|
+
{parts.map((part: string, i: number) => {
|
|
54
|
+
if (part.match(URL_REGEX)) {
|
|
55
|
+
return (
|
|
56
|
+
<Text
|
|
57
|
+
key={`link-${i}`}
|
|
58
|
+
style={{
|
|
59
|
+
color: '#007AFF', // skyBlue link color
|
|
60
|
+
textDecorationLine: 'underline',
|
|
61
|
+
}}
|
|
62
|
+
onPress={() => {
|
|
63
|
+
handleOpenExternalLink(part);
|
|
64
|
+
}}>
|
|
65
|
+
{part}
|
|
66
|
+
</Text>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return renderNormalOrHighlighted(part, `text-${i}`);
|
|
70
|
+
})}
|
|
71
|
+
</Text>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!search)
|
|
76
|
+
return (
|
|
77
|
+
<Text style={style} numberOfLines={numberOfLines} {...rest}>
|
|
78
|
+
{text}
|
|
79
|
+
</Text>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const regex = new RegExp(`(${escapeRegex(search)})`, 'gi');
|
|
83
|
+
const parts = text.split(regex);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Text style={style} numberOfLines={numberOfLines} {...rest}>
|
|
87
|
+
{parts.map((part: any, i: number) =>
|
|
88
|
+
part.toLowerCase() === search.toLowerCase() ? (
|
|
89
|
+
<Text key={i} style={highlightStyle}>
|
|
90
|
+
{part}
|
|
91
|
+
</Text>
|
|
92
|
+
) : (
|
|
93
|
+
<Text key={i}>{part}</Text>
|
|
94
|
+
),
|
|
95
|
+
)}
|
|
96
|
+
</Text>
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
export default HighlightText;
|