react-native-inapp-inspector 2.2.8 → 2.3.0
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/src/main/java/com/inappinspector/NetworkInspectorModule.kt +22 -7
- package/dist/commonjs/components/AppHeaderLogo.js +45 -12
- package/dist/commonjs/components/BrandSquareIcon.js +92 -49
- package/dist/commonjs/components/EmptyState.d.ts +7 -2
- package/dist/commonjs/components/EmptyState.js +11 -5
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +29 -18
- package/dist/commonjs/components/Inspector/ConsoleTab.js +6 -1
- package/dist/commonjs/components/Inspector/CrashDetail.js +43 -9
- package/dist/commonjs/components/Inspector/CrashTab.js +34 -3
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +80 -16
- package/dist/commonjs/components/Inspector/InspectorHeader.js +16 -3
- package/dist/commonjs/components/Inspector/NetworkDetail.js +3 -2
- package/dist/commonjs/components/Inspector/NetworkTab.js +103 -4
- package/dist/commonjs/components/Inspector/ReduxTab.js +19 -3
- package/dist/commonjs/components/Inspector/SettingsPanel.js +4 -4
- package/dist/commonjs/components/Inspector/StorageTab.js +19 -3
- package/dist/commonjs/components/JsonViewer.js +2 -0
- package/dist/commonjs/components/MetaAccordion.js +15 -3
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/networkLogger.d.ts +3 -0
- package/dist/commonjs/customHooks/networkLogger.js +10 -1
- package/dist/commonjs/helpers/index.d.ts +6 -0
- package/dist/commonjs/helpers/index.js +196 -6
- package/dist/commonjs/helpers/searchQueryParser.js +62 -20
- package/dist/commonjs/i18n/index.d.ts +13 -0
- package/dist/commonjs/i18n/index.js +35 -2
- package/dist/commonjs/index.d.ts +3 -0
- package/dist/commonjs/index.js +80 -11
- package/dist/commonjs/native/NativeInspector.js +13 -0
- package/dist/commonjs/native/NativeNetworkInspector.d.ts +1 -1
- package/dist/commonjs/styles/AppColors.d.ts +4 -0
- package/dist/commonjs/styles/AppColors.js +11 -1
- package/dist/commonjs/styles/AppFonts.d.ts +11 -0
- package/dist/commonjs/styles/AppFonts.js +11 -1
- package/dist/commonjs/types/interfaces.d.ts +1 -0
- package/dist/esm/components/AppHeaderLogo.js +45 -12
- package/dist/esm/components/BrandSquareIcon.js +92 -49
- package/dist/esm/components/EmptyState.d.ts +7 -2
- package/dist/esm/components/EmptyState.js +11 -5
- package/dist/esm/components/Inspector/AnalyticsTab.js +30 -19
- package/dist/esm/components/Inspector/ConsoleTab.js +6 -1
- package/dist/esm/components/Inspector/CrashDetail.js +43 -9
- package/dist/esm/components/Inspector/CrashTab.js +34 -3
- package/dist/esm/components/Inspector/DeviceInfoTab.js +80 -16
- package/dist/esm/components/Inspector/InspectorHeader.js +17 -4
- package/dist/esm/components/Inspector/NetworkDetail.js +3 -2
- package/dist/esm/components/Inspector/NetworkTab.js +103 -4
- package/dist/esm/components/Inspector/ReduxTab.js +19 -3
- package/dist/esm/components/Inspector/SettingsPanel.js +4 -4
- package/dist/esm/components/Inspector/StorageTab.js +19 -3
- package/dist/esm/components/JsonViewer.js +2 -0
- package/dist/esm/components/MetaAccordion.js +15 -3
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/networkLogger.d.ts +3 -0
- package/dist/esm/customHooks/networkLogger.js +8 -0
- package/dist/esm/helpers/index.d.ts +6 -0
- package/dist/esm/helpers/index.js +193 -5
- package/dist/esm/helpers/searchQueryParser.js +62 -20
- package/dist/esm/i18n/index.d.ts +13 -0
- package/dist/esm/i18n/index.js +33 -3
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +68 -12
- package/dist/esm/native/NativeInspector.js +13 -0
- package/dist/esm/native/NativeNetworkInspector.d.ts +1 -1
- package/dist/esm/styles/AppColors.d.ts +4 -0
- package/dist/esm/styles/AppColors.js +9 -0
- package/dist/esm/styles/AppFonts.d.ts +11 -0
- package/dist/esm/styles/AppFonts.js +9 -0
- package/dist/esm/types/interfaces.d.ts +1 -0
- package/ios/NetworkInspectorModule.mm +11 -1
- package/package.json +1 -1
- package/src/components/AppHeaderLogo.tsx +46 -12
- package/src/components/BrandSquareIcon.tsx +127 -78
- package/src/components/EmptyState.tsx +27 -5
- package/src/components/Inspector/AnalyticsTab.tsx +48 -27
- package/src/components/Inspector/ConsoleTab.tsx +10 -0
- package/src/components/Inspector/CrashDetail.tsx +65 -9
- package/src/components/Inspector/CrashTab.tsx +41 -3
- package/src/components/Inspector/DeviceInfoTab.tsx +87 -16
- package/src/components/Inspector/InspectorHeader.tsx +24 -4
- package/src/components/Inspector/NetworkDetail.tsx +4 -4
- package/src/components/Inspector/NetworkTab.tsx +129 -4
- package/src/components/Inspector/ReduxTab.tsx +26 -8
- package/src/components/Inspector/SettingsPanel.tsx +4 -4
- package/src/components/Inspector/StorageTab.tsx +21 -3
- package/src/components/JsonViewer.tsx +2 -0
- package/src/components/MetaAccordion.tsx +18 -3
- package/src/constants/version.ts +1 -1
- package/src/customHooks/networkLogger.ts +15 -0
- package/src/helpers/index.ts +213 -5
- package/src/helpers/searchQueryParser.ts +63 -20
- package/src/i18n/index.ts +38 -3
- package/src/index.tsx +89 -11
- package/src/native/NativeInspector.ts +13 -0
- package/src/native/NativeNetworkInspector.ts +1 -1
- package/src/styles/AppColors.ts +9 -0
- package/src/styles/AppFonts.ts +16 -0
- package/src/types/interfaces.ts +1 -0
|
@@ -86,9 +86,9 @@ const InfoRow = React.memo(
|
|
|
86
86
|
styles.infoRow,
|
|
87
87
|
isLast && {borderBottomWidth: 0},
|
|
88
88
|
]}>
|
|
89
|
-
<View style={{flex: 1, paddingRight: 8}}>
|
|
90
|
-
<View style={{flexDirection: 'row', alignItems: 'center', gap: 6}}>
|
|
91
|
-
<Text style={styles.infoLabel}>{label}</Text>
|
|
89
|
+
<View style={{flex: 1, paddingRight: 8, minWidth: 0}}>
|
|
90
|
+
<View style={{flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', gap: 6}}>
|
|
91
|
+
<Text style={styles.infoLabel} numberOfLines={2}>{label}</Text>
|
|
92
92
|
{badge && (
|
|
93
93
|
<View
|
|
94
94
|
style={[
|
|
@@ -101,9 +101,17 @@ const InfoRow = React.memo(
|
|
|
101
101
|
</View>
|
|
102
102
|
)}
|
|
103
103
|
</View>
|
|
104
|
-
{subtext && <Text style={styles.infoSubtext}>{subtext}</Text>}
|
|
104
|
+
{subtext && <Text style={styles.infoSubtext} numberOfLines={2}>{subtext}</Text>}
|
|
105
105
|
</View>
|
|
106
|
-
<View
|
|
106
|
+
<View
|
|
107
|
+
style={{
|
|
108
|
+
flexDirection: 'row',
|
|
109
|
+
alignItems: 'center',
|
|
110
|
+
gap: 6,
|
|
111
|
+
flexShrink: 0,
|
|
112
|
+
maxWidth: '58%',
|
|
113
|
+
justifyContent: 'flex-end',
|
|
114
|
+
}}>
|
|
107
115
|
<Text
|
|
108
116
|
style={[
|
|
109
117
|
styles.infoValue,
|
|
@@ -111,7 +119,7 @@ const InfoRow = React.memo(
|
|
|
111
119
|
color: value ? AppColors.emerald500 : AppColors.errorColor,
|
|
112
120
|
},
|
|
113
121
|
]}
|
|
114
|
-
numberOfLines={
|
|
122
|
+
numberOfLines={3}
|
|
115
123
|
selectable>
|
|
116
124
|
{displayValue}
|
|
117
125
|
</Text>
|
|
@@ -446,6 +454,16 @@ export const DeviceInfoTab = React.memo(() => {
|
|
|
446
454
|
return text.toLowerCase().includes(search.toLowerCase().trim());
|
|
447
455
|
};
|
|
448
456
|
|
|
457
|
+
const hasAnyMatch = useMemo(() => {
|
|
458
|
+
if (!search.trim()) return true;
|
|
459
|
+
const query = search.toLowerCase().trim();
|
|
460
|
+
return (
|
|
461
|
+
JSON.stringify(fullDeviceData).toLowerCase().includes(query) ||
|
|
462
|
+
ipAddress.toLowerCase().includes(query) ||
|
|
463
|
+
pseudoUDID.toLowerCase().includes(query)
|
|
464
|
+
);
|
|
465
|
+
}, [search, fullDeviceData, ipAddress, pseudoUDID]);
|
|
466
|
+
|
|
449
467
|
return (
|
|
450
468
|
<View style={styles.container}>
|
|
451
469
|
{/* ─── Top Sub-Tabs Navigation Bar ─── */}
|
|
@@ -527,11 +545,11 @@ export const DeviceInfoTab = React.memo(() => {
|
|
|
527
545
|
<AndroidIcon size={20} color={AppColors.white} />
|
|
528
546
|
)}
|
|
529
547
|
</View>
|
|
530
|
-
<View style={{flex: 1}}>
|
|
531
|
-
<Text style={styles.heroTitle}>
|
|
548
|
+
<View style={{flex: 1, minWidth: 0}}>
|
|
549
|
+
<Text style={styles.heroTitle} numberOfLines={1} ellipsizeMode="tail">
|
|
532
550
|
{deviceMetrics?.deviceModel || (Platform.constants as any)?.Model || (Platform.OS === 'ios' ? 'Apple iPhone' : 'Android Device')}
|
|
533
551
|
</Text>
|
|
534
|
-
<Text style={styles.heroSubtitle}>
|
|
552
|
+
<Text style={styles.heroSubtitle} numberOfLines={1} ellipsizeMode="tail">
|
|
535
553
|
{Platform.OS === 'ios' ? `iOS ${Platform.Version}` : `Android ${Platform.Version} (API ${deviceMetrics?.apiLevel || Platform.Version})`}
|
|
536
554
|
</Text>
|
|
537
555
|
</View>
|
|
@@ -544,22 +562,22 @@ export const DeviceInfoTab = React.memo(() => {
|
|
|
544
562
|
{/* Quick Metrics Strip */}
|
|
545
563
|
<View style={styles.heroMetricsStrip}>
|
|
546
564
|
<View style={styles.heroMetricItem}>
|
|
547
|
-
<Text style={styles.heroMetricLabel}>IP ADDRESS</Text>
|
|
548
|
-
<Text style={styles.heroMetricValue} numberOfLines={1}>
|
|
565
|
+
<Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">IP ADDRESS</Text>
|
|
566
|
+
<Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">
|
|
549
567
|
{ipAddress}
|
|
550
568
|
</Text>
|
|
551
569
|
</View>
|
|
552
570
|
<View style={styles.heroMetricDivider} />
|
|
553
571
|
<View style={styles.heroMetricItem}>
|
|
554
|
-
<Text style={styles.heroMetricLabel}>RAM (USED/TOTAL)</Text>
|
|
555
|
-
<Text style={styles.heroMetricValue}>
|
|
572
|
+
<Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">RAM (USED/TOTAL)</Text>
|
|
573
|
+
<Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">
|
|
556
574
|
{usedRamMb}/{totalRamMb} MB
|
|
557
575
|
</Text>
|
|
558
576
|
</View>
|
|
559
577
|
<View style={styles.heroMetricDivider} />
|
|
560
578
|
<View style={styles.heroMetricItem}>
|
|
561
|
-
<Text style={styles.heroMetricLabel}>UPTIME</Text>
|
|
562
|
-
<Text style={styles.heroMetricValue}>{deviceUptime}</Text>
|
|
579
|
+
<Text style={styles.heroMetricLabel} numberOfLines={1} ellipsizeMode="tail">UPTIME</Text>
|
|
580
|
+
<Text style={styles.heroMetricValue} numberOfLines={1} ellipsizeMode="tail">{deviceUptime}</Text>
|
|
563
581
|
</View>
|
|
564
582
|
</View>
|
|
565
583
|
</View>
|
|
@@ -947,6 +965,22 @@ export const DeviceInfoTab = React.memo(() => {
|
|
|
947
965
|
</View>
|
|
948
966
|
)}
|
|
949
967
|
|
|
968
|
+
{/* Empty search results state */}
|
|
969
|
+
{search.trim().length > 0 && !hasAnyMatch && (
|
|
970
|
+
<View style={styles.emptySearchCard}>
|
|
971
|
+
<SearchIcon size={26} color={AppColors.grayTextWeak} />
|
|
972
|
+
<Text style={styles.emptySearchTitle}>No matching device specifications</Text>
|
|
973
|
+
<Text style={styles.emptySearchSubtitle}>
|
|
974
|
+
No properties matched “{search}”
|
|
975
|
+
</Text>
|
|
976
|
+
<TouchableScale
|
|
977
|
+
onPress={() => setSearch('')}
|
|
978
|
+
style={styles.clearSearchBtn}>
|
|
979
|
+
<Text style={styles.clearSearchBtnText}>Clear Search</Text>
|
|
980
|
+
</TouchableScale>
|
|
981
|
+
</View>
|
|
982
|
+
)}
|
|
983
|
+
|
|
950
984
|
<View style={{height: 48}} />
|
|
951
985
|
</ScrollView>
|
|
952
986
|
</View>
|
|
@@ -1120,6 +1154,8 @@ const styles = StyleSheet.create({
|
|
|
1120
1154
|
heroMetricItem: {
|
|
1121
1155
|
flex: 1,
|
|
1122
1156
|
alignItems: 'center',
|
|
1157
|
+
paddingHorizontal: 2,
|
|
1158
|
+
minWidth: 0,
|
|
1123
1159
|
},
|
|
1124
1160
|
heroMetricLabel: {
|
|
1125
1161
|
fontFamily: AppFonts.interBold,
|
|
@@ -1191,7 +1227,7 @@ const styles = StyleSheet.create({
|
|
|
1191
1227
|
fontFamily: AppFonts.interBold,
|
|
1192
1228
|
fontSize: 12,
|
|
1193
1229
|
color: AppColors.primaryBlack,
|
|
1194
|
-
|
|
1230
|
+
flexShrink: 1,
|
|
1195
1231
|
textAlign: 'right',
|
|
1196
1232
|
},
|
|
1197
1233
|
rowCopyBtn: {
|
|
@@ -1199,6 +1235,41 @@ const styles = StyleSheet.create({
|
|
|
1199
1235
|
borderRadius: 4,
|
|
1200
1236
|
backgroundColor: AppColors.grayBackground,
|
|
1201
1237
|
},
|
|
1238
|
+
emptySearchCard: {
|
|
1239
|
+
backgroundColor: AppColors.primaryLight,
|
|
1240
|
+
borderRadius: 14,
|
|
1241
|
+
borderWidth: 1,
|
|
1242
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1243
|
+
padding: 24,
|
|
1244
|
+
alignItems: 'center',
|
|
1245
|
+
justifyContent: 'center',
|
|
1246
|
+
gap: 8,
|
|
1247
|
+
marginTop: 8,
|
|
1248
|
+
},
|
|
1249
|
+
emptySearchTitle: {
|
|
1250
|
+
fontFamily: AppFonts.interBold,
|
|
1251
|
+
fontSize: 13.5,
|
|
1252
|
+
color: AppColors.primaryBlack,
|
|
1253
|
+
textAlign: 'center',
|
|
1254
|
+
},
|
|
1255
|
+
emptySearchSubtitle: {
|
|
1256
|
+
fontFamily: AppFonts.interRegular,
|
|
1257
|
+
fontSize: 11.5,
|
|
1258
|
+
color: AppColors.grayTextWeak,
|
|
1259
|
+
textAlign: 'center',
|
|
1260
|
+
},
|
|
1261
|
+
clearSearchBtn: {
|
|
1262
|
+
marginTop: 6,
|
|
1263
|
+
paddingHorizontal: 14,
|
|
1264
|
+
paddingVertical: 6.5,
|
|
1265
|
+
borderRadius: 8,
|
|
1266
|
+
backgroundColor: AppColors.purple,
|
|
1267
|
+
},
|
|
1268
|
+
clearSearchBtnText: {
|
|
1269
|
+
fontFamily: AppFonts.interBold,
|
|
1270
|
+
fontSize: 11,
|
|
1271
|
+
color: AppColors.white,
|
|
1272
|
+
},
|
|
1202
1273
|
});
|
|
1203
1274
|
|
|
1204
1275
|
export default DeviceInfoTab;
|
|
@@ -18,7 +18,14 @@ import {AppFonts} from '../../styles/AppFonts';
|
|
|
18
18
|
import {METHOD_COLORS} from '../../constants';
|
|
19
19
|
import {LIB_VERSION} from '../../constants';
|
|
20
20
|
import {Method} from '../../types';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
getStatusColor,
|
|
23
|
+
getAppName,
|
|
24
|
+
formatTime,
|
|
25
|
+
getSize,
|
|
26
|
+
getAppVersionAndBuild,
|
|
27
|
+
} from '../../helpers';
|
|
28
|
+
import {getNativeDeviceMetrics} from '../../native/NativeInspector';
|
|
22
29
|
import {UpdateAvailableModal} from './UpdateAvailableModal';
|
|
23
30
|
import {
|
|
24
31
|
WhiteBackNavigation,
|
|
@@ -71,6 +78,21 @@ const InspectorHeader = React.memo(() => {
|
|
|
71
78
|
} = useInspector();
|
|
72
79
|
|
|
73
80
|
const [showUpdateModal, setShowUpdateModal] = React.useState<boolean>(false);
|
|
81
|
+
const [appVersionString, setAppVersionString] = React.useState<string>(() => {
|
|
82
|
+
return getAppVersionAndBuild().formatted;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
React.useEffect(() => {
|
|
86
|
+
getNativeDeviceMetrics()
|
|
87
|
+
.then(metrics => {
|
|
88
|
+
if (metrics?.appVersion) {
|
|
89
|
+
const v = metrics.appVersion;
|
|
90
|
+
const b = metrics.appBuild || '1';
|
|
91
|
+
setAppVersionString(`${v} (${b})`);
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
.catch(() => {});
|
|
95
|
+
}, []);
|
|
74
96
|
|
|
75
97
|
const envConfig = useMemo(() => {
|
|
76
98
|
const rawEnv = (environment || (__DEV__ ? 'DEV' : 'PROD')).trim();
|
|
@@ -375,9 +397,7 @@ const InspectorHeader = React.memo(() => {
|
|
|
375
397
|
letterSpacing: 0.1,
|
|
376
398
|
}}
|
|
377
399
|
numberOfLines={1}>
|
|
378
|
-
{
|
|
379
|
-
? `iOS ${Platform.Version}`
|
|
380
|
-
: `Android ${Platform.Version}`}
|
|
400
|
+
{appVersionString}
|
|
381
401
|
</Text>
|
|
382
402
|
</View>
|
|
383
403
|
|
|
@@ -568,10 +568,10 @@ const NetworkDetail = React.memo(() => {
|
|
|
568
568
|
/>
|
|
569
569
|
|
|
570
570
|
{(() => {
|
|
571
|
-
const routeInfo =
|
|
572
|
-
selected.id
|
|
573
|
-
|
|
574
|
-
if (!routeInfo || routeInfo.path === 'Navigators')
|
|
571
|
+
const routeInfo =
|
|
572
|
+
logRouteMapRef.current.get(selected.id) ||
|
|
573
|
+
(selected as any)?.routeInfo;
|
|
574
|
+
if (!routeInfo || !routeInfo.path || routeInfo.path === 'Navigators')
|
|
575
575
|
return null;
|
|
576
576
|
return <SourcePageCard routeInfo={routeInfo} />;
|
|
577
577
|
})()}
|
|
@@ -665,7 +665,7 @@ const NetworkTab = React.memo(() => {
|
|
|
665
665
|
style={{
|
|
666
666
|
backgroundColor: `${AppColors.purple}20`,
|
|
667
667
|
borderRadius: 10,
|
|
668
|
-
paddingHorizontal:
|
|
668
|
+
paddingHorizontal: 6,
|
|
669
669
|
paddingVertical: 1.5,
|
|
670
670
|
}}>
|
|
671
671
|
<Text
|
|
@@ -759,19 +759,130 @@ const NetworkTab = React.memo(() => {
|
|
|
759
759
|
styles.toolbarBtnActive,
|
|
760
760
|
]}
|
|
761
761
|
onPress={filtersAccordion.toggleOpen}
|
|
762
|
-
hitSlop={
|
|
762
|
+
hitSlop={6}>
|
|
763
763
|
<FilterIcon
|
|
764
764
|
color={
|
|
765
765
|
filtersAccordion.isOpen
|
|
766
766
|
? AppColors.purple
|
|
767
767
|
: AppColors.grayTextStrong
|
|
768
768
|
}
|
|
769
|
-
size={
|
|
769
|
+
size={16}
|
|
770
770
|
/>
|
|
771
|
+
{(statusFilters.size > 0 ||
|
|
772
|
+
methodFilters.size > 0) && (
|
|
773
|
+
<View style={styles.activeFilterDot} />
|
|
774
|
+
)}
|
|
771
775
|
</TouchableScale>
|
|
772
776
|
</View>
|
|
773
777
|
</View>
|
|
774
778
|
|
|
779
|
+
{/* Quick Search Scope & Filter Tags Row */}
|
|
780
|
+
<View style={{paddingBottom: 4}}>
|
|
781
|
+
<ScrollView
|
|
782
|
+
horizontal
|
|
783
|
+
showsHorizontalScrollIndicator={false}
|
|
784
|
+
contentContainerStyle={{
|
|
785
|
+
paddingHorizontal: 12,
|
|
786
|
+
flexDirection: 'row',
|
|
787
|
+
alignItems: 'center',
|
|
788
|
+
gap: 5,
|
|
789
|
+
paddingVertical: 2,
|
|
790
|
+
}}>
|
|
791
|
+
{/* Search Scopes */}
|
|
792
|
+
{SEARCH_SCOPES.map(s => {
|
|
793
|
+
const isActive = searchScope === s.id;
|
|
794
|
+
return (
|
|
795
|
+
<TouchableScale
|
|
796
|
+
key={`scope_${s.id}`}
|
|
797
|
+
onPress={() => setSearchScope(s.id)}
|
|
798
|
+
hitSlop={6}
|
|
799
|
+
style={{
|
|
800
|
+
flexDirection: 'row',
|
|
801
|
+
alignItems: 'center',
|
|
802
|
+
gap: 3.5,
|
|
803
|
+
paddingHorizontal: 7.5,
|
|
804
|
+
paddingVertical: 3.5,
|
|
805
|
+
borderRadius: 6,
|
|
806
|
+
backgroundColor: isActive
|
|
807
|
+
? AppColors.purple
|
|
808
|
+
: AppColors.grayBackground,
|
|
809
|
+
borderWidth: 1,
|
|
810
|
+
borderColor: isActive
|
|
811
|
+
? AppColors.purple
|
|
812
|
+
: AppColors.grayBorderSecondary,
|
|
813
|
+
}}>
|
|
814
|
+
{s.icon(isActive ? AppColors.white : AppColors.grayTextWeak)}
|
|
815
|
+
<Text
|
|
816
|
+
style={{
|
|
817
|
+
fontFamily: AppFonts.interBold,
|
|
818
|
+
fontSize: 10,
|
|
819
|
+
color: isActive ? AppColors.white : AppColors.grayText,
|
|
820
|
+
}}>
|
|
821
|
+
{s.label}
|
|
822
|
+
</Text>
|
|
823
|
+
</TouchableScale>
|
|
824
|
+
);
|
|
825
|
+
})}
|
|
826
|
+
|
|
827
|
+
<View
|
|
828
|
+
style={{
|
|
829
|
+
width: 1,
|
|
830
|
+
height: 14,
|
|
831
|
+
backgroundColor: AppColors.dividerColor,
|
|
832
|
+
marginHorizontal: 3,
|
|
833
|
+
}}
|
|
834
|
+
/>
|
|
835
|
+
|
|
836
|
+
{/* Quick Query Suggestions */}
|
|
837
|
+
{QUICK_API_QUERY_TAGS.map(q => {
|
|
838
|
+
const isActive = search.includes(q.query);
|
|
839
|
+
return (
|
|
840
|
+
<TouchableScale
|
|
841
|
+
key={`quick_${q.query}`}
|
|
842
|
+
onPress={() => {
|
|
843
|
+
setSearch(prev => {
|
|
844
|
+
if (prev.includes(q.query)) {
|
|
845
|
+
return prev
|
|
846
|
+
.replace(q.query, '')
|
|
847
|
+
.replace(/\s+/g, ' ')
|
|
848
|
+
.trim();
|
|
849
|
+
}
|
|
850
|
+
return `${prev} ${q.query}`.trim();
|
|
851
|
+
});
|
|
852
|
+
}}
|
|
853
|
+
hitSlop={6}
|
|
854
|
+
style={{
|
|
855
|
+
flexDirection: 'row',
|
|
856
|
+
alignItems: 'center',
|
|
857
|
+
gap: 3.5,
|
|
858
|
+
paddingHorizontal: 7.5,
|
|
859
|
+
paddingVertical: 3.5,
|
|
860
|
+
borderRadius: 6,
|
|
861
|
+
backgroundColor: isActive
|
|
862
|
+
? `${AppColors.purple}20`
|
|
863
|
+
: AppColors.grayBackground,
|
|
864
|
+
borderWidth: 1,
|
|
865
|
+
borderColor: isActive
|
|
866
|
+
? AppColors.purple
|
|
867
|
+
: AppColors.grayBorderSecondary,
|
|
868
|
+
}}>
|
|
869
|
+
{q.icon(isActive ? AppColors.purple : AppColors.grayTextWeak)}
|
|
870
|
+
<Text
|
|
871
|
+
style={{
|
|
872
|
+
fontFamily: AppFonts.interMedium,
|
|
873
|
+
fontSize: 10,
|
|
874
|
+
color: isActive
|
|
875
|
+
? AppColors.purple
|
|
876
|
+
: AppColors.grayText,
|
|
877
|
+
}}>
|
|
878
|
+
{q.label}
|
|
879
|
+
</Text>
|
|
880
|
+
</TouchableScale>
|
|
881
|
+
);
|
|
882
|
+
})}
|
|
883
|
+
</ScrollView>
|
|
884
|
+
</View>
|
|
885
|
+
|
|
775
886
|
{/* Quick Filter Horizontal Chips Bar with Live Counts */}
|
|
776
887
|
<View style={{marginBottom: 8}}>
|
|
777
888
|
<ScrollView
|
|
@@ -1138,8 +1249,22 @@ const NetworkTab = React.memo(() => {
|
|
|
1138
1249
|
ListEmptyComponent={
|
|
1139
1250
|
<EmptyState
|
|
1140
1251
|
isSearch={
|
|
1141
|
-
search.length > 0 ||
|
|
1252
|
+
search.length > 0 ||
|
|
1253
|
+
statusFilters.size > 0 ||
|
|
1254
|
+
methodFilters.size > 0
|
|
1255
|
+
}
|
|
1256
|
+
searchQuery={search}
|
|
1257
|
+
customTitle={
|
|
1258
|
+
search.length > 0
|
|
1259
|
+
? 'No matching API requests'
|
|
1260
|
+
: 'No network activity'
|
|
1142
1261
|
}
|
|
1262
|
+
onClearSearch={() => {
|
|
1263
|
+
setSearch('');
|
|
1264
|
+
setStatusFilters(new Set());
|
|
1265
|
+
setMethodFilters(new Set());
|
|
1266
|
+
setSearchScope('all');
|
|
1267
|
+
}}
|
|
1143
1268
|
/>
|
|
1144
1269
|
}
|
|
1145
1270
|
ListFooterComponent={
|
|
@@ -548,14 +548,32 @@ const ReduxTab = React.memo(() => {
|
|
|
548
548
|
autoCapitalize="none"
|
|
549
549
|
/>
|
|
550
550
|
{reduxSearch.length > 0 && (
|
|
551
|
-
<
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
551
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 4}}>
|
|
552
|
+
<View
|
|
553
|
+
style={{
|
|
554
|
+
backgroundColor: `${AppColors.purple}20`,
|
|
555
|
+
borderRadius: 10,
|
|
556
|
+
paddingHorizontal: 6,
|
|
557
|
+
paddingVertical: 1.5,
|
|
558
|
+
}}>
|
|
559
|
+
<Text
|
|
560
|
+
style={{
|
|
561
|
+
color: AppColors.purple,
|
|
562
|
+
fontSize: 9.5,
|
|
563
|
+
fontFamily: AppFonts.interBold,
|
|
564
|
+
}}>
|
|
565
|
+
{filteredSlices.length}
|
|
566
|
+
</Text>
|
|
567
|
+
</View>
|
|
568
|
+
<Pressable
|
|
569
|
+
accessible={true}
|
|
570
|
+
accessibilityRole="button"
|
|
571
|
+
accessibilityLabel="Clear search input"
|
|
572
|
+
onPress={() => setReduxSearch('')}
|
|
573
|
+
hitSlop={10}>
|
|
574
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14} />
|
|
575
|
+
</Pressable>
|
|
576
|
+
</View>
|
|
559
577
|
)}
|
|
560
578
|
</View>
|
|
561
579
|
|
|
@@ -207,8 +207,8 @@ const SettingsPanel = () => {
|
|
|
207
207
|
bundle: Boolean(tabVisibility?.bundle),
|
|
208
208
|
performance: Boolean(tabVisibility?.performance),
|
|
209
209
|
crash: Boolean(tabVisibility?.crash),
|
|
210
|
-
device: Boolean(tabVisibility?.device
|
|
211
|
-
storage: Boolean(tabVisibility?.storage
|
|
210
|
+
device: Boolean(tabVisibility?.device),
|
|
211
|
+
storage: Boolean(tabVisibility?.storage),
|
|
212
212
|
}));
|
|
213
213
|
|
|
214
214
|
// Synchronize staged state with tabVisibility when tabVisibility updates
|
|
@@ -221,8 +221,8 @@ const SettingsPanel = () => {
|
|
|
221
221
|
bundle: Boolean(tabVisibility?.bundle),
|
|
222
222
|
performance: Boolean(tabVisibility?.performance),
|
|
223
223
|
crash: Boolean(tabVisibility?.crash),
|
|
224
|
-
device: Boolean(tabVisibility?.device
|
|
225
|
-
storage: Boolean(tabVisibility?.storage
|
|
224
|
+
device: Boolean(tabVisibility?.device),
|
|
225
|
+
storage: Boolean(tabVisibility?.storage),
|
|
226
226
|
});
|
|
227
227
|
}, [tabVisibility]);
|
|
228
228
|
|
|
@@ -357,9 +357,27 @@ export const StorageTab = React.memo(() => {
|
|
|
357
357
|
clearButtonMode="while-editing"
|
|
358
358
|
/>
|
|
359
359
|
{search.length > 0 && (
|
|
360
|
-
<
|
|
361
|
-
<
|
|
362
|
-
|
|
360
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 4}}>
|
|
361
|
+
<View
|
|
362
|
+
style={{
|
|
363
|
+
backgroundColor: `${AppColors.purple}20`,
|
|
364
|
+
borderRadius: 10,
|
|
365
|
+
paddingHorizontal: 6,
|
|
366
|
+
paddingVertical: 1.5,
|
|
367
|
+
}}>
|
|
368
|
+
<Text
|
|
369
|
+
style={{
|
|
370
|
+
color: AppColors.purple,
|
|
371
|
+
fontSize: 9.5,
|
|
372
|
+
fontFamily: AppFonts.interBold,
|
|
373
|
+
}}>
|
|
374
|
+
{filteredEntries.length}
|
|
375
|
+
</Text>
|
|
376
|
+
</View>
|
|
377
|
+
<TouchableScale onPress={() => setSearch('')} hitSlop={8}>
|
|
378
|
+
<ClearIcon size={13} color={AppColors.grayTextWeak} />
|
|
379
|
+
</TouchableScale>
|
|
380
|
+
</View>
|
|
363
381
|
)}
|
|
364
382
|
</View>
|
|
365
383
|
|
|
@@ -6,6 +6,7 @@ import {useTranslation} from '../i18n';
|
|
|
6
6
|
import TreeNode from './TreeNode';
|
|
7
7
|
import SegmentedTabs from './SegmentedTabs';
|
|
8
8
|
import HighlightText from './HighlightText';
|
|
9
|
+
import CopyButton from './CopyButton';
|
|
9
10
|
import {PrettyIcon, RawIcon, TableIcon} from './NetworkIcons';
|
|
10
11
|
|
|
11
12
|
// Styles
|
|
@@ -260,6 +261,7 @@ const JsonViewer = React.memo(({
|
|
|
260
261
|
setMode(key as 'pretty' | 'raw' | 'table')
|
|
261
262
|
}
|
|
262
263
|
/>
|
|
264
|
+
<CopyButton value={data} label="JSON" />
|
|
263
265
|
</View>
|
|
264
266
|
)}
|
|
265
267
|
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
|
|
28
28
|
// Components
|
|
29
29
|
import TouchableScale from './TouchableScale';
|
|
30
|
+
import CopyButton from './CopyButton';
|
|
30
31
|
|
|
31
32
|
// Stylesheet
|
|
32
33
|
import {AppColors} from '../styles/AppColors';
|
|
@@ -97,9 +98,23 @@ const MetaAccordion = ({
|
|
|
97
98
|
<Pressable onPress={toggleOpen} hitSlop={12}>
|
|
98
99
|
<View style={styles.metaHeader}>
|
|
99
100
|
<Text style={styles.metaTitle}>Metadata</Text>
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
|
|
101
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}>
|
|
102
|
+
<CopyButton
|
|
103
|
+
value={{
|
|
104
|
+
status: status ?? 0,
|
|
105
|
+
duration: duration != null ? `${duration} ms` : '—',
|
|
106
|
+
size: size || '—',
|
|
107
|
+
triggeredAt: triggeredAt || '',
|
|
108
|
+
method: method || 'GET',
|
|
109
|
+
contentType: contentType || 'application/json',
|
|
110
|
+
url: url || '',
|
|
111
|
+
}}
|
|
112
|
+
label="Metadata"
|
|
113
|
+
/>
|
|
114
|
+
<Animated.View style={chevronStyle}>
|
|
115
|
+
<ChevronIcon color={AppColors.grayTextWeak} size={14} />
|
|
116
|
+
</Animated.View>
|
|
117
|
+
</View>
|
|
103
118
|
</View>
|
|
104
119
|
</Pressable>
|
|
105
120
|
|
package/src/constants/version.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import {setupGlobalCrashHandler} from "./crashHandler";
|
|
3
|
+
import {RouteInfo} from "../types";
|
|
3
4
|
|
|
4
5
|
type NetworkLog = {
|
|
5
6
|
id: number;
|
|
@@ -14,12 +15,20 @@ type NetworkLog = {
|
|
|
14
15
|
client?: string; // ✅ Captures request client: axios, fetch, xhr, apollo, etc.
|
|
15
16
|
requestHeaders?: Record<string, string>;
|
|
16
17
|
responseHeaders?: Record<string, string>;
|
|
18
|
+
routeInfo?: RouteInfo;
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
let logs: NetworkLog[] = [];
|
|
20
22
|
let listeners: ((logs: NetworkLog[]) => void)[] = [];
|
|
21
23
|
let counter = 0;
|
|
22
24
|
let isNetworkModuleEnabled = true;
|
|
25
|
+
let currentRouteProvider: (() => RouteInfo | null) | null = null;
|
|
26
|
+
|
|
27
|
+
export const setRouteInfoProvider = (
|
|
28
|
+
provider: (() => RouteInfo | null) | null,
|
|
29
|
+
) => {
|
|
30
|
+
currentRouteProvider = provider;
|
|
31
|
+
};
|
|
23
32
|
|
|
24
33
|
export const setNetworkModuleEnabled = (enabled: boolean) => {
|
|
25
34
|
isNetworkModuleEnabled = enabled;
|
|
@@ -232,6 +241,8 @@ export const setupNetworkLogger = () => {
|
|
|
232
241
|
client = 'axios';
|
|
233
242
|
}
|
|
234
243
|
|
|
244
|
+
const currentRoute = currentRouteProvider ? currentRouteProvider() : null;
|
|
245
|
+
|
|
235
246
|
addOrUpdateLog({
|
|
236
247
|
id,
|
|
237
248
|
url: finalUrl,
|
|
@@ -239,6 +250,7 @@ export const setupNetworkLogger = () => {
|
|
|
239
250
|
startTime: start,
|
|
240
251
|
caller,
|
|
241
252
|
client,
|
|
253
|
+
routeInfo: currentRoute || undefined,
|
|
242
254
|
request: method === "GET" ? undefined : parseRequestData(options?.body),
|
|
243
255
|
requestHeaders,
|
|
244
256
|
});
|
|
@@ -347,6 +359,8 @@ export const addAxiosInterceptors = (axiosInstance: any) => {
|
|
|
347
359
|
config.__logStart = start;
|
|
348
360
|
config.__logCaller = caller;
|
|
349
361
|
|
|
362
|
+
const currentRoute = currentRouteProvider ? currentRouteProvider() : null;
|
|
363
|
+
|
|
350
364
|
addOrUpdateLog({
|
|
351
365
|
id,
|
|
352
366
|
url,
|
|
@@ -354,6 +368,7 @@ export const addAxiosInterceptors = (axiosInstance: any) => {
|
|
|
354
368
|
startTime: start,
|
|
355
369
|
caller,
|
|
356
370
|
client: 'axios',
|
|
371
|
+
routeInfo: currentRoute || undefined,
|
|
357
372
|
request: method === "GET" ? undefined : parseRequestData(config.data),
|
|
358
373
|
requestHeaders: normaliseHeaders(config.headers),
|
|
359
374
|
});
|