react-native-inapp-inspector 2.3.14 → 2.3.15
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/AnimatedEntrance.js +3 -3
- package/dist/commonjs/components/ConsoleLogCard.js +174 -100
- package/dist/commonjs/components/Inspector/ConsoleTab.js +25 -16
- package/dist/commonjs/components/Inspector/CrashTab.js +19 -5
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +198 -98
- package/dist/commonjs/components/Inspector/InspectorHeader.js +2 -2
- package/dist/commonjs/components/Inspector/MainScreen.js +56 -56
- package/dist/commonjs/components/Inspector/NetworkTab.js +1 -335
- package/dist/commonjs/components/Inspector/PerformanceTab.js +32 -6
- package/dist/commonjs/components/Inspector/ReduxTab.js +3 -1
- package/dist/commonjs/components/Inspector/StorageTab.js +23 -5
- package/dist/commonjs/components/JsonViewer.js +14 -2
- package/dist/commonjs/components/LogCard.js +428 -227
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
- package/dist/commonjs/customHooks/consoleLogger.js +34 -2
- package/dist/commonjs/customHooks/crashHandler.js +1 -1
- package/dist/commonjs/customHooks/networkLogger.js +184 -26
- package/dist/commonjs/helpers/searchQueryParser.d.ts +1 -1
- package/dist/commonjs/helpers/searchQueryParser.js +37 -291
- package/dist/commonjs/index.js +141 -27
- package/dist/esm/components/AnimatedEntrance.js +3 -3
- package/dist/esm/components/ConsoleLogCard.js +141 -100
- package/dist/esm/components/Inspector/ConsoleTab.js +25 -16
- package/dist/esm/components/Inspector/CrashTab.js +19 -5
- package/dist/esm/components/Inspector/DeviceInfoTab.js +198 -98
- package/dist/esm/components/Inspector/InspectorHeader.js +3 -3
- package/dist/esm/components/Inspector/MainScreen.js +56 -56
- package/dist/esm/components/Inspector/NetworkTab.js +2 -336
- package/dist/esm/components/Inspector/PerformanceTab.js +32 -6
- package/dist/esm/components/Inspector/ReduxTab.js +3 -1
- package/dist/esm/components/Inspector/StorageTab.js +23 -5
- package/dist/esm/components/JsonViewer.js +14 -2
- package/dist/esm/components/LogCard.js +422 -221
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.js +1 -1
- package/dist/esm/customHooks/consoleLogger.js +34 -2
- package/dist/esm/customHooks/crashHandler.js +1 -1
- package/dist/esm/customHooks/networkLogger.js +184 -26
- package/dist/esm/helpers/searchQueryParser.d.ts +1 -1
- package/dist/esm/helpers/searchQueryParser.js +37 -291
- package/dist/esm/index.js +141 -27
- package/package.json +1 -1
- package/src/components/AnimatedEntrance.tsx +3 -3
- package/src/components/ConsoleLogCard.tsx +154 -103
- package/src/components/Inspector/ConsoleTab.tsx +27 -18
- package/src/components/Inspector/CrashTab.tsx +19 -5
- package/src/components/Inspector/DeviceInfoTab.tsx +224 -102
- package/src/components/Inspector/InspectorHeader.tsx +5 -3
- package/src/components/Inspector/MainScreen.tsx +2 -3
- package/src/components/Inspector/NetworkTab.tsx +1 -402
- package/src/components/Inspector/PerformanceTab.tsx +36 -7
- package/src/components/Inspector/ReduxTab.tsx +9 -1
- package/src/components/Inspector/StorageTab.tsx +27 -7
- package/src/components/JsonViewer.tsx +15 -2
- package/src/components/LogCard.tsx +528 -339
- package/src/constants/version.ts +1 -1
- package/src/customHooks/analyticsLogger.ts +1 -1
- package/src/customHooks/consoleLogger.ts +36 -3
- package/src/customHooks/crashHandler.ts +1 -1
- package/src/customHooks/networkLogger.ts +214 -26
- package/src/helpers/searchQueryParser.ts +40 -285
- package/src/index.tsx +332 -211
|
@@ -13,7 +13,7 @@ import { AppColors } from '../../styles/AppColors';
|
|
|
13
13
|
import { AppFonts } from '../../styles/AppFonts';
|
|
14
14
|
import { METHOD_COLORS } from '../../constants';
|
|
15
15
|
import { useTranslation } from '../../i18n';
|
|
16
|
-
import { SearchIcon, ClearIcon, TrashIcon, SortArrowIcon, FilterIcon, ChevronIcon, CircleCheckIcon, CircleXIcon,
|
|
16
|
+
import { SearchIcon, ClearIcon, TrashIcon, SortArrowIcon, FilterIcon, ChevronIcon, CircleCheckIcon, CircleXIcon, LayersIcon, HeaderPauseIcon, ClockIcon, RequestIcon, ResponseIcon, AtomIcon, } from '../NetworkIcons';
|
|
17
17
|
const NetworkTab = React.memo(() => {
|
|
18
18
|
const { groupedData, search, setSearch, searchScope, setSearchScope, isRegexSearch, setIsRegexSearch, isCaseSensitive, setIsCaseSensitive, quickFilter, setQuickFilter, handleDelete, selectedLogs, sortOrder, setSortOrder, statusFilters, setStatusFilters, methodFilters, setMethodFilters, availableMethods, filteredLogs, logs, toggleSectionFilter, toggleSectionCollapse, minStart, totalRange, newLogIds, toggleSelect, setSelected, isNetworkPaused, setIsNetworkPaused, } = useInspector();
|
|
19
19
|
const { t } = useTranslation();
|
|
@@ -135,85 +135,6 @@ const NetworkTab = React.memo(() => {
|
|
|
135
135
|
color: '#E10098',
|
|
136
136
|
},
|
|
137
137
|
], [quickCounts]);
|
|
138
|
-
const SEARCH_SCOPES = [
|
|
139
|
-
{
|
|
140
|
-
id: 'all',
|
|
141
|
-
label: 'All',
|
|
142
|
-
icon: color => <LayersIcon size={9.5} color={color}/>,
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
id: 'url',
|
|
146
|
-
label: 'URL / Path',
|
|
147
|
-
icon: color => <GlobeIcon size={9.5} color={color}/>,
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: 'reqBody',
|
|
151
|
-
label: 'Payload',
|
|
152
|
-
icon: color => <RequestIcon size={9.5} color={color}/>,
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
id: 'resBody',
|
|
156
|
-
label: 'Response',
|
|
157
|
-
icon: color => <ResponseIcon size={9.5} color={color}/>,
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
id: 'headers',
|
|
161
|
-
label: 'Headers',
|
|
162
|
-
icon: color => <HeadersIcon size={9.5} color={color}/>,
|
|
163
|
-
},
|
|
164
|
-
];
|
|
165
|
-
const QUICK_API_QUERY_TAGS = useMemo(() => [
|
|
166
|
-
{
|
|
167
|
-
label: 'Failed',
|
|
168
|
-
query: 'is:error',
|
|
169
|
-
icon: (color) => <CircleXIcon size={9.5} color={color}/>,
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
label: 'Slow (>1s)',
|
|
173
|
-
query: 'slow:>1s',
|
|
174
|
-
icon: (color) => <ClockIcon size={9.5} color={color}/>,
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
label: 'POST',
|
|
178
|
-
query: 'm:POST',
|
|
179
|
-
icon: (color) => <RequestIcon size={9.5} color={color}/>,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
label: 'GET',
|
|
183
|
-
query: 'm:GET',
|
|
184
|
-
icon: (color) => <ResponseIcon size={9.5} color={color}/>,
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
label: 'GraphQL',
|
|
188
|
-
query: 'is:graphql',
|
|
189
|
-
icon: (color) => <AtomIcon size={9.5} color={color}/>,
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
label: 'Axios',
|
|
193
|
-
query: 'client:axios',
|
|
194
|
-
icon: (color) => <BoltIcon size={9.5} color={color}/>,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
label: '200 OK',
|
|
198
|
-
query: 'status:200',
|
|
199
|
-
icon: (color) => <CircleCheckIcon size={9.5} color={color}/>,
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
label: '404',
|
|
203
|
-
query: 'status:404',
|
|
204
|
-
icon: (color) => <CircleAlertIcon size={9.5} color={color}/>,
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
label: '500',
|
|
208
|
-
query: 'status:500',
|
|
209
|
-
icon: (color) => <CircleXIcon size={9.5} color={color}/>,
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
label: 'HTTPS',
|
|
213
|
-
query: 'is:https',
|
|
214
|
-
icon: (color) => <ShieldAlertIcon size={9.5} color={color}/>,
|
|
215
|
-
},
|
|
216
|
-
], []);
|
|
217
138
|
const networkMetrics = useMemo(() => {
|
|
218
139
|
if (!logs || logs.length === 0)
|
|
219
140
|
return null;
|
|
@@ -359,61 +280,7 @@ const NetworkTab = React.memo(() => {
|
|
|
359
280
|
<SearchIcon color={isSearchFocused
|
|
360
281
|
? AppColors.purple
|
|
361
282
|
: AppColors.grayTextWeak} size={15}/>
|
|
362
|
-
<TextInput placeholder="Search
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
<View style={{
|
|
366
|
-
flexDirection: 'row',
|
|
367
|
-
alignItems: 'center',
|
|
368
|
-
gap: 3,
|
|
369
|
-
marginRight: 2,
|
|
370
|
-
}}>
|
|
371
|
-
<Pressable hitSlop={8} onPress={() => setIsCaseSensitive(prev => !prev)} style={{
|
|
372
|
-
paddingHorizontal: 4.5,
|
|
373
|
-
paddingVertical: 2,
|
|
374
|
-
borderRadius: 4,
|
|
375
|
-
backgroundColor: isCaseSensitive
|
|
376
|
-
? AppColors.purple
|
|
377
|
-
: 'transparent',
|
|
378
|
-
borderWidth: 1,
|
|
379
|
-
borderColor: isCaseSensitive
|
|
380
|
-
? AppColors.purple
|
|
381
|
-
: `${AppColors.grayBorderSecondary}`,
|
|
382
|
-
}}>
|
|
383
|
-
<Text style={{
|
|
384
|
-
fontFamily: AppFonts.interBold,
|
|
385
|
-
fontSize: 9.5,
|
|
386
|
-
color: isCaseSensitive
|
|
387
|
-
? AppColors.white
|
|
388
|
-
: AppColors.grayTextWeak,
|
|
389
|
-
}}>
|
|
390
|
-
Aa
|
|
391
|
-
</Text>
|
|
392
|
-
</Pressable>
|
|
393
|
-
|
|
394
|
-
<Pressable hitSlop={8} onPress={() => setIsRegexSearch(prev => !prev)} style={{
|
|
395
|
-
paddingHorizontal: 4.5,
|
|
396
|
-
paddingVertical: 2,
|
|
397
|
-
borderRadius: 4,
|
|
398
|
-
backgroundColor: isRegexSearch
|
|
399
|
-
? AppColors.purple
|
|
400
|
-
: 'transparent',
|
|
401
|
-
borderWidth: 1,
|
|
402
|
-
borderColor: isRegexSearch
|
|
403
|
-
? AppColors.purple
|
|
404
|
-
: `${AppColors.grayBorderSecondary}`,
|
|
405
|
-
}}>
|
|
406
|
-
<Text style={{
|
|
407
|
-
fontFamily: AppFonts.interBold,
|
|
408
|
-
fontSize: 9.5,
|
|
409
|
-
color: isRegexSearch
|
|
410
|
-
? AppColors.white
|
|
411
|
-
: AppColors.grayTextWeak,
|
|
412
|
-
}}>
|
|
413
|
-
.*
|
|
414
|
-
</Text>
|
|
415
|
-
</Pressable>
|
|
416
|
-
</View>
|
|
283
|
+
<TextInput placeholder="Search URL, status, method, headers, body..." placeholderTextColor={AppColors.grayTextWeak} value={search} onChangeText={setSearch} onFocus={() => setIsSearchFocused(true)} onBlur={() => setIsSearchFocused(false)} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
417
284
|
|
|
418
285
|
{search.length > 0 && (<View style={{
|
|
419
286
|
flexDirection: 'row',
|
|
@@ -489,94 +356,6 @@ const NetworkTab = React.memo(() => {
|
|
|
489
356
|
</View>
|
|
490
357
|
|
|
491
358
|
|
|
492
|
-
<View style={{ paddingBottom: 4 }}>
|
|
493
|
-
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
|
|
494
|
-
paddingHorizontal: 12,
|
|
495
|
-
flexDirection: 'row',
|
|
496
|
-
alignItems: 'center',
|
|
497
|
-
gap: 5,
|
|
498
|
-
paddingVertical: 2,
|
|
499
|
-
}}>
|
|
500
|
-
|
|
501
|
-
{SEARCH_SCOPES.map(s => {
|
|
502
|
-
const isActive = searchScope === s.id;
|
|
503
|
-
return (<TouchableScale key={`scope_${s.id}`} onPress={() => setSearchScope(s.id)} hitSlop={6} style={{
|
|
504
|
-
flexDirection: 'row',
|
|
505
|
-
alignItems: 'center',
|
|
506
|
-
gap: 3.5,
|
|
507
|
-
paddingHorizontal: 7.5,
|
|
508
|
-
paddingVertical: 3.5,
|
|
509
|
-
borderRadius: 6,
|
|
510
|
-
backgroundColor: isActive
|
|
511
|
-
? AppColors.purple
|
|
512
|
-
: AppColors.grayBackground,
|
|
513
|
-
borderWidth: 1,
|
|
514
|
-
borderColor: isActive
|
|
515
|
-
? AppColors.purple
|
|
516
|
-
: AppColors.grayBorderSecondary,
|
|
517
|
-
}}>
|
|
518
|
-
{s.icon(isActive ? AppColors.white : AppColors.grayTextWeak)}
|
|
519
|
-
<Text style={{
|
|
520
|
-
fontFamily: AppFonts.interBold,
|
|
521
|
-
fontSize: 10,
|
|
522
|
-
color: isActive ? AppColors.white : AppColors.grayText,
|
|
523
|
-
}}>
|
|
524
|
-
{s.label}
|
|
525
|
-
</Text>
|
|
526
|
-
</TouchableScale>);
|
|
527
|
-
})}
|
|
528
|
-
|
|
529
|
-
<View style={{
|
|
530
|
-
width: 1,
|
|
531
|
-
height: 14,
|
|
532
|
-
backgroundColor: AppColors.dividerColor,
|
|
533
|
-
marginHorizontal: 3,
|
|
534
|
-
}}/>
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
{QUICK_API_QUERY_TAGS.map(q => {
|
|
538
|
-
const isActive = search.includes(q.query);
|
|
539
|
-
return (<TouchableScale key={`quick_${q.query}`} onPress={() => {
|
|
540
|
-
setSearch(prev => {
|
|
541
|
-
if (prev.includes(q.query)) {
|
|
542
|
-
return prev
|
|
543
|
-
.replace(q.query, '')
|
|
544
|
-
.replace(/\s+/g, ' ')
|
|
545
|
-
.trim();
|
|
546
|
-
}
|
|
547
|
-
return `${prev} ${q.query}`.trim();
|
|
548
|
-
});
|
|
549
|
-
}} hitSlop={6} style={{
|
|
550
|
-
flexDirection: 'row',
|
|
551
|
-
alignItems: 'center',
|
|
552
|
-
gap: 3.5,
|
|
553
|
-
paddingHorizontal: 7.5,
|
|
554
|
-
paddingVertical: 3.5,
|
|
555
|
-
borderRadius: 6,
|
|
556
|
-
backgroundColor: isActive
|
|
557
|
-
? `${AppColors.purple}20`
|
|
558
|
-
: AppColors.grayBackground,
|
|
559
|
-
borderWidth: 1,
|
|
560
|
-
borderColor: isActive
|
|
561
|
-
? AppColors.purple
|
|
562
|
-
: AppColors.grayBorderSecondary,
|
|
563
|
-
}}>
|
|
564
|
-
{q.icon(isActive ? AppColors.purple : AppColors.grayTextWeak)}
|
|
565
|
-
<Text style={{
|
|
566
|
-
fontFamily: AppFonts.interMedium,
|
|
567
|
-
fontSize: 10,
|
|
568
|
-
color: isActive
|
|
569
|
-
? AppColors.purple
|
|
570
|
-
: AppColors.grayText,
|
|
571
|
-
}}>
|
|
572
|
-
{q.label}
|
|
573
|
-
</Text>
|
|
574
|
-
</TouchableScale>);
|
|
575
|
-
})}
|
|
576
|
-
</ScrollView>
|
|
577
|
-
</View>
|
|
578
|
-
|
|
579
|
-
|
|
580
359
|
<View style={{ marginBottom: 8 }}>
|
|
581
360
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
|
|
582
361
|
paddingHorizontal: 12,
|
|
@@ -690,110 +469,6 @@ const NetworkTab = React.memo(() => {
|
|
|
690
469
|
</View>
|
|
691
470
|
|
|
692
471
|
|
|
693
|
-
{(isSearchFocused || search.length > 0) && (<View style={{
|
|
694
|
-
flexDirection: 'row',
|
|
695
|
-
alignItems: 'center',
|
|
696
|
-
paddingHorizontal: 12,
|
|
697
|
-
marginBottom: 6,
|
|
698
|
-
gap: 6,
|
|
699
|
-
}}>
|
|
700
|
-
<Text style={{
|
|
701
|
-
fontFamily: AppFonts.interBold,
|
|
702
|
-
fontSize: 9.5,
|
|
703
|
-
color: AppColors.grayTextWeak,
|
|
704
|
-
textTransform: 'uppercase',
|
|
705
|
-
letterSpacing: 0.5,
|
|
706
|
-
}}>
|
|
707
|
-
Scope:
|
|
708
|
-
</Text>
|
|
709
|
-
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
|
|
710
|
-
flexDirection: 'row',
|
|
711
|
-
alignItems: 'center',
|
|
712
|
-
gap: 5,
|
|
713
|
-
}}>
|
|
714
|
-
{SEARCH_SCOPES.map(s => {
|
|
715
|
-
const isSelected = searchScope === s.id;
|
|
716
|
-
const iconColor = isSelected ? AppColors.white : AppColors.grayText;
|
|
717
|
-
return (<TouchableScale key={s.id} onPress={() => setSearchScope(s.id)}>
|
|
718
|
-
<View style={{
|
|
719
|
-
flexDirection: 'row',
|
|
720
|
-
alignItems: 'center',
|
|
721
|
-
gap: 4,
|
|
722
|
-
paddingHorizontal: 7,
|
|
723
|
-
paddingVertical: 2.5,
|
|
724
|
-
borderRadius: 5,
|
|
725
|
-
backgroundColor: isSelected
|
|
726
|
-
? AppColors.purple
|
|
727
|
-
: `${AppColors.grayBorderSecondary}40`,
|
|
728
|
-
borderWidth: 1,
|
|
729
|
-
borderColor: isSelected
|
|
730
|
-
? AppColors.purple
|
|
731
|
-
: AppColors.grayBorderSecondary,
|
|
732
|
-
}}>
|
|
733
|
-
{s.icon(iconColor)}
|
|
734
|
-
<Text style={{
|
|
735
|
-
fontFamily: AppFonts.interBold,
|
|
736
|
-
fontSize: 9.5,
|
|
737
|
-
color: isSelected
|
|
738
|
-
? AppColors.white
|
|
739
|
-
: AppColors.grayText,
|
|
740
|
-
}}>
|
|
741
|
-
{s.label}
|
|
742
|
-
</Text>
|
|
743
|
-
</View>
|
|
744
|
-
</TouchableScale>);
|
|
745
|
-
})}
|
|
746
|
-
</ScrollView>
|
|
747
|
-
</View>)}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
{(isSearchFocused || search.length > 0) && (<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginBottom: 8, maxHeight: 28 }} contentContainerStyle={{
|
|
751
|
-
paddingHorizontal: 12,
|
|
752
|
-
flexDirection: 'row',
|
|
753
|
-
alignItems: 'center',
|
|
754
|
-
gap: 5,
|
|
755
|
-
}}>
|
|
756
|
-
{QUICK_API_QUERY_TAGS.map(item => {
|
|
757
|
-
const isSelected = search.includes(item.query);
|
|
758
|
-
return (<TouchableScale key={item.query} onPress={() => {
|
|
759
|
-
if (isSelected) {
|
|
760
|
-
setSearch(prev => prev.replace(item.query, '').trim());
|
|
761
|
-
}
|
|
762
|
-
else {
|
|
763
|
-
setSearch(prev => prev ? `${prev} ${item.query}`.trim() : item.query);
|
|
764
|
-
}
|
|
765
|
-
}}>
|
|
766
|
-
<View style={{
|
|
767
|
-
flexDirection: 'row',
|
|
768
|
-
alignItems: 'center',
|
|
769
|
-
gap: 4,
|
|
770
|
-
paddingHorizontal: 7,
|
|
771
|
-
paddingVertical: 2.5,
|
|
772
|
-
borderRadius: 5,
|
|
773
|
-
backgroundColor: isSelected
|
|
774
|
-
? AppColors.purple
|
|
775
|
-
: `${AppColors.purple}14`,
|
|
776
|
-
borderWidth: 1,
|
|
777
|
-
borderColor: isSelected
|
|
778
|
-
? AppColors.purple
|
|
779
|
-
: `${AppColors.purple}30`,
|
|
780
|
-
}}>
|
|
781
|
-
{item.icon(isSelected ? AppColors.white : AppColors.purple)}
|
|
782
|
-
<Text style={{
|
|
783
|
-
fontFamily: AppFonts.interBold,
|
|
784
|
-
fontSize: 9.5,
|
|
785
|
-
color: isSelected
|
|
786
|
-
? AppColors.white
|
|
787
|
-
: AppColors.purple,
|
|
788
|
-
}}>
|
|
789
|
-
{item.label}
|
|
790
|
-
</Text>
|
|
791
|
-
</View>
|
|
792
|
-
</TouchableScale>);
|
|
793
|
-
})}
|
|
794
|
-
</ScrollView>)}
|
|
795
|
-
|
|
796
|
-
|
|
797
472
|
{(quickFilter !== 'all' ||
|
|
798
473
|
search.trim().length > 0 ||
|
|
799
474
|
statusFilters.size > 0 ||
|
|
@@ -833,15 +508,6 @@ const NetworkTab = React.memo(() => {
|
|
|
833
508
|
</Text>
|
|
834
509
|
</TouchableScale>
|
|
835
510
|
</View>)}
|
|
836
|
-
|
|
837
|
-
{(search ||
|
|
838
|
-
statusFilters.size > 0 ||
|
|
839
|
-
methodFilters.size > 0 ||
|
|
840
|
-
quickFilter !== 'all') && (<Text style={styles.resultCount}>
|
|
841
|
-
{filteredLogs.length === logs.length
|
|
842
|
-
? `${logs.length} requests`
|
|
843
|
-
: `${filteredLogs.length} of ${logs.length} filtered requests`}
|
|
844
|
-
</Text>)}
|
|
845
511
|
</View>} ListEmptyComponent={<EmptyState isSearch={search.length > 0 ||
|
|
846
512
|
statusFilters.size > 0 ||
|
|
847
513
|
methodFilters.size > 0 ||
|
|
@@ -148,10 +148,19 @@ const PerformanceTab = React.memo(() => {
|
|
|
148
148
|
}, [isRecording]);
|
|
149
149
|
const filteredEvents = useMemo(() => {
|
|
150
150
|
return events.filter(e => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
let matchSearch = true;
|
|
152
|
+
if (search && search.trim().length > 0) {
|
|
153
|
+
const queryTokens = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
154
|
+
const corpus = [
|
|
155
|
+
e.label || '',
|
|
156
|
+
e.detail || '',
|
|
157
|
+
e.source || '',
|
|
158
|
+
e.category || '',
|
|
159
|
+
e.severity || '',
|
|
160
|
+
e.bottleneckThread || '',
|
|
161
|
+
].join(' ').toLowerCase();
|
|
162
|
+
matchSearch = queryTokens.every(tok => corpus.includes(tok));
|
|
163
|
+
}
|
|
155
164
|
const matchFilter = filterCategory === 'ALL'
|
|
156
165
|
? true
|
|
157
166
|
: filterCategory === 'JANKY'
|
|
@@ -776,10 +785,27 @@ const PerformanceTab = React.memo(() => {
|
|
|
776
785
|
|
|
777
786
|
{filteredEvents.length === 0 ? (<View style={perfStyles.emptyCard}>
|
|
778
787
|
<BoltIcon color={AppColors.amber500} size={30}/>
|
|
779
|
-
<Text style={perfStyles.emptyTitle}>
|
|
788
|
+
<Text style={perfStyles.emptyTitle}>
|
|
789
|
+
{search.trim().length > 0 ? 'No Matching Events' : t('performance.emptyTitle')}
|
|
790
|
+
</Text>
|
|
780
791
|
<Text style={perfStyles.emptySub}>
|
|
781
|
-
{
|
|
792
|
+
{search.trim().length > 0
|
|
793
|
+
? `No performance events match "${search}"`
|
|
794
|
+
: t('performance.emptySubtitle')}
|
|
782
795
|
</Text>
|
|
796
|
+
{search.trim().length > 0 && (<TouchableScale onPress={() => setSearch('')} style={{
|
|
797
|
+
marginTop: 10,
|
|
798
|
+
paddingHorizontal: 14,
|
|
799
|
+
paddingVertical: 6,
|
|
800
|
+
borderRadius: 8,
|
|
801
|
+
backgroundColor: AppColors.grayBackground,
|
|
802
|
+
borderWidth: 1,
|
|
803
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
804
|
+
}}>
|
|
805
|
+
<Text style={{ color: AppColors.brandPurple, fontSize: 12, fontFamily: AppFonts.interBold }}>
|
|
806
|
+
Clear Search
|
|
807
|
+
</Text>
|
|
808
|
+
</TouchableScale>)}
|
|
783
809
|
</View>) : (filteredEvents.map(event => {
|
|
784
810
|
const isOptimal = event.severity === 'optimal';
|
|
785
811
|
const isWarning = event.severity === 'warning';
|
|
@@ -454,7 +454,9 @@ const ReduxTab = React.memo(() => {
|
|
|
454
454
|
</View>
|
|
455
455
|
|
|
456
456
|
|
|
457
|
-
<FlatList ref={listRef} data={filteredSlices} keyExtractor={item => item.id} renderItem={renderSliceItem} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} ListEmptyComponent={<EmptyState isSearch={reduxSearch.length > 0}
|
|
457
|
+
<FlatList ref={listRef} data={filteredSlices} keyExtractor={item => item.id} renderItem={renderSliceItem} initialNumToRender={12} maxToRenderPerBatch={8} windowSize={5} removeClippedSubviews={true} renderToHardwareTextureAndroid={true} ListEmptyComponent={<EmptyState isSearch={reduxSearch.trim().length > 0} searchQuery={reduxSearch} onClearSearch={() => setReduxSearch('')} customTitle={reduxSearch.trim().length > 0 ? 'No Matching Slices' : 'No Redux State Detected'} customSub={reduxSearch.trim().length > 0
|
|
458
|
+
? `No Redux slices match "${reduxSearch}"`
|
|
459
|
+
: 'Attach the Redux store or dispatch actions to see state slices.'}/>} ListFooterComponent={filteredSlices.length > 0 ? (<EndOfListFooter count={filteredSlices.length} label="slices"/>) : null} contentContainerStyle={[
|
|
458
460
|
reduxTabStyles.listContent,
|
|
459
461
|
filteredSlices.length === 0 && { flexGrow: 1 },
|
|
460
462
|
]} keyboardShouldPersistTaps="handled"/>
|
|
@@ -232,8 +232,11 @@ export const StorageTab = React.memo(() => {
|
|
|
232
232
|
const filteredEntries = useMemo(() => {
|
|
233
233
|
if (!search.trim())
|
|
234
234
|
return entries;
|
|
235
|
-
const
|
|
236
|
-
return entries.filter(e =>
|
|
235
|
+
const tokens = search.toLowerCase().trim().split(/\s+/).filter(Boolean);
|
|
236
|
+
return entries.filter(e => {
|
|
237
|
+
const corpus = `${e.key} ${e.value}`.toLowerCase();
|
|
238
|
+
return tokens.every(tok => corpus.includes(tok));
|
|
239
|
+
});
|
|
237
240
|
}, [entries, search]);
|
|
238
241
|
const totalBytes = useMemo(() => {
|
|
239
242
|
return entries.reduce((sum, e) => sum + e.byteSize, 0);
|
|
@@ -371,13 +374,28 @@ export const StorageTab = React.memo(() => {
|
|
|
371
374
|
<DatabaseIcon size={28} color={AppColors.grayTextWeak}/>
|
|
372
375
|
</View>
|
|
373
376
|
<Text style={styles.emptyTitle}>
|
|
374
|
-
{search
|
|
377
|
+
{search.trim().length > 0
|
|
378
|
+
? 'No matching keys found'
|
|
379
|
+
: `No ${activeDriver === 'asyncStorage' ? 'AsyncStorage' : 'MMKV'} Keys`}
|
|
375
380
|
</Text>
|
|
376
381
|
<Text style={styles.emptySubtitle}>
|
|
377
|
-
{search
|
|
378
|
-
?
|
|
382
|
+
{search.trim().length > 0
|
|
383
|
+
? `No keys or values match "${search}"`
|
|
379
384
|
: `Storage is auto-detected. Tap "+ Add" above to create your first ${activeDriver === 'asyncStorage' ? 'AsyncStorage' : 'MMKV'} key!`}
|
|
380
385
|
</Text>
|
|
386
|
+
{search.trim().length > 0 && (<TouchableScale onPress={() => setSearch('')} style={{
|
|
387
|
+
marginTop: 12,
|
|
388
|
+
paddingHorizontal: 14,
|
|
389
|
+
paddingVertical: 6,
|
|
390
|
+
borderRadius: 8,
|
|
391
|
+
backgroundColor: AppColors.grayBackground,
|
|
392
|
+
borderWidth: 1,
|
|
393
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
394
|
+
}}>
|
|
395
|
+
<Text style={{ color: AppColors.brandPurple, fontSize: 12, fontFamily: AppFonts.interBold }}>
|
|
396
|
+
Clear Search
|
|
397
|
+
</Text>
|
|
398
|
+
</TouchableScale>)}
|
|
381
399
|
</View>} ListFooterComponent={<View style={{ height: 60 }}/>}/>
|
|
382
400
|
|
|
383
401
|
<TouchableScale onPress={() => {
|
|
@@ -111,10 +111,22 @@ const JsonViewer = React.memo(({ data, search, forceOpen, defaultExpandDepth = 1
|
|
|
111
111
|
<Text style={localStyles.tableCellValue}>{String(data)}</Text>
|
|
112
112
|
</View>);
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
let keys = Object.keys(data);
|
|
115
|
+
if (search && search.trim().length > 0) {
|
|
116
|
+
const q = search.trim().toLowerCase();
|
|
117
|
+
keys = keys.filter(key => {
|
|
118
|
+
const val = data[key];
|
|
119
|
+
const valStr = typeof val === 'object' && val !== null ? JSON.stringify(val) : String(val);
|
|
120
|
+
return key.toLowerCase().includes(q) || valStr.toLowerCase().includes(q);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
115
123
|
if (keys.length === 0) {
|
|
116
124
|
return (<View style={localStyles.emptyTable}>
|
|
117
|
-
<Text style={localStyles.emptyTableText}>
|
|
125
|
+
<Text style={localStyles.emptyTableText}>
|
|
126
|
+
{search && search.trim().length > 0
|
|
127
|
+
? 'No matching keys or values found'
|
|
128
|
+
: t('network.jsonViewer.emptyTable')}
|
|
129
|
+
</Text>
|
|
118
130
|
</View>);
|
|
119
131
|
}
|
|
120
132
|
return (<View style={localStyles.tableView}>
|