react-native-inapp-inspector 2.0.4 → 2.0.6

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.
Files changed (108) hide show
  1. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  2. package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
  3. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  4. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  5. package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
  6. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  7. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  8. package/android/.gradle/8.9/gc.properties +0 -0
  9. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  10. package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
  11. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  12. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  13. package/android/.gradle/9.2.0/gc.properties +0 -0
  14. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  15. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  16. package/android/.gradle/vcs-1/gc.properties +0 -0
  17. package/android/build/reports/problems/problems-report.html +659 -0
  18. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +11 -0
  19. package/dist/commonjs/components/Inspector/AuditTab.d.ts +3 -0
  20. package/dist/commonjs/components/Inspector/AuditTab.js +741 -0
  21. package/dist/commonjs/components/Inspector/DeviceTab.d.ts +3 -0
  22. package/dist/commonjs/components/Inspector/DeviceTab.js +717 -0
  23. package/dist/commonjs/components/Inspector/InspectorHeader.js +115 -75
  24. package/dist/commonjs/components/Inspector/MainScreen.js +16 -2
  25. package/dist/commonjs/components/Inspector/NetworkDetail.js +15 -0
  26. package/dist/commonjs/components/Inspector/NetworkTab.js +317 -12
  27. package/dist/commonjs/components/Inspector/NpmUpdateToast.js +88 -39
  28. package/dist/commonjs/components/Inspector/PerformanceHud.d.ts +7 -0
  29. package/dist/commonjs/components/Inspector/PerformanceHud.js +210 -0
  30. package/dist/commonjs/components/Inspector/PerformanceTab.js +30 -18
  31. package/dist/commonjs/components/Inspector/RequestReplayModal.d.ts +9 -0
  32. package/dist/commonjs/components/Inspector/RequestReplayModal.js +792 -0
  33. package/dist/commonjs/components/Inspector/RequestReplayView.d.ts +8 -0
  34. package/dist/commonjs/components/Inspector/RequestReplayView.js +871 -0
  35. package/dist/commonjs/components/Inspector/SettingsPanel.js +847 -370
  36. package/dist/commonjs/components/Inspector/StorageTab.d.ts +3 -0
  37. package/dist/commonjs/components/Inspector/StorageTab.js +610 -0
  38. package/dist/commonjs/components/Inspector/TabBar.js +23 -2
  39. package/dist/commonjs/components/Inspector/UpdateAvailableModal.d.ts +8 -0
  40. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +469 -0
  41. package/dist/commonjs/components/NetworkIcons.d.ts +12 -0
  42. package/dist/commonjs/components/NetworkIcons.js +72 -3
  43. package/dist/commonjs/constants/version.d.ts +1 -1
  44. package/dist/commonjs/constants/version.js +1 -1
  45. package/dist/commonjs/customHooks/storageInspector.d.ts +13 -0
  46. package/dist/commonjs/customHooks/storageInspector.js +179 -0
  47. package/dist/commonjs/helpers/deviceInfo.d.ts +4 -0
  48. package/dist/commonjs/helpers/deviceInfo.js +94 -0
  49. package/dist/commonjs/helpers/index.d.ts +2 -0
  50. package/dist/commonjs/helpers/index.js +12 -1
  51. package/dist/commonjs/helpers/packageAuditor.d.ts +5 -0
  52. package/dist/commonjs/helpers/packageAuditor.js +182 -0
  53. package/dist/commonjs/helpers/searchQueryParser.d.ts +8 -3
  54. package/dist/commonjs/helpers/searchQueryParser.js +85 -31
  55. package/dist/commonjs/helpers/telemetry.js +4 -4
  56. package/dist/commonjs/i18n/locales/en.json +3 -2
  57. package/dist/commonjs/index.d.ts +1 -0
  58. package/dist/commonjs/index.js +171 -16
  59. package/dist/commonjs/native/NativeInspector.d.ts +1 -0
  60. package/dist/commonjs/types/enums.d.ts +7 -0
  61. package/dist/commonjs/types/enums.js +7 -0
  62. package/dist/commonjs/types/interfaces.d.ts +82 -0
  63. package/dist/esm/components/Inspector/AuditTab.d.ts +3 -0
  64. package/dist/esm/components/Inspector/AuditTab.js +702 -0
  65. package/dist/esm/components/Inspector/DeviceTab.d.ts +3 -0
  66. package/dist/esm/components/Inspector/DeviceTab.js +678 -0
  67. package/dist/esm/components/Inspector/InspectorHeader.js +115 -75
  68. package/dist/esm/components/Inspector/MainScreen.js +16 -2
  69. package/dist/esm/components/Inspector/NetworkDetail.js +16 -1
  70. package/dist/esm/components/Inspector/NetworkTab.js +317 -12
  71. package/dist/esm/components/Inspector/NpmUpdateToast.js +88 -39
  72. package/dist/esm/components/Inspector/PerformanceHud.d.ts +7 -0
  73. package/dist/esm/components/Inspector/PerformanceHud.js +170 -0
  74. package/dist/esm/components/Inspector/PerformanceTab.js +31 -19
  75. package/dist/esm/components/Inspector/RequestReplayModal.d.ts +9 -0
  76. package/dist/esm/components/Inspector/RequestReplayModal.js +752 -0
  77. package/dist/esm/components/Inspector/RequestReplayView.d.ts +8 -0
  78. package/dist/esm/components/Inspector/RequestReplayView.js +831 -0
  79. package/dist/esm/components/Inspector/SettingsPanel.js +848 -371
  80. package/dist/esm/components/Inspector/StorageTab.d.ts +3 -0
  81. package/dist/esm/components/Inspector/StorageTab.js +571 -0
  82. package/dist/esm/components/Inspector/TabBar.js +24 -3
  83. package/dist/esm/components/Inspector/UpdateAvailableModal.d.ts +8 -0
  84. package/dist/esm/components/Inspector/UpdateAvailableModal.js +432 -0
  85. package/dist/esm/components/NetworkIcons.d.ts +12 -0
  86. package/dist/esm/components/NetworkIcons.js +57 -0
  87. package/dist/esm/constants/version.d.ts +1 -1
  88. package/dist/esm/constants/version.js +1 -1
  89. package/dist/esm/customHooks/storageInspector.d.ts +13 -0
  90. package/dist/esm/customHooks/storageInspector.js +170 -0
  91. package/dist/esm/helpers/deviceInfo.d.ts +4 -0
  92. package/dist/esm/helpers/deviceInfo.js +89 -0
  93. package/dist/esm/helpers/index.d.ts +2 -0
  94. package/dist/esm/helpers/index.js +10 -0
  95. package/dist/esm/helpers/packageAuditor.d.ts +5 -0
  96. package/dist/esm/helpers/packageAuditor.js +173 -0
  97. package/dist/esm/helpers/searchQueryParser.d.ts +8 -3
  98. package/dist/esm/helpers/searchQueryParser.js +85 -31
  99. package/dist/esm/helpers/telemetry.js +4 -4
  100. package/dist/esm/i18n/locales/en.json +3 -2
  101. package/dist/esm/index.d.ts +1 -0
  102. package/dist/esm/index.js +167 -15
  103. package/dist/esm/native/NativeInspector.d.ts +1 -0
  104. package/dist/esm/types/enums.d.ts +7 -0
  105. package/dist/esm/types/enums.js +7 -0
  106. package/dist/esm/types/interfaces.d.ts +82 -0
  107. package/ios/NetworkInspectorModule.mm +12 -5
  108. package/package.json +4 -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 ? AppColors.purple : AppColors.grayTextWeak} size={16}/>
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: 6,
261
- paddingVertical: 2,
412
+ paddingHorizontal: 5,
413
+ paddingVertical: 1.5,
262
414
  }}>
263
415
  <Text style={{
264
416
  color: AppColors.purple,
265
- fontSize: 10,
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={14}/>
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: 6, maxHeight: 30 }} contentContainerStyle={{
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: 6,
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: 8,
340
- paddingVertical: 3.5,
341
- borderRadius: 6,
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: 10,
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 ExternalLinkSvg = ({ size = 12, color = '#FFFFFF' }) => (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
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 = 6500;
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 translateYAnim = useRef(new Animated.Value(50)).current;
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: 200,
73
+ duration: 180,
64
74
  useNativeDriver: true,
65
75
  }),
66
76
  Animated.timing(translateYAnim, {
67
- toValue: 50,
68
- duration: 200,
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={14} color="#CB3837"/>
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: 16,
144
- right: 16,
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: 10 },
151
- shadowOpacity: 0.35,
152
- shadowRadius: 20,
153
- elevation: 20,
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: 12,
161
- paddingHorizontal: 14,
162
- gap: 10,
186
+ paddingVertical: 11,
187
+ paddingHorizontal: 12,
188
+ gap: 8,
163
189
  },
164
190
  npmIconContainer: {
165
191
  width: 32,
166
192
  height: 32,
167
- borderRadius: 10,
193
+ borderRadius: 9,
168
194
  backgroundColor: '#FFFFFF',
169
195
  justifyContent: 'center',
170
196
  alignItems: 'center',
171
197
  borderWidth: 1,
172
- borderColor: '#CBD5E1',
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: 6,
213
+ gap: 5,
183
214
  },
184
215
  titleText: {
185
- fontSize: 13,
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: '#7C3AED26',
193
- paddingHorizontal: 6,
223
+ backgroundColor: '#7C3AED33',
224
+ paddingHorizontal: 5.5,
194
225
  paddingVertical: 1.5,
195
- borderRadius: 6,
226
+ borderRadius: 5,
196
227
  borderWidth: 1,
197
- borderColor: '#7C3AED59',
228
+ borderColor: '#8B5CF680',
198
229
  },
199
230
  versionPillText: {
200
- fontSize: 10.5,
231
+ fontSize: 10,
201
232
  fontWeight: '700',
202
- color: '#A78BFA',
233
+ color: '#C4B5FD',
203
234
  ...fontStack,
204
235
  },
205
236
  subtitleText: {
206
- fontSize: 11,
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: 4,
263
+ gap: 3.5,
215
264
  backgroundColor: '#7C3AED',
216
- paddingVertical: 6,
217
- paddingHorizontal: 10,
218
- borderRadius: 8,
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.3,
271
+ shadowOpacity: 0.35,
223
272
  shadowRadius: 4,
224
273
  elevation: 3,
225
274
  },
226
275
  actionButtonText: {
227
- fontSize: 11.5,
276
+ fontSize: 11,
228
277
  fontWeight: '700',
229
278
  color: '#FFFFFF',
230
279
  ...fontStack,
231
280
  },
232
281
  closeButton: {
233
- width: 24,
234
- height: 24,
235
- borderRadius: 12,
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: 3,
291
+ height: 2.5,
243
292
  width: '100%',
244
293
  backgroundColor: '#1E293B',
245
294
  },
246
295
  progressBarFill: {
247
296
  height: '100%',
248
- backgroundColor: '#7C3AED',
297
+ backgroundColor: '#8B5CF6',
249
298
  },
250
299
  });
251
300
  export default NpmUpdateToast;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface PerformanceHudProps {
3
+ visible: boolean;
4
+ onPress: () => void;
5
+ }
6
+ export declare const PerformanceHud: React.FC<PerformanceHudProps>;
7
+ export default PerformanceHud;