react-native-inapp-inspector 2.0.3 → 2.0.5
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/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/reports/problems/problems-report.html +659 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +87 -50
- package/dist/commonjs/components/Inspector/MainScreen.js +1 -0
- package/dist/commonjs/components/Inspector/NetworkTab.js +317 -12
- package/dist/commonjs/components/Inspector/NpmUpdateToast.js +88 -39
- package/dist/commonjs/components/Inspector/SettingsPanel.js +525 -359
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.d.ts +8 -0
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +469 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/helpers/searchQueryParser.d.ts +8 -3
- package/dist/commonjs/helpers/searchQueryParser.js +85 -31
- package/dist/commonjs/helpers/telemetry.js +4 -4
- package/dist/commonjs/index.js +58 -7
- package/dist/commonjs/types/interfaces.d.ts +9 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +87 -50
- package/dist/esm/components/Inspector/MainScreen.js +1 -0
- package/dist/esm/components/Inspector/NetworkTab.js +317 -12
- package/dist/esm/components/Inspector/NpmUpdateToast.js +88 -39
- package/dist/esm/components/Inspector/SettingsPanel.js +526 -360
- package/dist/esm/components/Inspector/UpdateAvailableModal.d.ts +8 -0
- package/dist/esm/components/Inspector/UpdateAvailableModal.js +432 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/helpers/searchQueryParser.d.ts +8 -3
- package/dist/esm/helpers/searchQueryParser.js +85 -31
- package/dist/esm/helpers/telemetry.js +4 -4
- package/dist/esm/index.js +58 -7
- package/dist/esm/types/interfaces.d.ts +9 -0
- package/package.json +1 -1
|
@@ -89,11 +89,105 @@ const FilterChip = React.memo(({ label, color, Icon, badge, active, onPress, })
|
|
|
89
89
|
</TouchableScale>);
|
|
90
90
|
});
|
|
91
91
|
const NetworkTab = React.memo(() => {
|
|
92
|
-
const { groupedData, search, setSearch, handleDelete, selectedLogs, sortOrder, setSortOrder, statusFilters, setStatusFilters, methodFilters, setMethodFilters, availableMethods, filteredLogs, logs, toggleSectionFilter, toggleSectionCollapse, minStart, totalRange, newLogIds, toggleSelect, setSelected, isNetworkPaused, setIsNetworkPaused, } = useInspector();
|
|
92
|
+
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();
|
|
93
93
|
const { t } = useTranslation();
|
|
94
94
|
const filtersAccordion = useAccordion(false, 300, 260);
|
|
95
95
|
const apisListRef = useRef(null);
|
|
96
96
|
const [isSearchFocused, setIsSearchFocused] = React.useState(false);
|
|
97
|
+
const quickCounts = useMemo(() => {
|
|
98
|
+
let errorCount = 0;
|
|
99
|
+
let successCount = 0;
|
|
100
|
+
let slowCount = 0;
|
|
101
|
+
let postCount = 0;
|
|
102
|
+
let getCount = 0;
|
|
103
|
+
let gqlCount = 0;
|
|
104
|
+
logs.forEach(l => {
|
|
105
|
+
const s = typeof l.status === 'number'
|
|
106
|
+
? l.status
|
|
107
|
+
: parseInt(String(l.status), 10);
|
|
108
|
+
if (l.status === 0 || l.status == null || (!isNaN(s) && s >= 400)) {
|
|
109
|
+
errorCount++;
|
|
110
|
+
}
|
|
111
|
+
else if (!isNaN(s) && s >= 200 && s < 400) {
|
|
112
|
+
successCount++;
|
|
113
|
+
}
|
|
114
|
+
if ((l.duration || 0) >= 500) {
|
|
115
|
+
slowCount++;
|
|
116
|
+
}
|
|
117
|
+
const m = (l.method || '').toUpperCase();
|
|
118
|
+
if (m === 'POST')
|
|
119
|
+
postCount++;
|
|
120
|
+
if (m === 'GET')
|
|
121
|
+
getCount++;
|
|
122
|
+
const u = (l.url || '').toLowerCase();
|
|
123
|
+
const c = (l.client || '').toLowerCase();
|
|
124
|
+
if (u.includes('graphql') ||
|
|
125
|
+
c.includes('graphql') ||
|
|
126
|
+
c.includes('apollo')) {
|
|
127
|
+
gqlCount++;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
all: logs.length,
|
|
132
|
+
errors: errorCount,
|
|
133
|
+
success: successCount,
|
|
134
|
+
slow: slowCount,
|
|
135
|
+
post: postCount,
|
|
136
|
+
get: getCount,
|
|
137
|
+
graphql: gqlCount,
|
|
138
|
+
};
|
|
139
|
+
}, [logs]);
|
|
140
|
+
const QUICK_CHIPS = useMemo(() => [
|
|
141
|
+
{
|
|
142
|
+
id: 'all',
|
|
143
|
+
label: 'All',
|
|
144
|
+
count: quickCounts.all,
|
|
145
|
+
color: AppColors.purple,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: 'errors',
|
|
149
|
+
label: 'Errors',
|
|
150
|
+
count: quickCounts.errors,
|
|
151
|
+
color: AppColors.errorColor,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'success',
|
|
155
|
+
label: '2xx OK',
|
|
156
|
+
count: quickCounts.success,
|
|
157
|
+
color: AppColors.greenColor,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'slow',
|
|
161
|
+
label: 'Slow >500ms',
|
|
162
|
+
count: quickCounts.slow,
|
|
163
|
+
color: AppColors.warningIconGold,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'POST',
|
|
167
|
+
label: 'POST',
|
|
168
|
+
count: quickCounts.post,
|
|
169
|
+
color: METHOD_COLORS.POST || '#3B82F6',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'GET',
|
|
173
|
+
label: 'GET',
|
|
174
|
+
count: quickCounts.get,
|
|
175
|
+
color: METHOD_COLORS.GET || '#10B981',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 'graphql',
|
|
179
|
+
label: 'GraphQL',
|
|
180
|
+
count: quickCounts.graphql,
|
|
181
|
+
color: '#E10098',
|
|
182
|
+
},
|
|
183
|
+
], [quickCounts]);
|
|
184
|
+
const SEARCH_SCOPES = [
|
|
185
|
+
{ id: 'all', label: 'All' },
|
|
186
|
+
{ id: 'url', label: 'URL / Path' },
|
|
187
|
+
{ id: 'reqBody', label: 'Payload' },
|
|
188
|
+
{ id: 'resBody', label: 'Response' },
|
|
189
|
+
{ id: 'headers', label: 'Headers' },
|
|
190
|
+
];
|
|
97
191
|
const QUICK_API_QUERY_TAGS = useMemo(() => [
|
|
98
192
|
{ label: '⚠️ Failed', query: 'is:error' },
|
|
99
193
|
{ label: '🐢 Slow >1s', query: 'slow:>1s' },
|
|
@@ -239,6 +333,7 @@ const NetworkTab = React.memo(() => {
|
|
|
239
333
|
</View>
|
|
240
334
|
</View>)}
|
|
241
335
|
|
|
336
|
+
{/* Toolbar Row with Search & Actions */}
|
|
242
337
|
<View style={styles.toolbarRow}>
|
|
243
338
|
<View style={[
|
|
244
339
|
styles.searchContainer,
|
|
@@ -247,8 +342,65 @@ const NetworkTab = React.memo(() => {
|
|
|
247
342
|
borderWidth: 1.5,
|
|
248
343
|
},
|
|
249
344
|
]}>
|
|
250
|
-
<SearchIcon color={isSearchFocused
|
|
345
|
+
<SearchIcon color={isSearchFocused
|
|
346
|
+
? AppColors.purple
|
|
347
|
+
: AppColors.grayTextWeak} size={15}/>
|
|
251
348
|
<TextInput placeholder="Search url, body, is:error, slow:>1s..." placeholderTextColor={AppColors.grayTextWeak} value={search} onChangeText={setSearch} onFocus={() => setIsSearchFocused(true)} onBlur={() => setIsSearchFocused(false)} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
349
|
+
|
|
350
|
+
{/* Match Case (Aa) & Regex (.*) Quick Toggles */}
|
|
351
|
+
<View style={{
|
|
352
|
+
flexDirection: 'row',
|
|
353
|
+
alignItems: 'center',
|
|
354
|
+
gap: 3,
|
|
355
|
+
marginRight: 2,
|
|
356
|
+
}}>
|
|
357
|
+
<Pressable hitSlop={8} onPress={() => setIsCaseSensitive(prev => !prev)} style={{
|
|
358
|
+
paddingHorizontal: 4.5,
|
|
359
|
+
paddingVertical: 2,
|
|
360
|
+
borderRadius: 4,
|
|
361
|
+
backgroundColor: isCaseSensitive
|
|
362
|
+
? AppColors.purple
|
|
363
|
+
: 'transparent',
|
|
364
|
+
borderWidth: 1,
|
|
365
|
+
borderColor: isCaseSensitive
|
|
366
|
+
? AppColors.purple
|
|
367
|
+
: `${AppColors.grayBorderSecondary}`,
|
|
368
|
+
}}>
|
|
369
|
+
<Text style={{
|
|
370
|
+
fontFamily: AppFonts.interBold,
|
|
371
|
+
fontSize: 9.5,
|
|
372
|
+
color: isCaseSensitive
|
|
373
|
+
? AppColors.white
|
|
374
|
+
: AppColors.grayTextWeak,
|
|
375
|
+
}}>
|
|
376
|
+
Aa
|
|
377
|
+
</Text>
|
|
378
|
+
</Pressable>
|
|
379
|
+
|
|
380
|
+
<Pressable hitSlop={8} onPress={() => setIsRegexSearch(prev => !prev)} style={{
|
|
381
|
+
paddingHorizontal: 4.5,
|
|
382
|
+
paddingVertical: 2,
|
|
383
|
+
borderRadius: 4,
|
|
384
|
+
backgroundColor: isRegexSearch
|
|
385
|
+
? AppColors.purple
|
|
386
|
+
: 'transparent',
|
|
387
|
+
borderWidth: 1,
|
|
388
|
+
borderColor: isRegexSearch
|
|
389
|
+
? AppColors.purple
|
|
390
|
+
: `${AppColors.grayBorderSecondary}`,
|
|
391
|
+
}}>
|
|
392
|
+
<Text style={{
|
|
393
|
+
fontFamily: AppFonts.interBold,
|
|
394
|
+
fontSize: 9.5,
|
|
395
|
+
color: isRegexSearch
|
|
396
|
+
? AppColors.white
|
|
397
|
+
: AppColors.grayTextWeak,
|
|
398
|
+
}}>
|
|
399
|
+
.*
|
|
400
|
+
</Text>
|
|
401
|
+
</Pressable>
|
|
402
|
+
</View>
|
|
403
|
+
|
|
252
404
|
{search.length > 0 && (<View style={{
|
|
253
405
|
flexDirection: 'row',
|
|
254
406
|
alignItems: 'center',
|
|
@@ -257,19 +409,19 @@ const NetworkTab = React.memo(() => {
|
|
|
257
409
|
<View style={{
|
|
258
410
|
backgroundColor: `${AppColors.purple}20`,
|
|
259
411
|
borderRadius: 10,
|
|
260
|
-
paddingHorizontal:
|
|
261
|
-
paddingVertical:
|
|
412
|
+
paddingHorizontal: 5,
|
|
413
|
+
paddingVertical: 1.5,
|
|
262
414
|
}}>
|
|
263
415
|
<Text style={{
|
|
264
416
|
color: AppColors.purple,
|
|
265
|
-
fontSize:
|
|
417
|
+
fontSize: 9.5,
|
|
266
418
|
fontFamily: AppFonts.interBold,
|
|
267
419
|
}}>
|
|
268
420
|
{filteredLogs.length}
|
|
269
421
|
</Text>
|
|
270
422
|
</View>
|
|
271
423
|
<Pressable onPress={() => setSearch('')} hitSlop={10} style={styles.clearBtn}>
|
|
272
|
-
<ClearIcon color={AppColors.grayTextWeak} size={
|
|
424
|
+
<ClearIcon color={AppColors.grayTextWeak} size={13}/>
|
|
273
425
|
</Pressable>
|
|
274
426
|
</View>)}
|
|
275
427
|
</View>
|
|
@@ -318,12 +470,124 @@ const NetworkTab = React.memo(() => {
|
|
|
318
470
|
</View>
|
|
319
471
|
</View>
|
|
320
472
|
|
|
473
|
+
{/* Quick Filter Horizontal Chips Bar with Live Counts */}
|
|
474
|
+
<View style={{ marginBottom: 8 }}>
|
|
475
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
|
|
476
|
+
paddingHorizontal: 12,
|
|
477
|
+
flexDirection: 'row',
|
|
478
|
+
alignItems: 'center',
|
|
479
|
+
gap: 6,
|
|
480
|
+
}}>
|
|
481
|
+
{QUICK_CHIPS.map(chip => {
|
|
482
|
+
const isActive = quickFilter === chip.id;
|
|
483
|
+
const chipColor = chip.color || AppColors.purple;
|
|
484
|
+
return (<TouchableScale key={chip.id} onPress={() => {
|
|
485
|
+
setQuickFilter(isActive ? 'all' : chip.id);
|
|
486
|
+
}}>
|
|
487
|
+
<View style={{
|
|
488
|
+
flexDirection: 'row',
|
|
489
|
+
alignItems: 'center',
|
|
490
|
+
paddingHorizontal: 9,
|
|
491
|
+
paddingVertical: 4.5,
|
|
492
|
+
borderRadius: 8,
|
|
493
|
+
backgroundColor: isActive
|
|
494
|
+
? chipColor
|
|
495
|
+
: `${chipColor}12`,
|
|
496
|
+
borderWidth: 1,
|
|
497
|
+
borderColor: isActive
|
|
498
|
+
? chipColor
|
|
499
|
+
: `${chipColor}30`,
|
|
500
|
+
gap: 5,
|
|
501
|
+
}}>
|
|
502
|
+
<Text style={{
|
|
503
|
+
fontFamily: AppFonts.interBold,
|
|
504
|
+
fontSize: 10.5,
|
|
505
|
+
color: isActive
|
|
506
|
+
? AppColors.white
|
|
507
|
+
: AppColors.primaryBlack,
|
|
508
|
+
}}>
|
|
509
|
+
{chip.label}
|
|
510
|
+
</Text>
|
|
511
|
+
<View style={{
|
|
512
|
+
backgroundColor: isActive
|
|
513
|
+
? 'rgba(255,255,255,0.25)'
|
|
514
|
+
: `${chipColor}20`,
|
|
515
|
+
paddingHorizontal: 5,
|
|
516
|
+
paddingVertical: 1,
|
|
517
|
+
borderRadius: 8,
|
|
518
|
+
}}>
|
|
519
|
+
<Text style={{
|
|
520
|
+
fontFamily: AppFonts.interBold,
|
|
521
|
+
fontSize: 9,
|
|
522
|
+
color: isActive ? AppColors.white : chipColor,
|
|
523
|
+
}}>
|
|
524
|
+
{chip.count}
|
|
525
|
+
</Text>
|
|
526
|
+
</View>
|
|
527
|
+
</View>
|
|
528
|
+
</TouchableScale>);
|
|
529
|
+
})}
|
|
530
|
+
</ScrollView>
|
|
531
|
+
</View>
|
|
532
|
+
|
|
533
|
+
{/* Search Scope Selector Bar (Visible on search or focus) */}
|
|
534
|
+
{(isSearchFocused || search.length > 0) && (<View style={{
|
|
535
|
+
flexDirection: 'row',
|
|
536
|
+
alignItems: 'center',
|
|
537
|
+
paddingHorizontal: 12,
|
|
538
|
+
marginBottom: 6,
|
|
539
|
+
gap: 6,
|
|
540
|
+
}}>
|
|
541
|
+
<Text style={{
|
|
542
|
+
fontFamily: AppFonts.interBold,
|
|
543
|
+
fontSize: 9.5,
|
|
544
|
+
color: AppColors.grayTextWeak,
|
|
545
|
+
textTransform: 'uppercase',
|
|
546
|
+
letterSpacing: 0.5,
|
|
547
|
+
}}>
|
|
548
|
+
Scope:
|
|
549
|
+
</Text>
|
|
550
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
|
|
551
|
+
flexDirection: 'row',
|
|
552
|
+
alignItems: 'center',
|
|
553
|
+
gap: 5,
|
|
554
|
+
}}>
|
|
555
|
+
{SEARCH_SCOPES.map(s => {
|
|
556
|
+
const isSelected = searchScope === s.id;
|
|
557
|
+
return (<TouchableScale key={s.id} onPress={() => setSearchScope(s.id)}>
|
|
558
|
+
<View style={{
|
|
559
|
+
paddingHorizontal: 7,
|
|
560
|
+
paddingVertical: 2.5,
|
|
561
|
+
borderRadius: 5,
|
|
562
|
+
backgroundColor: isSelected
|
|
563
|
+
? AppColors.purple
|
|
564
|
+
: `${AppColors.grayBorderSecondary}40`,
|
|
565
|
+
borderWidth: 1,
|
|
566
|
+
borderColor: isSelected
|
|
567
|
+
? AppColors.purple
|
|
568
|
+
: AppColors.grayBorderSecondary,
|
|
569
|
+
}}>
|
|
570
|
+
<Text style={{
|
|
571
|
+
fontFamily: AppFonts.interBold,
|
|
572
|
+
fontSize: 9.5,
|
|
573
|
+
color: isSelected
|
|
574
|
+
? AppColors.white
|
|
575
|
+
: AppColors.grayText,
|
|
576
|
+
}}>
|
|
577
|
+
{s.label}
|
|
578
|
+
</Text>
|
|
579
|
+
</View>
|
|
580
|
+
</TouchableScale>);
|
|
581
|
+
})}
|
|
582
|
+
</ScrollView>
|
|
583
|
+
</View>)}
|
|
584
|
+
|
|
321
585
|
{/* Advanced Search Quick Query Suggestions Bar */}
|
|
322
|
-
{(isSearchFocused || search.length > 0) && (<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginBottom:
|
|
586
|
+
{(isSearchFocused || search.length > 0) && (<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginBottom: 8, maxHeight: 28 }} contentContainerStyle={{
|
|
323
587
|
paddingHorizontal: 12,
|
|
324
588
|
flexDirection: 'row',
|
|
325
589
|
alignItems: 'center',
|
|
326
|
-
gap:
|
|
590
|
+
gap: 5,
|
|
327
591
|
}}>
|
|
328
592
|
{QUICK_API_QUERY_TAGS.map(item => {
|
|
329
593
|
const isSelected = search.includes(item.query);
|
|
@@ -336,9 +600,9 @@ const NetworkTab = React.memo(() => {
|
|
|
336
600
|
}
|
|
337
601
|
}}>
|
|
338
602
|
<View style={{
|
|
339
|
-
paddingHorizontal:
|
|
340
|
-
paddingVertical:
|
|
341
|
-
borderRadius:
|
|
603
|
+
paddingHorizontal: 7,
|
|
604
|
+
paddingVertical: 2.5,
|
|
605
|
+
borderRadius: 5,
|
|
342
606
|
backgroundColor: isSelected
|
|
343
607
|
? AppColors.purple
|
|
344
608
|
: `${AppColors.purple}14`,
|
|
@@ -349,7 +613,7 @@ const NetworkTab = React.memo(() => {
|
|
|
349
613
|
}}>
|
|
350
614
|
<Text style={{
|
|
351
615
|
fontFamily: AppFonts.interBold,
|
|
352
|
-
fontSize:
|
|
616
|
+
fontSize: 9.5,
|
|
353
617
|
color: isSelected
|
|
354
618
|
? AppColors.white
|
|
355
619
|
: AppColors.purple,
|
|
@@ -361,6 +625,47 @@ const NetworkTab = React.memo(() => {
|
|
|
361
625
|
})}
|
|
362
626
|
</ScrollView>)}
|
|
363
627
|
|
|
628
|
+
{/* Active Filter Helper Status Bar */}
|
|
629
|
+
{(quickFilter !== 'all' ||
|
|
630
|
+
search.trim().length > 0 ||
|
|
631
|
+
statusFilters.size > 0 ||
|
|
632
|
+
methodFilters.size > 0 ||
|
|
633
|
+
filteredLogs.length !== logs.length) && (<View style={{
|
|
634
|
+
flexDirection: 'row',
|
|
635
|
+
alignItems: 'center',
|
|
636
|
+
justifyContent: 'space-between',
|
|
637
|
+
marginHorizontal: 12,
|
|
638
|
+
marginBottom: 8,
|
|
639
|
+
paddingHorizontal: 10,
|
|
640
|
+
paddingVertical: 5.5,
|
|
641
|
+
backgroundColor: `${AppColors.purple}10`,
|
|
642
|
+
borderRadius: 8,
|
|
643
|
+
borderWidth: 1,
|
|
644
|
+
borderColor: `${AppColors.purple}25`,
|
|
645
|
+
}}>
|
|
646
|
+
<Text style={{
|
|
647
|
+
fontFamily: AppFonts.interMedium,
|
|
648
|
+
fontSize: 10.5,
|
|
649
|
+
color: AppColors.purple,
|
|
650
|
+
}}>
|
|
651
|
+
Showing {filteredLogs.length} of {logs.length} requests
|
|
652
|
+
</Text>
|
|
653
|
+
<TouchableScale onPress={() => {
|
|
654
|
+
setSearch('');
|
|
655
|
+
setQuickFilter('all');
|
|
656
|
+
setStatusFilters(new Set());
|
|
657
|
+
setMethodFilters(new Set());
|
|
658
|
+
}}>
|
|
659
|
+
<Text style={{
|
|
660
|
+
fontFamily: AppFonts.interBold,
|
|
661
|
+
fontSize: 10.5,
|
|
662
|
+
color: AppColors.errorColor,
|
|
663
|
+
}}>
|
|
664
|
+
Clear All Filters
|
|
665
|
+
</Text>
|
|
666
|
+
</TouchableScale>
|
|
667
|
+
</View>)}
|
|
668
|
+
|
|
364
669
|
<Animated.View style={[
|
|
365
670
|
filtersAccordion.bodyStyle,
|
|
366
671
|
{ overflow: 'hidden' },
|
|
@@ -4,20 +4,30 @@ import Svg, { Path } from 'react-native-svg';
|
|
|
4
4
|
import { useInspector } from './InspectorContext';
|
|
5
5
|
import { LIB_VERSION } from '../../constants';
|
|
6
6
|
import { NpmIcon } from '../NetworkIcons';
|
|
7
|
+
import { copyToClipboard } from '../../helpers';
|
|
8
|
+
import { showToast } from '../../helpers/toast';
|
|
7
9
|
const CloseSvg = ({ size = 13, color = '#94A3B8' }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
8
10
|
<Path d="M18 6L6 18M6 6l12 12" stroke={color} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/>
|
|
9
11
|
</Svg>);
|
|
10
|
-
const
|
|
12
|
+
const CopySvg = ({ size = 11, color = '#94A3B8' }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
13
|
+
<Path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
14
|
+
<Path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
15
|
+
</Svg>);
|
|
16
|
+
const CheckSvg = ({ size = 11, color = '#10B981' }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
17
|
+
<Path d="M20 6L9 17l-5-5" stroke={color} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/>
|
|
18
|
+
</Svg>);
|
|
19
|
+
const ExternalLinkSvg = ({ size = 11, color = '#FFFFFF' }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
11
20
|
<Path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
12
21
|
<Path d="M15 3h6v6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
13
22
|
<Path d="M10 14L21 3" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
14
23
|
</Svg>);
|
|
15
|
-
const TOAST_TIMEOUT_MS =
|
|
24
|
+
const TOAST_TIMEOUT_MS = 7000;
|
|
16
25
|
export const NpmUpdateToast = () => {
|
|
17
26
|
const { updateAvailable, latestNpmVersion, showUpdateToast } = useInspector();
|
|
18
27
|
const [dismissed, setDismissed] = useState(false);
|
|
19
28
|
const [visible, setVisible] = useState(false);
|
|
20
|
-
const
|
|
29
|
+
const [copied, setCopied] = useState(false);
|
|
30
|
+
const translateYAnim = useRef(new Animated.Value(60)).current;
|
|
21
31
|
const opacityAnim = useRef(new Animated.Value(0)).current;
|
|
22
32
|
const progressAnim = useRef(new Animated.Value(1)).current;
|
|
23
33
|
const timerRef = useRef(null);
|
|
@@ -60,12 +70,12 @@ export const NpmUpdateToast = () => {
|
|
|
60
70
|
Animated.parallel([
|
|
61
71
|
Animated.timing(opacityAnim, {
|
|
62
72
|
toValue: 0,
|
|
63
|
-
duration:
|
|
73
|
+
duration: 180,
|
|
64
74
|
useNativeDriver: true,
|
|
65
75
|
}),
|
|
66
76
|
Animated.timing(translateYAnim, {
|
|
67
|
-
toValue:
|
|
68
|
-
duration:
|
|
77
|
+
toValue: 60,
|
|
78
|
+
duration: 180,
|
|
69
79
|
useNativeDriver: true,
|
|
70
80
|
}),
|
|
71
81
|
]).start(() => {
|
|
@@ -73,6 +83,14 @@ export const NpmUpdateToast = () => {
|
|
|
73
83
|
setDismissed(true);
|
|
74
84
|
});
|
|
75
85
|
};
|
|
86
|
+
const handleCopyCommand = () => {
|
|
87
|
+
copyToClipboard('npm install react-native-inapp-inspector@latest', 'Install Command');
|
|
88
|
+
setCopied(true);
|
|
89
|
+
showToast('Copied npm install command!');
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
setCopied(false);
|
|
92
|
+
}, 2000);
|
|
93
|
+
};
|
|
76
94
|
const handleOpenNpm = () => {
|
|
77
95
|
Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { });
|
|
78
96
|
handleDismiss();
|
|
@@ -93,7 +111,7 @@ export const NpmUpdateToast = () => {
|
|
|
93
111
|
<View style={styles.contentRow}>
|
|
94
112
|
{/* Left NPM Badge Icon */}
|
|
95
113
|
<View style={styles.npmIconContainer}>
|
|
96
|
-
<NpmIcon size={
|
|
114
|
+
<NpmIcon size={15} color="#CB3837"/>
|
|
97
115
|
</View>
|
|
98
116
|
|
|
99
117
|
{/* Text Details */}
|
|
@@ -109,6 +127,14 @@ export const NpmUpdateToast = () => {
|
|
|
109
127
|
</Text>
|
|
110
128
|
</View>
|
|
111
129
|
|
|
130
|
+
{/* Copy command quick button */}
|
|
131
|
+
<TouchableOpacity style={styles.copyButton} onPress={handleCopyCommand} hitSlop={6} activeOpacity={0.75}>
|
|
132
|
+
{copied ? <CheckSvg size={11} color="#10B981"/> : <CopySvg size={11} color="#94A3B8"/>}
|
|
133
|
+
<Text style={[styles.copyButtonText, copied && { color: '#10B981' }]}>
|
|
134
|
+
{copied ? 'Copied' : 'Copy'}
|
|
135
|
+
</Text>
|
|
136
|
+
</TouchableOpacity>
|
|
137
|
+
|
|
112
138
|
{/* Action Button: View */}
|
|
113
139
|
<TouchableOpacity style={styles.actionButton} onPress={handleOpenNpm} activeOpacity={0.8}>
|
|
114
140
|
<Text style={styles.actionButtonText}>View</Text>
|
|
@@ -140,37 +166,42 @@ const styles = StyleSheet.create({
|
|
|
140
166
|
container: {
|
|
141
167
|
position: 'absolute',
|
|
142
168
|
bottom: 24,
|
|
143
|
-
left:
|
|
144
|
-
right:
|
|
169
|
+
left: 14,
|
|
170
|
+
right: 14,
|
|
145
171
|
backgroundColor: '#0F172A',
|
|
146
172
|
borderRadius: 16,
|
|
147
173
|
borderWidth: 1,
|
|
148
174
|
borderColor: '#334155',
|
|
149
175
|
shadowColor: '#000000',
|
|
150
|
-
shadowOffset: { width: 0, height:
|
|
151
|
-
shadowOpacity: 0.
|
|
152
|
-
shadowRadius:
|
|
153
|
-
elevation:
|
|
176
|
+
shadowOffset: { width: 0, height: 12 },
|
|
177
|
+
shadowOpacity: 0.4,
|
|
178
|
+
shadowRadius: 24,
|
|
179
|
+
elevation: 24,
|
|
154
180
|
overflow: 'hidden',
|
|
155
181
|
zIndex: 99999,
|
|
156
182
|
},
|
|
157
183
|
contentRow: {
|
|
158
184
|
flexDirection: 'row',
|
|
159
185
|
alignItems: 'center',
|
|
160
|
-
paddingVertical:
|
|
161
|
-
paddingHorizontal:
|
|
162
|
-
gap:
|
|
186
|
+
paddingVertical: 11,
|
|
187
|
+
paddingHorizontal: 12,
|
|
188
|
+
gap: 8,
|
|
163
189
|
},
|
|
164
190
|
npmIconContainer: {
|
|
165
191
|
width: 32,
|
|
166
192
|
height: 32,
|
|
167
|
-
borderRadius:
|
|
193
|
+
borderRadius: 9,
|
|
168
194
|
backgroundColor: '#FFFFFF',
|
|
169
195
|
justifyContent: 'center',
|
|
170
196
|
alignItems: 'center',
|
|
171
197
|
borderWidth: 1,
|
|
172
|
-
borderColor: '#
|
|
198
|
+
borderColor: '#E2E8F0',
|
|
173
199
|
flexShrink: 0,
|
|
200
|
+
shadowColor: '#000000',
|
|
201
|
+
shadowOffset: { width: 0, height: 1 },
|
|
202
|
+
shadowOpacity: 0.15,
|
|
203
|
+
shadowRadius: 2,
|
|
204
|
+
elevation: 2,
|
|
174
205
|
},
|
|
175
206
|
textContainer: {
|
|
176
207
|
flex: 1,
|
|
@@ -179,73 +210,91 @@ const styles = StyleSheet.create({
|
|
|
179
210
|
titleRow: {
|
|
180
211
|
flexDirection: 'row',
|
|
181
212
|
alignItems: 'center',
|
|
182
|
-
gap:
|
|
213
|
+
gap: 5,
|
|
183
214
|
},
|
|
184
215
|
titleText: {
|
|
185
|
-
fontSize:
|
|
216
|
+
fontSize: 12.5,
|
|
186
217
|
fontWeight: '700',
|
|
187
218
|
color: '#F8FAFC',
|
|
188
219
|
letterSpacing: -0.2,
|
|
189
220
|
...fontStack,
|
|
190
221
|
},
|
|
191
222
|
versionPill: {
|
|
192
|
-
backgroundColor: '#
|
|
193
|
-
paddingHorizontal:
|
|
223
|
+
backgroundColor: '#7C3AED33',
|
|
224
|
+
paddingHorizontal: 5.5,
|
|
194
225
|
paddingVertical: 1.5,
|
|
195
|
-
borderRadius:
|
|
226
|
+
borderRadius: 5,
|
|
196
227
|
borderWidth: 1,
|
|
197
|
-
borderColor: '#
|
|
228
|
+
borderColor: '#8B5CF680',
|
|
198
229
|
},
|
|
199
230
|
versionPillText: {
|
|
200
|
-
fontSize: 10
|
|
231
|
+
fontSize: 10,
|
|
201
232
|
fontWeight: '700',
|
|
202
|
-
color: '#
|
|
233
|
+
color: '#C4B5FD',
|
|
203
234
|
...fontStack,
|
|
204
235
|
},
|
|
205
236
|
subtitleText: {
|
|
206
|
-
fontSize:
|
|
237
|
+
fontSize: 10.5,
|
|
238
|
+
color: '#94A3B8',
|
|
239
|
+
marginTop: 1,
|
|
240
|
+
...fontStack,
|
|
241
|
+
},
|
|
242
|
+
copyButton: {
|
|
243
|
+
flexDirection: 'row',
|
|
244
|
+
alignItems: 'center',
|
|
245
|
+
gap: 3.5,
|
|
246
|
+
backgroundColor: '#1E293B',
|
|
247
|
+
paddingVertical: 5.5,
|
|
248
|
+
paddingHorizontal: 8,
|
|
249
|
+
borderRadius: 7,
|
|
250
|
+
borderWidth: 1,
|
|
251
|
+
borderColor: '#334155',
|
|
252
|
+
flexShrink: 0,
|
|
253
|
+
},
|
|
254
|
+
copyButtonText: {
|
|
255
|
+
fontSize: 10.5,
|
|
256
|
+
fontWeight: '600',
|
|
207
257
|
color: '#94A3B8',
|
|
208
|
-
marginTop: 1.5,
|
|
209
258
|
...fontStack,
|
|
210
259
|
},
|
|
211
260
|
actionButton: {
|
|
212
261
|
flexDirection: 'row',
|
|
213
262
|
alignItems: 'center',
|
|
214
|
-
gap:
|
|
263
|
+
gap: 3.5,
|
|
215
264
|
backgroundColor: '#7C3AED',
|
|
216
|
-
paddingVertical:
|
|
217
|
-
paddingHorizontal:
|
|
218
|
-
borderRadius:
|
|
265
|
+
paddingVertical: 5.5,
|
|
266
|
+
paddingHorizontal: 9,
|
|
267
|
+
borderRadius: 7,
|
|
219
268
|
flexShrink: 0,
|
|
220
269
|
shadowColor: '#7C3AED',
|
|
221
270
|
shadowOffset: { width: 0, height: 2 },
|
|
222
|
-
shadowOpacity: 0.
|
|
271
|
+
shadowOpacity: 0.35,
|
|
223
272
|
shadowRadius: 4,
|
|
224
273
|
elevation: 3,
|
|
225
274
|
},
|
|
226
275
|
actionButtonText: {
|
|
227
|
-
fontSize: 11
|
|
276
|
+
fontSize: 11,
|
|
228
277
|
fontWeight: '700',
|
|
229
278
|
color: '#FFFFFF',
|
|
230
279
|
...fontStack,
|
|
231
280
|
},
|
|
232
281
|
closeButton: {
|
|
233
|
-
width:
|
|
234
|
-
height:
|
|
235
|
-
borderRadius:
|
|
282
|
+
width: 22,
|
|
283
|
+
height: 22,
|
|
284
|
+
borderRadius: 11,
|
|
236
285
|
backgroundColor: '#1E293B',
|
|
237
286
|
justifyContent: 'center',
|
|
238
287
|
alignItems: 'center',
|
|
239
288
|
flexShrink: 0,
|
|
240
289
|
},
|
|
241
290
|
progressBarTrack: {
|
|
242
|
-
height:
|
|
291
|
+
height: 2.5,
|
|
243
292
|
width: '100%',
|
|
244
293
|
backgroundColor: '#1E293B',
|
|
245
294
|
},
|
|
246
295
|
progressBarFill: {
|
|
247
296
|
height: '100%',
|
|
248
|
-
backgroundColor: '#
|
|
297
|
+
backgroundColor: '#8B5CF6',
|
|
249
298
|
},
|
|
250
299
|
});
|
|
251
300
|
export default NpmUpdateToast;
|