react-native-inapp-inspector 2.3.7 → 2.3.9
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/Inspector/AnalyticsTab.js +27 -2
- package/dist/commonjs/components/Inspector/BundleTab.js +3 -0
- package/dist/commonjs/components/Inspector/ConsoleTab.js +24 -1
- package/dist/commonjs/components/Inspector/CrashTab.js +30 -1
- package/dist/commonjs/components/Inspector/FeatureUnderDevNotice.d.ts +7 -0
- package/dist/commonjs/components/Inspector/FeatureUnderDevNotice.js +111 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +225 -108
- package/dist/commonjs/components/Inspector/NpmUpdateToast.js +1 -1
- package/dist/commonjs/components/Inspector/PerformanceTab.js +3 -0
- package/dist/commonjs/components/Inspector/ReduxTab.js +24 -1
- package/dist/commonjs/components/Inspector/SettingsPanel.js +73 -88
- package/dist/commonjs/components/Inspector/StorageTab.js +37 -11
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +2 -0
- package/dist/commonjs/components/LogCard.js +33 -3
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/networkLogger.js +2 -0
- package/dist/commonjs/helpers/telemetry.js +34 -0
- package/dist/commonjs/index.js +3 -0
- package/dist/esm/components/Inspector/AnalyticsTab.js +29 -4
- package/dist/esm/components/Inspector/BundleTab.js +3 -0
- package/dist/esm/components/Inspector/ConsoleTab.js +26 -3
- package/dist/esm/components/Inspector/CrashTab.js +32 -3
- package/dist/esm/components/Inspector/FeatureUnderDevNotice.d.ts +7 -0
- package/dist/esm/components/Inspector/FeatureUnderDevNotice.js +74 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +226 -109
- package/dist/esm/components/Inspector/NpmUpdateToast.js +1 -1
- package/dist/esm/components/Inspector/PerformanceTab.js +3 -0
- package/dist/esm/components/Inspector/ReduxTab.js +26 -3
- package/dist/esm/components/Inspector/SettingsPanel.js +73 -88
- package/dist/esm/components/Inspector/StorageTab.js +39 -13
- package/dist/esm/components/Inspector/UpdateAvailableModal.js +2 -0
- package/dist/esm/components/LogCard.js +34 -4
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/networkLogger.js +2 -0
- package/dist/esm/helpers/telemetry.js +34 -0
- package/dist/esm/index.js +3 -0
- package/package.json +1 -1
- package/src/components/Inspector/AnalyticsTab.tsx +71 -43
- package/src/components/Inspector/BundleTab.tsx +3 -0
- package/src/components/Inspector/ConsoleTab.tsx +28 -1
- package/src/components/Inspector/CrashTab.tsx +45 -14
- package/src/components/Inspector/FeatureUnderDevNotice.tsx +94 -0
- package/src/components/Inspector/InspectorHeader.tsx +257 -115
- package/src/components/Inspector/NpmUpdateToast.tsx +1 -1
- package/src/components/Inspector/PerformanceTab.tsx +3 -0
- package/src/components/Inspector/ReduxTab.tsx +28 -1
- package/src/components/Inspector/SettingsPanel.tsx +93 -132
- package/src/components/Inspector/StorageTab.tsx +56 -27
- package/src/components/Inspector/UpdateAvailableModal.tsx +2 -0
- package/src/components/LogCard.tsx +41 -4
- package/src/constants/version.ts +1 -1
- package/src/customHooks/networkLogger.ts +2 -0
- package/src/helpers/telemetry.ts +36 -0
- package/src/index.tsx +5 -0
|
@@ -169,7 +169,7 @@ export const NpmUpdateToast = () => {
|
|
|
169
169
|
handleDismiss();
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
-
if (!showUpdateToast || !visible || !updateAvailable || !latestNpmVersion) return null;
|
|
172
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__ || !showUpdateToast || !visible || !updateAvailable || !latestNpmVersion) return null;
|
|
173
173
|
|
|
174
174
|
const progressWidth = progressAnim.interpolate({
|
|
175
175
|
inputRange: [0, 1],
|
|
@@ -22,6 +22,7 @@ import TouchableScale from '../TouchableScale';
|
|
|
22
22
|
import CopyButton from '../CopyButton';
|
|
23
23
|
import HighlightText from '../HighlightText';
|
|
24
24
|
import EndOfListFooter from '../EndOfListFooter';
|
|
25
|
+
import FeatureUnderDevNotice from './FeatureUnderDevNotice';
|
|
25
26
|
import {AppColors} from '../../styles/AppColors';
|
|
26
27
|
import {AppFonts} from '../../styles/AppFonts';
|
|
27
28
|
import {useTranslation} from '../../i18n';
|
|
@@ -500,6 +501,8 @@ const PerformanceTab = React.memo(() => {
|
|
|
500
501
|
</TouchableScale>
|
|
501
502
|
</View>
|
|
502
503
|
|
|
504
|
+
<FeatureUnderDevNotice featureName="Performance & FPS Profiler" />
|
|
505
|
+
|
|
503
506
|
{/* Filter Category Tabs Carousel */}
|
|
504
507
|
<View style={perfStyles.categoryScrollWrapper}>
|
|
505
508
|
<ScrollView
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useCallback, useMemo, useState} from 'react';
|
|
1
|
+
import React, {useCallback, useMemo, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
FlatList,
|
|
4
4
|
Pressable,
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
TextAaIcon,
|
|
43
43
|
StorageIcon,
|
|
44
44
|
HeaderPauseIcon,
|
|
45
|
+
ChevronIcon,
|
|
45
46
|
} from '../NetworkIcons';
|
|
46
47
|
|
|
47
48
|
interface ReduxSliceItem {
|
|
@@ -121,6 +122,8 @@ const ReduxTab = React.memo(() => {
|
|
|
121
122
|
setSelectedReduxSlice,
|
|
122
123
|
} = useInspector();
|
|
123
124
|
|
|
125
|
+
const listRef = useRef<FlatList>(null);
|
|
126
|
+
|
|
124
127
|
// Sort mode: 'latest' (newest updated first) vs 'alpha' (A-Z)
|
|
125
128
|
const [sortMode, setSortMode] = useState<'latest' | 'alpha'>('latest');
|
|
126
129
|
|
|
@@ -656,6 +659,7 @@ const ReduxTab = React.memo(() => {
|
|
|
656
659
|
|
|
657
660
|
{/* ─── FlatList of Slices ─── */}
|
|
658
661
|
<FlatList
|
|
662
|
+
ref={listRef}
|
|
659
663
|
data={filteredSlices}
|
|
660
664
|
keyExtractor={item => item.id}
|
|
661
665
|
renderItem={renderSliceItem}
|
|
@@ -683,6 +687,29 @@ const ReduxTab = React.memo(() => {
|
|
|
683
687
|
]}
|
|
684
688
|
keyboardShouldPersistTaps="handled"
|
|
685
689
|
/>
|
|
690
|
+
|
|
691
|
+
<TouchableScale
|
|
692
|
+
onPress={() => {
|
|
693
|
+
try {
|
|
694
|
+
listRef.current?.scrollToOffset({
|
|
695
|
+
offset: 0,
|
|
696
|
+
animated: true,
|
|
697
|
+
});
|
|
698
|
+
} catch {
|
|
699
|
+
try {
|
|
700
|
+
listRef.current?.scrollToIndex({
|
|
701
|
+
index: 0,
|
|
702
|
+
animated: true,
|
|
703
|
+
});
|
|
704
|
+
} catch {}
|
|
705
|
+
}
|
|
706
|
+
}}
|
|
707
|
+
hitSlop={12}
|
|
708
|
+
style={styles.scrollTopBtn}>
|
|
709
|
+
<View style={{transform: [{rotate: '180deg'}]}}>
|
|
710
|
+
<ChevronIcon color={AppColors.white} size={18} />
|
|
711
|
+
</View>
|
|
712
|
+
</TouchableScale>
|
|
686
713
|
</View>
|
|
687
714
|
);
|
|
688
715
|
});
|
|
@@ -457,12 +457,13 @@ const SettingsPanel = () => {
|
|
|
457
457
|
contentContainerStyle={{padding: 16, paddingBottom: 100, gap: 14}}
|
|
458
458
|
showsVerticalScrollIndicator={false}>
|
|
459
459
|
{/* Segmented Top Navigation Sub-Tabs */}
|
|
460
|
+
{/* ─── Modern Scrollable Settings Sub-Tabs Bar ─── */}
|
|
460
461
|
<View
|
|
461
462
|
style={{
|
|
462
|
-
flexDirection: 'row',
|
|
463
463
|
backgroundColor: AppColors.primaryLight,
|
|
464
|
-
borderRadius:
|
|
465
|
-
|
|
464
|
+
borderRadius: 13,
|
|
465
|
+
paddingVertical: 4,
|
|
466
|
+
paddingHorizontal: 4,
|
|
466
467
|
borderWidth: 1,
|
|
467
468
|
borderColor: AppColors.grayBorderSecondary,
|
|
468
469
|
shadowColor: AppColors.black,
|
|
@@ -470,139 +471,99 @@ const SettingsPanel = () => {
|
|
|
470
471
|
shadowRadius: 4,
|
|
471
472
|
shadowOffset: {width: 0, height: 2},
|
|
472
473
|
}}>
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
accessibilityState={{selected: settingsActiveSubTab === 'module'}}
|
|
478
|
-
onPress={() => {
|
|
479
|
-
animateNextLayout();
|
|
480
|
-
setSettingsActiveSubTab('module');
|
|
481
|
-
}}
|
|
482
|
-
style={{
|
|
483
|
-
flex: 1,
|
|
484
|
-
paddingVertical: 9,
|
|
474
|
+
<ScrollView
|
|
475
|
+
horizontal
|
|
476
|
+
showsHorizontalScrollIndicator={false}
|
|
477
|
+
contentContainerStyle={{
|
|
485
478
|
flexDirection: 'row',
|
|
486
479
|
alignItems: 'center',
|
|
487
|
-
justifyContent: 'center',
|
|
488
480
|
gap: 6,
|
|
489
|
-
|
|
490
|
-
backgroundColor:
|
|
491
|
-
settingsActiveSubTab === 'module'
|
|
492
|
-
? AppColors.purple
|
|
493
|
-
: 'transparent',
|
|
494
|
-
}}>
|
|
495
|
-
<LayersIcon
|
|
496
|
-
color={
|
|
497
|
-
settingsActiveSubTab === 'module'
|
|
498
|
-
? AppColors.white
|
|
499
|
-
: AppColors.grayText
|
|
500
|
-
}
|
|
501
|
-
size={13}
|
|
502
|
-
/>
|
|
503
|
-
<Text
|
|
504
|
-
style={{
|
|
505
|
-
fontFamily: AppFonts.interBold,
|
|
506
|
-
fontSize: 12.5,
|
|
507
|
-
lineHeight: 16,
|
|
508
|
-
color:
|
|
509
|
-
settingsActiveSubTab === 'module'
|
|
510
|
-
? AppColors.white
|
|
511
|
-
: AppColors.grayText,
|
|
512
|
-
}}>
|
|
513
|
-
{t('settings.modulesAndTools')}
|
|
514
|
-
</Text>
|
|
515
|
-
</TouchableScale>
|
|
516
|
-
|
|
517
|
-
<TouchableScale
|
|
518
|
-
accessible={true}
|
|
519
|
-
accessibilityRole="tab"
|
|
520
|
-
accessibilityLabel={t('settings.uiPreferences')}
|
|
521
|
-
accessibilityState={{selected: settingsActiveSubTab === 'ui'}}
|
|
522
|
-
onPress={() => {
|
|
523
|
-
animateNextLayout();
|
|
524
|
-
setSettingsActiveSubTab('ui');
|
|
525
|
-
}}
|
|
526
|
-
style={{
|
|
527
|
-
flex: 1,
|
|
528
|
-
paddingVertical: 9,
|
|
529
|
-
flexDirection: 'row',
|
|
530
|
-
alignItems: 'center',
|
|
531
|
-
justifyContent: 'center',
|
|
532
|
-
gap: 5,
|
|
533
|
-
borderRadius: 9,
|
|
534
|
-
backgroundColor:
|
|
535
|
-
settingsActiveSubTab === 'ui'
|
|
536
|
-
? AppColors.purple
|
|
537
|
-
: 'transparent',
|
|
538
|
-
}}>
|
|
539
|
-
<ScreenIcon
|
|
540
|
-
color={
|
|
541
|
-
settingsActiveSubTab === 'ui'
|
|
542
|
-
? AppColors.white
|
|
543
|
-
: AppColors.grayText
|
|
544
|
-
}
|
|
545
|
-
size={13}
|
|
546
|
-
/>
|
|
547
|
-
<Text
|
|
548
|
-
numberOfLines={1}
|
|
549
|
-
style={{
|
|
550
|
-
fontFamily: AppFonts.interBold,
|
|
551
|
-
fontSize: 12,
|
|
552
|
-
lineHeight: 16,
|
|
553
|
-
color:
|
|
554
|
-
settingsActiveSubTab === 'ui'
|
|
555
|
-
? AppColors.white
|
|
556
|
-
: AppColors.grayText,
|
|
557
|
-
}}>
|
|
558
|
-
{t('settings.uiPreferences')}
|
|
559
|
-
</Text>
|
|
560
|
-
</TouchableScale>
|
|
561
|
-
|
|
562
|
-
<TouchableScale
|
|
563
|
-
accessible={true}
|
|
564
|
-
accessibilityRole="tab"
|
|
565
|
-
accessibilityLabel={t('settings.ramLimits')}
|
|
566
|
-
accessibilityState={{selected: settingsActiveSubTab === 'limits'}}
|
|
567
|
-
onPress={() => {
|
|
568
|
-
animateNextLayout();
|
|
569
|
-
setSettingsActiveSubTab('limits');
|
|
570
|
-
}}
|
|
571
|
-
style={{
|
|
572
|
-
flex: 1,
|
|
573
|
-
paddingVertical: 9,
|
|
574
|
-
flexDirection: 'row',
|
|
575
|
-
alignItems: 'center',
|
|
576
|
-
justifyContent: 'center',
|
|
577
|
-
gap: 5,
|
|
578
|
-
borderRadius: 9,
|
|
579
|
-
backgroundColor:
|
|
580
|
-
settingsActiveSubTab === 'limits'
|
|
581
|
-
? AppColors.purple
|
|
582
|
-
: 'transparent',
|
|
481
|
+
paddingHorizontal: 2,
|
|
583
482
|
}}>
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
483
|
+
{[
|
|
484
|
+
{
|
|
485
|
+
key: 'module' as const,
|
|
486
|
+
label: t('settings.modulesAndTools', 'Modules & Tools'),
|
|
487
|
+
Icon: LayersIcon,
|
|
488
|
+
badge: `${allModules.filter(m => stagedTabVisibility?.[m.key as ActiveTab] || m.key === 'apis').length}/${allModules.length}`,
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
key: 'ui' as const,
|
|
492
|
+
label: t('settings.uiPreferences', 'UI Preferences'),
|
|
493
|
+
Icon: ScreenIcon,
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
key: 'limits' as const,
|
|
497
|
+
label: t('settings.ramLimits', 'RAM & Limits'),
|
|
498
|
+
Icon: BrainIcon,
|
|
499
|
+
},
|
|
500
|
+
].map(tab => {
|
|
501
|
+
const isActive = settingsActiveSubTab === tab.key;
|
|
502
|
+
const IconComp = tab.Icon;
|
|
503
|
+
return (
|
|
504
|
+
<TouchableScale
|
|
505
|
+
key={tab.key}
|
|
506
|
+
accessible={true}
|
|
507
|
+
accessibilityRole="tab"
|
|
508
|
+
accessibilityLabel={tab.label}
|
|
509
|
+
accessibilityState={{selected: isActive}}
|
|
510
|
+
onPress={() => {
|
|
511
|
+
animateNextLayout();
|
|
512
|
+
setSettingsActiveSubTab(tab.key);
|
|
513
|
+
}}
|
|
514
|
+
style={{
|
|
515
|
+
paddingVertical: 8,
|
|
516
|
+
paddingHorizontal: 14,
|
|
517
|
+
flexDirection: 'row',
|
|
518
|
+
alignItems: 'center',
|
|
519
|
+
justifyContent: 'center',
|
|
520
|
+
gap: 6,
|
|
521
|
+
borderRadius: 9,
|
|
522
|
+
backgroundColor: isActive
|
|
523
|
+
? AppColors.purple
|
|
524
|
+
: 'transparent',
|
|
525
|
+
}}>
|
|
526
|
+
<IconComp
|
|
527
|
+
color={isActive ? AppColors.white : AppColors.grayText}
|
|
528
|
+
size={13}
|
|
529
|
+
/>
|
|
530
|
+
<Text
|
|
531
|
+
style={{
|
|
532
|
+
fontFamily: AppFonts.interBold,
|
|
533
|
+
fontSize: 12.5,
|
|
534
|
+
lineHeight: 16,
|
|
535
|
+
color: isActive
|
|
536
|
+
? AppColors.white
|
|
537
|
+
: AppColors.grayText,
|
|
538
|
+
}}>
|
|
539
|
+
{tab.label}
|
|
540
|
+
</Text>
|
|
541
|
+
{tab.badge && (
|
|
542
|
+
<View
|
|
543
|
+
style={{
|
|
544
|
+
backgroundColor: isActive
|
|
545
|
+
? 'rgba(255,255,255,0.25)'
|
|
546
|
+
: `${AppColors.purple}18`,
|
|
547
|
+
paddingHorizontal: 5.5,
|
|
548
|
+
paddingVertical: 1,
|
|
549
|
+
borderRadius: 10,
|
|
550
|
+
}}>
|
|
551
|
+
<Text
|
|
552
|
+
style={{
|
|
553
|
+
fontFamily: AppFonts.interBold,
|
|
554
|
+
fontSize: 9.5,
|
|
555
|
+
color: isActive
|
|
556
|
+
? AppColors.white
|
|
557
|
+
: AppColors.purple,
|
|
558
|
+
}}>
|
|
559
|
+
{tab.badge}
|
|
560
|
+
</Text>
|
|
561
|
+
</View>
|
|
562
|
+
)}
|
|
563
|
+
</TouchableScale>
|
|
564
|
+
);
|
|
565
|
+
})}
|
|
566
|
+
</ScrollView>
|
|
606
567
|
</View>
|
|
607
568
|
|
|
608
569
|
{settingsActiveSubTab === 'module' && (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useState, useEffect, useMemo, useCallback} from 'react';
|
|
1
|
+
import React, {useState, useEffect, useMemo, useCallback, useRef} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from 'react-native';
|
|
14
14
|
import TouchableScale from '../TouchableScale';
|
|
15
15
|
import CopyButton from '../CopyButton';
|
|
16
|
+
import globalStyles from '../../styles';
|
|
16
17
|
import {AppColors} from '../../styles/AppColors';
|
|
17
18
|
import {AppFonts} from '../../styles/AppFonts';
|
|
18
19
|
import {useTranslation} from '../../i18n';
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
CircleAlertIcon,
|
|
29
30
|
LayersIcon,
|
|
30
31
|
ResetIcon,
|
|
32
|
+
ChevronIcon,
|
|
31
33
|
} from '../NetworkIcons';
|
|
32
34
|
import {
|
|
33
35
|
fetchStorageEntries,
|
|
@@ -171,6 +173,7 @@ const StorageEntryCard = React.memo(function StorageEntryCard({
|
|
|
171
173
|
|
|
172
174
|
export const StorageTab = React.memo(() => {
|
|
173
175
|
const {t} = useTranslation();
|
|
176
|
+
const listRef = useRef<FlatList>(null);
|
|
174
177
|
const [activeDriver, setActiveDriver] = useState<StorageDriver>('asyncStorage');
|
|
175
178
|
const [activeMMKVId, setActiveMMKVId] = useState<string>('default');
|
|
176
179
|
const [entries, setEntries] = useState<StorageEntry[]>([]);
|
|
@@ -555,34 +558,60 @@ export const StorageTab = React.memo(() => {
|
|
|
555
558
|
<Text style={styles.loadingText}>Loading storage entries...</Text>
|
|
556
559
|
</View>
|
|
557
560
|
) : (
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
561
|
+
<>
|
|
562
|
+
<FlatList
|
|
563
|
+
ref={listRef}
|
|
564
|
+
data={filteredEntries}
|
|
565
|
+
keyExtractor={item => item.key}
|
|
566
|
+
renderItem={renderItem}
|
|
567
|
+
initialNumToRender={10}
|
|
568
|
+
maxToRenderPerBatch={10}
|
|
569
|
+
windowSize={5}
|
|
570
|
+
removeClippedSubviews={Platform.OS === 'android'}
|
|
571
|
+
style={styles.scrollArea}
|
|
572
|
+
contentContainerStyle={styles.scrollContent}
|
|
573
|
+
showsVerticalScrollIndicator={false}
|
|
574
|
+
ListEmptyComponent={
|
|
575
|
+
<View style={styles.emptyContainer}>
|
|
576
|
+
<View style={styles.emptyIconWrap}>
|
|
577
|
+
<DatabaseIcon size={28} color={AppColors.grayTextWeak} />
|
|
578
|
+
</View>
|
|
579
|
+
<Text style={styles.emptyTitle}>
|
|
580
|
+
{search ? 'No matching keys found' : `No ${activeDriver === 'asyncStorage' ? 'AsyncStorage' : 'MMKV'} Keys`}
|
|
581
|
+
</Text>
|
|
582
|
+
<Text style={styles.emptySubtitle}>
|
|
583
|
+
{search
|
|
584
|
+
? 'Try modifying your search query'
|
|
585
|
+
: `Storage is auto-detected. Tap "+ Add" above to create your first ${activeDriver === 'asyncStorage' ? 'AsyncStorage' : 'MMKV'} key!`}
|
|
586
|
+
</Text>
|
|
573
587
|
</View>
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
588
|
+
}
|
|
589
|
+
ListFooterComponent={<View style={{height: 60}} />}
|
|
590
|
+
/>
|
|
591
|
+
|
|
592
|
+
<TouchableScale
|
|
593
|
+
onPress={() => {
|
|
594
|
+
try {
|
|
595
|
+
listRef.current?.scrollToOffset({
|
|
596
|
+
offset: 0,
|
|
597
|
+
animated: true,
|
|
598
|
+
});
|
|
599
|
+
} catch {
|
|
600
|
+
try {
|
|
601
|
+
listRef.current?.scrollToIndex({
|
|
602
|
+
index: 0,
|
|
603
|
+
animated: true,
|
|
604
|
+
});
|
|
605
|
+
} catch {}
|
|
606
|
+
}
|
|
607
|
+
}}
|
|
608
|
+
hitSlop={12}
|
|
609
|
+
style={globalStyles.scrollTopBtn}>
|
|
610
|
+
<View style={{transform: [{rotate: '180deg'}]}}>
|
|
611
|
+
<ChevronIcon color={AppColors.white} size={18} />
|
|
582
612
|
</View>
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
/>
|
|
613
|
+
</TouchableScale>
|
|
614
|
+
</>
|
|
586
615
|
)}
|
|
587
616
|
|
|
588
617
|
{/* ── Create / Edit Key Modal ── */}
|
|
@@ -125,6 +125,8 @@ export const UpdateAvailableModal: React.FC<UpdateAvailableModalProps> = ({
|
|
|
125
125
|
|
|
126
126
|
const installCommand = `npm install react-native-inapp-inspector@latest`;
|
|
127
127
|
|
|
128
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__) return null;
|
|
129
|
+
|
|
128
130
|
useEffect(() => {
|
|
129
131
|
if (visible) {
|
|
130
132
|
setCopied(false);
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
CircleAlertIcon,
|
|
28
28
|
CircleXIcon,
|
|
29
29
|
RepeatIcon,
|
|
30
|
+
PinIcon,
|
|
30
31
|
} from './NetworkIcons';
|
|
31
32
|
import {AppFonts} from '../styles/AppFonts';
|
|
32
33
|
import styles from '../styles';
|
|
@@ -408,11 +409,47 @@ const LogCard = React.memo(function LogCard({
|
|
|
408
409
|
</View>
|
|
409
410
|
</View>
|
|
410
411
|
|
|
411
|
-
{/* Row 3: Footer (Timestamp on Left, Response Size & Duration on Right) */}
|
|
412
|
+
{/* Row 3: Footer (Timestamp & Origin on Left, Response Size & Duration on Right) */}
|
|
412
413
|
<View style={styles.cardFooterRow}>
|
|
413
|
-
<View style={
|
|
414
|
-
<
|
|
415
|
-
|
|
414
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 6, flexShrink: 1, minWidth: 0}}>
|
|
415
|
+
<View style={styles.cardDateRow}>
|
|
416
|
+
<CalendarIcon color={AppColors.grayTextWeak} size={10} />
|
|
417
|
+
<Text style={styles.cardDateText}>{triggeredAt}</Text>
|
|
418
|
+
</View>
|
|
419
|
+
|
|
420
|
+
{item.caller && item.caller !== 'Unknown' && (
|
|
421
|
+
<View
|
|
422
|
+
style={[
|
|
423
|
+
styles.chip,
|
|
424
|
+
{
|
|
425
|
+
flexDirection: 'row',
|
|
426
|
+
alignItems: 'center',
|
|
427
|
+
gap: 3,
|
|
428
|
+
backgroundColor: `${AppColors.skyBlue}14`,
|
|
429
|
+
borderColor: `${AppColors.skyBlue}30`,
|
|
430
|
+
paddingHorizontal: 5,
|
|
431
|
+
paddingVertical: 1,
|
|
432
|
+
borderRadius: 4,
|
|
433
|
+
flexShrink: 1,
|
|
434
|
+
maxWidth: 160,
|
|
435
|
+
},
|
|
436
|
+
]}>
|
|
437
|
+
<PinIcon color={AppColors.skyBlue} size={8.5} />
|
|
438
|
+
<Text
|
|
439
|
+
style={[
|
|
440
|
+
styles.chipText,
|
|
441
|
+
{
|
|
442
|
+
color: AppColors.skyBlue,
|
|
443
|
+
fontSize: 8.5,
|
|
444
|
+
fontFamily: AppFonts.interMedium,
|
|
445
|
+
},
|
|
446
|
+
]}
|
|
447
|
+
numberOfLines={1}
|
|
448
|
+
ellipsizeMode="middle">
|
|
449
|
+
{item.caller}
|
|
450
|
+
</Text>
|
|
451
|
+
</View>
|
|
452
|
+
)}
|
|
416
453
|
</View>
|
|
417
454
|
|
|
418
455
|
<View style={styles.cardFooterRight}>
|
package/src/constants/version.ts
CHANGED
|
@@ -47,6 +47,8 @@ const IGNORED_URL_PATTERNS: RegExp[] = [
|
|
|
47
47
|
/\/status(?:\?|$)/i,
|
|
48
48
|
/127\.0\.0\.1:(?:8081|8082|8083|19000|19001|19002|3000|8000)/i,
|
|
49
49
|
/localhost:(?:8081|8082|8083|19000|19001|19002|3000|8000)\/index\.bundle/i,
|
|
50
|
+
/google-analytics\.com\/mp\/collect/i,
|
|
51
|
+
/analytics\.google\.com/i,
|
|
50
52
|
];
|
|
51
53
|
|
|
52
54
|
function shouldIgnoreUrl(url: string | undefined | null): boolean {
|
package/src/helpers/telemetry.ts
CHANGED
|
@@ -98,6 +98,38 @@ async function getOrCreateClientId(): Promise<string> {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
function isDeviceEmulator(): boolean {
|
|
102
|
+
try {
|
|
103
|
+
if (Platform.OS === 'android') {
|
|
104
|
+
const c = (Platform.constants as any) || {};
|
|
105
|
+
const model = String(c.Model || '').toLowerCase();
|
|
106
|
+
const brand = String(c.Brand || '').toLowerCase();
|
|
107
|
+
const fingerprint = String(c.Fingerprint || '').toLowerCase();
|
|
108
|
+
const hardware = String(c.Hardware || '').toLowerCase();
|
|
109
|
+
const manufacturer = String(c.Manufacturer || '').toLowerCase();
|
|
110
|
+
return (
|
|
111
|
+
model.includes('emulator') ||
|
|
112
|
+
model.includes('sdk') ||
|
|
113
|
+
model.includes('google_sdk') ||
|
|
114
|
+
model.includes('vbox') ||
|
|
115
|
+
brand.includes('generic') ||
|
|
116
|
+
fingerprint.startsWith('generic') ||
|
|
117
|
+
hardware.includes('goldfish') ||
|
|
118
|
+
hardware.includes('ranchu') ||
|
|
119
|
+
manufacturer.includes('genymotion')
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (Platform.OS === 'ios') {
|
|
123
|
+
const c = (Platform.constants as any) || {};
|
|
124
|
+
const model = String(c.Model || '').toLowerCase();
|
|
125
|
+
return model.includes('simulator') || Boolean(c.isSimulator);
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
101
133
|
function getSystemMetadata(environment?: string) {
|
|
102
134
|
const rnConstants = Platform.constants as any;
|
|
103
135
|
const rnVersion = rnConstants?.reactNativeVersion
|
|
@@ -107,6 +139,7 @@ function getSystemMetadata(environment?: string) {
|
|
|
107
139
|
const isHermes = Boolean(typeof (global as any).HermesInternal === 'object' && (global as any).HermesInternal !== null);
|
|
108
140
|
const isFabric = Boolean((global as any)?.nativeFabricUIManager !== undefined);
|
|
109
141
|
const isDev = Boolean(typeof __DEV__ !== 'undefined' && __DEV__);
|
|
142
|
+
const isEmulator = isDeviceEmulator();
|
|
110
143
|
|
|
111
144
|
return {
|
|
112
145
|
lib_version: LIB_VERSION,
|
|
@@ -116,6 +149,9 @@ function getSystemMetadata(environment?: string) {
|
|
|
116
149
|
is_hermes: isHermes,
|
|
117
150
|
is_fabric: isFabric,
|
|
118
151
|
is_dev: isDev,
|
|
152
|
+
is_emulator: isEmulator,
|
|
153
|
+
device_type: isEmulator ? 'emulator' : 'real_device',
|
|
154
|
+
app_mode: isDev ? 'local_mode' : 'bundled_application',
|
|
119
155
|
environment: environment || (isDev ? 'DEV' : 'PROD'),
|
|
120
156
|
engagement_time_msec: 1000,
|
|
121
157
|
};
|
package/src/index.tsx
CHANGED
|
@@ -567,6 +567,11 @@ const NetworkInspector = ({
|
|
|
567
567
|
}, [latestNpmVersion]);
|
|
568
568
|
|
|
569
569
|
useEffect(() => {
|
|
570
|
+
// Only check for npm updates when running in local development / debug mode (__DEV__)
|
|
571
|
+
// Never show or check in production / bundled application
|
|
572
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
570
575
|
let cancelled = false;
|
|
571
576
|
fetch('https://registry.npmjs.org/react-native-inapp-inspector/latest')
|
|
572
577
|
.then(res => (res.ok ? res.json() : null))
|