react-native-inapp-inspector 1.1.35 → 2.0.1
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 +123 -101
- package/android/build.gradle +13 -1
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +890 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
- package/dist/commonjs/components/ConsoleLogCard.js +5 -5
- package/dist/commonjs/components/CopyButton.js +3 -0
- package/dist/commonjs/components/EndOfListFooter.js +1 -1
- package/dist/commonjs/components/ErrorBoundary.js +3 -0
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +25 -73
- package/dist/commonjs/components/Inspector/BundleTab.js +671 -189
- package/dist/commonjs/components/Inspector/ConsoleTab.js +110 -99
- package/dist/commonjs/components/Inspector/CrashTab.js +99 -91
- package/dist/commonjs/components/Inspector/InspectorHeader.js +107 -20
- package/dist/commonjs/components/Inspector/MainScreen.js +111 -68
- package/dist/commonjs/components/Inspector/NetworkTab.js +151 -30
- package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
- package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
- package/dist/commonjs/components/Inspector/SettingsPanel.js +1218 -1238
- package/dist/commonjs/components/Inspector/TabBar.js +4 -2
- package/dist/commonjs/components/JsonViewer.js +9 -4
- package/dist/commonjs/components/LogCard.js +31 -1
- package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
- package/dist/commonjs/components/NetworkIcons.d.ts +3 -0
- package/dist/commonjs/components/NetworkIcons.js +15 -1
- package/dist/commonjs/components/Slider.d.ts +13 -0
- package/dist/commonjs/components/Slider.js +261 -0
- package/dist/commonjs/components/TouchableScale.d.ts +1 -0
- package/dist/commonjs/components/TouchableScale.js +30 -32
- package/dist/commonjs/constants/index.d.ts +1 -2
- package/dist/commonjs/constants/index.js +4 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +4 -0
- package/dist/commonjs/customHooks/analyticsLogger.js +8 -6
- package/dist/commonjs/customHooks/crashHandler.js +8 -1
- package/dist/commonjs/helpers/index.d.ts +1 -0
- package/dist/commonjs/helpers/index.js +25 -1
- package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
- package/dist/commonjs/helpers/searchQueryParser.js +236 -0
- package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
- package/dist/commonjs/helpers/settingsStore.js +59 -3
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +220 -43
- package/dist/commonjs/native/NativeInspector.d.ts +125 -0
- package/dist/commonjs/native/NativeInspector.js +313 -0
- package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
- package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
- package/dist/commonjs/styles/index.js +41 -41
- package/dist/commonjs/types/enums.d.ts +1 -1
- package/dist/commonjs/types/interfaces.d.ts +9 -0
- package/dist/esm/components/ConsoleLogCard.js +5 -5
- package/dist/esm/components/CopyButton.js +3 -0
- package/dist/esm/components/EndOfListFooter.js +2 -2
- package/dist/esm/components/ErrorBoundary.js +3 -0
- package/dist/esm/components/Inspector/AnalyticsTab.js +27 -75
- package/dist/esm/components/Inspector/BundleTab.js +671 -189
- package/dist/esm/components/Inspector/ConsoleTab.js +111 -100
- package/dist/esm/components/Inspector/CrashTab.js +99 -91
- package/dist/esm/components/Inspector/InspectorHeader.js +108 -21
- package/dist/esm/components/Inspector/MainScreen.js +113 -70
- package/dist/esm/components/Inspector/NetworkTab.js +152 -31
- package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
- package/dist/esm/components/Inspector/ReduxTab.js +18 -10
- package/dist/esm/components/Inspector/SettingsPanel.js +1222 -1242
- package/dist/esm/components/Inspector/TabBar.js +4 -2
- package/dist/esm/components/JsonViewer.js +9 -4
- package/dist/esm/components/LogCard.js +32 -2
- package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
- package/dist/esm/components/NetworkIcons.d.ts +3 -0
- package/dist/esm/components/NetworkIcons.js +11 -0
- package/dist/esm/components/Slider.d.ts +13 -0
- package/dist/esm/components/Slider.js +222 -0
- package/dist/esm/components/TouchableScale.d.ts +1 -0
- package/dist/esm/components/TouchableScale.js +31 -33
- package/dist/esm/constants/index.d.ts +1 -2
- package/dist/esm/constants/index.js +4 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
- package/dist/esm/customHooks/analyticsLogger.js +6 -5
- package/dist/esm/customHooks/crashHandler.js +8 -1
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +11 -1
- package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
- package/dist/esm/helpers/searchQueryParser.js +233 -0
- package/dist/esm/helpers/settingsStore.d.ts +9 -0
- package/dist/esm/helpers/settingsStore.js +58 -3
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +207 -44
- package/dist/esm/native/NativeInspector.d.ts +125 -0
- package/dist/esm/native/NativeInspector.js +289 -0
- package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
- package/dist/esm/native/NativeNetworkInspector.js +2 -0
- package/dist/esm/styles/index.js +41 -41
- package/dist/esm/types/enums.d.ts +1 -1
- package/dist/esm/types/interfaces.d.ts +9 -0
- package/ios/NetworkInspectorModule.h +6 -0
- package/ios/NetworkInspectorModule.m +760 -5
- package/package.json +13 -2
- package/react-native-inapp-inspector.podspec +7 -2
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
- package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +0 -28
|
@@ -10,7 +10,7 @@ import EndOfListFooter from '../EndOfListFooter';
|
|
|
10
10
|
import styles from '../../styles';
|
|
11
11
|
import { AppColors } from '../../styles/AppColors';
|
|
12
12
|
import { AppFonts } from '../../styles/AppFonts';
|
|
13
|
-
import { SearchIcon, ClearIcon, SortArrowIcon, TrashIcon, LayersIcon,
|
|
13
|
+
import { SearchIcon, ClearIcon, SortArrowIcon, TrashIcon, LayersIcon, UserIcon, InfoCircleIcon, WarningTriangleIcon, ErrorCircleIcon, AnalyticsIcon, HeaderPauseIcon, } from '../NetworkIcons';
|
|
14
14
|
const ConsoleTab = React.memo(() => {
|
|
15
15
|
const { t } = useTranslation();
|
|
16
16
|
const { logSearch, setLogSearch, logSortOrder, setLogSortOrder, handleDelete, logFilters, setLogFilters, logCounts, filteredConsoleLogs, visibleConsoleLogs, isConsolePaused, setIsConsolePaused, } = useInspector();
|
|
@@ -51,6 +51,8 @@ const ConsoleTab = React.memo(() => {
|
|
|
51
51
|
</Text>);
|
|
52
52
|
}
|
|
53
53
|
}, [visibleConsoleLogs.length, filteredConsoleLogs.length, logFilters]);
|
|
54
|
+
const [isSearchFocused, setIsSearchFocused] = React.useState(false);
|
|
55
|
+
const QUICK_TAG_SUGGESTIONS = useMemo(() => ['[AXIOS]', '[API]', '[REDUX]', '[ANALYTICS]', '[AUTH]', '[WARN]', '[ERROR]'], []);
|
|
54
56
|
return (<View style={{ flex: 1 }}>
|
|
55
57
|
<View style={{
|
|
56
58
|
backgroundColor: AppColors.white,
|
|
@@ -62,12 +64,38 @@ const ConsoleTab = React.memo(() => {
|
|
|
62
64
|
styles.toolbarRow,
|
|
63
65
|
{ marginTop: 12, marginBottom: 8 },
|
|
64
66
|
]}>
|
|
65
|
-
<View style={
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
<View style={[
|
|
68
|
+
styles.searchContainer,
|
|
69
|
+
isSearchFocused && {
|
|
70
|
+
borderColor: AppColors.purple,
|
|
71
|
+
borderWidth: 1.5,
|
|
72
|
+
},
|
|
73
|
+
]}>
|
|
74
|
+
<SearchIcon color={isSearchFocused ? AppColors.purple : AppColors.grayTextWeak} size={16}/>
|
|
75
|
+
<TextInput placeholder={t('console.searchPlaceholder')} placeholderTextColor={AppColors.grayTextWeak} value={logSearch} onChangeText={setLogSearch} onFocus={() => setIsSearchFocused(true)} onBlur={() => setIsSearchFocused(false)} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
76
|
+
{logSearch.length > 0 && (<View style={{
|
|
77
|
+
flexDirection: 'row',
|
|
78
|
+
alignItems: 'center',
|
|
79
|
+
gap: 4,
|
|
80
|
+
}}>
|
|
81
|
+
<View style={{
|
|
82
|
+
backgroundColor: `${AppColors.purple}20`,
|
|
83
|
+
borderRadius: 10,
|
|
84
|
+
paddingHorizontal: 6,
|
|
85
|
+
paddingVertical: 2,
|
|
86
|
+
}}>
|
|
87
|
+
<Text style={{
|
|
88
|
+
color: AppColors.purple,
|
|
89
|
+
fontSize: 10,
|
|
90
|
+
fontFamily: AppFonts.interBold,
|
|
91
|
+
}}>
|
|
92
|
+
{filteredConsoleLogs.length}
|
|
93
|
+
</Text>
|
|
94
|
+
</View>
|
|
95
|
+
<Pressable onPress={() => setLogSearch('')} hitSlop={10} style={styles.clearBtn}>
|
|
96
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
97
|
+
</Pressable>
|
|
98
|
+
</View>)}
|
|
71
99
|
</View>
|
|
72
100
|
|
|
73
101
|
<View style={styles.toolbarRight}>
|
|
@@ -97,6 +125,49 @@ const ConsoleTab = React.memo(() => {
|
|
|
97
125
|
</View>
|
|
98
126
|
</View>
|
|
99
127
|
|
|
128
|
+
{/* Quick Tag Search Suggestions Bar */}
|
|
129
|
+
{(isSearchFocused || logSearch.length > 0) && (<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginBottom: 6, maxHeight: 30 }} contentContainerStyle={{
|
|
130
|
+
paddingHorizontal: 16,
|
|
131
|
+
flexDirection: 'row',
|
|
132
|
+
alignItems: 'center',
|
|
133
|
+
gap: 6,
|
|
134
|
+
}}>
|
|
135
|
+
{QUICK_TAG_SUGGESTIONS.map(tag => {
|
|
136
|
+
const isSelected = logSearch.includes(tag);
|
|
137
|
+
return (<TouchableScale key={tag} onPress={() => {
|
|
138
|
+
if (isSelected) {
|
|
139
|
+
setLogSearch(prev => prev.replace(tag, '').trim());
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
setLogSearch(prev => prev ? `${prev} ${tag}`.trim() : tag);
|
|
143
|
+
}
|
|
144
|
+
}}>
|
|
145
|
+
<View style={{
|
|
146
|
+
paddingHorizontal: 8,
|
|
147
|
+
paddingVertical: 3,
|
|
148
|
+
borderRadius: 6,
|
|
149
|
+
backgroundColor: isSelected
|
|
150
|
+
? AppColors.purple
|
|
151
|
+
: `${AppColors.purple}14`,
|
|
152
|
+
borderWidth: 1,
|
|
153
|
+
borderColor: isSelected
|
|
154
|
+
? AppColors.purple
|
|
155
|
+
: `${AppColors.purple}30`,
|
|
156
|
+
}}>
|
|
157
|
+
<Text style={{
|
|
158
|
+
fontFamily: AppFonts.interBold,
|
|
159
|
+
fontSize: 10,
|
|
160
|
+
color: isSelected
|
|
161
|
+
? AppColors.white
|
|
162
|
+
: AppColors.purple,
|
|
163
|
+
}}>
|
|
164
|
+
{tag}
|
|
165
|
+
</Text>
|
|
166
|
+
</View>
|
|
167
|
+
</TouchableScale>);
|
|
168
|
+
})}
|
|
169
|
+
</ScrollView>)}
|
|
170
|
+
|
|
100
171
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginVertical: 4, maxHeight: 46 }} contentContainerStyle={{
|
|
101
172
|
paddingHorizontal: 16,
|
|
102
173
|
paddingBottom: 4,
|
|
@@ -115,7 +186,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
115
186
|
{
|
|
116
187
|
backgroundColor: active ? AppColors.indigo600Alt : AppColors.indigo50,
|
|
117
188
|
borderColor: active ? AppColors.indigo600 : AppColors.indigo400,
|
|
118
|
-
borderRadius:
|
|
189
|
+
borderRadius: 8,
|
|
190
|
+
paddingHorizontal: 10,
|
|
191
|
+
paddingVertical: 6,
|
|
119
192
|
},
|
|
120
193
|
active && {
|
|
121
194
|
shadowColor: AppColors.indigo600Alt,
|
|
@@ -128,21 +201,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
128
201
|
<View style={{
|
|
129
202
|
flexDirection: 'row',
|
|
130
203
|
alignItems: 'center',
|
|
131
|
-
gap:
|
|
132
|
-
}}>
|
|
133
|
-
<View style={{
|
|
134
|
-
width: 12,
|
|
135
|
-
height: 12,
|
|
136
|
-
borderRadius: 3,
|
|
137
|
-
borderWidth: 1.2,
|
|
138
|
-
borderColor: active ? AppColors.white : AppColors.indigo400,
|
|
139
|
-
backgroundColor: active ? AppColors.white : 'transparent',
|
|
140
|
-
alignItems: 'center',
|
|
141
|
-
justifyContent: 'center',
|
|
204
|
+
gap: 6,
|
|
142
205
|
}}>
|
|
143
|
-
|
|
144
|
-
</View>
|
|
145
|
-
<LayersIcon size={12} color={active ? AppColors.white : AppColors.indigo600Alt}/>
|
|
206
|
+
<LayersIcon size={13} color={active ? AppColors.white : AppColors.indigo600Alt}/>
|
|
146
207
|
<Text numberOfLines={1} style={[
|
|
147
208
|
styles.statusFilterText,
|
|
148
209
|
{
|
|
@@ -177,7 +238,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
177
238
|
{
|
|
178
239
|
backgroundColor: active ? AppColors.teal600 : AppColors.teal100,
|
|
179
240
|
borderColor: active ? AppColors.teal600 : AppColors.teal400,
|
|
180
|
-
borderRadius:
|
|
241
|
+
borderRadius: 8,
|
|
242
|
+
paddingHorizontal: 10,
|
|
243
|
+
paddingVertical: 6,
|
|
181
244
|
},
|
|
182
245
|
active && {
|
|
183
246
|
shadowColor: AppColors.teal600,
|
|
@@ -190,21 +253,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
190
253
|
<View style={{
|
|
191
254
|
flexDirection: 'row',
|
|
192
255
|
alignItems: 'center',
|
|
193
|
-
gap:
|
|
256
|
+
gap: 6,
|
|
194
257
|
}}>
|
|
195
|
-
<
|
|
196
|
-
width: 12,
|
|
197
|
-
height: 12,
|
|
198
|
-
borderRadius: 3,
|
|
199
|
-
borderWidth: 1.2,
|
|
200
|
-
borderColor: active ? AppColors.white : AppColors.teal400,
|
|
201
|
-
backgroundColor: active ? AppColors.white : 'transparent',
|
|
202
|
-
alignItems: 'center',
|
|
203
|
-
justifyContent: 'center',
|
|
204
|
-
}}>
|
|
205
|
-
{active && <CheckIcon color={AppColors.teal600} size={8}/>}
|
|
206
|
-
</View>
|
|
207
|
-
<UserIcon size={12} color={active ? AppColors.white : AppColors.teal600}/>
|
|
258
|
+
<UserIcon size={13} color={active ? AppColors.white : AppColors.teal600}/>
|
|
208
259
|
<Text numberOfLines={1} style={[
|
|
209
260
|
styles.statusFilterText,
|
|
210
261
|
{
|
|
@@ -239,7 +290,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
239
290
|
{
|
|
240
291
|
backgroundColor: active ? AppColors.sky600 : AppColors.sky100,
|
|
241
292
|
borderColor: active ? AppColors.blue700 : AppColors.sky400,
|
|
242
|
-
borderRadius:
|
|
293
|
+
borderRadius: 8,
|
|
294
|
+
paddingHorizontal: 10,
|
|
295
|
+
paddingVertical: 6,
|
|
243
296
|
},
|
|
244
297
|
active && {
|
|
245
298
|
shadowColor: AppColors.sky600,
|
|
@@ -252,21 +305,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
252
305
|
<View style={{
|
|
253
306
|
flexDirection: 'row',
|
|
254
307
|
alignItems: 'center',
|
|
255
|
-
gap:
|
|
308
|
+
gap: 6,
|
|
256
309
|
}}>
|
|
257
|
-
<
|
|
258
|
-
width: 12,
|
|
259
|
-
height: 12,
|
|
260
|
-
borderRadius: 3,
|
|
261
|
-
borderWidth: 1.2,
|
|
262
|
-
borderColor: active ? AppColors.white : AppColors.sky400,
|
|
263
|
-
backgroundColor: active ? AppColors.white : 'transparent',
|
|
264
|
-
alignItems: 'center',
|
|
265
|
-
justifyContent: 'center',
|
|
266
|
-
}}>
|
|
267
|
-
{active && <CheckIcon color={AppColors.sky600} size={8}/>}
|
|
268
|
-
</View>
|
|
269
|
-
<InfoCircleIcon size={12} color={active ? AppColors.white : AppColors.sky600}/>
|
|
310
|
+
<InfoCircleIcon size={13} color={active ? AppColors.white : AppColors.sky600}/>
|
|
270
311
|
<Text numberOfLines={1} style={[
|
|
271
312
|
styles.statusFilterText,
|
|
272
313
|
{
|
|
@@ -301,7 +342,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
301
342
|
{
|
|
302
343
|
backgroundColor: active ? AppColors.amber600 : AppColors.amber100,
|
|
303
344
|
borderColor: active ? AppColors.amber700 : AppColors.amber200,
|
|
304
|
-
borderRadius:
|
|
345
|
+
borderRadius: 8,
|
|
346
|
+
paddingHorizontal: 10,
|
|
347
|
+
paddingVertical: 6,
|
|
305
348
|
},
|
|
306
349
|
active && {
|
|
307
350
|
shadowColor: AppColors.amber600,
|
|
@@ -314,21 +357,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
314
357
|
<View style={{
|
|
315
358
|
flexDirection: 'row',
|
|
316
359
|
alignItems: 'center',
|
|
317
|
-
gap:
|
|
318
|
-
}}>
|
|
319
|
-
<View style={{
|
|
320
|
-
width: 12,
|
|
321
|
-
height: 12,
|
|
322
|
-
borderRadius: 3,
|
|
323
|
-
borderWidth: 1.2,
|
|
324
|
-
borderColor: active ? AppColors.white : AppColors.amber500,
|
|
325
|
-
backgroundColor: active ? AppColors.white : 'transparent',
|
|
326
|
-
alignItems: 'center',
|
|
327
|
-
justifyContent: 'center',
|
|
360
|
+
gap: 6,
|
|
328
361
|
}}>
|
|
329
|
-
|
|
330
|
-
</View>
|
|
331
|
-
<WarningTriangleIcon size={12} color={active ? AppColors.white : AppColors.amber700}/>
|
|
362
|
+
<WarningTriangleIcon size={13} color={active ? AppColors.white : AppColors.amber700}/>
|
|
332
363
|
<Text numberOfLines={1} style={[
|
|
333
364
|
styles.statusFilterText,
|
|
334
365
|
{
|
|
@@ -363,7 +394,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
363
394
|
{
|
|
364
395
|
backgroundColor: active ? AppColors.red500 : AppColors.red100,
|
|
365
396
|
borderColor: active ? AppColors.red600 : AppColors.errorBorder,
|
|
366
|
-
borderRadius:
|
|
397
|
+
borderRadius: 8,
|
|
398
|
+
paddingHorizontal: 10,
|
|
399
|
+
paddingVertical: 6,
|
|
367
400
|
},
|
|
368
401
|
active && {
|
|
369
402
|
shadowColor: AppColors.red500,
|
|
@@ -376,21 +409,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
376
409
|
<View style={{
|
|
377
410
|
flexDirection: 'row',
|
|
378
411
|
alignItems: 'center',
|
|
379
|
-
gap:
|
|
380
|
-
}}>
|
|
381
|
-
<View style={{
|
|
382
|
-
width: 12,
|
|
383
|
-
height: 12,
|
|
384
|
-
borderRadius: 3,
|
|
385
|
-
borderWidth: 1.2,
|
|
386
|
-
borderColor: active ? AppColors.white : AppColors.red500,
|
|
387
|
-
backgroundColor: active ? AppColors.white : 'transparent',
|
|
388
|
-
alignItems: 'center',
|
|
389
|
-
justifyContent: 'center',
|
|
412
|
+
gap: 6,
|
|
390
413
|
}}>
|
|
391
|
-
|
|
392
|
-
</View>
|
|
393
|
-
<ErrorCircleIcon size={12} color={active ? AppColors.white : AppColors.red500}/>
|
|
414
|
+
<ErrorCircleIcon size={13} color={active ? AppColors.white : AppColors.red500}/>
|
|
394
415
|
<Text numberOfLines={1} style={[
|
|
395
416
|
styles.statusFilterText,
|
|
396
417
|
{
|
|
@@ -425,7 +446,9 @@ const ConsoleTab = React.memo(() => {
|
|
|
425
446
|
{
|
|
426
447
|
backgroundColor: active ? AppColors.violet600 : AppColors.purple100,
|
|
427
448
|
borderColor: active ? AppColors.purple700 : AppColors.purple200,
|
|
428
|
-
borderRadius:
|
|
449
|
+
borderRadius: 8,
|
|
450
|
+
paddingHorizontal: 10,
|
|
451
|
+
paddingVertical: 6,
|
|
429
452
|
},
|
|
430
453
|
active && {
|
|
431
454
|
shadowColor: AppColors.violet600,
|
|
@@ -438,29 +461,17 @@ const ConsoleTab = React.memo(() => {
|
|
|
438
461
|
<View style={{
|
|
439
462
|
flexDirection: 'row',
|
|
440
463
|
alignItems: 'center',
|
|
441
|
-
gap:
|
|
442
|
-
}}>
|
|
443
|
-
<View style={{
|
|
444
|
-
width: 12,
|
|
445
|
-
height: 12,
|
|
446
|
-
borderRadius: 3,
|
|
447
|
-
borderWidth: 1.2,
|
|
448
|
-
borderColor: active ? AppColors.white : AppColors.purple400,
|
|
449
|
-
backgroundColor: active ? AppColors.white : 'transparent',
|
|
450
|
-
alignItems: 'center',
|
|
451
|
-
justifyContent: 'center',
|
|
464
|
+
gap: 6,
|
|
452
465
|
}}>
|
|
453
|
-
|
|
454
|
-
</View>
|
|
455
|
-
<AnalyticsIcon size={12} color={active ? AppColors.white : AppColors.purple}/>
|
|
466
|
+
<AnalyticsIcon size={13} color={active ? AppColors.white : AppColors.violet600}/>
|
|
456
467
|
<Text numberOfLines={1} style={[
|
|
457
468
|
styles.statusFilterText,
|
|
458
469
|
{
|
|
459
|
-
color: active ? AppColors.white : AppColors.
|
|
470
|
+
color: active ? AppColors.white : AppColors.purpleText,
|
|
460
471
|
fontFamily: AppFonts.interBold,
|
|
461
472
|
},
|
|
462
473
|
]}>
|
|
463
|
-
{t('
|
|
474
|
+
{t('console.analytics', 'Analytics')} ({logCounts.analytics})
|
|
464
475
|
</Text>
|
|
465
476
|
</View>
|
|
466
477
|
</View>
|
|
@@ -469,7 +480,7 @@ const ConsoleTab = React.memo(() => {
|
|
|
469
480
|
</ScrollView>
|
|
470
481
|
</View>
|
|
471
482
|
|
|
472
|
-
<FlatList data={filteredConsoleLogs} keyExtractor={keyExtractor} ListHeaderComponent={listHeader} renderItem={renderItem} initialNumToRender={
|
|
483
|
+
<FlatList data={filteredConsoleLogs} keyExtractor={keyExtractor} ListHeaderComponent={listHeader} renderItem={renderItem} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} ListEmptyComponent={<EmptyState isSearch={logSearch.length > 0 || logFilters.size > 0}/>} ListFooterComponent={filteredConsoleLogs.length > 0 ? (<EndOfListFooter count={filteredConsoleLogs.length} label="logs"/>) : null} contentContainerStyle={[
|
|
473
484
|
styles.listContent,
|
|
474
485
|
filteredConsoleLogs.length === 0 && { flexGrow: 1 },
|
|
475
486
|
]} keyboardShouldPersistTaps="handled"/>
|
|
@@ -109,11 +109,16 @@ const CrashTab = React.memo(() => {
|
|
|
109
109
|
}
|
|
110
110
|
// Search filter
|
|
111
111
|
if (searchQuery.trim().length > 0) {
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
const queryTokens = searchQuery.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
113
|
+
const searchTarget = [
|
|
114
|
+
item.message || '',
|
|
115
|
+
item.name || '',
|
|
116
|
+
item.stack || '',
|
|
117
|
+
item.type || '',
|
|
118
|
+
item.deviceInfo?.platform || '',
|
|
119
|
+
...(item.breadcrumbs || []).map(b => `${b.type || ''} ${b.message || ''}`),
|
|
120
|
+
].join(' ').toLowerCase();
|
|
121
|
+
return queryTokens.every(token => searchTarget.includes(token));
|
|
117
122
|
}
|
|
118
123
|
return true;
|
|
119
124
|
});
|
|
@@ -250,74 +255,75 @@ const CrashTab = React.memo(() => {
|
|
|
250
255
|
</AnimatedEntrance>);
|
|
251
256
|
}, [searchQuery, setSelectedCrash]);
|
|
252
257
|
return (<View style={localStyles.container}>
|
|
253
|
-
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
258
|
+
{crashRecords.length > 0 && (<>
|
|
259
|
+
{/* ─── Top Stats Bar ─── */}
|
|
260
|
+
<View style={localStyles.statsBar}>
|
|
261
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.statsScrollContent}>
|
|
262
|
+
<View style={[localStyles.statChip, localStyles.statChipActive]}>
|
|
263
|
+
<Text style={localStyles.statChipValue}>{stats.total}</Text>
|
|
264
|
+
<Text style={localStyles.statChipLabel}>{t('crash.statCrashes')}</Text>
|
|
265
|
+
</View>
|
|
260
266
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
<View style={localStyles.statChip}>
|
|
268
|
+
<Text style={[localStyles.statChipValue, { color: AppColors.errorColor }]}>
|
|
269
|
+
{stats.fatalCount}
|
|
270
|
+
</Text>
|
|
271
|
+
<Text style={localStyles.statChipLabel}>{t('crash.statFatal')}</Text>
|
|
272
|
+
</View>
|
|
267
273
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
<View style={localStyles.statChip}>
|
|
275
|
+
<Text style={[localStyles.statChipValue, { color: AppColors.offerPurple }]}>
|
|
276
|
+
{stats.jsCount}
|
|
277
|
+
</Text>
|
|
278
|
+
<Text style={localStyles.statChipLabel}>{t('crash.statJsErrors')}</Text>
|
|
279
|
+
</View>
|
|
274
280
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
+
<View style={localStyles.statChip}>
|
|
282
|
+
<Text style={[localStyles.statChipValue, { color: AppColors.darkOrange }]}>
|
|
283
|
+
{stats.promiseCount}
|
|
284
|
+
</Text>
|
|
285
|
+
<Text style={localStyles.statChipLabel}>{t('crash.statPromises')}</Text>
|
|
286
|
+
</View>
|
|
281
287
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
+
<View style={localStyles.statChip}>
|
|
289
|
+
<Text style={[localStyles.statChipValue, { color: AppColors.purple }]}>
|
|
290
|
+
{stats.renderCount}
|
|
291
|
+
</Text>
|
|
292
|
+
<Text style={localStyles.statChipLabel}>{t('crash.statRender')}</Text>
|
|
293
|
+
</View>
|
|
288
294
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
295
|
+
<View style={localStyles.statChip}>
|
|
296
|
+
<Text style={[localStyles.statChipValue, { color: AppColors.skyBlue }]}>
|
|
297
|
+
{stats.nativeCount}
|
|
298
|
+
</Text>
|
|
299
|
+
<Text style={localStyles.statChipLabel}>{t('crash.statNative')}</Text>
|
|
300
|
+
</View>
|
|
301
|
+
</ScrollView>
|
|
294
302
|
</View>
|
|
295
|
-
</ScrollView>
|
|
296
|
-
</View>
|
|
297
303
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
304
|
+
{/* ─── Search & Controls ─── */}
|
|
305
|
+
<View style={localStyles.controlsContainer}>
|
|
306
|
+
<View style={localStyles.searchRow}>
|
|
307
|
+
<View style={localStyles.searchInputWrapper}>
|
|
308
|
+
<SearchIcon color={AppColors.grayTextWeak} size={14}/>
|
|
309
|
+
<TextInput value={searchQuery} onChangeText={setSearchQuery} placeholder={t('crash.searchPlaceholder')} placeholderTextColor={AppColors.grayTextWeak} style={localStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
|
|
310
|
+
{searchQuery.length > 0 && (<TouchableOpacity onPress={() => setSearchQuery('')} hitSlop={8}>
|
|
311
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
312
|
+
</TouchableOpacity>)}
|
|
313
|
+
</View>
|
|
308
314
|
|
|
309
|
-
|
|
310
|
-
|
|
315
|
+
{/* Crash Filters */}
|
|
316
|
+
<TouchableScale onPress={() => setIsFilterModalOpen(true)} style={[
|
|
311
317
|
localStyles.filterButton,
|
|
312
318
|
!isCrashFiltersDefault(crashFilters) && {
|
|
313
319
|
borderColor: `${AppColors.brandPurple}60`,
|
|
314
320
|
backgroundColor: `${AppColors.brandPurple}15`,
|
|
315
321
|
},
|
|
316
322
|
]}>
|
|
317
|
-
|
|
323
|
+
<FilterIcon size={14} color={isCrashFiltersDefault(crashFilters)
|
|
318
324
|
? AppColors.grayTextStrong
|
|
319
325
|
: AppColors.brandPurple}/>
|
|
320
|
-
|
|
326
|
+
{!isCrashFiltersDefault(crashFilters) && (<View style={{
|
|
321
327
|
position: 'absolute',
|
|
322
328
|
top: 2,
|
|
323
329
|
right: 2,
|
|
@@ -328,40 +334,41 @@ const CrashTab = React.memo(() => {
|
|
|
328
334
|
borderWidth: 1,
|
|
329
335
|
borderColor: AppColors.white,
|
|
330
336
|
}}/>)}
|
|
331
|
-
|
|
337
|
+
</TouchableScale>
|
|
332
338
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
339
|
+
{/* Clear Crashes */}
|
|
340
|
+
<TouchableScale onPress={handleClearAll} style={localStyles.clearButton}>
|
|
341
|
+
<TrashIcon size={14} color={AppColors.errorColor}/>
|
|
342
|
+
</TouchableScale>
|
|
343
|
+
</View>
|
|
338
344
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
345
|
+
{/* ─── Filter Chips ─── */}
|
|
346
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={localStyles.filterScrollContent}>
|
|
347
|
+
{[
|
|
348
|
+
{ key: 'all', label: t('crash.filterAll'), Icon: LayersIcon },
|
|
349
|
+
{ key: 'fatal', label: t('crash.filterFatal'), Icon: SkullIcon },
|
|
350
|
+
{ key: 'js', label: t('crash.filterJsError'), Icon: JsIcon },
|
|
351
|
+
{ key: 'promise', label: t('crash.filterPromise'), Icon: HourglassIcon },
|
|
352
|
+
{ key: 'render', label: t('crash.filterRender'), Icon: LayoutIcon },
|
|
353
|
+
{ key: 'native', label: t('crash.filterNative'), Icon: ChipIcon },
|
|
354
|
+
].map(chip => {
|
|
355
|
+
const isActive = filterType === chip.key;
|
|
356
|
+
return (<TouchableOpacity key={chip.key} onPress={() => setFilterType(chip.key)} style={[
|
|
357
|
+
localStyles.filterChip,
|
|
358
|
+
isActive && localStyles.filterChipActive,
|
|
359
|
+
]}>
|
|
360
|
+
<chip.Icon size={12} color={isActive ? AppColors.white : AppColors.grayTextStrong}/>
|
|
361
|
+
<Text style={[
|
|
362
|
+
localStyles.filterChipText,
|
|
363
|
+
isActive && localStyles.filterChipTextActive,
|
|
364
|
+
]}>
|
|
365
|
+
{chip.label}
|
|
366
|
+
</Text>
|
|
367
|
+
</TouchableOpacity>);
|
|
368
|
+
})}
|
|
369
|
+
</ScrollView>
|
|
370
|
+
</View>
|
|
371
|
+
</>)}
|
|
365
372
|
|
|
366
373
|
{/* ─── Crash List or Empty State ─── */}
|
|
367
374
|
{filteredList.length === 0 ? (<ScrollView contentContainerStyle={localStyles.emptyContainer} showsVerticalScrollIndicator={false}>
|
|
@@ -374,7 +381,7 @@ const CrashTab = React.memo(() => {
|
|
|
374
381
|
? t('crash.emptySearchSubtitle')
|
|
375
382
|
: t('crash.emptySubtitle')}
|
|
376
383
|
</Text>
|
|
377
|
-
</ScrollView>) : (<FlatList data={filteredList} keyExtractor={item => item.id} renderItem={renderCard} contentContainerStyle={localStyles.listContent} showsVerticalScrollIndicator={false} ListFooterComponent={<EndOfListFooter />}/>)}
|
|
384
|
+
</ScrollView>) : (<FlatList data={filteredList} keyExtractor={item => item.id} renderItem={renderCard} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} contentContainerStyle={localStyles.listContent} showsVerticalScrollIndicator={false} ListFooterComponent={<EndOfListFooter />}/>)}
|
|
378
385
|
|
|
379
386
|
{/* Filter Modal */}
|
|
380
387
|
<CrashFilterModal visible={isFilterModalOpen} onClose={() => setIsFilterModalOpen(false)} filters={crashFilters} onApply={setCrashFilters} searchQuery={searchQuery}/>
|
|
@@ -650,10 +657,11 @@ const localStyles = StyleSheet.create({
|
|
|
650
657
|
color: AppColors.grayTextWeak,
|
|
651
658
|
},
|
|
652
659
|
emptyContainer: {
|
|
660
|
+
flexGrow: 1,
|
|
653
661
|
alignItems: 'center',
|
|
654
662
|
justifyContent: 'center',
|
|
655
663
|
padding: 32,
|
|
656
|
-
|
|
664
|
+
paddingBottom: 80,
|
|
657
665
|
},
|
|
658
666
|
emptyIconCircle: {
|
|
659
667
|
width: 72,
|