react-native-inapp-inspector 2.3.9 → 2.3.11
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/DebuggingTab.d.ts +3 -0
- package/dist/commonjs/components/Inspector/DebuggingTab.js +682 -0
- package/dist/commonjs/components/Inspector/MainScreen.js +2 -0
- package/dist/commonjs/components/Inspector/NetworkDetail.js +2 -1
- package/dist/commonjs/components/Inspector/NetworkFilterModal.d.ts +19 -0
- package/dist/commonjs/components/Inspector/NetworkFilterModal.js +648 -0
- package/dist/commonjs/components/Inspector/NetworkTab.js +89 -147
- package/dist/commonjs/components/Inspector/SettingsPanel.js +12 -0
- package/dist/commonjs/components/Inspector/TabBar.js +9 -0
- package/dist/commonjs/components/LogCard.js +5 -26
- package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
- package/dist/commonjs/components/NetworkIcons.js +13 -1
- package/dist/commonjs/components/QRCodeView.d.ts +9 -0
- package/dist/commonjs/components/QRCodeView.js +79 -0
- package/dist/commonjs/constants/index.js +3 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/helpers/qrGenerator.d.ts +2 -0
- package/dist/commonjs/helpers/qrGenerator.js +170 -0
- package/dist/commonjs/index.js +2 -0
- package/dist/commonjs/styles/index.d.ts +11 -0
- package/dist/commonjs/styles/index.js +20 -5
- package/dist/commonjs/types/enums.d.ts +5 -0
- package/dist/commonjs/types/enums.js +5 -0
- package/dist/esm/components/Inspector/DebuggingTab.d.ts +3 -0
- package/dist/esm/components/Inspector/DebuggingTab.js +642 -0
- package/dist/esm/components/Inspector/MainScreen.js +2 -0
- package/dist/esm/components/Inspector/NetworkDetail.js +2 -1
- package/dist/esm/components/Inspector/NetworkFilterModal.d.ts +19 -0
- package/dist/esm/components/Inspector/NetworkFilterModal.js +607 -0
- package/dist/esm/components/Inspector/NetworkTab.js +91 -149
- package/dist/esm/components/Inspector/SettingsPanel.js +13 -1
- package/dist/esm/components/Inspector/TabBar.js +10 -1
- package/dist/esm/components/LogCard.js +5 -26
- package/dist/esm/components/NetworkIcons.d.ts +2 -0
- package/dist/esm/components/NetworkIcons.js +10 -0
- package/dist/esm/components/QRCodeView.d.ts +9 -0
- package/dist/esm/components/QRCodeView.js +42 -0
- package/dist/esm/constants/index.js +3 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/helpers/qrGenerator.d.ts +2 -0
- package/dist/esm/helpers/qrGenerator.js +167 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/styles/index.d.ts +11 -0
- package/dist/esm/styles/index.js +20 -5
- package/dist/esm/types/enums.d.ts +5 -0
- package/dist/esm/types/enums.js +5 -0
- package/package.json +2 -2
- package/src/components/Inspector/DebuggingTab.tsx +755 -0
- package/src/components/Inspector/MainScreen.tsx +2 -0
- package/src/components/Inspector/NetworkDetail.tsx +2 -1
- package/src/components/Inspector/NetworkFilterModal.tsx +710 -0
- package/src/components/Inspector/NetworkTab.tsx +127 -204
- package/src/components/Inspector/SettingsPanel.tsx +20 -0
- package/src/components/Inspector/TabBar.tsx +11 -0
- package/src/components/LogCard.tsx +5 -30
- package/src/components/NetworkIcons.tsx +66 -0
- package/src/components/QRCodeView.tsx +71 -0
- package/src/constants/index.ts +3 -0
- package/src/constants/version.ts +1 -1
- package/src/helpers/qrGenerator.ts +184 -0
- package/src/index.tsx +2 -0
- package/src/styles/index.ts +20 -5
- package/src/types/enums.ts +5 -0
|
@@ -9,13 +9,17 @@ import {
|
|
|
9
9
|
View,
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
import {animateNextLayout, useInspector} from './InspectorContext';
|
|
12
|
-
import useAccordion from '../../customHooks/useAccordion';
|
|
13
12
|
import TouchableScale from '../TouchableScale';
|
|
14
13
|
import AnimatedEntrance from '../AnimatedEntrance';
|
|
15
14
|
import DomainHeader from '../DomainHeader';
|
|
16
15
|
import LogCard from '../LogCard';
|
|
17
16
|
import EmptyState from '../EmptyState';
|
|
18
17
|
import EndOfListFooter from '../EndOfListFooter';
|
|
18
|
+
import NetworkFilterModal, {
|
|
19
|
+
NetworkFilterState,
|
|
20
|
+
DEFAULT_NETWORK_FILTERS,
|
|
21
|
+
isNetworkFiltersDefault,
|
|
22
|
+
} from './NetworkFilterModal';
|
|
19
23
|
import styles from '../../styles';
|
|
20
24
|
import {AppColors} from '../../styles/AppColors';
|
|
21
25
|
import {AppFonts} from '../../styles/AppFonts';
|
|
@@ -45,109 +49,7 @@ import {
|
|
|
45
49
|
ShieldAlertIcon,
|
|
46
50
|
} from '../NetworkIcons';
|
|
47
51
|
|
|
48
|
-
const STATUS_META: Record<
|
|
49
|
-
string,
|
|
50
|
-
{color: string; Icon: (props: {color?: string; size?: number}) => React.JSX.Element}
|
|
51
|
-
> = {
|
|
52
|
-
ALL: {color: AppColors.grayText, Icon: LayersIcon},
|
|
53
|
-
'2xx': {color: AppColors.greenColor, Icon: CircleCheckIcon},
|
|
54
|
-
'200': {color: AppColors.greenColor, Icon: CircleCheckIcon},
|
|
55
|
-
'3xx': {color: AppColors.warningIconGold, Icon: CircleAlertIcon},
|
|
56
|
-
'300': {color: AppColors.warningIconGold, Icon: CircleAlertIcon},
|
|
57
|
-
'4xx': {color: AppColors.darkOrange, Icon: CircleAlertIcon},
|
|
58
|
-
'400': {color: AppColors.darkOrange, Icon: CircleAlertIcon},
|
|
59
|
-
'404': {color: AppColors.darkOrange, Icon: CircleAlertIcon},
|
|
60
|
-
'5xx': {color: AppColors.errorColor, Icon: CircleXIcon},
|
|
61
|
-
'500': {color: AppColors.errorColor, Icon: CircleXIcon},
|
|
62
|
-
Failed: {color: AppColors.errorColor, Icon: CircleXIcon},
|
|
63
|
-
};
|
|
64
52
|
|
|
65
|
-
const getStatusMeta = (filter: string) => {
|
|
66
|
-
if (STATUS_META[filter]) return STATUS_META[filter];
|
|
67
|
-
const num = parseInt(filter, 10);
|
|
68
|
-
if (!isNaN(num)) {
|
|
69
|
-
if (num >= 200 && num < 300) return {color: AppColors.greenColor, Icon: CircleCheckIcon};
|
|
70
|
-
if (num >= 300 && num < 400) return {color: AppColors.warningIconGold, Icon: CircleAlertIcon};
|
|
71
|
-
if (num >= 400 && num < 500) return {color: AppColors.darkOrange, Icon: CircleAlertIcon};
|
|
72
|
-
if (num >= 500) return {color: AppColors.errorColor, Icon: CircleXIcon};
|
|
73
|
-
}
|
|
74
|
-
if (filter.startsWith('2')) return {color: AppColors.greenColor, Icon: CircleCheckIcon};
|
|
75
|
-
if (filter.startsWith('3')) return {color: AppColors.warningIconGold, Icon: CircleAlertIcon};
|
|
76
|
-
if (filter.startsWith('4')) return {color: AppColors.darkOrange, Icon: CircleAlertIcon};
|
|
77
|
-
if (filter.startsWith('5')) return {color: AppColors.errorColor, Icon: CircleXIcon};
|
|
78
|
-
return {color: AppColors.grayText, Icon: LayersIcon};
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const FilterChip = React.memo(({
|
|
82
|
-
label,
|
|
83
|
-
color,
|
|
84
|
-
Icon,
|
|
85
|
-
badge,
|
|
86
|
-
active,
|
|
87
|
-
onPress,
|
|
88
|
-
}: {
|
|
89
|
-
label: string;
|
|
90
|
-
color: string;
|
|
91
|
-
Icon?: (props: {color?: string; size?: number}) => React.JSX.Element;
|
|
92
|
-
badge?: string;
|
|
93
|
-
active: boolean;
|
|
94
|
-
onPress: () => void;
|
|
95
|
-
}) => {
|
|
96
|
-
const iconColor = active ? color : AppColors.grayTextWeak;
|
|
97
|
-
return (
|
|
98
|
-
<TouchableScale
|
|
99
|
-
style={styles.statusFilterWrap}
|
|
100
|
-
onPress={onPress}
|
|
101
|
-
hitSlop={10}>
|
|
102
|
-
<View
|
|
103
|
-
style={[
|
|
104
|
-
styles.statusFilterChip,
|
|
105
|
-
{
|
|
106
|
-
paddingHorizontal: 9,
|
|
107
|
-
paddingVertical: 5,
|
|
108
|
-
borderRadius: 7,
|
|
109
|
-
borderWidth: 1,
|
|
110
|
-
borderColor: active ? color : `${AppColors.grayBorderSecondary}`,
|
|
111
|
-
backgroundColor: active ? `${color}14` : AppColors.grayBackground,
|
|
112
|
-
},
|
|
113
|
-
active && {
|
|
114
|
-
shadowColor: color,
|
|
115
|
-
shadowOffset: {width: 0, height: 1},
|
|
116
|
-
shadowOpacity: 0.2,
|
|
117
|
-
shadowRadius: 2,
|
|
118
|
-
elevation: 1.5,
|
|
119
|
-
},
|
|
120
|
-
]}>
|
|
121
|
-
{badge != null ? (
|
|
122
|
-
<View
|
|
123
|
-
style={[
|
|
124
|
-
styles.methodBadgeMini,
|
|
125
|
-
{backgroundColor: badge},
|
|
126
|
-
]}
|
|
127
|
-
/>
|
|
128
|
-
) : (
|
|
129
|
-
Icon && (
|
|
130
|
-
<Icon
|
|
131
|
-
color={iconColor}
|
|
132
|
-
size={13}
|
|
133
|
-
/>
|
|
134
|
-
)
|
|
135
|
-
)}
|
|
136
|
-
<Text
|
|
137
|
-
numberOfLines={1}
|
|
138
|
-
style={[
|
|
139
|
-
styles.statusFilterText,
|
|
140
|
-
{
|
|
141
|
-
color: active ? color : AppColors.grayText,
|
|
142
|
-
fontFamily: active ? AppFonts.interBold : AppFonts.interMedium,
|
|
143
|
-
},
|
|
144
|
-
]}>
|
|
145
|
-
{label}
|
|
146
|
-
</Text>
|
|
147
|
-
</View>
|
|
148
|
-
</TouchableScale>
|
|
149
|
-
);
|
|
150
|
-
});
|
|
151
53
|
|
|
152
54
|
const NetworkTab = React.memo(() => {
|
|
153
55
|
const {
|
|
@@ -185,11 +87,52 @@ const NetworkTab = React.memo(() => {
|
|
|
185
87
|
} = useInspector();
|
|
186
88
|
|
|
187
89
|
const {t} = useTranslation();
|
|
188
|
-
const filtersAccordion = useAccordion(false, 300, 260);
|
|
189
90
|
const apisListRef = useRef<FlatList<any>>(null);
|
|
190
91
|
|
|
92
|
+
const [isFilterModalOpen, setIsFilterModalOpen] = React.useState(false);
|
|
191
93
|
const [isSearchFocused, setIsSearchFocused] = React.useState(false);
|
|
192
94
|
|
|
95
|
+
const modalFilterState: NetworkFilterState = useMemo(
|
|
96
|
+
() => ({
|
|
97
|
+
statusCodes:
|
|
98
|
+
statusFilters.size > 0 ? new Set(statusFilters) : new Set(['all']),
|
|
99
|
+
methods:
|
|
100
|
+
methodFilters.size > 0 ? new Set(methodFilters) : new Set(['all']),
|
|
101
|
+
latency: 'all',
|
|
102
|
+
protocol: 'all',
|
|
103
|
+
sortBy: sortOrder === 'newest' ? 'time_desc' : 'time_asc',
|
|
104
|
+
}),
|
|
105
|
+
[statusFilters, methodFilters, sortOrder],
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const handleApplyNetworkFilters = useCallback(
|
|
109
|
+
(newFilters: NetworkFilterState) => {
|
|
110
|
+
if (
|
|
111
|
+
newFilters.statusCodes.has('all') ||
|
|
112
|
+
newFilters.statusCodes.size === 0
|
|
113
|
+
) {
|
|
114
|
+
setStatusFilters(new Set());
|
|
115
|
+
} else {
|
|
116
|
+
setStatusFilters(new Set(newFilters.statusCodes));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (newFilters.methods.has('all') || newFilters.methods.size === 0) {
|
|
120
|
+
setMethodFilters(new Set());
|
|
121
|
+
} else {
|
|
122
|
+
setMethodFilters(
|
|
123
|
+
new Set([...newFilters.methods].map(m => m as Method)),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (newFilters.sortBy === 'time_asc') {
|
|
128
|
+
setSortOrder('oldest');
|
|
129
|
+
} else {
|
|
130
|
+
setSortOrder('newest');
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
[setStatusFilters, setMethodFilters, setSortOrder],
|
|
134
|
+
);
|
|
135
|
+
|
|
193
136
|
const quickCounts = useMemo(() => {
|
|
194
137
|
let errorCount = 0;
|
|
195
138
|
let successCount = 0;
|
|
@@ -755,14 +698,16 @@ const NetworkTab = React.memo(() => {
|
|
|
755
698
|
<TouchableScale
|
|
756
699
|
style={[
|
|
757
700
|
styles.toolbarBtn,
|
|
758
|
-
|
|
759
|
-
|
|
701
|
+
(statusFilters.size > 0 || methodFilters.size > 0) && {
|
|
702
|
+
borderColor: AppColors.purple,
|
|
703
|
+
backgroundColor: `${AppColors.purple}15`,
|
|
704
|
+
},
|
|
760
705
|
]}
|
|
761
|
-
onPress={
|
|
706
|
+
onPress={() => setIsFilterModalOpen(true)}
|
|
762
707
|
hitSlop={6}>
|
|
763
708
|
<FilterIcon
|
|
764
709
|
color={
|
|
765
|
-
|
|
710
|
+
statusFilters.size > 0 || methodFilters.size > 0
|
|
766
711
|
? AppColors.purple
|
|
767
712
|
: AppColors.grayTextStrong
|
|
768
713
|
}
|
|
@@ -959,6 +904,66 @@ const NetworkTab = React.memo(() => {
|
|
|
959
904
|
</TouchableScale>
|
|
960
905
|
);
|
|
961
906
|
})}
|
|
907
|
+
|
|
908
|
+
<TouchableScale
|
|
909
|
+
onPress={() => setIsFilterModalOpen(true)}>
|
|
910
|
+
<View
|
|
911
|
+
style={{
|
|
912
|
+
flexDirection: 'row',
|
|
913
|
+
alignItems: 'center',
|
|
914
|
+
paddingHorizontal: 10,
|
|
915
|
+
paddingVertical: 4.5,
|
|
916
|
+
borderRadius: 8,
|
|
917
|
+
backgroundColor:
|
|
918
|
+
statusFilters.size > 0 || methodFilters.size > 0
|
|
919
|
+
? `${AppColors.purple}20`
|
|
920
|
+
: AppColors.grayBackground,
|
|
921
|
+
borderWidth: 1,
|
|
922
|
+
borderColor:
|
|
923
|
+
statusFilters.size > 0 || methodFilters.size > 0
|
|
924
|
+
? AppColors.purple
|
|
925
|
+
: AppColors.grayBorderSecondary,
|
|
926
|
+
gap: 5,
|
|
927
|
+
}}>
|
|
928
|
+
<FilterIcon
|
|
929
|
+
size={11}
|
|
930
|
+
color={
|
|
931
|
+
statusFilters.size > 0 || methodFilters.size > 0
|
|
932
|
+
? AppColors.purple
|
|
933
|
+
: AppColors.grayText
|
|
934
|
+
}
|
|
935
|
+
/>
|
|
936
|
+
<Text
|
|
937
|
+
style={{
|
|
938
|
+
fontFamily: AppFonts.interBold,
|
|
939
|
+
fontSize: 10.5,
|
|
940
|
+
color:
|
|
941
|
+
statusFilters.size > 0 || methodFilters.size > 0
|
|
942
|
+
? AppColors.purple
|
|
943
|
+
: AppColors.grayText,
|
|
944
|
+
}}>
|
|
945
|
+
More Filters
|
|
946
|
+
</Text>
|
|
947
|
+
{(statusFilters.size > 0 || methodFilters.size > 0) && (
|
|
948
|
+
<View
|
|
949
|
+
style={{
|
|
950
|
+
backgroundColor: AppColors.purple,
|
|
951
|
+
paddingHorizontal: 4.5,
|
|
952
|
+
paddingVertical: 1,
|
|
953
|
+
borderRadius: 6,
|
|
954
|
+
}}>
|
|
955
|
+
<Text
|
|
956
|
+
style={{
|
|
957
|
+
fontFamily: AppFonts.interBold,
|
|
958
|
+
fontSize: 8.5,
|
|
959
|
+
color: AppColors.white,
|
|
960
|
+
}}>
|
|
961
|
+
{statusFilters.size + methodFilters.size}
|
|
962
|
+
</Text>
|
|
963
|
+
</View>
|
|
964
|
+
)}
|
|
965
|
+
</View>
|
|
966
|
+
</TouchableScale>
|
|
962
967
|
</ScrollView>
|
|
963
968
|
</View>
|
|
964
969
|
|
|
@@ -1141,103 +1146,10 @@ const NetworkTab = React.memo(() => {
|
|
|
1141
1146
|
</View>
|
|
1142
1147
|
)}
|
|
1143
1148
|
|
|
1144
|
-
<Animated.View
|
|
1145
|
-
style={[
|
|
1146
|
-
filtersAccordion.bodyStyle,
|
|
1147
|
-
{overflow: 'hidden'},
|
|
1148
|
-
]}>
|
|
1149
|
-
<View style={styles.filtersContainer}>
|
|
1150
|
-
<Text style={styles.filtersHeading}>
|
|
1151
|
-
STATUS
|
|
1152
|
-
</Text>
|
|
1153
|
-
<ScrollView
|
|
1154
|
-
horizontal
|
|
1155
|
-
showsHorizontalScrollIndicator={false}
|
|
1156
|
-
contentContainerStyle={
|
|
1157
|
-
styles.statusRowContent
|
|
1158
|
-
}>
|
|
1159
|
-
{STATUS_FILTERS.map(filter => {
|
|
1160
|
-
const isAll = filter === 'ALL';
|
|
1161
|
-
const active = isAll
|
|
1162
|
-
? statusFilters.size === 0
|
|
1163
|
-
: statusFilters.has(filter);
|
|
1164
|
-
const meta = getStatusMeta(filter);
|
|
1165
|
-
return (
|
|
1166
|
-
<FilterChip
|
|
1167
|
-
key={filter}
|
|
1168
|
-
label={filter}
|
|
1169
|
-
color={meta.color}
|
|
1170
|
-
Icon={meta.Icon}
|
|
1171
|
-
active={active}
|
|
1172
|
-
onPress={() => {
|
|
1173
|
-
if (isAll) {
|
|
1174
|
-
setStatusFilters(new Set());
|
|
1175
|
-
} else {
|
|
1176
|
-
setStatusFilters(prev => {
|
|
1177
|
-
const next = new Set(prev);
|
|
1178
|
-
next.has(filter)
|
|
1179
|
-
? next.delete(filter)
|
|
1180
|
-
: next.add(filter);
|
|
1181
|
-
return next;
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
}}
|
|
1185
|
-
/>
|
|
1186
|
-
);
|
|
1187
|
-
})}
|
|
1188
|
-
</ScrollView>
|
|
1189
|
-
|
|
1190
|
-
<Text
|
|
1191
|
-
style={[
|
|
1192
|
-
styles.filtersHeading,
|
|
1193
|
-
{marginTop: 16},
|
|
1194
|
-
]}>
|
|
1195
|
-
METHOD
|
|
1196
|
-
</Text>
|
|
1197
|
-
<ScrollView
|
|
1198
|
-
horizontal
|
|
1199
|
-
showsHorizontalScrollIndicator={false}
|
|
1200
|
-
contentContainerStyle={
|
|
1201
|
-
styles.statusRowContent
|
|
1202
|
-
}>
|
|
1203
|
-
{availableMethods.map(filter => {
|
|
1204
|
-
const isAll = filter === 'ALL';
|
|
1205
|
-
const active = isAll
|
|
1206
|
-
? methodFilters.size === 0
|
|
1207
|
-
: methodFilters.has(filter as Method);
|
|
1208
|
-
const methodColor =
|
|
1209
|
-
METHOD_COLORS[filter as Method] ??
|
|
1210
|
-
METHOD_COLORS.ALL;
|
|
1211
|
-
return (
|
|
1212
|
-
<FilterChip
|
|
1213
|
-
key={filter}
|
|
1214
|
-
label={filter}
|
|
1215
|
-
color={methodColor}
|
|
1216
|
-
badge={methodColor}
|
|
1217
|
-
active={active}
|
|
1218
|
-
onPress={() => {
|
|
1219
|
-
if (isAll) {
|
|
1220
|
-
setMethodFilters(new Set());
|
|
1221
|
-
} else {
|
|
1222
|
-
setMethodFilters(prev => {
|
|
1223
|
-
const next = new Set(prev);
|
|
1224
|
-
next.has(filter as Method)
|
|
1225
|
-
? next.delete(filter as Method)
|
|
1226
|
-
: next.add(filter as Method);
|
|
1227
|
-
return next;
|
|
1228
|
-
});
|
|
1229
|
-
}
|
|
1230
|
-
}}
|
|
1231
|
-
/>
|
|
1232
|
-
);
|
|
1233
|
-
})}
|
|
1234
|
-
</ScrollView>
|
|
1235
|
-
</View>
|
|
1236
|
-
</Animated.View>
|
|
1237
|
-
|
|
1238
1149
|
{(search ||
|
|
1239
1150
|
statusFilters.size > 0 ||
|
|
1240
|
-
methodFilters.size > 0
|
|
1151
|
+
methodFilters.size > 0 ||
|
|
1152
|
+
quickFilter !== 'all') && (
|
|
1241
1153
|
<Text style={styles.resultCount}>
|
|
1242
1154
|
{filteredLogs.length === logs.length
|
|
1243
1155
|
? `${logs.length} requests`
|
|
@@ -1251,7 +1163,8 @@ const NetworkTab = React.memo(() => {
|
|
|
1251
1163
|
isSearch={
|
|
1252
1164
|
search.length > 0 ||
|
|
1253
1165
|
statusFilters.size > 0 ||
|
|
1254
|
-
methodFilters.size > 0
|
|
1166
|
+
methodFilters.size > 0 ||
|
|
1167
|
+
quickFilter !== 'all'
|
|
1255
1168
|
}
|
|
1256
1169
|
searchQuery={search}
|
|
1257
1170
|
customTitle={
|
|
@@ -1263,6 +1176,7 @@ const NetworkTab = React.memo(() => {
|
|
|
1263
1176
|
setSearch('');
|
|
1264
1177
|
setStatusFilters(new Set());
|
|
1265
1178
|
setMethodFilters(new Set());
|
|
1179
|
+
setQuickFilter('all');
|
|
1266
1180
|
setSearchScope('all');
|
|
1267
1181
|
}}
|
|
1268
1182
|
/>
|
|
@@ -1301,6 +1215,15 @@ const NetworkTab = React.memo(() => {
|
|
|
1301
1215
|
<ChevronIcon color={AppColors.white} size={18} />
|
|
1302
1216
|
</View>
|
|
1303
1217
|
</TouchableScale>
|
|
1218
|
+
|
|
1219
|
+
{/* Modern Network Filter Modal */}
|
|
1220
|
+
<NetworkFilterModal
|
|
1221
|
+
visible={isFilterModalOpen}
|
|
1222
|
+
onClose={() => setIsFilterModalOpen(false)}
|
|
1223
|
+
filters={modalFilterState}
|
|
1224
|
+
onApply={handleApplyNetworkFilters}
|
|
1225
|
+
searchQuery={search}
|
|
1226
|
+
/>
|
|
1304
1227
|
</View>
|
|
1305
1228
|
);
|
|
1306
1229
|
});
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
BrainIcon,
|
|
57
57
|
SmartphoneIcon,
|
|
58
58
|
DatabaseIcon,
|
|
59
|
+
QrCodeIcon,
|
|
59
60
|
} from '../NetworkIcons';
|
|
60
61
|
import {LIB_VERSION} from '../../constants';
|
|
61
62
|
import {copyToClipboard} from '../../helpers';
|
|
@@ -194,6 +195,13 @@ const SettingsPanel = () => {
|
|
|
194
195
|
icon: 'storage',
|
|
195
196
|
desc: 'AsyncStorage & MMKV key-value store viewer with full CRUD support',
|
|
196
197
|
},
|
|
198
|
+
{
|
|
199
|
+
key: 'debugging',
|
|
200
|
+
label: 'Multi-Device Debugging',
|
|
201
|
+
category: 'diagnostic',
|
|
202
|
+
icon: 'debugging',
|
|
203
|
+
desc: 'QR Code bridge for direct Debug APK download & Metro live-reload sync',
|
|
204
|
+
},
|
|
197
205
|
] as const;
|
|
198
206
|
|
|
199
207
|
// Staged selection state for checkboxes before clicking "Save Changes"
|
|
@@ -209,6 +217,7 @@ const SettingsPanel = () => {
|
|
|
209
217
|
crash: Boolean(tabVisibility?.crash),
|
|
210
218
|
device: Boolean(tabVisibility?.device),
|
|
211
219
|
storage: Boolean(tabVisibility?.storage),
|
|
220
|
+
debugging: Boolean(tabVisibility?.debugging ?? true),
|
|
212
221
|
}));
|
|
213
222
|
|
|
214
223
|
// Synchronize staged state with tabVisibility when tabVisibility updates
|
|
@@ -223,6 +232,7 @@ const SettingsPanel = () => {
|
|
|
223
232
|
crash: Boolean(tabVisibility?.crash),
|
|
224
233
|
device: Boolean(tabVisibility?.device),
|
|
225
234
|
storage: Boolean(tabVisibility?.storage),
|
|
235
|
+
debugging: Boolean(tabVisibility?.debugging ?? true),
|
|
226
236
|
});
|
|
227
237
|
}, [tabVisibility]);
|
|
228
238
|
|
|
@@ -823,6 +833,16 @@ const SettingsPanel = () => {
|
|
|
823
833
|
size={16}
|
|
824
834
|
/>
|
|
825
835
|
)}
|
|
836
|
+
{moduleItem.icon === 'debugging' && (
|
|
837
|
+
<QrCodeIcon
|
|
838
|
+
color={
|
|
839
|
+
isChecked
|
|
840
|
+
? AppColors.purple
|
|
841
|
+
: AppColors.grayTextWeak
|
|
842
|
+
}
|
|
843
|
+
size={16}
|
|
844
|
+
/>
|
|
845
|
+
)}
|
|
826
846
|
</View>
|
|
827
847
|
|
|
828
848
|
{/* Titles & Status Pill */}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
CrashIcon,
|
|
15
15
|
SmartphoneIcon,
|
|
16
16
|
DatabaseIcon,
|
|
17
|
+
QrCodeIcon,
|
|
17
18
|
} from '../NetworkIcons';
|
|
18
19
|
|
|
19
20
|
import {isReduxConnected} from '../../customHooks/reduxLogger';
|
|
@@ -100,9 +101,16 @@ const TabBar = React.memo(() => {
|
|
|
100
101
|
count: 0,
|
|
101
102
|
icon: 'storage',
|
|
102
103
|
},
|
|
104
|
+
{
|
|
105
|
+
key: 'debugging',
|
|
106
|
+
label: 'Debugging',
|
|
107
|
+
count: 0,
|
|
108
|
+
icon: 'debugging',
|
|
109
|
+
},
|
|
103
110
|
] as const
|
|
104
111
|
)
|
|
105
112
|
.filter(tab => {
|
|
113
|
+
if (tab.key === 'debugging') return true;
|
|
106
114
|
if (!tabVisibility?.[tab.key]) return false;
|
|
107
115
|
if (tab.key === 'redux' && !isReduxAvail) return false;
|
|
108
116
|
if (tab.key === 'analytics' && !isAnalyticsAvail) return false;
|
|
@@ -169,6 +177,9 @@ const TabBar = React.memo(() => {
|
|
|
169
177
|
{tab.icon === 'storage' && (
|
|
170
178
|
<DatabaseIcon color={iconColor} size={14} />
|
|
171
179
|
)}
|
|
180
|
+
{tab.icon === 'debugging' && (
|
|
181
|
+
<QrCodeIcon color={iconColor} size={14} />
|
|
182
|
+
)}
|
|
172
183
|
<Text
|
|
173
184
|
numberOfLines={1}
|
|
174
185
|
ellipsizeMode="tail"
|
|
@@ -275,33 +275,6 @@ const LogCard = React.memo(function LogCard({
|
|
|
275
275
|
</Text>
|
|
276
276
|
</View>
|
|
277
277
|
)}
|
|
278
|
-
|
|
279
|
-
{/* In-Line Duration / Latency Pill */}
|
|
280
|
-
{item.duration != null && !isFailed && (
|
|
281
|
-
<View
|
|
282
|
-
style={[
|
|
283
|
-
styles.chip,
|
|
284
|
-
{
|
|
285
|
-
backgroundColor: `${durationColor}12`,
|
|
286
|
-
borderColor: `${durationColor}2E`,
|
|
287
|
-
paddingHorizontal: 4.5,
|
|
288
|
-
paddingVertical: 1,
|
|
289
|
-
borderRadius: 4,
|
|
290
|
-
},
|
|
291
|
-
]}>
|
|
292
|
-
<Text
|
|
293
|
-
style={[
|
|
294
|
-
styles.chipText,
|
|
295
|
-
{
|
|
296
|
-
fontFamily: AppFonts.interBold,
|
|
297
|
-
fontSize: 8.5,
|
|
298
|
-
color: durationColor,
|
|
299
|
-
},
|
|
300
|
-
]}>
|
|
301
|
-
{item.duration}ms
|
|
302
|
-
</Text>
|
|
303
|
-
</View>
|
|
304
|
-
)}
|
|
305
278
|
</View>
|
|
306
279
|
|
|
307
280
|
<View
|
|
@@ -321,6 +294,7 @@ const LogCard = React.memo(function LogCard({
|
|
|
321
294
|
: isLoading
|
|
322
295
|
? `${AppColors.darkOrange}30`
|
|
323
296
|
: `${statusColor}30`,
|
|
297
|
+
flexShrink: 0,
|
|
324
298
|
},
|
|
325
299
|
]}>
|
|
326
300
|
{renderStatusIcon()}
|
|
@@ -359,6 +333,7 @@ const LogCard = React.memo(function LogCard({
|
|
|
359
333
|
alignItems: 'center',
|
|
360
334
|
justifyContent: 'center',
|
|
361
335
|
marginRight: 4,
|
|
336
|
+
flexShrink: 0,
|
|
362
337
|
}}>
|
|
363
338
|
<GlobeIcon color={AppColors.skyBlue} size={11} />
|
|
364
339
|
</View>
|
|
@@ -411,8 +386,8 @@ const LogCard = React.memo(function LogCard({
|
|
|
411
386
|
|
|
412
387
|
{/* Row 3: Footer (Timestamp & Origin on Left, Response Size & Duration on Right) */}
|
|
413
388
|
<View style={styles.cardFooterRow}>
|
|
414
|
-
<View style={{flexDirection: 'row', alignItems: 'center', gap: 6,
|
|
415
|
-
<View style={styles.cardDateRow}>
|
|
389
|
+
<View style={{flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1, minWidth: 0, marginRight: 8}}>
|
|
390
|
+
<View style={[styles.cardDateRow, {flexShrink: 0}]}>
|
|
416
391
|
<CalendarIcon color={AppColors.grayTextWeak} size={10} />
|
|
417
392
|
<Text style={styles.cardDateText}>{triggeredAt}</Text>
|
|
418
393
|
</View>
|
|
@@ -431,7 +406,7 @@ const LogCard = React.memo(function LogCard({
|
|
|
431
406
|
paddingVertical: 1,
|
|
432
407
|
borderRadius: 4,
|
|
433
408
|
flexShrink: 1,
|
|
434
|
-
|
|
409
|
+
minWidth: 0,
|
|
435
410
|
},
|
|
436
411
|
]}>
|
|
437
412
|
<PinIcon color={AppColors.skyBlue} size={8.5} />
|
|
@@ -2219,3 +2219,69 @@ export const PlusIcon = ({
|
|
|
2219
2219
|
</Svg>
|
|
2220
2220
|
);
|
|
2221
2221
|
|
|
2222
|
+
export const LockIcon = ({
|
|
2223
|
+
color = AppColors.grayTextWeak,
|
|
2224
|
+
size = 14,
|
|
2225
|
+
}: IconProps) => (
|
|
2226
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2227
|
+
<Rect
|
|
2228
|
+
x="3"
|
|
2229
|
+
y="11"
|
|
2230
|
+
width="18"
|
|
2231
|
+
height="11"
|
|
2232
|
+
rx="2"
|
|
2233
|
+
ry="2"
|
|
2234
|
+
stroke={color}
|
|
2235
|
+
strokeWidth="2"
|
|
2236
|
+
strokeLinecap="round"
|
|
2237
|
+
strokeLinejoin="round"
|
|
2238
|
+
/>
|
|
2239
|
+
<Path
|
|
2240
|
+
d="M7 11V7a5 5 0 0 1 10 0v4"
|
|
2241
|
+
stroke={color}
|
|
2242
|
+
strokeWidth="2"
|
|
2243
|
+
strokeLinecap="round"
|
|
2244
|
+
strokeLinejoin="round"
|
|
2245
|
+
/>
|
|
2246
|
+
</Svg>
|
|
2247
|
+
);
|
|
2248
|
+
|
|
2249
|
+
export const QrCodeIcon = ({
|
|
2250
|
+
color = AppColors.grayTextWeak,
|
|
2251
|
+
size = 14,
|
|
2252
|
+
}: IconProps) => (
|
|
2253
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2254
|
+
<Rect
|
|
2255
|
+
x="3"
|
|
2256
|
+
y="3"
|
|
2257
|
+
width="7"
|
|
2258
|
+
height="7"
|
|
2259
|
+
rx="1.5"
|
|
2260
|
+
stroke={color}
|
|
2261
|
+
strokeWidth="2"
|
|
2262
|
+
/>
|
|
2263
|
+
<Rect
|
|
2264
|
+
x="14"
|
|
2265
|
+
y="3"
|
|
2266
|
+
width="7"
|
|
2267
|
+
height="7"
|
|
2268
|
+
rx="1.5"
|
|
2269
|
+
stroke={color}
|
|
2270
|
+
strokeWidth="2"
|
|
2271
|
+
/>
|
|
2272
|
+
<Rect
|
|
2273
|
+
x="3"
|
|
2274
|
+
y="14"
|
|
2275
|
+
width="7"
|
|
2276
|
+
height="7"
|
|
2277
|
+
rx="1.5"
|
|
2278
|
+
stroke={color}
|
|
2279
|
+
strokeWidth="2"
|
|
2280
|
+
/>
|
|
2281
|
+
<Path
|
|
2282
|
+
d="M14 14h3v3h-3zM18 18h3v3h-3zM14 19h3v2h-3zM19 14h2v3h-2z"
|
|
2283
|
+
fill={color}
|
|
2284
|
+
/>
|
|
2285
|
+
</Svg>
|
|
2286
|
+
);
|
|
2287
|
+
|