react-native-inapp-inspector 1.0.14 → 1.0.16
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/README.md +203 -44
- package/dist/commonjs/components/AnimatedEntrance.d.ts +12 -0
- package/dist/commonjs/components/AnimatedEntrance.js +72 -0
- package/dist/commonjs/components/ConsoleLogCard.js +114 -29
- package/dist/commonjs/components/EmptyState.js +56 -5
- package/dist/commonjs/components/ReduxTreeView.js +96 -27
- package/dist/commonjs/components/TouchableScale.js +18 -2
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +1 -0
- package/dist/commonjs/customHooks/analyticsLogger.js +57 -17
- package/dist/commonjs/customHooks/networkLogger.d.ts +1 -1
- package/dist/commonjs/customHooks/networkLogger.js +54 -46
- package/dist/commonjs/index.js +1595 -822
- package/dist/esm/components/AnimatedEntrance.d.ts +12 -0
- package/dist/esm/components/AnimatedEntrance.js +37 -0
- package/dist/esm/components/ConsoleLogCard.js +116 -31
- package/dist/esm/components/EmptyState.js +24 -6
- package/dist/esm/components/ReduxTreeView.js +95 -29
- package/dist/esm/components/TouchableScale.js +18 -2
- package/dist/esm/customHooks/analyticsLogger.d.ts +1 -0
- package/dist/esm/customHooks/analyticsLogger.js +55 -16
- package/dist/esm/customHooks/networkLogger.d.ts +1 -1
- package/dist/esm/customHooks/networkLogger.js +56 -48
- package/dist/esm/index.js +1597 -824
- package/example/App.tsx +1 -3
- package/package.json +5 -3
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react';
|
|
2
|
-
import { Alert, Animated, StyleSheet, FlatList, Modal, Platform, Pressable, ScrollView, Text, TextInput, View, Linking, Image, InteractionManager, ActivityIndicator, StatusBar, TouchableOpacity, LogBox, } from 'react-native';
|
|
2
|
+
import { Alert, Animated, StyleSheet, FlatList, LayoutAnimation, Modal, Platform, Pressable, ScrollView, Text, TextInput, View, Linking, Image, InteractionManager, ActivityIndicator, StatusBar, TouchableOpacity, UIManager, LogBox, } from 'react-native';
|
|
3
3
|
import Svg, { Circle, Path } from 'react-native-svg';
|
|
4
4
|
import LinearGradient from 'react-native-linear-gradient';
|
|
5
5
|
import { useNavigationState, NavigationContext } from '@react-navigation/native';
|
|
@@ -20,6 +20,7 @@ import SourcePageCard from './components/SourcePageCard';
|
|
|
20
20
|
import { ConsoleLogCard } from './components/ConsoleLogCard';
|
|
21
21
|
import HighlightText from './components/HighlightText';
|
|
22
22
|
import CodeSnippet from './components/CodeSnippet';
|
|
23
|
+
import AnimatedEntrance from './components/AnimatedEntrance';
|
|
23
24
|
// Helpers
|
|
24
25
|
import { formatDateTime, getStatusColor, getNavigationInfo, deduplicateLogs, getDomainColor, formatDisplayUrl, getFetchCommand, getCurlCommand, getSize, } from './helpers';
|
|
25
26
|
// Assets
|
|
@@ -34,7 +35,7 @@ import { setupNetworkLogger, clearNetworkLogs, subscribeNetworkLogs, } from './c
|
|
|
34
35
|
// Console
|
|
35
36
|
import { setupConsoleLogger, clearConsoleLogs, subscribeConsoleLogs, } from './customHooks/consoleLogger';
|
|
36
37
|
import { IGNORED_LOG_PREFIXES } from './customHooks/logFilters';
|
|
37
|
-
import { subscribeAnalyticsEvents, clearAnalyticsEvents, } from './customHooks/analyticsLogger';
|
|
38
|
+
import { subscribeAnalyticsEvents, clearAnalyticsEvents, autoSetupAnalyticsLogger, } from './customHooks/analyticsLogger';
|
|
38
39
|
import AnalyticsEventCard, { getEventColor, } from './components/AnalyticsEventCard';
|
|
39
40
|
import AnalyticsDetail from './components/AnalyticsDetail';
|
|
40
41
|
import { getWebViewLogs, getWebViewNavHistory, getWebViewHtml, getWebViewCss, getWebViewJs, getWebViewHtmlUrl, clearWebViewData, subscribeWebView, } from './customHooks/webViewLogger';
|
|
@@ -107,7 +108,10 @@ const NavigationTracker = ({ onStateChange }) => {
|
|
|
107
108
|
}, [navState, onStateChange]);
|
|
108
109
|
return null;
|
|
109
110
|
};
|
|
110
|
-
const
|
|
111
|
+
const animateNextLayout = () => {
|
|
112
|
+
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
113
|
+
};
|
|
114
|
+
const NetworkInspector = ({ enabled = true, }) => {
|
|
111
115
|
const [isDark, setIsDark] = useState(false);
|
|
112
116
|
const [reduxState, setReduxState] = useState(null);
|
|
113
117
|
const [expandedReducers, setExpandedReducers] = useState({});
|
|
@@ -122,16 +126,11 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
122
126
|
const [reduxActiveSubTab, setReduxActiveSubTab] = useState('timeline');
|
|
123
127
|
const [apiDetailActiveTab, setApiDetailActiveTab] = useState('response');
|
|
124
128
|
useEffect(() => {
|
|
125
|
-
|
|
126
|
-
LogBox.ignoreAllLogs(true);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
LogBox.ignoreAllLogs(false);
|
|
130
|
-
}
|
|
129
|
+
LogBox.ignoreAllLogs(enabled);
|
|
131
130
|
return () => {
|
|
132
131
|
LogBox.ignoreAllLogs(false);
|
|
133
132
|
};
|
|
134
|
-
}, [enabled
|
|
133
|
+
}, [enabled]);
|
|
135
134
|
useEffect(() => {
|
|
136
135
|
if (selected) {
|
|
137
136
|
setApiDetailActiveTab('response');
|
|
@@ -240,12 +239,18 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
240
239
|
const nextVal = !prev[key];
|
|
241
240
|
const newVisibility = { ...prev, [key]: nextVal };
|
|
242
241
|
if (!nextVal && activeTab === key) {
|
|
242
|
+
animateNextLayout();
|
|
243
243
|
setActiveTab('apis');
|
|
244
244
|
}
|
|
245
245
|
return newVisibility;
|
|
246
246
|
});
|
|
247
247
|
};
|
|
248
|
+
const switchActiveTab = useCallback((key) => {
|
|
249
|
+
animateNextLayout();
|
|
250
|
+
setActiveTab(key);
|
|
251
|
+
}, []);
|
|
248
252
|
const navigateFromDashboard = (key) => {
|
|
253
|
+
animateNextLayout();
|
|
249
254
|
setTabVisibility(prev => ({ ...prev, [key]: true }));
|
|
250
255
|
setActiveTab(key);
|
|
251
256
|
};
|
|
@@ -318,6 +323,11 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
318
323
|
const badgeAnim = useRef(new Animated.Value(1)).current;
|
|
319
324
|
const activePulseAnim = useRef(new Animated.Value(0.4)).current;
|
|
320
325
|
const unreadPulseAnim = useRef(new Animated.Value(1)).current;
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
if (Platform.OS === 'android') {
|
|
328
|
+
UIManager.setLayoutAnimationEnabledExperimental?.(true);
|
|
329
|
+
}
|
|
330
|
+
}, []);
|
|
321
331
|
useEffect(() => {
|
|
322
332
|
const loop = Animated.loop(Animated.sequence([
|
|
323
333
|
Animated.timing(pulseAnim, {
|
|
@@ -393,7 +403,7 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
393
403
|
setupNetworkLogger();
|
|
394
404
|
clearNetworkLogs();
|
|
395
405
|
setupConsoleLogger();
|
|
396
|
-
|
|
406
|
+
autoSetupAnalyticsLogger();
|
|
397
407
|
let timeoutId;
|
|
398
408
|
const unsubscribe = subscribeNetworkLogs((raw) => {
|
|
399
409
|
clearTimeout(timeoutId);
|
|
@@ -777,6 +787,7 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
777
787
|
return Object.entries(freq).sort((a, b) => b[1] - a[1]);
|
|
778
788
|
}, [filteredAnalyticsEvents]);
|
|
779
789
|
function closeModal() {
|
|
790
|
+
animateNextLayout();
|
|
780
791
|
setVisible(false);
|
|
781
792
|
setSelected(null);
|
|
782
793
|
setSelectedEvent(null);
|
|
@@ -894,12 +905,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
894
905
|
return next;
|
|
895
906
|
});
|
|
896
907
|
}, []);
|
|
897
|
-
const renderItem = useCallback(({ item }) => {
|
|
908
|
+
const renderItem = useCallback(({ item, index }) => {
|
|
898
909
|
if (item.type === 'header') {
|
|
899
|
-
return (<
|
|
910
|
+
return (<AnimatedEntrance index={index} distance={8}>
|
|
911
|
+
<DomainHeader pageName={item.pageName} color={item.color} stats={item.stats} activeFilters={item.activeFilters} onToggleFilter={toggleSectionFilter} isCollapsed={item.isCollapsed} onToggleCollapse={toggleSectionCollapse} isFirst={item.isFirst} timestamp={item.timestamp}/>
|
|
912
|
+
</AnimatedEntrance>);
|
|
900
913
|
}
|
|
901
914
|
const { log, isLast, color } = item;
|
|
902
|
-
return (<
|
|
915
|
+
return (<AnimatedEntrance index={index} distance={8} style={styles.treeNodeRow}>
|
|
903
916
|
<View style={styles.treeLines}>
|
|
904
917
|
<View style={[
|
|
905
918
|
styles.modernTreeLine,
|
|
@@ -909,9 +922,12 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
909
922
|
{!isLast && (<View style={[styles.modernTreeBranch, { borderColor: color }]}/>)}
|
|
910
923
|
</View>
|
|
911
924
|
<View style={styles.treeCardWrapper}>
|
|
912
|
-
<LogCard item={log} isSelected={selectedLogs.has(log.id)} onToggleSelect={toggleSelect} onPress={() =>
|
|
925
|
+
<LogCard item={log} isSelected={selectedLogs.has(log.id)} onToggleSelect={toggleSelect} onPress={() => {
|
|
926
|
+
animateNextLayout();
|
|
927
|
+
setSelected(log);
|
|
928
|
+
}} timelineMinStart={minStart} timelineTotalRange={totalRange} isNew={newLogIds.has(log.id)} searchStr={search}/>
|
|
913
929
|
</View>
|
|
914
|
-
</
|
|
930
|
+
</AnimatedEntrance>);
|
|
915
931
|
}, [
|
|
916
932
|
minStart,
|
|
917
933
|
totalRange,
|
|
@@ -937,8 +953,9 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
937
953
|
<LinearGradient colors={[AppColors.purple, '#6B4EFF']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.headerGradient}>
|
|
938
954
|
<View style={[styles.header, { paddingHorizontal: 16, gap: 12 }]}>
|
|
939
955
|
<TouchableScale onPress={() => {
|
|
956
|
+
animateNextLayout();
|
|
940
957
|
setSettingsPage(null);
|
|
941
|
-
|
|
958
|
+
switchActiveTab('apis');
|
|
942
959
|
}} hitSlop={12} style={{
|
|
943
960
|
padding: 8,
|
|
944
961
|
borderRadius: 10,
|
|
@@ -949,8 +966,21 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
949
966
|
<WhiteBackNavigation color="#FFFFFF" size={16}/>
|
|
950
967
|
</TouchableScale>
|
|
951
968
|
<View style={{ flex: 1 }}>
|
|
952
|
-
<Text style={{
|
|
953
|
-
|
|
969
|
+
<Text style={{
|
|
970
|
+
fontFamily: AppFonts.interBold,
|
|
971
|
+
fontSize: 17,
|
|
972
|
+
color: '#FFFFFF',
|
|
973
|
+
}}>
|
|
974
|
+
Settings
|
|
975
|
+
</Text>
|
|
976
|
+
<Text style={{
|
|
977
|
+
fontFamily: AppFonts.interRegular,
|
|
978
|
+
fontSize: 11,
|
|
979
|
+
color: 'rgba(255,255,255,0.75)',
|
|
980
|
+
marginTop: 1,
|
|
981
|
+
}}>
|
|
982
|
+
Manage modules and preferences
|
|
983
|
+
</Text>
|
|
954
984
|
</View>
|
|
955
985
|
<View style={{
|
|
956
986
|
backgroundColor: 'rgba(255, 255, 255, 0.15)',
|
|
@@ -958,17 +988,28 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
958
988
|
paddingVertical: 4,
|
|
959
989
|
borderRadius: 8,
|
|
960
990
|
borderWidth: 1,
|
|
961
|
-
borderColor: 'rgba(255, 255, 255, 0.1)'
|
|
991
|
+
borderColor: 'rgba(255, 255, 255, 0.1)',
|
|
962
992
|
}}>
|
|
963
|
-
<Text style={{
|
|
993
|
+
<Text style={{
|
|
994
|
+
fontFamily: AppFonts.interBold,
|
|
995
|
+
fontSize: 10.5,
|
|
996
|
+
color: '#FFFFFF',
|
|
997
|
+
}}>
|
|
998
|
+
v1.0.13
|
|
999
|
+
</Text>
|
|
964
1000
|
</View>
|
|
965
1001
|
</View>
|
|
966
1002
|
</LinearGradient>
|
|
967
1003
|
|
|
968
1004
|
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16, gap: 12 }}>
|
|
969
|
-
|
|
970
1005
|
{/* Tab list */}
|
|
971
|
-
<View style={{
|
|
1006
|
+
<View style={{
|
|
1007
|
+
backgroundColor: AppColors.primaryLight,
|
|
1008
|
+
borderRadius: 12,
|
|
1009
|
+
borderWidth: 1,
|
|
1010
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1011
|
+
overflow: 'hidden',
|
|
1012
|
+
}}>
|
|
972
1013
|
{/* Table Header */}
|
|
973
1014
|
<View style={{
|
|
974
1015
|
flexDirection: 'row',
|
|
@@ -980,8 +1021,26 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
980
1021
|
borderBottomColor: AppColors.dividerColor,
|
|
981
1022
|
gap: 12,
|
|
982
1023
|
}}>
|
|
983
|
-
<Text style={{
|
|
984
|
-
|
|
1024
|
+
<Text style={{
|
|
1025
|
+
fontFamily: AppFonts.interBold,
|
|
1026
|
+
fontSize: 10,
|
|
1027
|
+
color: AppColors.grayTextWeak,
|
|
1028
|
+
letterSpacing: 0.6,
|
|
1029
|
+
flex: 1,
|
|
1030
|
+
}}>
|
|
1031
|
+
MODULE
|
|
1032
|
+
</Text>
|
|
1033
|
+
<Text style={{
|
|
1034
|
+
fontFamily: AppFonts.interBold,
|
|
1035
|
+
fontSize: 10,
|
|
1036
|
+
color: AppColors.grayTextWeak,
|
|
1037
|
+
letterSpacing: 0.6,
|
|
1038
|
+
width: 90,
|
|
1039
|
+
textAlign: 'right',
|
|
1040
|
+
paddingRight: 4,
|
|
1041
|
+
}}>
|
|
1042
|
+
VISIBILITY
|
|
1043
|
+
</Text>
|
|
985
1044
|
</View>
|
|
986
1045
|
|
|
987
1046
|
{settingsTabs.map((tab, idx) => {
|
|
@@ -998,27 +1057,53 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
998
1057
|
gap: 12,
|
|
999
1058
|
}}>
|
|
1000
1059
|
{/* Icon + Label — fills remaining space */}
|
|
1001
|
-
<View style={{
|
|
1060
|
+
<View style={{
|
|
1061
|
+
flex: 1,
|
|
1062
|
+
flexDirection: 'row',
|
|
1063
|
+
alignItems: 'center',
|
|
1064
|
+
gap: 8,
|
|
1065
|
+
}}>
|
|
1002
1066
|
{/* Small icon tile */}
|
|
1003
1067
|
<View style={{
|
|
1004
|
-
width: 20,
|
|
1005
|
-
|
|
1068
|
+
width: 20,
|
|
1069
|
+
height: 20,
|
|
1070
|
+
borderRadius: 6,
|
|
1071
|
+
backgroundColor: isLocked
|
|
1072
|
+
? AppColors.grayBorderSecondary
|
|
1073
|
+
: AppColors.purpleShade50,
|
|
1006
1074
|
borderWidth: 1,
|
|
1007
|
-
borderColor: isLocked
|
|
1008
|
-
|
|
1075
|
+
borderColor: isLocked
|
|
1076
|
+
? AppColors.dividerColor
|
|
1077
|
+
: 'rgba(104,75,155,0.2)',
|
|
1078
|
+
alignItems: 'center',
|
|
1079
|
+
justifyContent: 'center',
|
|
1009
1080
|
}}>
|
|
1010
|
-
{tab.icon === 'insights' && <InsightsIcon color={isLocked
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
{tab.icon === '
|
|
1014
|
-
|
|
1015
|
-
|
|
1081
|
+
{tab.icon === 'insights' && (<InsightsIcon color={isLocked
|
|
1082
|
+
? AppColors.grayTextWeak
|
|
1083
|
+
: AppColors.purple} size={11}/>)}
|
|
1084
|
+
{tab.icon === 'apis' && (<SignalIcon color={isLocked
|
|
1085
|
+
? AppColors.grayTextWeak
|
|
1086
|
+
: AppColors.purple} size={11}/>)}
|
|
1087
|
+
{tab.icon === 'logs' && (<TerminalIcon color={isLocked
|
|
1088
|
+
? AppColors.grayTextWeak
|
|
1089
|
+
: AppColors.purple} size={11}/>)}
|
|
1090
|
+
{tab.icon === 'analytics' && (<AnalyticsIcon color={isLocked
|
|
1091
|
+
? AppColors.grayTextWeak
|
|
1092
|
+
: AppColors.purple} size={11}/>)}
|
|
1093
|
+
{tab.icon === 'webview' && (<GlobeIcon color={isLocked
|
|
1094
|
+
? AppColors.grayTextWeak
|
|
1095
|
+
: AppColors.purple} size={11}/>)}
|
|
1096
|
+
{tab.icon === 'redux' && (<TerminalIcon color={isLocked
|
|
1097
|
+
? AppColors.grayTextWeak
|
|
1098
|
+
: AppColors.purple} size={11}/>)}
|
|
1016
1099
|
</View>
|
|
1017
1100
|
{/* Label + Required badge */}
|
|
1018
1101
|
<Text style={{
|
|
1019
1102
|
fontFamily: AppFonts.interBold,
|
|
1020
1103
|
fontSize: 13,
|
|
1021
|
-
color: isLocked
|
|
1104
|
+
color: isLocked
|
|
1105
|
+
? AppColors.grayText
|
|
1106
|
+
: AppColors.primaryBlack,
|
|
1022
1107
|
}}>
|
|
1023
1108
|
{tab.label}
|
|
1024
1109
|
</Text>
|
|
@@ -1033,14 +1118,28 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1033
1118
|
borderColor: 'rgba(104,75,155,0.18)',
|
|
1034
1119
|
gap: 3,
|
|
1035
1120
|
}}>
|
|
1036
|
-
<View style={{
|
|
1037
|
-
|
|
1121
|
+
<View style={{
|
|
1122
|
+
width: 4,
|
|
1123
|
+
height: 4,
|
|
1124
|
+
borderRadius: 2,
|
|
1125
|
+
backgroundColor: AppColors.purple,
|
|
1126
|
+
opacity: 0.7,
|
|
1127
|
+
}}/>
|
|
1128
|
+
<Text style={{
|
|
1129
|
+
fontFamily: AppFonts.interBold,
|
|
1130
|
+
fontSize: 8.5,
|
|
1131
|
+
color: AppColors.purple,
|
|
1132
|
+
letterSpacing: 0.4,
|
|
1133
|
+
}}>
|
|
1038
1134
|
DEFAULT
|
|
1039
1135
|
</Text>
|
|
1040
1136
|
</View>)}
|
|
1041
1137
|
|
|
1042
1138
|
{/* Settings gear icon next to label */}
|
|
1043
|
-
<TouchableScale onPress={() =>
|
|
1139
|
+
<TouchableScale onPress={() => {
|
|
1140
|
+
animateNextLayout();
|
|
1141
|
+
setSettingsPage(tab.key);
|
|
1142
|
+
}} hitSlop={8} style={{
|
|
1044
1143
|
marginLeft: 4,
|
|
1045
1144
|
padding: 4,
|
|
1046
1145
|
borderRadius: 6,
|
|
@@ -1055,12 +1154,18 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1055
1154
|
</View>
|
|
1056
1155
|
|
|
1057
1156
|
{/* Visibility Switch in VISIBILITY column */}
|
|
1058
|
-
<View style={{
|
|
1157
|
+
<View style={{
|
|
1158
|
+
width: 90,
|
|
1159
|
+
alignItems: 'flex-end',
|
|
1160
|
+
justifyContent: 'center',
|
|
1161
|
+
}}>
|
|
1059
1162
|
<TouchableScale disabled={isLocked} onPress={() => toggleTabVisibility(tab.key)} style={{
|
|
1060
1163
|
width: 38,
|
|
1061
1164
|
height: 22,
|
|
1062
1165
|
borderRadius: 11,
|
|
1063
|
-
backgroundColor: isVisible
|
|
1166
|
+
backgroundColor: isVisible
|
|
1167
|
+
? AppColors.purple
|
|
1168
|
+
: AppColors.grayBorderSecondary,
|
|
1064
1169
|
padding: 2,
|
|
1065
1170
|
justifyContent: 'center',
|
|
1066
1171
|
alignItems: isVisible ? 'flex-end' : 'flex-start',
|
|
@@ -1083,8 +1188,22 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1083
1188
|
|
|
1084
1189
|
{/* Preferences Section */}
|
|
1085
1190
|
<View style={{ marginTop: 8 }}>
|
|
1086
|
-
<Text style={{
|
|
1087
|
-
|
|
1191
|
+
<Text style={{
|
|
1192
|
+
fontFamily: AppFonts.interBold,
|
|
1193
|
+
fontSize: 10,
|
|
1194
|
+
color: AppColors.grayTextWeak,
|
|
1195
|
+
letterSpacing: 0.6,
|
|
1196
|
+
marginBottom: 8,
|
|
1197
|
+
}}>
|
|
1198
|
+
PREFERENCES
|
|
1199
|
+
</Text>
|
|
1200
|
+
<View style={{
|
|
1201
|
+
backgroundColor: AppColors.primaryLight,
|
|
1202
|
+
borderRadius: 12,
|
|
1203
|
+
borderWidth: 1,
|
|
1204
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1205
|
+
overflow: 'hidden',
|
|
1206
|
+
}}>
|
|
1088
1207
|
<View style={{
|
|
1089
1208
|
flexDirection: 'row',
|
|
1090
1209
|
alignItems: 'center',
|
|
@@ -1093,13 +1212,21 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1093
1212
|
gap: 12,
|
|
1094
1213
|
}}>
|
|
1095
1214
|
{/* Icon + Label */}
|
|
1096
|
-
<View style={{
|
|
1215
|
+
<View style={{
|
|
1216
|
+
flex: 1,
|
|
1217
|
+
flexDirection: 'row',
|
|
1218
|
+
alignItems: 'center',
|
|
1219
|
+
gap: 8,
|
|
1220
|
+
}}>
|
|
1097
1221
|
<View style={{
|
|
1098
|
-
width: 20,
|
|
1222
|
+
width: 20,
|
|
1223
|
+
height: 20,
|
|
1224
|
+
borderRadius: 6,
|
|
1099
1225
|
backgroundColor: AppColors.purpleShade50,
|
|
1100
1226
|
borderWidth: 1,
|
|
1101
1227
|
borderColor: 'rgba(104,75,155,0.2)',
|
|
1102
|
-
alignItems: 'center',
|
|
1228
|
+
alignItems: 'center',
|
|
1229
|
+
justifyContent: 'center',
|
|
1103
1230
|
}}>
|
|
1104
1231
|
{isDark ? (<SunIcon color={AppColors.purple} size={11}/>) : (<MoonIcon color={AppColors.purple} size={11}/>)}
|
|
1105
1232
|
</View>
|
|
@@ -1123,7 +1250,9 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1123
1250
|
width: 38,
|
|
1124
1251
|
height: 22,
|
|
1125
1252
|
borderRadius: 11,
|
|
1126
|
-
backgroundColor: isDark
|
|
1253
|
+
backgroundColor: isDark
|
|
1254
|
+
? AppColors.purple
|
|
1255
|
+
: AppColors.grayBorderSecondary,
|
|
1127
1256
|
padding: 2,
|
|
1128
1257
|
justifyContent: 'center',
|
|
1129
1258
|
alignItems: isDark ? 'flex-end' : 'flex-start',
|
|
@@ -1145,7 +1274,10 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1145
1274
|
</ScrollView>
|
|
1146
1275
|
</View>);
|
|
1147
1276
|
}
|
|
1148
|
-
const goBackToMain = () =>
|
|
1277
|
+
const goBackToMain = () => {
|
|
1278
|
+
animateNextLayout();
|
|
1279
|
+
setSettingsPage('main');
|
|
1280
|
+
};
|
|
1149
1281
|
const renderSubHeader = (title, icon, rightInfo) => (<View style={{
|
|
1150
1282
|
flexDirection: 'row',
|
|
1151
1283
|
alignItems: 'center',
|
|
@@ -1168,14 +1300,23 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1168
1300
|
<WhiteBackNavigation color={AppColors.purple} size={16}/>
|
|
1169
1301
|
</TouchableScale>
|
|
1170
1302
|
{icon && (<View style={{
|
|
1171
|
-
width: 36,
|
|
1303
|
+
width: 36,
|
|
1304
|
+
height: 36,
|
|
1305
|
+
borderRadius: 10,
|
|
1172
1306
|
backgroundColor: AppColors.purpleShade50,
|
|
1173
|
-
borderWidth: 1,
|
|
1174
|
-
|
|
1307
|
+
borderWidth: 1,
|
|
1308
|
+
borderColor: 'rgba(104,75,155,0.2)',
|
|
1309
|
+
alignItems: 'center',
|
|
1310
|
+
justifyContent: 'center',
|
|
1175
1311
|
}}>
|
|
1176
1312
|
{icon}
|
|
1177
1313
|
</View>)}
|
|
1178
|
-
<Text style={{
|
|
1314
|
+
<Text style={{
|
|
1315
|
+
fontFamily: AppFonts.interBold,
|
|
1316
|
+
fontSize: 18,
|
|
1317
|
+
color: AppColors.primaryBlack,
|
|
1318
|
+
flex: 1,
|
|
1319
|
+
}}>
|
|
1179
1320
|
{title}
|
|
1180
1321
|
</Text>
|
|
1181
1322
|
{rightInfo ? (<View style={{
|
|
@@ -1186,7 +1327,11 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1186
1327
|
borderWidth: 1,
|
|
1187
1328
|
borderColor: 'rgba(104,75,155,0.15)',
|
|
1188
1329
|
}}>
|
|
1189
|
-
<Text style={{
|
|
1330
|
+
<Text style={{
|
|
1331
|
+
fontFamily: AppFonts.interBold,
|
|
1332
|
+
fontSize: 11,
|
|
1333
|
+
color: AppColors.purple,
|
|
1334
|
+
}}>
|
|
1190
1335
|
{rightInfo}
|
|
1191
1336
|
</Text>
|
|
1192
1337
|
</View>) : null}
|
|
@@ -1203,18 +1348,31 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1203
1348
|
gap: 12,
|
|
1204
1349
|
}}>
|
|
1205
1350
|
<View style={{
|
|
1206
|
-
width: 36,
|
|
1351
|
+
width: 36,
|
|
1352
|
+
height: 36,
|
|
1353
|
+
borderRadius: 10,
|
|
1207
1354
|
backgroundColor: AppColors.purpleShade50,
|
|
1208
|
-
borderWidth: 1,
|
|
1209
|
-
|
|
1355
|
+
borderWidth: 1,
|
|
1356
|
+
borderColor: 'rgba(104,75,155,0.18)',
|
|
1357
|
+
alignItems: 'center',
|
|
1358
|
+
justifyContent: 'center',
|
|
1210
1359
|
}}>
|
|
1211
1360
|
{opts.icon}
|
|
1212
1361
|
</View>
|
|
1213
1362
|
<View style={{ flex: 1 }}>
|
|
1214
|
-
<Text style={{
|
|
1363
|
+
<Text style={{
|
|
1364
|
+
fontFamily: AppFonts.interBold,
|
|
1365
|
+
fontSize: 14,
|
|
1366
|
+
color: AppColors.primaryBlack,
|
|
1367
|
+
}}>
|
|
1215
1368
|
{opts.label}
|
|
1216
1369
|
</Text>
|
|
1217
|
-
{opts.description ? (<Text style={{
|
|
1370
|
+
{opts.description ? (<Text style={{
|
|
1371
|
+
fontFamily: AppFonts.interRegular,
|
|
1372
|
+
fontSize: 11,
|
|
1373
|
+
color: AppColors.grayText,
|
|
1374
|
+
marginTop: 1,
|
|
1375
|
+
}}>
|
|
1218
1376
|
{opts.description}
|
|
1219
1377
|
</Text>) : null}
|
|
1220
1378
|
</View>
|
|
@@ -1236,14 +1394,20 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1236
1394
|
paddingVertical: 6,
|
|
1237
1395
|
alignItems: 'center',
|
|
1238
1396
|
borderRadius: 6,
|
|
1239
|
-
backgroundColor: isActive
|
|
1397
|
+
backgroundColor: isActive
|
|
1398
|
+
? AppColors.purple
|
|
1399
|
+
: 'transparent',
|
|
1240
1400
|
}}>
|
|
1241
1401
|
<Text style={{
|
|
1242
1402
|
fontFamily: AppFonts.interBold,
|
|
1243
1403
|
fontSize: 11,
|
|
1244
1404
|
color: isActive ? '#FFFFFF' : AppColors.grayText,
|
|
1245
1405
|
}}>
|
|
1246
|
-
{typeof opt === 'number' &&
|
|
1406
|
+
{typeof opt === 'number' &&
|
|
1407
|
+
opt >= 500 &&
|
|
1408
|
+
settingsPage === 'insights'
|
|
1409
|
+
? `${opt}ms`
|
|
1410
|
+
: opt}
|
|
1247
1411
|
</Text>
|
|
1248
1412
|
</TouchableScale>);
|
|
1249
1413
|
})}
|
|
@@ -1252,7 +1416,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1252
1416
|
if (settingsPage === 'apis') {
|
|
1253
1417
|
return (<ScrollView style={{ flex: 1, backgroundColor: AppColors.grayBackground }} contentContainerStyle={{ padding: 16 }}>
|
|
1254
1418
|
{renderSubHeader('APIs Settings', <SignalIcon color={AppColors.purple} size={16}/>, `Total: ${logs.length}`)}
|
|
1255
|
-
<View style={{
|
|
1419
|
+
<View style={{
|
|
1420
|
+
backgroundColor: AppColors.primaryLight,
|
|
1421
|
+
padding: 16,
|
|
1422
|
+
borderRadius: 12,
|
|
1423
|
+
borderWidth: 1,
|
|
1424
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1425
|
+
gap: 4,
|
|
1426
|
+
}}>
|
|
1256
1427
|
{renderSettingRow({
|
|
1257
1428
|
icon: <SignalIcon color={AppColors.purple} size={16}/>,
|
|
1258
1429
|
label: 'Max Request Logs',
|
|
@@ -1266,7 +1437,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1266
1437
|
})}
|
|
1267
1438
|
</View>
|
|
1268
1439
|
|
|
1269
|
-
<View style={{
|
|
1440
|
+
<View style={{
|
|
1441
|
+
backgroundColor: AppColors.primaryLight,
|
|
1442
|
+
borderRadius: 12,
|
|
1443
|
+
borderWidth: 1,
|
|
1444
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1445
|
+
padding: 16,
|
|
1446
|
+
marginTop: 12,
|
|
1447
|
+
}}>
|
|
1270
1448
|
{renderSettingRow({
|
|
1271
1449
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1272
1450
|
label: 'Clear Network Logs',
|
|
@@ -1277,8 +1455,21 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1277
1455
|
setSelected(null);
|
|
1278
1456
|
Alert.alert('Success', 'Network logs cleared.');
|
|
1279
1457
|
},
|
|
1280
|
-
right: (<View style={{
|
|
1281
|
-
|
|
1458
|
+
right: (<View style={{
|
|
1459
|
+
paddingHorizontal: 10,
|
|
1460
|
+
paddingVertical: 5,
|
|
1461
|
+
borderRadius: 7,
|
|
1462
|
+
backgroundColor: 'rgba(255,46,87,0.08)',
|
|
1463
|
+
borderWidth: 1,
|
|
1464
|
+
borderColor: 'rgba(255,46,87,0.2)',
|
|
1465
|
+
}}>
|
|
1466
|
+
<Text style={{
|
|
1467
|
+
fontFamily: AppFonts.interBold,
|
|
1468
|
+
fontSize: 11,
|
|
1469
|
+
color: AppColors.errorColor,
|
|
1470
|
+
}}>
|
|
1471
|
+
Clear
|
|
1472
|
+
</Text>
|
|
1282
1473
|
</View>),
|
|
1283
1474
|
})}
|
|
1284
1475
|
</View>
|
|
@@ -1287,7 +1478,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1287
1478
|
if (settingsPage === 'logs') {
|
|
1288
1479
|
return (<ScrollView style={{ flex: 1, backgroundColor: AppColors.grayBackground }} contentContainerStyle={{ padding: 16 }}>
|
|
1289
1480
|
{renderSubHeader('Logs Settings', <TerminalIcon color={AppColors.purple} size={16}/>, `Total: ${consoleLogs.length}`)}
|
|
1290
|
-
<View style={{
|
|
1481
|
+
<View style={{
|
|
1482
|
+
backgroundColor: AppColors.primaryLight,
|
|
1483
|
+
padding: 16,
|
|
1484
|
+
borderRadius: 12,
|
|
1485
|
+
borderWidth: 1,
|
|
1486
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1487
|
+
gap: 4,
|
|
1488
|
+
}}>
|
|
1291
1489
|
{renderSettingRow({
|
|
1292
1490
|
icon: <TerminalIcon color={AppColors.purple} size={16}/>,
|
|
1293
1491
|
label: 'Max Console Logs',
|
|
@@ -1299,30 +1497,67 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1299
1497
|
},
|
|
1300
1498
|
})}
|
|
1301
1499
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
1302
|
-
<Text style={{
|
|
1500
|
+
<Text style={{
|
|
1501
|
+
fontFamily: AppFonts.interBold,
|
|
1502
|
+
fontSize: 13,
|
|
1503
|
+
color: AppColors.primaryBlack,
|
|
1504
|
+
paddingTop: 4,
|
|
1505
|
+
}}>
|
|
1506
|
+
Log Levels
|
|
1507
|
+
</Text>
|
|
1303
1508
|
{['info', 'warn', 'error'].map((level, li) => {
|
|
1304
1509
|
const isLvlActive = showConsoleLevels[level];
|
|
1305
|
-
const levelColor = level === 'error'
|
|
1510
|
+
const levelColor = level === 'error'
|
|
1511
|
+
? AppColors.errorColor
|
|
1512
|
+
: level === 'warn'
|
|
1513
|
+
? AppColors.warningIconGold
|
|
1514
|
+
: AppColors.skyBlue;
|
|
1306
1515
|
return renderSettingRow({
|
|
1307
|
-
icon: <View style={{
|
|
1516
|
+
icon: (<View style={{
|
|
1517
|
+
width: 10,
|
|
1518
|
+
height: 10,
|
|
1519
|
+
borderRadius: 5,
|
|
1520
|
+
backgroundColor: levelColor,
|
|
1521
|
+
}}/>),
|
|
1308
1522
|
label: `Show ${level.charAt(0).toUpperCase() + level.slice(1)} logs`,
|
|
1309
|
-
description: level === 'info'
|
|
1523
|
+
description: level === 'info'
|
|
1524
|
+
? 'Informational messages'
|
|
1525
|
+
: level === 'warn'
|
|
1526
|
+
? 'Warning messages'
|
|
1527
|
+
: 'Error messages',
|
|
1310
1528
|
isLast: level === 'error',
|
|
1311
|
-
onPress: () => setShowConsoleLevels(prev => ({
|
|
1529
|
+
onPress: () => setShowConsoleLevels(prev => ({
|
|
1530
|
+
...prev,
|
|
1531
|
+
[level]: !prev[level],
|
|
1532
|
+
})),
|
|
1312
1533
|
right: (<View style={{
|
|
1313
|
-
width: 22,
|
|
1534
|
+
width: 22,
|
|
1535
|
+
height: 22,
|
|
1536
|
+
borderRadius: 6,
|
|
1314
1537
|
borderWidth: 2,
|
|
1315
|
-
borderColor: isLvlActive
|
|
1316
|
-
|
|
1317
|
-
|
|
1538
|
+
borderColor: isLvlActive
|
|
1539
|
+
? AppColors.purple
|
|
1540
|
+
: AppColors.grayTextWeak,
|
|
1541
|
+
backgroundColor: isLvlActive
|
|
1542
|
+
? 'rgba(104, 75, 155, 0.1)'
|
|
1543
|
+
: 'transparent',
|
|
1544
|
+
alignItems: 'center',
|
|
1545
|
+
justifyContent: 'center',
|
|
1318
1546
|
}}>
|
|
1319
|
-
{isLvlActive && <CheckIcon size={12} color={AppColors.purple}/>}
|
|
1547
|
+
{isLvlActive && (<CheckIcon size={12} color={AppColors.purple}/>)}
|
|
1320
1548
|
</View>),
|
|
1321
1549
|
});
|
|
1322
1550
|
})}
|
|
1323
1551
|
</View>
|
|
1324
1552
|
|
|
1325
|
-
<View style={{
|
|
1553
|
+
<View style={{
|
|
1554
|
+
backgroundColor: AppColors.primaryLight,
|
|
1555
|
+
borderRadius: 12,
|
|
1556
|
+
borderWidth: 1,
|
|
1557
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1558
|
+
padding: 16,
|
|
1559
|
+
marginTop: 12,
|
|
1560
|
+
}}>
|
|
1326
1561
|
{renderSettingRow({
|
|
1327
1562
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1328
1563
|
label: 'Clear Console Logs',
|
|
@@ -1332,8 +1567,21 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1332
1567
|
clearConsoleLogs();
|
|
1333
1568
|
Alert.alert('Success', 'Console logs cleared.');
|
|
1334
1569
|
},
|
|
1335
|
-
right: (<View style={{
|
|
1336
|
-
|
|
1570
|
+
right: (<View style={{
|
|
1571
|
+
paddingHorizontal: 10,
|
|
1572
|
+
paddingVertical: 5,
|
|
1573
|
+
borderRadius: 7,
|
|
1574
|
+
backgroundColor: 'rgba(255,46,87,0.08)',
|
|
1575
|
+
borderWidth: 1,
|
|
1576
|
+
borderColor: 'rgba(255,46,87,0.2)',
|
|
1577
|
+
}}>
|
|
1578
|
+
<Text style={{
|
|
1579
|
+
fontFamily: AppFonts.interBold,
|
|
1580
|
+
fontSize: 11,
|
|
1581
|
+
color: AppColors.errorColor,
|
|
1582
|
+
}}>
|
|
1583
|
+
Clear
|
|
1584
|
+
</Text>
|
|
1337
1585
|
</View>),
|
|
1338
1586
|
})}
|
|
1339
1587
|
</View>
|
|
@@ -1342,7 +1590,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1342
1590
|
if (settingsPage === 'analytics') {
|
|
1343
1591
|
return (<ScrollView style={{ flex: 1, backgroundColor: AppColors.grayBackground }} contentContainerStyle={{ padding: 16 }}>
|
|
1344
1592
|
{renderSubHeader('Analytics Settings', <AnalyticsIcon color={AppColors.purple} size={16}/>, `Events: ${analyticsEvents.length}`)}
|
|
1345
|
-
<View style={{
|
|
1593
|
+
<View style={{
|
|
1594
|
+
backgroundColor: AppColors.primaryLight,
|
|
1595
|
+
padding: 16,
|
|
1596
|
+
borderRadius: 12,
|
|
1597
|
+
borderWidth: 1,
|
|
1598
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1599
|
+
gap: 4,
|
|
1600
|
+
}}>
|
|
1346
1601
|
{renderSettingRow({
|
|
1347
1602
|
icon: <AnalyticsIcon color={AppColors.purple} size={16}/>,
|
|
1348
1603
|
label: 'Events Captured',
|
|
@@ -1350,7 +1605,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1350
1605
|
isLast: true,
|
|
1351
1606
|
})}
|
|
1352
1607
|
</View>
|
|
1353
|
-
<View style={{
|
|
1608
|
+
<View style={{
|
|
1609
|
+
backgroundColor: AppColors.primaryLight,
|
|
1610
|
+
borderRadius: 12,
|
|
1611
|
+
borderWidth: 1,
|
|
1612
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1613
|
+
padding: 16,
|
|
1614
|
+
marginTop: 12,
|
|
1615
|
+
}}>
|
|
1354
1616
|
{renderSettingRow({
|
|
1355
1617
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1356
1618
|
label: 'Clear Analytics History',
|
|
@@ -1361,8 +1623,21 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1361
1623
|
setSelectedEvent(null);
|
|
1362
1624
|
Alert.alert('Success', 'Analytics events cleared.');
|
|
1363
1625
|
},
|
|
1364
|
-
right: (<View style={{
|
|
1365
|
-
|
|
1626
|
+
right: (<View style={{
|
|
1627
|
+
paddingHorizontal: 10,
|
|
1628
|
+
paddingVertical: 5,
|
|
1629
|
+
borderRadius: 7,
|
|
1630
|
+
backgroundColor: 'rgba(255,46,87,0.08)',
|
|
1631
|
+
borderWidth: 1,
|
|
1632
|
+
borderColor: 'rgba(255,46,87,0.2)',
|
|
1633
|
+
}}>
|
|
1634
|
+
<Text style={{
|
|
1635
|
+
fontFamily: AppFonts.interBold,
|
|
1636
|
+
fontSize: 11,
|
|
1637
|
+
color: AppColors.errorColor,
|
|
1638
|
+
}}>
|
|
1639
|
+
Clear
|
|
1640
|
+
</Text>
|
|
1366
1641
|
</View>),
|
|
1367
1642
|
})}
|
|
1368
1643
|
</View>
|
|
@@ -1371,25 +1646,46 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1371
1646
|
if (settingsPage === 'webview') {
|
|
1372
1647
|
return (<ScrollView style={{ flex: 1, backgroundColor: AppColors.grayBackground }} contentContainerStyle={{ padding: 16 }}>
|
|
1373
1648
|
{renderSubHeader('WebView Settings', <GlobeIcon color={AppColors.purple} size={16}/>, `History: ${webViewNavHistory.length}`)}
|
|
1374
|
-
<View style={{
|
|
1649
|
+
<View style={{
|
|
1650
|
+
backgroundColor: AppColors.primaryLight,
|
|
1651
|
+
padding: 16,
|
|
1652
|
+
borderRadius: 12,
|
|
1653
|
+
borderWidth: 1,
|
|
1654
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1655
|
+
gap: 4,
|
|
1656
|
+
}}>
|
|
1375
1657
|
{renderSettingRow({
|
|
1376
1658
|
icon: <GlobeIcon color={AppColors.purple} size={16}/>,
|
|
1377
1659
|
label: 'Capture CSS & JavaScript',
|
|
1378
1660
|
description: 'Extract stylesheet and script source from pages',
|
|
1379
1661
|
onPress: () => setWebViewCaptureCssJs(prev => !prev),
|
|
1380
1662
|
right: (<View style={{
|
|
1381
|
-
width: 22,
|
|
1663
|
+
width: 22,
|
|
1664
|
+
height: 22,
|
|
1665
|
+
borderRadius: 6,
|
|
1382
1666
|
borderWidth: 2,
|
|
1383
|
-
borderColor: webViewCaptureCssJs
|
|
1384
|
-
|
|
1385
|
-
|
|
1667
|
+
borderColor: webViewCaptureCssJs
|
|
1668
|
+
? AppColors.purple
|
|
1669
|
+
: AppColors.grayTextWeak,
|
|
1670
|
+
backgroundColor: webViewCaptureCssJs
|
|
1671
|
+
? 'rgba(104, 75, 155, 0.1)'
|
|
1672
|
+
: 'transparent',
|
|
1673
|
+
alignItems: 'center',
|
|
1674
|
+
justifyContent: 'center',
|
|
1386
1675
|
}}>
|
|
1387
|
-
{webViewCaptureCssJs && <CheckIcon size={12} color={AppColors.purple}/>}
|
|
1676
|
+
{webViewCaptureCssJs && (<CheckIcon size={12} color={AppColors.purple}/>)}
|
|
1388
1677
|
</View>),
|
|
1389
1678
|
isLast: true,
|
|
1390
1679
|
})}
|
|
1391
1680
|
</View>
|
|
1392
|
-
<View style={{
|
|
1681
|
+
<View style={{
|
|
1682
|
+
backgroundColor: AppColors.primaryLight,
|
|
1683
|
+
borderRadius: 12,
|
|
1684
|
+
borderWidth: 1,
|
|
1685
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1686
|
+
padding: 16,
|
|
1687
|
+
marginTop: 12,
|
|
1688
|
+
}}>
|
|
1393
1689
|
{renderSettingRow({
|
|
1394
1690
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1395
1691
|
label: 'Clear WebView Data',
|
|
@@ -1399,8 +1695,21 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1399
1695
|
clearWebViewData();
|
|
1400
1696
|
Alert.alert('Success', 'WebView source history cleared.');
|
|
1401
1697
|
},
|
|
1402
|
-
right: (<View style={{
|
|
1403
|
-
|
|
1698
|
+
right: (<View style={{
|
|
1699
|
+
paddingHorizontal: 10,
|
|
1700
|
+
paddingVertical: 5,
|
|
1701
|
+
borderRadius: 7,
|
|
1702
|
+
backgroundColor: 'rgba(255,46,87,0.08)',
|
|
1703
|
+
borderWidth: 1,
|
|
1704
|
+
borderColor: 'rgba(255,46,87,0.2)',
|
|
1705
|
+
}}>
|
|
1706
|
+
<Text style={{
|
|
1707
|
+
fontFamily: AppFonts.interBold,
|
|
1708
|
+
fontSize: 11,
|
|
1709
|
+
color: AppColors.errorColor,
|
|
1710
|
+
}}>
|
|
1711
|
+
Clear
|
|
1712
|
+
</Text>
|
|
1404
1713
|
</View>),
|
|
1405
1714
|
})}
|
|
1406
1715
|
</View>
|
|
@@ -1409,20 +1718,34 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1409
1718
|
if (settingsPage === 'redux') {
|
|
1410
1719
|
return (<ScrollView style={{ flex: 1, backgroundColor: AppColors.grayBackground }} contentContainerStyle={{ padding: 16 }}>
|
|
1411
1720
|
{renderSubHeader('Redux Settings', <TerminalIcon color={AppColors.purple} size={16}/>, `Reducers: ${Object.keys(reduxState || {}).length}`)}
|
|
1412
|
-
<View style={{
|
|
1721
|
+
<View style={{
|
|
1722
|
+
backgroundColor: AppColors.primaryLight,
|
|
1723
|
+
padding: 16,
|
|
1724
|
+
borderRadius: 12,
|
|
1725
|
+
borderWidth: 1,
|
|
1726
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1727
|
+
gap: 4,
|
|
1728
|
+
}}>
|
|
1413
1729
|
{renderSettingRow({
|
|
1414
1730
|
icon: <TerminalIcon color={AppColors.purple} size={16}/>,
|
|
1415
1731
|
label: 'Auto-refresh Store',
|
|
1416
1732
|
description: 'Automatically capture Redux store state updates',
|
|
1417
1733
|
onPress: () => setReduxAutoRefreshState(prev => !prev),
|
|
1418
1734
|
right: (<View style={{
|
|
1419
|
-
width: 22,
|
|
1735
|
+
width: 22,
|
|
1736
|
+
height: 22,
|
|
1737
|
+
borderRadius: 6,
|
|
1420
1738
|
borderWidth: 2,
|
|
1421
|
-
borderColor: reduxAutoRefresh
|
|
1422
|
-
|
|
1423
|
-
|
|
1739
|
+
borderColor: reduxAutoRefresh
|
|
1740
|
+
? AppColors.purple
|
|
1741
|
+
: AppColors.grayTextWeak,
|
|
1742
|
+
backgroundColor: reduxAutoRefresh
|
|
1743
|
+
? 'rgba(104, 75, 155, 0.1)'
|
|
1744
|
+
: 'transparent',
|
|
1745
|
+
alignItems: 'center',
|
|
1746
|
+
justifyContent: 'center',
|
|
1424
1747
|
}}>
|
|
1425
|
-
{reduxAutoRefresh && <CheckIcon size={12} color={AppColors.purple}/>}
|
|
1748
|
+
{reduxAutoRefresh && (<CheckIcon size={12} color={AppColors.purple}/>)}
|
|
1426
1749
|
</View>),
|
|
1427
1750
|
})}
|
|
1428
1751
|
<View style={{ height: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
@@ -1439,18 +1762,40 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1439
1762
|
})}
|
|
1440
1763
|
</View>
|
|
1441
1764
|
|
|
1442
|
-
<View style={{
|
|
1765
|
+
<View style={{
|
|
1766
|
+
backgroundColor: AppColors.primaryLight,
|
|
1767
|
+
borderRadius: 12,
|
|
1768
|
+
borderWidth: 1,
|
|
1769
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1770
|
+
padding: 16,
|
|
1771
|
+
marginTop: 12,
|
|
1772
|
+
}}>
|
|
1443
1773
|
{renderSettingRow({
|
|
1444
1774
|
icon: <TrashIcon color={AppColors.errorColor} size={16}/>,
|
|
1445
1775
|
label: 'Clear Redux State',
|
|
1446
|
-
description: reduxState
|
|
1776
|
+
description: reduxState
|
|
1777
|
+
? 'Reset state snapshot in inspector'
|
|
1778
|
+
: 'No store snapshot stored',
|
|
1447
1779
|
isLast: true,
|
|
1448
1780
|
onPress: () => {
|
|
1449
1781
|
setReduxState(null);
|
|
1450
1782
|
Alert.alert('Success', 'Redux state snapshot cleared.');
|
|
1451
1783
|
},
|
|
1452
|
-
right: (<View style={{
|
|
1453
|
-
|
|
1784
|
+
right: (<View style={{
|
|
1785
|
+
paddingHorizontal: 10,
|
|
1786
|
+
paddingVertical: 5,
|
|
1787
|
+
borderRadius: 7,
|
|
1788
|
+
backgroundColor: 'rgba(255,46,87,0.08)',
|
|
1789
|
+
borderWidth: 1,
|
|
1790
|
+
borderColor: 'rgba(255,46,87,0.2)',
|
|
1791
|
+
}}>
|
|
1792
|
+
<Text style={{
|
|
1793
|
+
fontFamily: AppFonts.interBold,
|
|
1794
|
+
fontSize: 11,
|
|
1795
|
+
color: AppColors.errorColor,
|
|
1796
|
+
}}>
|
|
1797
|
+
Clear
|
|
1798
|
+
</Text>
|
|
1454
1799
|
</View>),
|
|
1455
1800
|
})}
|
|
1456
1801
|
</View>
|
|
@@ -1459,7 +1804,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1459
1804
|
// Default return page is Insights settings
|
|
1460
1805
|
return (<ScrollView style={{ flex: 1, backgroundColor: AppColors.grayBackground }} contentContainerStyle={{ padding: 16 }}>
|
|
1461
1806
|
{renderSubHeader('Insights Settings', <InsightsIcon color={AppColors.purple} size={16}/>)}
|
|
1462
|
-
<View style={{
|
|
1807
|
+
<View style={{
|
|
1808
|
+
backgroundColor: AppColors.primaryLight,
|
|
1809
|
+
padding: 16,
|
|
1810
|
+
borderRadius: 12,
|
|
1811
|
+
borderWidth: 1,
|
|
1812
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
1813
|
+
gap: 4,
|
|
1814
|
+
}}>
|
|
1463
1815
|
{renderSettingRow({
|
|
1464
1816
|
icon: <SignalIcon color={AppColors.purple} size={16}/>,
|
|
1465
1817
|
label: 'Slow Latency Warning',
|
|
@@ -1478,13 +1830,20 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1478
1830
|
isLast: true,
|
|
1479
1831
|
onPress: () => setInsightsShowConsoleAlerts(prev => !prev),
|
|
1480
1832
|
right: (<View style={{
|
|
1481
|
-
width: 22,
|
|
1833
|
+
width: 22,
|
|
1834
|
+
height: 22,
|
|
1835
|
+
borderRadius: 6,
|
|
1482
1836
|
borderWidth: 2,
|
|
1483
|
-
borderColor: insightsShowConsoleAlerts
|
|
1484
|
-
|
|
1485
|
-
|
|
1837
|
+
borderColor: insightsShowConsoleAlerts
|
|
1838
|
+
? AppColors.purple
|
|
1839
|
+
: AppColors.grayTextWeak,
|
|
1840
|
+
backgroundColor: insightsShowConsoleAlerts
|
|
1841
|
+
? 'rgba(104, 75, 155, 0.1)'
|
|
1842
|
+
: 'transparent',
|
|
1843
|
+
alignItems: 'center',
|
|
1844
|
+
justifyContent: 'center',
|
|
1486
1845
|
}}>
|
|
1487
|
-
{insightsShowConsoleAlerts && <CheckIcon size={12} color={AppColors.purple}/>}
|
|
1846
|
+
{insightsShowConsoleAlerts && (<CheckIcon size={12} color={AppColors.purple}/>)}
|
|
1488
1847
|
</View>),
|
|
1489
1848
|
})}
|
|
1490
1849
|
</View>
|
|
@@ -1492,10 +1851,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1492
1851
|
};
|
|
1493
1852
|
const renderInsightsDashboard = () => {
|
|
1494
1853
|
const apiTotal = logs.length;
|
|
1495
|
-
const apiErrors = logs.filter(l => (l.status != null && l.status >= 400) ||
|
|
1854
|
+
const apiErrors = logs.filter(l => (l.status != null && l.status >= 400) ||
|
|
1855
|
+
l.status === 0 ||
|
|
1856
|
+
l.status == null).length;
|
|
1496
1857
|
const apiSuccess = apiTotal - apiErrors;
|
|
1497
1858
|
const apiSuccessRate = apiTotal > 0 ? Math.round((apiSuccess / apiTotal) * 100) : 100;
|
|
1498
|
-
const durations = logs
|
|
1859
|
+
const durations = logs
|
|
1860
|
+
.filter(l => l.duration != null)
|
|
1861
|
+
.map(l => l.duration);
|
|
1499
1862
|
const avgTime = durations.length > 0
|
|
1500
1863
|
? Math.round(durations.reduce((a, b) => a + b, 0) / durations.length)
|
|
1501
1864
|
: null;
|
|
@@ -1505,11 +1868,13 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1505
1868
|
const logInfos = visibleConsoleLogs.filter(l => l.type === 'info').length;
|
|
1506
1869
|
const analyticsTotal = analyticsEvents.length;
|
|
1507
1870
|
const uniqueEvents = new Set(analyticsEvents.map(e => e.name)).size;
|
|
1508
|
-
const screenViews = analyticsEvents.filter(e => e.name === 'screen_view' ||
|
|
1871
|
+
const screenViews = analyticsEvents.filter(e => e.name === 'screen_view' ||
|
|
1872
|
+
e.name === 'page_view' ||
|
|
1873
|
+
e.name === 'firebase_screen_class').length;
|
|
1509
1874
|
const webviewTotal = webViewNavHistory.length;
|
|
1510
1875
|
return (<View style={styles.dashboardContainer}>
|
|
1511
1876
|
{/* Module 1: APIs */}
|
|
1512
|
-
{tabVisibility.apis && (<TouchableScale style={styles.dashboardModuleCard} onPress={() =>
|
|
1877
|
+
{tabVisibility.apis && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('apis')}>
|
|
1513
1878
|
<View style={styles.dashboardModuleHeader}>
|
|
1514
1879
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
1515
1880
|
<SignalIcon color={AppColors.purple} size={18}/>
|
|
@@ -1523,13 +1888,19 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1523
1888
|
<Text style={styles.dashboardGridLbl}>Requests</Text>
|
|
1524
1889
|
</View>
|
|
1525
1890
|
<View style={styles.dashboardGridItem}>
|
|
1526
|
-
<Text style={[
|
|
1891
|
+
<Text style={[
|
|
1892
|
+
styles.dashboardGridVal,
|
|
1893
|
+
apiSuccessRate < 90 && { color: AppColors.warningIconGold },
|
|
1894
|
+
]}>
|
|
1527
1895
|
{apiSuccessRate}%
|
|
1528
1896
|
</Text>
|
|
1529
1897
|
<Text style={styles.dashboardGridLbl}>Success Rate</Text>
|
|
1530
1898
|
</View>
|
|
1531
1899
|
<View style={styles.dashboardGridItem}>
|
|
1532
|
-
<Text style={[
|
|
1900
|
+
<Text style={[
|
|
1901
|
+
styles.dashboardGridVal,
|
|
1902
|
+
apiErrors > 0 && { color: AppColors.errorColor },
|
|
1903
|
+
]}>
|
|
1533
1904
|
{apiErrors}
|
|
1534
1905
|
</Text>
|
|
1535
1906
|
<Text style={styles.dashboardGridLbl}>Errors</Text>
|
|
@@ -1544,7 +1915,7 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1544
1915
|
</TouchableScale>)}
|
|
1545
1916
|
|
|
1546
1917
|
{/* Module 2: Logs */}
|
|
1547
|
-
{tabVisibility.logs && (<TouchableScale style={styles.dashboardModuleCard} onPress={() =>
|
|
1918
|
+
{tabVisibility.logs && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('logs')}>
|
|
1548
1919
|
<View style={styles.dashboardModuleHeader}>
|
|
1549
1920
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
1550
1921
|
<TerminalIcon color="#0D9488" size={18}/>
|
|
@@ -1558,17 +1929,25 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1558
1929
|
<Text style={styles.dashboardGridLbl}>Total Logs</Text>
|
|
1559
1930
|
</View>
|
|
1560
1931
|
<View style={styles.dashboardGridItem}>
|
|
1561
|
-
<Text style={[styles.dashboardGridVal, { color: '#0D9488' }]}>
|
|
1932
|
+
<Text style={[styles.dashboardGridVal, { color: '#0D9488' }]}>
|
|
1933
|
+
{logInfos}
|
|
1934
|
+
</Text>
|
|
1562
1935
|
<Text style={styles.dashboardGridLbl}>Info</Text>
|
|
1563
1936
|
</View>
|
|
1564
1937
|
<View style={styles.dashboardGridItem}>
|
|
1565
|
-
<Text style={[
|
|
1938
|
+
<Text style={[
|
|
1939
|
+
styles.dashboardGridVal,
|
|
1940
|
+
logWarns > 0 && { color: AppColors.warningIconGold },
|
|
1941
|
+
]}>
|
|
1566
1942
|
{logWarns}
|
|
1567
1943
|
</Text>
|
|
1568
1944
|
<Text style={styles.dashboardGridLbl}>Warnings</Text>
|
|
1569
1945
|
</View>
|
|
1570
1946
|
<View style={styles.dashboardGridItem}>
|
|
1571
|
-
<Text style={[
|
|
1947
|
+
<Text style={[
|
|
1948
|
+
styles.dashboardGridVal,
|
|
1949
|
+
logErrors > 0 && { color: AppColors.errorColor },
|
|
1950
|
+
]}>
|
|
1572
1951
|
{logErrors}
|
|
1573
1952
|
</Text>
|
|
1574
1953
|
<Text style={styles.dashboardGridLbl}>Errors</Text>
|
|
@@ -1577,11 +1956,13 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1577
1956
|
</TouchableScale>)}
|
|
1578
1957
|
|
|
1579
1958
|
{/* Module 3: Analytics */}
|
|
1580
|
-
{tabVisibility.analytics && (<TouchableScale style={styles.dashboardModuleCard} onPress={() =>
|
|
1959
|
+
{tabVisibility.analytics && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('analytics')}>
|
|
1581
1960
|
<View style={styles.dashboardModuleHeader}>
|
|
1582
1961
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
1583
1962
|
<AnalyticsIcon color="#EA580C" size={18}/>
|
|
1584
|
-
<Text style={styles.dashboardModuleTitle}>
|
|
1963
|
+
<Text style={styles.dashboardModuleTitle}>
|
|
1964
|
+
Analytics Events
|
|
1965
|
+
</Text>
|
|
1585
1966
|
</View>
|
|
1586
1967
|
<Text style={styles.dashboardModuleGoText}>View Details →</Text>
|
|
1587
1968
|
</View>
|
|
@@ -1591,7 +1972,9 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1591
1972
|
<Text style={styles.dashboardGridLbl}>Total Events</Text>
|
|
1592
1973
|
</View>
|
|
1593
1974
|
<View style={styles.dashboardGridItem}>
|
|
1594
|
-
<Text style={[styles.dashboardGridVal, { color: '#EA580C' }]}>
|
|
1975
|
+
<Text style={[styles.dashboardGridVal, { color: '#EA580C' }]}>
|
|
1976
|
+
{uniqueEvents}
|
|
1977
|
+
</Text>
|
|
1595
1978
|
<Text style={styles.dashboardGridLbl}>Unique Names</Text>
|
|
1596
1979
|
</View>
|
|
1597
1980
|
<View style={styles.dashboardGridItem}>
|
|
@@ -1600,7 +1983,9 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1600
1983
|
</View>
|
|
1601
1984
|
<View style={styles.dashboardGridItem}>
|
|
1602
1985
|
<Text style={styles.dashboardGridVal}>
|
|
1603
|
-
{analyticsTotal > 0
|
|
1986
|
+
{analyticsTotal > 0
|
|
1987
|
+
? Math.round(analyticsTotal / Math.max(1, logs.length / 5))
|
|
1988
|
+
: 0}
|
|
1604
1989
|
</Text>
|
|
1605
1990
|
<Text style={styles.dashboardGridLbl}>Events Ratio</Text>
|
|
1606
1991
|
</View>
|
|
@@ -1608,11 +1993,13 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1608
1993
|
</TouchableScale>)}
|
|
1609
1994
|
|
|
1610
1995
|
{/* Module 4: WebView */}
|
|
1611
|
-
{tabVisibility.webview && (<TouchableScale style={styles.dashboardModuleCard} onPress={() =>
|
|
1996
|
+
{tabVisibility.webview && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('webview')}>
|
|
1612
1997
|
<View style={styles.dashboardModuleHeader}>
|
|
1613
1998
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
1614
1999
|
<GlobeIcon color="#2563EB" size={18}/>
|
|
1615
|
-
<Text style={styles.dashboardModuleTitle}>
|
|
2000
|
+
<Text style={styles.dashboardModuleTitle}>
|
|
2001
|
+
WebView Captures
|
|
2002
|
+
</Text>
|
|
1616
2003
|
</View>
|
|
1617
2004
|
<Text style={styles.dashboardModuleGoText}>View Details →</Text>
|
|
1618
2005
|
</View>
|
|
@@ -1622,12 +2009,16 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1622
2009
|
<Text style={styles.dashboardGridLbl}>History Size</Text>
|
|
1623
2010
|
</View>
|
|
1624
2011
|
<View style={styles.dashboardGridItem}>
|
|
1625
|
-
<Text style={[styles.dashboardGridVal, { color: '#16A34A' }]}>
|
|
2012
|
+
<Text style={[styles.dashboardGridVal, { color: '#16A34A' }]}>
|
|
2013
|
+
Active
|
|
2014
|
+
</Text>
|
|
1626
2015
|
<Text style={styles.dashboardGridLbl}>Status</Text>
|
|
1627
2016
|
</View>
|
|
1628
2017
|
<View style={styles.dashboardGridItem}>
|
|
1629
2018
|
<Text numberOfLines={1} style={styles.dashboardGridVal}>
|
|
1630
|
-
{webviewTotal > 0
|
|
2019
|
+
{webviewTotal > 0
|
|
2020
|
+
? `${webViewNavHistory[0]?.title?.substring(0, 10) ?? ''}...`
|
|
2021
|
+
: '—'}
|
|
1631
2022
|
</Text>
|
|
1632
2023
|
<Text style={styles.dashboardGridLbl}>Last URL</Text>
|
|
1633
2024
|
</View>
|
|
@@ -1635,38 +2026,73 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1635
2026
|
</TouchableScale>)}
|
|
1636
2027
|
|
|
1637
2028
|
{/* Module 5: Redux Store */}
|
|
1638
|
-
{tabVisibility.redux && (<TouchableScale style={styles.dashboardModuleCard} onPress={() =>
|
|
2029
|
+
{tabVisibility.redux && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('redux')}>
|
|
1639
2030
|
<View style={styles.dashboardModuleHeader}>
|
|
1640
2031
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
1641
2032
|
<TerminalIcon color={AppColors.purple} size={18}/>
|
|
1642
|
-
<Text style={styles.dashboardModuleTitle}>
|
|
2033
|
+
<Text style={styles.dashboardModuleTitle}>
|
|
2034
|
+
Redux Store State
|
|
2035
|
+
</Text>
|
|
1643
2036
|
</View>
|
|
1644
2037
|
<Text style={styles.dashboardModuleGoText}>View Details →</Text>
|
|
1645
2038
|
</View>
|
|
1646
2039
|
{reduxState ? (<View style={{ paddingHorizontal: 12, paddingBottom: 12, gap: 6 }}>
|
|
1647
|
-
<View style={{
|
|
1648
|
-
|
|
2040
|
+
<View style={{
|
|
2041
|
+
flexDirection: 'row',
|
|
2042
|
+
justifyContent: 'space-between',
|
|
2043
|
+
marginBottom: 4,
|
|
2044
|
+
}}>
|
|
2045
|
+
<Text style={{
|
|
2046
|
+
fontFamily: AppFonts.interBold,
|
|
2047
|
+
fontSize: 10,
|
|
2048
|
+
color: AppColors.grayTextWeak,
|
|
2049
|
+
letterSpacing: 0.5,
|
|
2050
|
+
}}>
|
|
1649
2051
|
REDUCER NAME
|
|
1650
2052
|
</Text>
|
|
1651
|
-
<Text style={{
|
|
2053
|
+
<Text style={{
|
|
2054
|
+
fontFamily: AppFonts.interBold,
|
|
2055
|
+
fontSize: 10,
|
|
2056
|
+
color: AppColors.grayTextWeak,
|
|
2057
|
+
letterSpacing: 0.5,
|
|
2058
|
+
}}>
|
|
1652
2059
|
SIZE / FIELDS
|
|
1653
2060
|
</Text>
|
|
1654
2061
|
</View>
|
|
1655
2062
|
{Object.keys(reduxState).map(key => {
|
|
1656
2063
|
const val = reduxState[key];
|
|
1657
|
-
const fieldsCount = typeof val === 'object' && val !== null
|
|
2064
|
+
const fieldsCount = typeof val === 'object' && val !== null
|
|
2065
|
+
? Object.keys(val).length
|
|
2066
|
+
: 0;
|
|
1658
2067
|
const sizeStr = getSize(val);
|
|
1659
|
-
return (<View key={key} style={{
|
|
1660
|
-
|
|
2068
|
+
return (<View key={key} style={{
|
|
2069
|
+
flexDirection: 'row',
|
|
2070
|
+
justifyContent: 'space-between',
|
|
2071
|
+
alignItems: 'center',
|
|
2072
|
+
paddingVertical: 2,
|
|
2073
|
+
}}>
|
|
2074
|
+
<Text style={{
|
|
2075
|
+
fontFamily: AppFonts.interMedium,
|
|
2076
|
+
fontSize: 12,
|
|
2077
|
+
color: AppColors.grayTextStrong,
|
|
2078
|
+
}}>
|
|
1661
2079
|
{key}
|
|
1662
2080
|
</Text>
|
|
1663
|
-
<Text style={{
|
|
2081
|
+
<Text style={{
|
|
2082
|
+
fontFamily: AppFonts.interRegular,
|
|
2083
|
+
fontSize: 11,
|
|
2084
|
+
color: AppColors.grayTextWeak,
|
|
2085
|
+
}}>
|
|
1664
2086
|
{sizeStr} ({fieldsCount} fields)
|
|
1665
2087
|
</Text>
|
|
1666
2088
|
</View>);
|
|
1667
2089
|
})}
|
|
1668
2090
|
</View>) : (<View style={{ padding: 12, alignItems: 'center' }}>
|
|
1669
|
-
<Text style={{
|
|
2091
|
+
<Text style={{
|
|
2092
|
+
fontFamily: AppFonts.interRegular,
|
|
2093
|
+
fontSize: 12,
|
|
2094
|
+
color: AppColors.grayTextWeak,
|
|
2095
|
+
}}>
|
|
1670
2096
|
No connected Redux store.
|
|
1671
2097
|
</Text>
|
|
1672
2098
|
</View>)}
|
|
@@ -1721,10 +2147,19 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1721
2147
|
<TerminalIcon color={AppColors.purple} size={20}/>
|
|
1722
2148
|
</View>
|
|
1723
2149
|
<View style={{ flex: 1 }}>
|
|
1724
|
-
<Text style={{
|
|
2150
|
+
<Text style={{
|
|
2151
|
+
fontFamily: AppFonts.interBold,
|
|
2152
|
+
fontSize: 13,
|
|
2153
|
+
color: AppColors.primaryBlack,
|
|
2154
|
+
}}>
|
|
1725
2155
|
Redux Store Snapshot
|
|
1726
2156
|
</Text>
|
|
1727
|
-
<Text style={{
|
|
2157
|
+
<Text style={{
|
|
2158
|
+
fontFamily: AppFonts.interRegular,
|
|
2159
|
+
fontSize: 11,
|
|
2160
|
+
color: AppColors.grayText,
|
|
2161
|
+
marginTop: 2,
|
|
2162
|
+
}}>
|
|
1728
2163
|
Total size: {getSize(reduxState)} • {reducerKeys.length} Reducers
|
|
1729
2164
|
</Text>
|
|
1730
2165
|
</View>
|
|
@@ -1742,23 +2177,33 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1742
2177
|
borderWidth: 1,
|
|
1743
2178
|
borderColor: AppColors.dividerColor,
|
|
1744
2179
|
}}>
|
|
1745
|
-
<TouchableOpacity onPress={() =>
|
|
2180
|
+
<TouchableOpacity onPress={() => {
|
|
2181
|
+
animateNextLayout();
|
|
2182
|
+
setReduxActiveSubTab('timeline');
|
|
2183
|
+
}} style={{
|
|
1746
2184
|
flex: 1,
|
|
1747
2185
|
paddingVertical: 6,
|
|
1748
2186
|
alignItems: 'center',
|
|
1749
2187
|
justifyContent: 'center',
|
|
1750
2188
|
borderRadius: 8,
|
|
1751
|
-
backgroundColor: reduxActiveSubTab === 'timeline'
|
|
2189
|
+
backgroundColor: reduxActiveSubTab === 'timeline'
|
|
2190
|
+
? AppColors.purple
|
|
2191
|
+
: 'transparent',
|
|
1752
2192
|
}}>
|
|
1753
2193
|
<Text style={{
|
|
1754
2194
|
fontFamily: AppFonts.interBold,
|
|
1755
2195
|
fontSize: 11,
|
|
1756
|
-
color: reduxActiveSubTab === 'timeline'
|
|
2196
|
+
color: reduxActiveSubTab === 'timeline'
|
|
2197
|
+
? '#FFFFFF'
|
|
2198
|
+
: AppColors.grayText,
|
|
1757
2199
|
}}>
|
|
1758
2200
|
⚡ Action Timeline
|
|
1759
2201
|
</Text>
|
|
1760
2202
|
</TouchableOpacity>
|
|
1761
|
-
<TouchableOpacity onPress={() =>
|
|
2203
|
+
<TouchableOpacity onPress={() => {
|
|
2204
|
+
animateNextLayout();
|
|
2205
|
+
setReduxActiveSubTab('tree');
|
|
2206
|
+
}} style={{
|
|
1762
2207
|
flex: 1,
|
|
1763
2208
|
paddingVertical: 6,
|
|
1764
2209
|
alignItems: 'center',
|
|
@@ -1789,7 +2234,9 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1789
2234
|
borderColor: AppColors.dividerColor,
|
|
1790
2235
|
height: 36,
|
|
1791
2236
|
}}>
|
|
1792
|
-
<TextInput placeholder={reduxActiveSubTab === 'timeline'
|
|
2237
|
+
<TextInput placeholder={reduxActiveSubTab === 'timeline'
|
|
2238
|
+
? 'Search actions or payloads...'
|
|
2239
|
+
: 'Search Redux keys or values...'} placeholderTextColor={AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
|
|
1793
2240
|
flex: 1,
|
|
1794
2241
|
fontFamily: AppFonts.interRegular,
|
|
1795
2242
|
fontSize: 12,
|
|
@@ -1835,23 +2282,24 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1835
2282
|
<Modal visible={visible} animationType="slide" transparent>
|
|
1836
2283
|
{visible && (<ErrorBoundary onClose={closeModal}>
|
|
1837
2284
|
<View style={styles.modalBackdrop}>
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
2285
|
+
<Pressable style={styles.modalBackdropPressable} onPress={closeModal}/>
|
|
2286
|
+
<View style={styles.modalContentCard}>
|
|
2287
|
+
<StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
|
|
1841
2288
|
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
2289
|
+
<LinearGradient colors={[AppColors.purple, '#6B4EFF']} style={styles.headerGradient}>
|
|
2290
|
+
<View style={styles.header}>
|
|
2291
|
+
<View style={[
|
|
1845
2292
|
styles.headerLeft,
|
|
1846
2293
|
{
|
|
1847
2294
|
flexDirection: 'row',
|
|
1848
2295
|
alignItems: 'center',
|
|
1849
2296
|
gap: 16,
|
|
1850
|
-
flex:
|
|
2297
|
+
flex: selected == null && selectedEvent == null ? 5 : 1,
|
|
1851
2298
|
},
|
|
1852
2299
|
]}>
|
|
1853
|
-
|
|
2300
|
+
<TouchableScale onPress={() => {
|
|
1854
2301
|
requestAnimationFrame(() => {
|
|
2302
|
+
animateNextLayout();
|
|
1855
2303
|
setSelected(null);
|
|
1856
2304
|
setSelectedEvent(null);
|
|
1857
2305
|
});
|
|
@@ -1860,14 +2308,19 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1860
2308
|
selected == null &&
|
|
1861
2309
|
selectedEvent == null && { display: 'none' },
|
|
1862
2310
|
]}>
|
|
1863
|
-
|
|
1864
|
-
|
|
2311
|
+
<WhiteBackNavigation />
|
|
2312
|
+
</TouchableScale>
|
|
1865
2313
|
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
2314
|
+
{selected == null && selectedEvent == null ? (<View style={{
|
|
2315
|
+
flexDirection: 'row',
|
|
2316
|
+
alignItems: 'center',
|
|
2317
|
+
gap: 14,
|
|
2318
|
+
flex: 1,
|
|
2319
|
+
}}>
|
|
2320
|
+
<View style={{
|
|
2321
|
+
width: 42,
|
|
2322
|
+
height: 42,
|
|
2323
|
+
borderRadius: 10,
|
|
1871
2324
|
backgroundColor: 'rgba(255,255,255,0.13)',
|
|
1872
2325
|
borderWidth: 1.5,
|
|
1873
2326
|
borderColor: 'rgba(255,255,255,0.25)',
|
|
@@ -1878,56 +2331,80 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1878
2331
|
shadowRadius: 4,
|
|
1879
2332
|
shadowOffset: { width: 0, height: 2 },
|
|
1880
2333
|
}}>
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2334
|
+
<BrandSquareIcon size={36}/>
|
|
2335
|
+
</View>
|
|
2336
|
+
<View style={{ gap: 3 }}>
|
|
2337
|
+
<Text style={[
|
|
2338
|
+
styles.headerTitle,
|
|
2339
|
+
{ fontSize: 17, letterSpacing: 0.2 },
|
|
2340
|
+
]}>
|
|
2341
|
+
RN InApp Inspector
|
|
1889
2342
|
</Text>
|
|
2343
|
+
<View style={{
|
|
2344
|
+
flexDirection: 'row',
|
|
2345
|
+
alignItems: 'center',
|
|
2346
|
+
gap: 5,
|
|
2347
|
+
}}>
|
|
2348
|
+
<Animated.View style={{
|
|
2349
|
+
width: 6,
|
|
2350
|
+
height: 6,
|
|
2351
|
+
borderRadius: 3,
|
|
2352
|
+
backgroundColor: '#4ADE80',
|
|
2353
|
+
opacity: activePulseAnim,
|
|
2354
|
+
}}/>
|
|
2355
|
+
<Text style={{
|
|
2356
|
+
fontFamily: AppFonts.interMedium,
|
|
2357
|
+
fontSize: 10,
|
|
2358
|
+
color: 'rgba(255,255,255,0.78)',
|
|
2359
|
+
letterSpacing: 0.3,
|
|
2360
|
+
}}>
|
|
2361
|
+
Active •{' '}
|
|
2362
|
+
{Platform.OS === 'ios' ? 'iOS' : 'Android'}{' '}
|
|
2363
|
+
(v1.0.13)
|
|
2364
|
+
</Text>
|
|
2365
|
+
</View>
|
|
1890
2366
|
</View>
|
|
1891
|
-
</View>
|
|
1892
|
-
|
|
1893
|
-
</View>
|
|
2367
|
+
</View>) : null}
|
|
2368
|
+
</View>
|
|
1894
2369
|
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
2370
|
+
<View style={styles.headerCenter}>
|
|
2371
|
+
{selected != null ? (<View style={styles.headerDetailCenter}>
|
|
2372
|
+
<View style={styles.headerDetailRow}>
|
|
2373
|
+
<View style={[
|
|
1899
2374
|
styles.headerMethodBadge,
|
|
1900
2375
|
{
|
|
1901
2376
|
backgroundColor: METHOD_COLORS[selected.method] ??
|
|
1902
2377
|
AppColors.grayText,
|
|
1903
2378
|
},
|
|
1904
2379
|
]}>
|
|
1905
|
-
|
|
1906
|
-
|
|
2380
|
+
<Text style={styles.headerMethodText}>
|
|
2381
|
+
{selected.method}
|
|
2382
|
+
</Text>
|
|
2383
|
+
</View>
|
|
2384
|
+
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
2385
|
+
{detailTitle}
|
|
1907
2386
|
</Text>
|
|
1908
2387
|
</View>
|
|
1909
|
-
<
|
|
1910
|
-
{
|
|
1911
|
-
</Text>
|
|
1912
|
-
</View>
|
|
1913
|
-
<View style={styles.headerDetailSubRow}>
|
|
1914
|
-
<View style={[
|
|
2388
|
+
<View style={styles.headerDetailSubRow}>
|
|
2389
|
+
<View style={[
|
|
1915
2390
|
styles.headerStatusDot,
|
|
1916
|
-
{
|
|
2391
|
+
{
|
|
2392
|
+
backgroundColor: getStatusColor(selected.status),
|
|
2393
|
+
},
|
|
1917
2394
|
]}/>
|
|
1918
|
-
|
|
1919
|
-
|
|
2395
|
+
<Text style={styles.headerSubTitle}>
|
|
2396
|
+
{selected.status === 0
|
|
1920
2397
|
? 'Failed'
|
|
1921
2398
|
: selected.status ?? 'Pending'}{' '}
|
|
1922
|
-
|
|
1923
|
-
|
|
2399
|
+
•{' '}
|
|
2400
|
+
{selected.duration != null
|
|
1924
2401
|
? `${selected.duration}ms`
|
|
1925
2402
|
: '-'}
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
2403
|
+
</Text>
|
|
2404
|
+
</View>
|
|
2405
|
+
</View>) : selectedEvent != null ? (<View style={styles.headerDetailCenter}>
|
|
2406
|
+
<View style={styles.headerDetailRow}>
|
|
2407
|
+
<View style={[
|
|
1931
2408
|
styles.headerMethodBadge,
|
|
1932
2409
|
{
|
|
1933
2410
|
backgroundColor: selectedEvent.source === 'firebase'
|
|
@@ -1935,16 +2412,18 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1935
2412
|
: 'rgba(124,92,191,0.3)',
|
|
1936
2413
|
},
|
|
1937
2414
|
]}>
|
|
1938
|
-
|
|
1939
|
-
|
|
2415
|
+
<Text style={styles.headerMethodText}>
|
|
2416
|
+
{selectedEvent.source === 'firebase'
|
|
2417
|
+
? 'FB'
|
|
2418
|
+
: 'MAN'}
|
|
2419
|
+
</Text>
|
|
2420
|
+
</View>
|
|
2421
|
+
<Text style={styles.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
|
|
2422
|
+
{selectedEvent.name}
|
|
1940
2423
|
</Text>
|
|
1941
2424
|
</View>
|
|
1942
|
-
<
|
|
1943
|
-
{
|
|
1944
|
-
</Text>
|
|
1945
|
-
</View>
|
|
1946
|
-
<View style={styles.headerDetailSubRow}>
|
|
1947
|
-
<View style={[
|
|
2425
|
+
<View style={styles.headerDetailSubRow}>
|
|
2426
|
+
<View style={[
|
|
1948
2427
|
styles.headerStatusDot,
|
|
1949
2428
|
{
|
|
1950
2429
|
backgroundColor: selectedEvent.source === 'firebase'
|
|
@@ -1952,68 +2431,119 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
1952
2431
|
: AppColors.purple,
|
|
1953
2432
|
},
|
|
1954
2433
|
]}/>
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2434
|
+
<Text style={styles.headerSubTitle}>
|
|
2435
|
+
{Object.keys(selectedEvent.params).length} param
|
|
2436
|
+
{Object.keys(selectedEvent.params).length !== 1
|
|
1958
2437
|
? 's'
|
|
1959
2438
|
: ''}
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2439
|
+
{' · '}
|
|
2440
|
+
{selectedEvent.source}
|
|
2441
|
+
</Text>
|
|
2442
|
+
</View>
|
|
2443
|
+
</View>) : null}
|
|
2444
|
+
</View>
|
|
1966
2445
|
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2446
|
+
<View style={styles.headerRight}>
|
|
2447
|
+
{selected == null && selectedEvent == null && (<TouchableScale onPress={() => setSettingsPage('main')} hitSlop={15} style={[
|
|
2448
|
+
styles.closeButtonSquare,
|
|
2449
|
+
{
|
|
2450
|
+
marginRight: 8,
|
|
2451
|
+
backgroundColor: 'rgba(255,255,255,0.15)',
|
|
2452
|
+
},
|
|
2453
|
+
]}>
|
|
2454
|
+
<SettingsIcon color="#FFFFFF" size={16}/>
|
|
2455
|
+
</TouchableScale>)}
|
|
1971
2456
|
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
2457
|
+
<TouchableScale onPress={closeModal} hitSlop={15} style={styles.closeButtonSquare}>
|
|
2458
|
+
<CloseWhite size={16}/>
|
|
2459
|
+
</TouchableScale>
|
|
2460
|
+
</View>
|
|
1975
2461
|
</View>
|
|
1976
|
-
</
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
{
|
|
1983
|
-
|
|
1984
|
-
{
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2462
|
+
</LinearGradient>
|
|
2463
|
+
|
|
2464
|
+
{/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
|
|
2465
|
+
{selected == null &&
|
|
2466
|
+
selectedEvent == null &&
|
|
2467
|
+
settingsPage === null ? (<View style={styles.tabBarContainer}>
|
|
2468
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ paddingRight: 16 }}>
|
|
2469
|
+
{[
|
|
2470
|
+
{
|
|
2471
|
+
key: 'insights',
|
|
2472
|
+
label: 'Insights',
|
|
2473
|
+
count: 0,
|
|
2474
|
+
icon: 'insights',
|
|
2475
|
+
},
|
|
2476
|
+
{
|
|
2477
|
+
key: 'apis',
|
|
2478
|
+
label: 'APIs',
|
|
2479
|
+
count: logs.length,
|
|
2480
|
+
icon: 'apis',
|
|
2481
|
+
},
|
|
2482
|
+
{
|
|
2483
|
+
key: 'logs',
|
|
2484
|
+
label: 'Logs',
|
|
2485
|
+
count: consoleLogs.length,
|
|
2486
|
+
icon: 'logs',
|
|
2487
|
+
},
|
|
2488
|
+
{
|
|
2489
|
+
key: 'analytics',
|
|
2490
|
+
label: 'Analytics',
|
|
2491
|
+
count: analyticsEvents.length,
|
|
2492
|
+
icon: 'analytics',
|
|
2493
|
+
},
|
|
2494
|
+
{
|
|
2495
|
+
key: 'webview',
|
|
2496
|
+
label: 'WebView',
|
|
2497
|
+
count: webViewNavHistory.length,
|
|
2498
|
+
icon: 'webview',
|
|
2499
|
+
},
|
|
2500
|
+
{
|
|
2501
|
+
key: 'redux',
|
|
2502
|
+
label: 'Redux',
|
|
2503
|
+
count: 0,
|
|
2504
|
+
icon: 'redux',
|
|
2505
|
+
},
|
|
2506
|
+
]
|
|
2507
|
+
.filter(tab => tabVisibility[tab.key])
|
|
2508
|
+
.map(tab => {
|
|
1990
2509
|
const isActive = activeTab === tab.key;
|
|
1991
|
-
const iconColor = isActive
|
|
2510
|
+
const iconColor = isActive
|
|
2511
|
+
? '#FFFFFF'
|
|
2512
|
+
: AppColors.grayText;
|
|
1992
2513
|
const countLabel = tab.count > 9 ? '9+' : String(tab.count);
|
|
1993
|
-
const hasUnreadApis = activeTab !== 'apis' &&
|
|
1994
|
-
|
|
2514
|
+
const hasUnreadApis = activeTab !== 'apis' &&
|
|
2515
|
+
logs.length > lastReadApisCount;
|
|
2516
|
+
const hasUnreadLogs = activeTab !== 'logs' &&
|
|
2517
|
+
consoleLogs.length > lastReadLogsCount;
|
|
1995
2518
|
return (<TouchableScale key={tab.key} onPress={() => {
|
|
1996
2519
|
requestAnimationFrame(() => {
|
|
1997
|
-
|
|
2520
|
+
switchActiveTab(tab.key);
|
|
1998
2521
|
});
|
|
1999
2522
|
}} style={[
|
|
2000
2523
|
styles.contentTabButton,
|
|
2001
2524
|
isActive && styles.contentTabButtonActive,
|
|
2002
2525
|
]}>
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2526
|
+
<View style={{
|
|
2527
|
+
flexDirection: 'row',
|
|
2528
|
+
alignItems: 'center',
|
|
2529
|
+
gap: 6,
|
|
2530
|
+
}}>
|
|
2531
|
+
{tab.icon === 'insights' && (<InsightsIcon color={iconColor} size={14}/>)}
|
|
2532
|
+
{tab.icon === 'apis' && (<SignalIcon color={iconColor} size={14}/>)}
|
|
2533
|
+
{tab.icon === 'logs' && (<TerminalIcon color={iconColor} size={14}/>)}
|
|
2534
|
+
{tab.icon === 'analytics' && (<AnalyticsIcon color={iconColor} size={14}/>)}
|
|
2535
|
+
{tab.icon === 'webview' && (<GlobeIcon color={iconColor} size={14}/>)}
|
|
2536
|
+
{tab.icon === 'redux' && (<TerminalIcon color={iconColor} size={14}/>)}
|
|
2537
|
+
<Text numberOfLines={1} ellipsizeMode="tail" style={[
|
|
2011
2538
|
styles.contentTabButtonText,
|
|
2012
|
-
isActive &&
|
|
2539
|
+
isActive &&
|
|
2540
|
+
styles.contentTabButtonTextActive,
|
|
2013
2541
|
]}>
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2542
|
+
{tab.label}{' '}
|
|
2543
|
+
{tab.count > 0 ? `(${countLabel})` : ''}
|
|
2544
|
+
</Text>
|
|
2545
|
+
{((tab.key === 'apis' && hasUnreadApis) ||
|
|
2546
|
+
(tab.key === 'logs' && hasUnreadLogs)) && (<Animated.View style={{
|
|
2017
2547
|
width: 6,
|
|
2018
2548
|
height: 6,
|
|
2019
2549
|
borderRadius: 3,
|
|
@@ -2022,42 +2552,45 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2022
2552
|
alignSelf: 'center',
|
|
2023
2553
|
transform: [{ scale: unreadPulseAnim }],
|
|
2024
2554
|
}}/>)}
|
|
2025
|
-
|
|
2026
|
-
|
|
2555
|
+
</View>
|
|
2556
|
+
</TouchableScale>);
|
|
2027
2557
|
})}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2558
|
+
</ScrollView>
|
|
2559
|
+
</View>) : null}
|
|
2032
2560
|
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
{
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2561
|
+
{/* ─── Secondary Tab Bar for Analytics ──────────────────────── */}
|
|
2562
|
+
{isReady &&
|
|
2563
|
+
activeTab === 'analytics' &&
|
|
2564
|
+
selectedEvent == null && (<View>
|
|
2565
|
+
{/* ─── Search + Shared Toolbar for Analytics ──────────────────────── */}
|
|
2566
|
+
<View style={[
|
|
2567
|
+
styles.toolbarRow,
|
|
2568
|
+
{ marginTop: 12, marginBottom: 4 },
|
|
2569
|
+
]}>
|
|
2570
|
+
<View style={styles.searchContainer}>
|
|
2571
|
+
<SearchIcon color={AppColors.grayTextWeak} size={16}/>
|
|
2572
|
+
<TextInput placeholder="Search events..." placeholderTextColor={AppColors.grayTextWeak} value={analyticsSearch} onChangeText={setAnalyticsSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
2573
|
+
{analyticsSearch.length > 0 && (<Pressable onPress={() => setAnalyticsSearch('')} hitSlop={10} style={styles.clearBtn}>
|
|
2574
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
2575
|
+
</Pressable>)}
|
|
2576
|
+
</View>
|
|
2577
|
+
{analyticsSubTab === 'ga_events' && (<View style={styles.toolbarRight}>
|
|
2578
|
+
<TouchableScale style={[
|
|
2046
2579
|
styles.toolbarBtn,
|
|
2047
2580
|
!hideScreenView && styles.toolbarBtnActive,
|
|
2048
2581
|
]} onPress={() => setHideScreenView(prev => !prev)} hitSlop={10}>
|
|
2049
|
-
|
|
2582
|
+
<ScreenIcon color={!hideScreenView
|
|
2050
2583
|
? AppColors.purple
|
|
2051
2584
|
: AppColors.grayTextStrong} size={18}/>
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2585
|
+
</TouchableScale>
|
|
2586
|
+
<TouchableScale style={styles.toolbarBtn} onPress={handleDelete} hitSlop={10}>
|
|
2587
|
+
<TrashIcon color={AppColors.grayTextStrong} size={18}/>
|
|
2588
|
+
</TouchableScale>
|
|
2589
|
+
</View>)}
|
|
2590
|
+
</View>
|
|
2058
2591
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2592
|
+
{/* ─── Secondary Tab Bar for Analytics ──────────────────────── */}
|
|
2593
|
+
<View style={{
|
|
2061
2594
|
marginHorizontal: 16,
|
|
2062
2595
|
marginTop: 4,
|
|
2063
2596
|
marginBottom: 8,
|
|
@@ -2068,7 +2601,7 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2068
2601
|
borderWidth: 1,
|
|
2069
2602
|
borderColor: AppColors.grayBorderSecondary,
|
|
2070
2603
|
}}>
|
|
2071
|
-
|
|
2604
|
+
<Pressable style={[
|
|
2072
2605
|
{
|
|
2073
2606
|
flex: 1,
|
|
2074
2607
|
paddingVertical: 8,
|
|
@@ -2083,8 +2616,11 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2083
2616
|
shadowOffset: { width: 0, height: 1 },
|
|
2084
2617
|
elevation: 2,
|
|
2085
2618
|
},
|
|
2086
|
-
]} onPress={() =>
|
|
2087
|
-
|
|
2619
|
+
]} onPress={() => {
|
|
2620
|
+
animateNextLayout();
|
|
2621
|
+
setAnalyticsSubTab('ga_events');
|
|
2622
|
+
}}>
|
|
2623
|
+
<Text style={[
|
|
2088
2624
|
{
|
|
2089
2625
|
fontFamily: AppFonts.interMedium,
|
|
2090
2626
|
fontSize: 13,
|
|
@@ -2095,14 +2631,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2095
2631
|
color: AppColors.purple,
|
|
2096
2632
|
},
|
|
2097
2633
|
]}>
|
|
2098
|
-
|
|
2099
|
-
|
|
2634
|
+
GA Events (
|
|
2635
|
+
{analyticsSearch
|
|
2100
2636
|
? filteredAnalyticsEvents.length
|
|
2101
2637
|
: analyticsEvents.length}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2638
|
+
)
|
|
2639
|
+
</Text>
|
|
2640
|
+
</Pressable>
|
|
2641
|
+
<Pressable style={[
|
|
2106
2642
|
{
|
|
2107
2643
|
flex: 1,
|
|
2108
2644
|
paddingVertical: 8,
|
|
@@ -2117,8 +2653,11 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2117
2653
|
shadowOffset: { width: 0, height: 1 },
|
|
2118
2654
|
elevation: 2,
|
|
2119
2655
|
},
|
|
2120
|
-
]} onPress={() =>
|
|
2121
|
-
|
|
2656
|
+
]} onPress={() => {
|
|
2657
|
+
animateNextLayout();
|
|
2658
|
+
setAnalyticsSubTab('top_events');
|
|
2659
|
+
}}>
|
|
2660
|
+
<Text style={[
|
|
2122
2661
|
{
|
|
2123
2662
|
fontFamily: AppFonts.interMedium,
|
|
2124
2663
|
fontSize: 13,
|
|
@@ -2129,63 +2668,63 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2129
2668
|
color: AppColors.purple,
|
|
2130
2669
|
},
|
|
2131
2670
|
]}>
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2671
|
+
Top Events ({topEventsArray.length})
|
|
2672
|
+
</Text>
|
|
2673
|
+
</Pressable>
|
|
2674
|
+
</View>
|
|
2675
|
+
</View>)}
|
|
2137
2676
|
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2677
|
+
{isReady ? (activeTab === 'insights' ? (<ScrollView style={styles.insightsContainer} contentContainerStyle={styles.insightsContent} showsVerticalScrollIndicator={false}>
|
|
2678
|
+
{renderInsightsDashboard()}
|
|
2679
|
+
</ScrollView>) : activeTab === 'analytics' ? (selectedEvent != null ? (<AnalyticsDetail event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
|
|
2141
2680
|
styles.listContent,
|
|
2142
2681
|
{ paddingHorizontal: 16, paddingTop: 16 },
|
|
2143
|
-
]} renderItem={({ item: [name, count] }) => {
|
|
2682
|
+
]} renderItem={({ item: [name, count], index }) => {
|
|
2144
2683
|
const maxCount = topEventsArray[0]?.[1] || 1;
|
|
2145
2684
|
const color = getEventColor(name);
|
|
2146
|
-
return (<
|
|
2685
|
+
return (<AnimatedEntrance index={index} distance={8} style={[
|
|
2147
2686
|
styles.analyticsTopEventsCard,
|
|
2148
2687
|
{ marginBottom: 12, paddingVertical: 16 },
|
|
2149
2688
|
]}>
|
|
2150
|
-
|
|
2151
|
-
|
|
2689
|
+
<View style={styles.analyticsTopEventRow}>
|
|
2690
|
+
<View style={{
|
|
2152
2691
|
flexDirection: 'row',
|
|
2153
2692
|
alignItems: 'center',
|
|
2154
2693
|
gap: 8,
|
|
2155
2694
|
flex: 1,
|
|
2156
2695
|
}}>
|
|
2157
|
-
|
|
2696
|
+
<View style={[
|
|
2158
2697
|
styles.analyticsIconCircle,
|
|
2159
2698
|
{ backgroundColor: `${color}1A` },
|
|
2160
2699
|
]}>
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2700
|
+
<Svg width={14} height={14} viewBox="0 0 24 24" fill={color}>
|
|
2701
|
+
<Circle cx="12" cy="12" r="10" opacity="0.3"/>
|
|
2702
|
+
<Path d="M7 14l3-3 4 4 6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
|
2703
|
+
</Svg>
|
|
2704
|
+
</View>
|
|
2705
|
+
<Text style={styles.analyticsTopEventName} numberOfLines={2}>
|
|
2706
|
+
{name}
|
|
2707
|
+
</Text>
|
|
2708
|
+
</View>
|
|
2709
|
+
<View style={styles.analyticsTopEventBarWrap}>
|
|
2710
|
+
<LinearGradient colors={[color, `${color}99`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={[
|
|
2172
2711
|
styles.analyticsTopEventBar,
|
|
2173
2712
|
{
|
|
2174
2713
|
width: `${Math.max(6, (count / maxCount) * 100)}%`,
|
|
2175
2714
|
},
|
|
2176
2715
|
]}/>
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2716
|
+
</View>
|
|
2717
|
+
<Text style={styles.analyticsTopEventCount}>
|
|
2718
|
+
{count}
|
|
2719
|
+
</Text>
|
|
2720
|
+
</View>
|
|
2721
|
+
</AnimatedEntrance>);
|
|
2183
2722
|
}} ListEmptyComponent={<View style={styles.emptyContainer}>
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2723
|
+
<View style={styles.emptyIconWrap}>
|
|
2724
|
+
<EmptyRadarIcon color={AppColors.purple} size={32}/>
|
|
2725
|
+
</View>
|
|
2726
|
+
<Text style={styles.emptyTitle}>No Top Events</Text>
|
|
2727
|
+
</View>}/>) : (<FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
|
|
2189
2728
|
const prev = filteredAnalyticsEvents[index + 1];
|
|
2190
2729
|
const next = filteredAnalyticsEvents[index - 1];
|
|
2191
2730
|
const msSincePrev = prev
|
|
@@ -2196,7 +2735,11 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2196
2735
|
? Math.floor(next.timestamp / 60000)
|
|
2197
2736
|
: -1;
|
|
2198
2737
|
const showTimestamp = index === 0 || thisMin !== nextMin;
|
|
2199
|
-
return (<
|
|
2738
|
+
return (<AnimatedEntrance index={index} distance={8}>
|
|
2739
|
+
<AnalyticsEventCard event={item} onPress={() => {
|
|
2740
|
+
animateNextLayout();
|
|
2741
|
+
setSelectedEvent(item);
|
|
2742
|
+
}} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === filteredAnalyticsEvents.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={(() => {
|
|
2200
2743
|
let screenName = item.screenName ||
|
|
2201
2744
|
item.screenClass ||
|
|
2202
2745
|
item.pageTitle ||
|
|
@@ -2214,69 +2757,71 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2214
2757
|
}
|
|
2215
2758
|
}
|
|
2216
2759
|
return screenName;
|
|
2217
|
-
})()}/>
|
|
2760
|
+
})()}/>
|
|
2761
|
+
</AnimatedEntrance>);
|
|
2218
2762
|
}} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListEmptyComponent={<View style={styles.emptyContainer}>
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2763
|
+
<View style={styles.emptyIconWrap}>
|
|
2764
|
+
<EmptyRadarIcon color={AppColors.purple} size={32}/>
|
|
2765
|
+
</View>
|
|
2766
|
+
<Text style={styles.emptyTitle}>
|
|
2767
|
+
{analyticsSearch.length > 0
|
|
2224
2768
|
? 'No matching events'
|
|
2225
2769
|
: 'No analytics events yet'}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2770
|
+
</Text>
|
|
2771
|
+
<Text style={styles.emptySub}>
|
|
2772
|
+
{analyticsSearch.length > 0
|
|
2229
2773
|
? 'Try adjusting your search.'
|
|
2230
2774
|
: 'Call setupAnalyticsLogger(analytics()) at app start.'}
|
|
2231
|
-
|
|
2232
|
-
|
|
2775
|
+
</Text>
|
|
2776
|
+
</View>} contentContainerStyle={[
|
|
2233
2777
|
styles.listContent,
|
|
2234
|
-
filteredAnalyticsEvents.length === 0 && {
|
|
2778
|
+
filteredAnalyticsEvents.length === 0 && {
|
|
2779
|
+
flexGrow: 1,
|
|
2780
|
+
},
|
|
2235
2781
|
]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'apis' && selected == null ? (<FlatList data={groupedData} keyExtractor={item => item?.id?.toString()} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<View style={{ marginTop: 8 }}>
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
<View style={styles.toolbarRight}>
|
|
2246
|
-
<TouchableScale style={styles.toolbarBtn} onPress={handleDelete} hitSlop={10}>
|
|
2247
|
-
<TrashIcon color={AppColors.grayTextStrong} size={18}/>
|
|
2248
|
-
{selectedLogs.size > 0 && (<View style={styles.trashBadge}>
|
|
2249
|
-
<Text style={styles.trashBadgeText}>
|
|
2250
|
-
{selectedLogs.size}
|
|
2251
|
-
</Text>
|
|
2252
|
-
</View>)}
|
|
2253
|
-
</TouchableScale>
|
|
2782
|
+
<View style={styles.toolbarRow}>
|
|
2783
|
+
<View style={styles.searchContainer}>
|
|
2784
|
+
<SearchIcon color={AppColors.grayTextWeak} size={16}/>
|
|
2785
|
+
<TextInput placeholder="Search endpoints..." placeholderTextColor={AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
2786
|
+
{search.length > 0 && (<Pressable onPress={() => setSearch('')} hitSlop={10} style={styles.clearBtn}>
|
|
2787
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
2788
|
+
</Pressable>)}
|
|
2789
|
+
</View>
|
|
2254
2790
|
|
|
2791
|
+
<View style={styles.toolbarRight}>
|
|
2792
|
+
<TouchableScale style={styles.toolbarBtn} onPress={handleDelete} hitSlop={10}>
|
|
2793
|
+
<TrashIcon color={AppColors.grayTextStrong} size={18}/>
|
|
2794
|
+
{selectedLogs.size > 0 && (<View style={styles.trashBadge}>
|
|
2795
|
+
<Text style={styles.trashBadgeText}>
|
|
2796
|
+
{selectedLogs.size}
|
|
2797
|
+
</Text>
|
|
2798
|
+
</View>)}
|
|
2799
|
+
</TouchableScale>
|
|
2255
2800
|
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2801
|
+
<TouchableScale style={styles.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
|
|
2802
|
+
<SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors.grayTextStrong} size={18}/>
|
|
2803
|
+
</TouchableScale>
|
|
2259
2804
|
|
|
2260
|
-
|
|
2805
|
+
<TouchableScale style={[
|
|
2261
2806
|
styles.toolbarBtn,
|
|
2262
2807
|
filtersAccordion.isOpen &&
|
|
2263
2808
|
styles.toolbarBtnActive,
|
|
2264
2809
|
]} onPress={filtersAccordion.toggleOpen} hitSlop={10}>
|
|
2265
|
-
|
|
2810
|
+
<FilterIcon color={filtersAccordion.isOpen
|
|
2266
2811
|
? AppColors.purple
|
|
2267
2812
|
: AppColors.grayTextStrong} size={18}/>
|
|
2268
|
-
|
|
2813
|
+
</TouchableScale>
|
|
2814
|
+
</View>
|
|
2269
2815
|
</View>
|
|
2270
|
-
</View>
|
|
2271
2816
|
|
|
2272
|
-
|
|
2817
|
+
<Animated.View style={[
|
|
2273
2818
|
filtersAccordion.bodyStyle,
|
|
2274
2819
|
{ overflow: 'hidden' },
|
|
2275
2820
|
]}>
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2821
|
+
<View style={styles.filtersContainer}>
|
|
2822
|
+
<Text style={styles.filtersHeading}>STATUS</Text>
|
|
2823
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.statusRowContent}>
|
|
2824
|
+
{STATUS_FILTERS.map(filter => {
|
|
2280
2825
|
const isAll = filter === 'ALL';
|
|
2281
2826
|
const active = isAll
|
|
2282
2827
|
? statusFilters.size === 0
|
|
@@ -2295,35 +2840,38 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2295
2840
|
});
|
|
2296
2841
|
}
|
|
2297
2842
|
}} hitSlop={10}>
|
|
2298
|
-
|
|
2843
|
+
{active ? (<View style={[
|
|
2299
2844
|
styles.statusFilterChip,
|
|
2300
2845
|
styles.statusFilterActive,
|
|
2301
2846
|
{ overflow: 'hidden' },
|
|
2302
2847
|
]}>
|
|
2303
|
-
|
|
2848
|
+
<LinearGradient colors={[
|
|
2304
2849
|
AppColors.purpleShade50,
|
|
2305
2850
|
'#EAE5FF',
|
|
2306
2851
|
]} style={StyleSheet.absoluteFill} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}/>
|
|
2307
|
-
|
|
2852
|
+
<Text style={[
|
|
2308
2853
|
styles.statusFilterText,
|
|
2309
2854
|
{ color: AppColors.purple },
|
|
2310
2855
|
]}>
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2856
|
+
{filter}
|
|
2857
|
+
</Text>
|
|
2858
|
+
</View>) : (<View style={styles.statusFilterChip}>
|
|
2859
|
+
<Text style={styles.statusFilterText}>
|
|
2860
|
+
{filter}
|
|
2861
|
+
</Text>
|
|
2862
|
+
</View>)}
|
|
2863
|
+
</TouchableScale>);
|
|
2319
2864
|
})}
|
|
2320
|
-
|
|
2865
|
+
</ScrollView>
|
|
2321
2866
|
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2867
|
+
<Text style={[
|
|
2868
|
+
styles.filtersHeading,
|
|
2869
|
+
{ marginTop: 16 },
|
|
2870
|
+
]}>
|
|
2871
|
+
METHOD
|
|
2872
|
+
</Text>
|
|
2873
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.statusRowContent}>
|
|
2874
|
+
{availableMethods.map(filter => {
|
|
2327
2875
|
const isAll = filter === 'ALL';
|
|
2328
2876
|
const active = isAll
|
|
2329
2877
|
? methodFilters.size === 0
|
|
@@ -2342,101 +2890,101 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2342
2890
|
});
|
|
2343
2891
|
}
|
|
2344
2892
|
}} hitSlop={10}>
|
|
2345
|
-
|
|
2893
|
+
{active ? (<View style={[
|
|
2346
2894
|
styles.statusFilterChip,
|
|
2347
2895
|
styles.statusFilterActive,
|
|
2348
2896
|
{ overflow: 'hidden' },
|
|
2349
2897
|
]}>
|
|
2350
|
-
|
|
2898
|
+
<LinearGradient colors={[
|
|
2351
2899
|
AppColors.purpleShade50,
|
|
2352
2900
|
'#EAE5FF',
|
|
2353
2901
|
]} style={StyleSheet.absoluteFill} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}/>
|
|
2354
|
-
|
|
2902
|
+
<Text style={[
|
|
2355
2903
|
styles.statusFilterText,
|
|
2356
2904
|
{ color: AppColors.purple },
|
|
2357
2905
|
]}>
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2906
|
+
{filter}
|
|
2907
|
+
</Text>
|
|
2908
|
+
</View>) : (<View style={styles.statusFilterChip}>
|
|
2909
|
+
<Text style={styles.statusFilterText}>
|
|
2910
|
+
{filter}
|
|
2911
|
+
</Text>
|
|
2912
|
+
</View>)}
|
|
2913
|
+
</TouchableScale>);
|
|
2366
2914
|
})}
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2915
|
+
</ScrollView>
|
|
2916
|
+
</View>
|
|
2917
|
+
</Animated.View>
|
|
2370
2918
|
|
|
2371
|
-
|
|
2919
|
+
{(search ||
|
|
2372
2920
|
statusFilters.size > 0 ||
|
|
2373
2921
|
methodFilters.size > 0) && (<Text style={styles.resultCount}>
|
|
2374
|
-
|
|
2922
|
+
{filteredLogs.length === logs.length
|
|
2375
2923
|
? `${logs.length} requests`
|
|
2376
2924
|
: `${filteredLogs.length} of ${logs.length} filtered requests`}
|
|
2377
|
-
|
|
2378
|
-
|
|
2925
|
+
</Text>)}
|
|
2926
|
+
</View>} ListEmptyComponent={<EmptyState isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
|
|
2379
2927
|
styles.listContent,
|
|
2380
2928
|
filteredLogs.length === 0 && { flexGrow: 1 },
|
|
2381
2929
|
]} keyboardShouldPersistTaps="handled"/>) : activeTab === 'logs' ? (<View style={{ flex: 1 }}>
|
|
2382
|
-
|
|
2930
|
+
<View style={{
|
|
2383
2931
|
backgroundColor: '#FFFFFF',
|
|
2384
2932
|
borderBottomWidth: 1,
|
|
2385
2933
|
borderBottomColor: AppColors.dividerColor,
|
|
2386
2934
|
paddingBottom: 6,
|
|
2387
2935
|
}}>
|
|
2388
|
-
|
|
2936
|
+
<View style={[
|
|
2389
2937
|
styles.toolbarRow,
|
|
2390
2938
|
{ marginTop: 12, marginBottom: 8 },
|
|
2391
2939
|
]}>
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2940
|
+
<View style={styles.searchContainer}>
|
|
2941
|
+
<SearchIcon color={AppColors.grayTextWeak} size={16}/>
|
|
2942
|
+
<TextInput placeholder="Search logs..." placeholderTextColor={AppColors.grayTextWeak} value={logSearch} onChangeText={setLogSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
2943
|
+
{logSearch.length > 0 && (<Pressable onPress={() => setLogSearch('')} hitSlop={10} style={styles.clearBtn}>
|
|
2944
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
2945
|
+
</Pressable>)}
|
|
2946
|
+
</View>
|
|
2399
2947
|
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2948
|
+
<View style={styles.toolbarRight}>
|
|
2949
|
+
<TouchableScale style={styles.toolbarBtn} onPress={handleDelete} hitSlop={10}>
|
|
2950
|
+
<TrashIcon color={AppColors.grayTextStrong} size={18}/>
|
|
2951
|
+
</TouchableScale>
|
|
2952
|
+
</View>
|
|
2953
|
+
</View>
|
|
2406
2954
|
|
|
2407
|
-
|
|
2955
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginVertical: 4, maxHeight: 46 }} contentContainerStyle={{
|
|
2408
2956
|
paddingHorizontal: 16,
|
|
2409
2957
|
paddingBottom: 4,
|
|
2410
2958
|
flexDirection: 'row',
|
|
2411
2959
|
alignItems: 'center',
|
|
2412
2960
|
gap: 8,
|
|
2413
2961
|
}}>
|
|
2414
|
-
|
|
2962
|
+
{(() => {
|
|
2415
2963
|
const active = logFilters.has('all');
|
|
2416
2964
|
return (<TouchableScale onPress={() => {
|
|
2417
2965
|
setLogFilters(new Set(['all']));
|
|
2418
2966
|
}}>
|
|
2419
|
-
|
|
2967
|
+
<View style={[
|
|
2420
2968
|
styles.statusFilterChip,
|
|
2421
2969
|
active && {
|
|
2422
2970
|
borderColor: AppColors.purpleShade700,
|
|
2423
2971
|
backgroundColor: '#F4EBFF',
|
|
2424
2972
|
},
|
|
2425
2973
|
]}>
|
|
2426
|
-
|
|
2974
|
+
<Text numberOfLines={1} style={[
|
|
2427
2975
|
styles.statusFilterText,
|
|
2428
2976
|
active && {
|
|
2429
2977
|
color: AppColors.purpleShade700,
|
|
2430
2978
|
fontFamily: AppFonts.interBold,
|
|
2431
2979
|
},
|
|
2432
2980
|
]}>
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2981
|
+
All ({logCounts.all})
|
|
2982
|
+
</Text>
|
|
2983
|
+
</View>
|
|
2984
|
+
</TouchableScale>);
|
|
2437
2985
|
})()}
|
|
2438
2986
|
|
|
2439
|
-
|
|
2987
|
+
{(() => {
|
|
2440
2988
|
const active = logFilters.has('user-log');
|
|
2441
2989
|
return (<TouchableScale onPress={() => {
|
|
2442
2990
|
setLogFilters(prev => {
|
|
@@ -2450,27 +2998,27 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2450
2998
|
return next;
|
|
2451
2999
|
});
|
|
2452
3000
|
}}>
|
|
2453
|
-
|
|
3001
|
+
<View style={[
|
|
2454
3002
|
styles.statusFilterChip,
|
|
2455
3003
|
active && {
|
|
2456
3004
|
borderColor: '#64748B',
|
|
2457
3005
|
backgroundColor: '#F1F5F9',
|
|
2458
3006
|
},
|
|
2459
3007
|
]}>
|
|
2460
|
-
|
|
3008
|
+
<Text numberOfLines={1} style={[
|
|
2461
3009
|
styles.statusFilterText,
|
|
2462
3010
|
active && {
|
|
2463
3011
|
color: '#334155',
|
|
2464
3012
|
fontFamily: AppFonts.interBold,
|
|
2465
3013
|
},
|
|
2466
3014
|
]}>
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
3015
|
+
User Log ({logCounts['user-log']})
|
|
3016
|
+
</Text>
|
|
3017
|
+
</View>
|
|
3018
|
+
</TouchableScale>);
|
|
2471
3019
|
})()}
|
|
2472
3020
|
|
|
2473
|
-
|
|
3021
|
+
{(() => {
|
|
2474
3022
|
const active = logFilters.has('info');
|
|
2475
3023
|
return (<TouchableScale onPress={() => {
|
|
2476
3024
|
setLogFilters(prev => {
|
|
@@ -2484,27 +3032,27 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2484
3032
|
return next;
|
|
2485
3033
|
});
|
|
2486
3034
|
}}>
|
|
2487
|
-
|
|
3035
|
+
<View style={[
|
|
2488
3036
|
styles.statusFilterChip,
|
|
2489
3037
|
active && {
|
|
2490
3038
|
borderColor: AppColors.purple,
|
|
2491
3039
|
backgroundColor: AppColors.purpleShade50,
|
|
2492
3040
|
},
|
|
2493
3041
|
]}>
|
|
2494
|
-
|
|
3042
|
+
<Text numberOfLines={1} style={[
|
|
2495
3043
|
styles.statusFilterText,
|
|
2496
3044
|
active && {
|
|
2497
3045
|
color: AppColors.purple,
|
|
2498
3046
|
fontFamily: AppFonts.interBold,
|
|
2499
3047
|
},
|
|
2500
3048
|
]}>
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
3049
|
+
Info ({logCounts.info})
|
|
3050
|
+
</Text>
|
|
3051
|
+
</View>
|
|
3052
|
+
</TouchableScale>);
|
|
2505
3053
|
})()}
|
|
2506
3054
|
|
|
2507
|
-
|
|
3055
|
+
{(() => {
|
|
2508
3056
|
const active = logFilters.has('warn');
|
|
2509
3057
|
return (<TouchableScale onPress={() => {
|
|
2510
3058
|
setLogFilters(prev => {
|
|
@@ -2518,14 +3066,14 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2518
3066
|
return next;
|
|
2519
3067
|
});
|
|
2520
3068
|
}}>
|
|
2521
|
-
|
|
3069
|
+
<View style={[
|
|
2522
3070
|
styles.statusFilterChip,
|
|
2523
3071
|
active && {
|
|
2524
3072
|
borderColor: AppColors.lightOrange,
|
|
2525
3073
|
backgroundColor: '#FFFDF6',
|
|
2526
3074
|
},
|
|
2527
3075
|
]}>
|
|
2528
|
-
|
|
3076
|
+
<Text numberOfLines={1} style={[
|
|
2529
3077
|
styles.statusFilterText,
|
|
2530
3078
|
active && {
|
|
2531
3079
|
color: AppColors.darkOrange ||
|
|
@@ -2533,13 +3081,13 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2533
3081
|
fontFamily: AppFonts.interBold,
|
|
2534
3082
|
},
|
|
2535
3083
|
]}>
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
3084
|
+
Warning ({logCounts.warn})
|
|
3085
|
+
</Text>
|
|
3086
|
+
</View>
|
|
3087
|
+
</TouchableScale>);
|
|
2540
3088
|
})()}
|
|
2541
3089
|
|
|
2542
|
-
|
|
3090
|
+
{(() => {
|
|
2543
3091
|
const active = logFilters.has('error');
|
|
2544
3092
|
return (<TouchableScale onPress={() => {
|
|
2545
3093
|
setLogFilters(prev => {
|
|
@@ -2553,27 +3101,27 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2553
3101
|
return next;
|
|
2554
3102
|
});
|
|
2555
3103
|
}}>
|
|
2556
|
-
|
|
3104
|
+
<View style={[
|
|
2557
3105
|
styles.statusFilterChip,
|
|
2558
3106
|
active && {
|
|
2559
3107
|
borderColor: AppColors.errorColor,
|
|
2560
3108
|
backgroundColor: '#FFF5F6',
|
|
2561
3109
|
},
|
|
2562
3110
|
]}>
|
|
2563
|
-
|
|
3111
|
+
<Text numberOfLines={1} style={[
|
|
2564
3112
|
styles.statusFilterText,
|
|
2565
3113
|
active && {
|
|
2566
3114
|
color: AppColors.errorColor,
|
|
2567
3115
|
fontFamily: AppFonts.interBold,
|
|
2568
3116
|
},
|
|
2569
3117
|
]}>
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
3118
|
+
Error ({logCounts.error})
|
|
3119
|
+
</Text>
|
|
3120
|
+
</View>
|
|
3121
|
+
</TouchableScale>);
|
|
2574
3122
|
})()}
|
|
2575
3123
|
|
|
2576
|
-
|
|
3124
|
+
{(() => {
|
|
2577
3125
|
const active = logFilters.has('analytics');
|
|
2578
3126
|
return (<TouchableScale onPress={() => {
|
|
2579
3127
|
setLogFilters(prev => {
|
|
@@ -2587,29 +3135,29 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2587
3135
|
return next;
|
|
2588
3136
|
});
|
|
2589
3137
|
}}>
|
|
2590
|
-
|
|
3138
|
+
<View style={[
|
|
2591
3139
|
styles.statusFilterChip,
|
|
2592
3140
|
active && {
|
|
2593
3141
|
borderColor: AppColors.skyBlue,
|
|
2594
3142
|
backgroundColor: `${AppColors.skyBlue}15`,
|
|
2595
3143
|
},
|
|
2596
3144
|
]}>
|
|
2597
|
-
|
|
3145
|
+
<Text numberOfLines={1} style={[
|
|
2598
3146
|
styles.statusFilterText,
|
|
2599
3147
|
active && {
|
|
2600
3148
|
color: AppColors.skyBlue,
|
|
2601
3149
|
fontFamily: AppFonts.interBold,
|
|
2602
3150
|
},
|
|
2603
3151
|
]}>
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
3152
|
+
Analytics ({logCounts.analytics})
|
|
3153
|
+
</Text>
|
|
3154
|
+
</View>
|
|
3155
|
+
</TouchableScale>);
|
|
2608
3156
|
})()}
|
|
2609
|
-
|
|
2610
|
-
|
|
3157
|
+
</ScrollView>
|
|
3158
|
+
</View>
|
|
2611
3159
|
|
|
2612
|
-
|
|
3160
|
+
<FlatList data={filteredConsoleLogs} keyExtractor={item => item.id.toString()} ListHeaderComponent={(() => {
|
|
2613
3161
|
const total = visibleConsoleLogs.length;
|
|
2614
3162
|
const filtered = filteredConsoleLogs.length;
|
|
2615
3163
|
const isAllSelected = logFilters.has('all') ||
|
|
@@ -2619,8 +3167,8 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2619
3167
|
styles.resultCount,
|
|
2620
3168
|
{ marginBottom: 4, marginTop: 12 },
|
|
2621
3169
|
]}>
|
|
2622
|
-
|
|
2623
|
-
|
|
3170
|
+
Showing ({filtered}/{total}) logs showing
|
|
3171
|
+
</Text>);
|
|
2624
3172
|
}
|
|
2625
3173
|
else {
|
|
2626
3174
|
const activeFilterNames = Array.from(logFilters)
|
|
@@ -2630,31 +3178,37 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2630
3178
|
return 'User Log';
|
|
2631
3179
|
if (f === 'analytics')
|
|
2632
3180
|
return 'Analytics';
|
|
2633
|
-
return f.charAt(0).toUpperCase() +
|
|
3181
|
+
return (f.charAt(0).toUpperCase() +
|
|
3182
|
+
f.slice(1));
|
|
2634
3183
|
});
|
|
2635
3184
|
return (<Text style={[
|
|
2636
3185
|
styles.resultCount,
|
|
2637
3186
|
{ marginBottom: 4, marginTop: 12 },
|
|
2638
3187
|
]}>
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
3188
|
+
Filtering with {activeFilterNames.join(', ')} (
|
|
3189
|
+
{filtered}/{total}) logs is showing
|
|
3190
|
+
</Text>);
|
|
2642
3191
|
}
|
|
2643
|
-
})()} renderItem={({ item }) => (<
|
|
3192
|
+
})()} renderItem={({ item, index }) => (<AnimatedEntrance index={index} distance={8}>
|
|
3193
|
+
<ConsoleLogCard item={item} searchStr={logSearch}/>
|
|
3194
|
+
</AnimatedEntrance>)} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState isSearch={logSearch.length > 0 || logFilters.size > 0}/>} contentContainerStyle={[
|
|
2644
3195
|
styles.listContent,
|
|
2645
3196
|
filteredConsoleLogs.length === 0 && { flexGrow: 1 },
|
|
2646
3197
|
]} keyboardShouldPersistTaps="handled"/>
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
3198
|
+
</View>) : activeTab === 'webview' ? (webViewNavHistory.length === 0 ? (<View style={styles.emptyContainer}>
|
|
3199
|
+
<View style={styles.emptyIconWrap}>
|
|
3200
|
+
<GlobeIcon color={AppColors.purple} size={32}/>
|
|
3201
|
+
</View>
|
|
3202
|
+
<Text style={styles.emptyTitle}>
|
|
3203
|
+
No WebView Activity
|
|
3204
|
+
</Text>
|
|
3205
|
+
<Text style={styles.emptySub}>
|
|
3206
|
+
Load a webpage within a connected WebView component to
|
|
3207
|
+
inspect pages, page source, and console logs.
|
|
3208
|
+
</Text>
|
|
3209
|
+
</View>) : (<View style={{ flex: 1 }}>
|
|
3210
|
+
{/* ─── Current Page Address Bar (Now on top) ─── */}
|
|
3211
|
+
{(() => {
|
|
2658
3212
|
const currentUrl = webViewNavHistory[0]?.url;
|
|
2659
3213
|
if (!currentUrl)
|
|
2660
3214
|
return null;
|
|
@@ -2666,7 +3220,7 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2666
3220
|
borderBottomWidth: 1,
|
|
2667
3221
|
borderBottomColor: AppColors.dividerColor,
|
|
2668
3222
|
}}>
|
|
2669
|
-
|
|
3223
|
+
<View style={{
|
|
2670
3224
|
flexDirection: 'row',
|
|
2671
3225
|
alignItems: 'center',
|
|
2672
3226
|
backgroundColor: AppColors.grayBackground,
|
|
@@ -2677,27 +3231,42 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2677
3231
|
paddingVertical: 5,
|
|
2678
3232
|
gap: 8,
|
|
2679
3233
|
}}>
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
3234
|
+
{/* Left: Lock and HTTPS label */}
|
|
3235
|
+
<View style={{
|
|
3236
|
+
flexDirection: 'row',
|
|
3237
|
+
alignItems: 'center',
|
|
3238
|
+
gap: 4,
|
|
3239
|
+
}}>
|
|
3240
|
+
<Text style={{ fontSize: 11 }}>🔒</Text>
|
|
3241
|
+
<Text style={{
|
|
3242
|
+
fontFamily: AppFonts.interBold,
|
|
3243
|
+
fontSize: 9.5,
|
|
3244
|
+
color: AppColors.greenColor,
|
|
3245
|
+
letterSpacing: 0.5,
|
|
3246
|
+
}}>
|
|
3247
|
+
HTTPS
|
|
3248
|
+
</Text>
|
|
3249
|
+
</View>
|
|
3250
|
+
<View style={{
|
|
3251
|
+
width: 1.5,
|
|
3252
|
+
height: 12,
|
|
3253
|
+
backgroundColor: AppColors.grayBorderSecondary,
|
|
3254
|
+
}}/>
|
|
2686
3255
|
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
3256
|
+
{/* Middle: URL text (Address style) */}
|
|
3257
|
+
<View style={{ flex: 1 }}>
|
|
3258
|
+
<HighlightText text={currentUrl} search={webViewSearch} numberOfLines={1} ellipsizeMode="tail" style={{
|
|
2690
3259
|
fontFamily: AppFonts.interMedium,
|
|
2691
3260
|
fontSize: 11.5,
|
|
2692
3261
|
color: AppColors.primaryBlack,
|
|
2693
3262
|
}} highlightStyle={styles.highlight} detectLinks={false}/>
|
|
2694
|
-
|
|
3263
|
+
</View>
|
|
2695
3264
|
|
|
2696
|
-
|
|
2697
|
-
|
|
3265
|
+
{/* Right: Copy Button */}
|
|
3266
|
+
<CopyButton value={currentUrl} label="URL"/>
|
|
2698
3267
|
|
|
2699
|
-
|
|
2700
|
-
|
|
3268
|
+
{/* Right: Globe Icon button to open browser */}
|
|
3269
|
+
<TouchableScale onPress={() => Linking.openURL(currentUrl)} hitSlop={8} style={{
|
|
2701
3270
|
width: 26,
|
|
2702
3271
|
height: 26,
|
|
2703
3272
|
borderRadius: 13,
|
|
@@ -2707,26 +3276,26 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2707
3276
|
alignItems: 'center',
|
|
2708
3277
|
justifyContent: 'center',
|
|
2709
3278
|
}}>
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
3279
|
+
<GlobeIcon size={11} color={AppColors.purple}/>
|
|
3280
|
+
</TouchableScale>
|
|
3281
|
+
</View>
|
|
3282
|
+
</View>);
|
|
2714
3283
|
})()}
|
|
2715
3284
|
|
|
2716
|
-
|
|
2717
|
-
|
|
3285
|
+
{/* ─── WebView Sub-Tabs (Now below Address Bar) ─── */}
|
|
3286
|
+
<View style={{
|
|
2718
3287
|
backgroundColor: AppColors.primaryLight,
|
|
2719
3288
|
borderBottomWidth: 1,
|
|
2720
3289
|
borderBottomColor: AppColors.dividerColor,
|
|
2721
3290
|
paddingVertical: 6,
|
|
2722
3291
|
}}>
|
|
2723
|
-
|
|
3292
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
|
|
2724
3293
|
paddingHorizontal: 12,
|
|
2725
3294
|
flexDirection: 'row',
|
|
2726
3295
|
gap: 8,
|
|
2727
3296
|
}}>
|
|
2728
|
-
|
|
2729
|
-
|
|
3297
|
+
{/* Sub-tab 1: Preview */}
|
|
3298
|
+
<Pressable style={[
|
|
2730
3299
|
{
|
|
2731
3300
|
paddingVertical: 6,
|
|
2732
3301
|
paddingHorizontal: 14,
|
|
@@ -2742,19 +3311,28 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2742
3311
|
backgroundColor: AppColors.purple,
|
|
2743
3312
|
borderColor: AppColors.purple,
|
|
2744
3313
|
},
|
|
2745
|
-
]} onPress={() =>
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
3314
|
+
]} onPress={() => {
|
|
3315
|
+
animateNextLayout();
|
|
3316
|
+
setWebViewSubTab('preview');
|
|
3317
|
+
}}>
|
|
3318
|
+
<EyeIcon color={webViewSubTab === 'preview'
|
|
3319
|
+
? '#FFFFFF'
|
|
3320
|
+
: AppColors.grayTextWeak} size={13}/>
|
|
3321
|
+
<Text style={{
|
|
3322
|
+
fontFamily: webViewSubTab === 'preview'
|
|
3323
|
+
? AppFonts.interBold
|
|
3324
|
+
: AppFonts.interMedium,
|
|
2749
3325
|
fontSize: 12,
|
|
2750
|
-
color: webViewSubTab === 'preview'
|
|
3326
|
+
color: webViewSubTab === 'preview'
|
|
3327
|
+
? '#FFFFFF'
|
|
3328
|
+
: AppColors.grayTextStrong,
|
|
2751
3329
|
}}>
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
3330
|
+
Preview
|
|
3331
|
+
</Text>
|
|
3332
|
+
</Pressable>
|
|
2755
3333
|
|
|
2756
|
-
|
|
2757
|
-
|
|
3334
|
+
{/* Sub-tab 2: Page Source */}
|
|
3335
|
+
<Pressable style={[
|
|
2758
3336
|
{
|
|
2759
3337
|
paddingVertical: 6,
|
|
2760
3338
|
paddingHorizontal: 14,
|
|
@@ -2770,19 +3348,28 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2770
3348
|
backgroundColor: AppColors.purple,
|
|
2771
3349
|
borderColor: AppColors.purple,
|
|
2772
3350
|
},
|
|
2773
|
-
]} onPress={() =>
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
3351
|
+
]} onPress={() => {
|
|
3352
|
+
animateNextLayout();
|
|
3353
|
+
setWebViewSubTab('html');
|
|
3354
|
+
}}>
|
|
3355
|
+
<HtmlIcon color={webViewSubTab === 'html'
|
|
3356
|
+
? '#FFFFFF'
|
|
3357
|
+
: AppColors.grayTextWeak} size={13}/>
|
|
3358
|
+
<Text style={{
|
|
3359
|
+
fontFamily: webViewSubTab === 'html'
|
|
3360
|
+
? AppFonts.interBold
|
|
3361
|
+
: AppFonts.interMedium,
|
|
2777
3362
|
fontSize: 12,
|
|
2778
|
-
color: webViewSubTab === 'html'
|
|
3363
|
+
color: webViewSubTab === 'html'
|
|
3364
|
+
? '#FFFFFF'
|
|
3365
|
+
: AppColors.grayTextStrong,
|
|
2779
3366
|
}}>
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
3367
|
+
Page Source
|
|
3368
|
+
</Text>
|
|
3369
|
+
</Pressable>
|
|
2783
3370
|
|
|
2784
|
-
|
|
2785
|
-
|
|
3371
|
+
{/* Sub-tab 3: History */}
|
|
3372
|
+
<Pressable style={[
|
|
2786
3373
|
{
|
|
2787
3374
|
paddingVertical: 6,
|
|
2788
3375
|
paddingHorizontal: 14,
|
|
@@ -2798,19 +3385,28 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2798
3385
|
backgroundColor: AppColors.purple,
|
|
2799
3386
|
borderColor: AppColors.purple,
|
|
2800
3387
|
},
|
|
2801
|
-
]} onPress={() =>
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
3388
|
+
]} onPress={() => {
|
|
3389
|
+
animateNextLayout();
|
|
3390
|
+
setWebViewSubTab('navigation');
|
|
3391
|
+
}}>
|
|
3392
|
+
<ClockIcon color={webViewSubTab === 'navigation'
|
|
3393
|
+
? '#FFFFFF'
|
|
3394
|
+
: AppColors.grayTextWeak} size={13}/>
|
|
3395
|
+
<Text style={{
|
|
3396
|
+
fontFamily: webViewSubTab === 'navigation'
|
|
3397
|
+
? AppFonts.interBold
|
|
3398
|
+
: AppFonts.interMedium,
|
|
2805
3399
|
fontSize: 12,
|
|
2806
|
-
color: webViewSubTab === 'navigation'
|
|
3400
|
+
color: webViewSubTab === 'navigation'
|
|
3401
|
+
? '#FFFFFF'
|
|
3402
|
+
: AppColors.grayTextStrong,
|
|
2807
3403
|
}}>
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
3404
|
+
History ({webViewNavHistory.length})
|
|
3405
|
+
</Text>
|
|
3406
|
+
</Pressable>
|
|
2811
3407
|
|
|
2812
|
-
|
|
2813
|
-
|
|
3408
|
+
{/* Sub-tab 4: Console */}
|
|
3409
|
+
<Pressable style={[
|
|
2814
3410
|
{
|
|
2815
3411
|
paddingVertical: 6,
|
|
2816
3412
|
paddingHorizontal: 14,
|
|
@@ -2826,23 +3422,32 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2826
3422
|
backgroundColor: AppColors.purple,
|
|
2827
3423
|
borderColor: AppColors.purple,
|
|
2828
3424
|
},
|
|
2829
|
-
]} onPress={() =>
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
3425
|
+
]} onPress={() => {
|
|
3426
|
+
animateNextLayout();
|
|
3427
|
+
setWebViewSubTab('console');
|
|
3428
|
+
}}>
|
|
3429
|
+
<TerminalIcon color={webViewSubTab === 'console'
|
|
3430
|
+
? '#FFFFFF'
|
|
3431
|
+
: AppColors.grayTextWeak} size={13}/>
|
|
3432
|
+
<Text style={{
|
|
3433
|
+
fontFamily: webViewSubTab === 'console'
|
|
3434
|
+
? AppFonts.interBold
|
|
3435
|
+
: AppFonts.interMedium,
|
|
2833
3436
|
fontSize: 12,
|
|
2834
|
-
color: webViewSubTab === 'console'
|
|
3437
|
+
color: webViewSubTab === 'console'
|
|
3438
|
+
? '#FFFFFF'
|
|
3439
|
+
: AppColors.grayTextStrong,
|
|
2835
3440
|
}}>
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
3441
|
+
Console ({webViewLogs.length})
|
|
3442
|
+
</Text>
|
|
3443
|
+
</Pressable>
|
|
3444
|
+
</ScrollView>
|
|
3445
|
+
</View>
|
|
2841
3446
|
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
3447
|
+
{webViewSubTab === 'html' ? (<View style={{ flex: 1 }}>
|
|
3448
|
+
{webViewHtml || webViewCss || webViewJs ? (<View style={{ flex: 1 }}>
|
|
3449
|
+
{/* Clear Inspect Banner */}
|
|
3450
|
+
{inspectedElement && (<View style={{
|
|
2846
3451
|
flexDirection: 'row',
|
|
2847
3452
|
alignItems: 'center',
|
|
2848
3453
|
justifyContent: 'space-between',
|
|
@@ -2852,36 +3457,44 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2852
3457
|
borderBottomWidth: 1,
|
|
2853
3458
|
borderBottomColor: AppColors.dividerColor,
|
|
2854
3459
|
}}>
|
|
2855
|
-
|
|
3460
|
+
<Text style={{
|
|
2856
3461
|
fontFamily: AppFonts.interMedium,
|
|
2857
3462
|
fontSize: 11.5,
|
|
2858
3463
|
color: AppColors.purple,
|
|
2859
3464
|
flex: 1,
|
|
2860
3465
|
}}>
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
3466
|
+
Inspecting element:{' '}
|
|
3467
|
+
<Text style={{
|
|
3468
|
+
fontFamily: AppFonts.interBold,
|
|
3469
|
+
}}>
|
|
3470
|
+
<{inspectedElement.tagName}
|
|
3471
|
+
{inspectedElement.id
|
|
3472
|
+
? ` id="${inspectedElement.id}"`
|
|
3473
|
+
: ''}
|
|
3474
|
+
{inspectedElement.className
|
|
3475
|
+
? ` class="${inspectedElement.className
|
|
3476
|
+
.trim()
|
|
3477
|
+
.split(/\s+/)[0]}"`
|
|
3478
|
+
: ''}
|
|
3479
|
+
>
|
|
3480
|
+
</Text>
|
|
3481
|
+
</Text>
|
|
3482
|
+
<Pressable onPress={() => setInspectedElement(null)} style={{
|
|
2870
3483
|
paddingHorizontal: 8,
|
|
2871
3484
|
paddingVertical: 4,
|
|
2872
3485
|
}}>
|
|
2873
|
-
|
|
3486
|
+
<Text style={{
|
|
2874
3487
|
fontFamily: AppFonts.interBold,
|
|
2875
3488
|
fontSize: 11,
|
|
2876
3489
|
color: AppColors.purple,
|
|
2877
3490
|
}}>
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
3491
|
+
Clear Inspect
|
|
3492
|
+
</Text>
|
|
3493
|
+
</Pressable>
|
|
3494
|
+
</View>)}
|
|
2882
3495
|
|
|
2883
|
-
|
|
2884
|
-
|
|
3496
|
+
{/* Inner sub-tabs inside HTML source view */}
|
|
3497
|
+
<View style={{
|
|
2885
3498
|
flexDirection: 'row',
|
|
2886
3499
|
borderBottomWidth: 1,
|
|
2887
3500
|
borderBottomColor: AppColors.dividerColor,
|
|
@@ -2889,7 +3502,7 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2889
3502
|
paddingHorizontal: 12,
|
|
2890
3503
|
gap: 12,
|
|
2891
3504
|
}}>
|
|
2892
|
-
|
|
3505
|
+
{['html', 'css', 'javascript'].map(tab => {
|
|
2893
3506
|
const active = htmlSubTab === tab;
|
|
2894
3507
|
const label = tab === 'html'
|
|
2895
3508
|
? 'HTML'
|
|
@@ -2901,7 +3514,10 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2901
3514
|
: tab === 'css'
|
|
2902
3515
|
? '#2563EB' // Blue
|
|
2903
3516
|
: '#D97706'; // Dark Yellow/Amber
|
|
2904
|
-
return (<Pressable key={tab} onPress={() =>
|
|
3517
|
+
return (<Pressable key={tab} onPress={() => {
|
|
3518
|
+
animateNextLayout();
|
|
3519
|
+
setHtmlSubTab(tab);
|
|
3520
|
+
}} style={{
|
|
2905
3521
|
paddingVertical: 8,
|
|
2906
3522
|
paddingHorizontal: 4,
|
|
2907
3523
|
borderBottomWidth: 2,
|
|
@@ -2912,10 +3528,16 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2912
3528
|
alignItems: 'center',
|
|
2913
3529
|
gap: 4,
|
|
2914
3530
|
}}>
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
3531
|
+
{tab === 'html' && (<HtmlIcon color={active
|
|
3532
|
+
? activeColor
|
|
3533
|
+
: AppColors.grayTextWeak} size={14}/>)}
|
|
3534
|
+
{tab === 'css' && (<CssIcon color={active
|
|
3535
|
+
? activeColor
|
|
3536
|
+
: AppColors.grayTextWeak} size={14}/>)}
|
|
3537
|
+
{tab === 'javascript' && (<JsIcon color={active
|
|
3538
|
+
? activeColor
|
|
3539
|
+
: AppColors.grayTextWeak} size={14}/>)}
|
|
3540
|
+
<Text style={{
|
|
2919
3541
|
fontFamily: active
|
|
2920
3542
|
? AppFonts.interBold
|
|
2921
3543
|
: AppFonts.interMedium,
|
|
@@ -2924,70 +3546,81 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2924
3546
|
? activeColor
|
|
2925
3547
|
: AppColors.grayTextWeak,
|
|
2926
3548
|
}}>
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
3549
|
+
{label}
|
|
3550
|
+
</Text>
|
|
3551
|
+
</Pressable>);
|
|
2930
3552
|
})}
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
3553
|
+
</View>
|
|
3554
|
+
<View style={{ flex: 1, padding: 12 }}>
|
|
3555
|
+
{!isHtmlTabReady ? (<View style={{
|
|
3556
|
+
flex: 1,
|
|
3557
|
+
justifyContent: 'center',
|
|
3558
|
+
alignItems: 'center',
|
|
3559
|
+
minHeight: 200,
|
|
3560
|
+
}}>
|
|
3561
|
+
<ActivityIndicator size="large" color={AppColors.purple}/>
|
|
3562
|
+
</View>) : htmlSubTab === 'html' ? (webViewHtml ? (<CodeSnippet code={webViewHtml} language="html" search={getSearchTermForTab()}/>) : (<Text style={{
|
|
2936
3563
|
fontFamily: 'monospace',
|
|
2937
3564
|
fontSize: 11,
|
|
2938
3565
|
color: '#94A3B8',
|
|
2939
3566
|
padding: 12,
|
|
2940
3567
|
}}>
|
|
2941
|
-
|
|
2942
|
-
|
|
3568
|
+
No HTML content captured.
|
|
3569
|
+
</Text>)) : htmlSubTab === 'css' ? (webViewCss ? (<CodeSnippet code={webViewCss} language="css" search={getSearchTermForTab()}/>) : (<Text style={{
|
|
2943
3570
|
fontFamily: 'monospace',
|
|
2944
3571
|
fontSize: 11,
|
|
2945
3572
|
color: '#94A3B8',
|
|
2946
3573
|
padding: 12,
|
|
2947
3574
|
}}>
|
|
2948
|
-
|
|
2949
|
-
|
|
3575
|
+
No CSS styles detected on this page.
|
|
3576
|
+
</Text>)) : webViewJs ? (<CodeSnippet code={webViewJs} language="javascript" search={getSearchTermForTab()}/>) : (<Text style={{
|
|
2950
3577
|
fontFamily: 'monospace',
|
|
2951
3578
|
fontSize: 11,
|
|
2952
3579
|
color: '#94A3B8',
|
|
2953
3580
|
padding: 12,
|
|
2954
3581
|
}}>
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
3582
|
+
No scripts detected on this page.
|
|
3583
|
+
</Text>)}
|
|
3584
|
+
</View>
|
|
3585
|
+
</View>) : (<View style={styles.emptyContainer}>
|
|
3586
|
+
<View style={styles.emptyIconWrap}>
|
|
3587
|
+
<GlobeIcon color={AppColors.purple} size={32}/>
|
|
3588
|
+
</View>
|
|
3589
|
+
<Text style={styles.emptyTitle}>
|
|
3590
|
+
No Page Source Captured
|
|
3591
|
+
</Text>
|
|
3592
|
+
<Text style={styles.emptySub}>
|
|
3593
|
+
Load a page in the WebView to inspect its
|
|
3594
|
+
HTML, CSS, or Javascript source.
|
|
3595
|
+
</Text>
|
|
3596
|
+
</View>)}
|
|
3597
|
+
</View>) : webViewSubTab === 'navigation' ? (<FlatList data={filteredNavHistory} keyExtractor={(item, index) => `${index}-${item.timestamp}`} style={{
|
|
3598
|
+
flex: 1,
|
|
3599
|
+
backgroundColor: AppColors.grayBackground,
|
|
3600
|
+
}} ListHeaderComponent={<View style={{
|
|
2971
3601
|
paddingHorizontal: 16,
|
|
2972
3602
|
paddingTop: 12,
|
|
2973
3603
|
paddingBottom: 8,
|
|
2974
3604
|
}}>
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3605
|
+
<Text style={styles.resultCount}>
|
|
3606
|
+
Navigation History ({webViewNavHistory.length}
|
|
3607
|
+
)
|
|
3608
|
+
</Text>
|
|
3609
|
+
</View>} renderItem={({ item, index, }) => {
|
|
2979
3610
|
const isLatest = index === 0;
|
|
2980
3611
|
const formatNavTime = (ts) => {
|
|
2981
3612
|
const d = new Date(ts);
|
|
2982
3613
|
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
|
|
2983
3614
|
};
|
|
2984
|
-
return (<
|
|
3615
|
+
return (<AnimatedEntrance index={index} distance={8} style={{
|
|
2985
3616
|
marginHorizontal: 16,
|
|
2986
3617
|
marginVertical: 6,
|
|
2987
3618
|
borderRadius: 12,
|
|
2988
3619
|
borderWidth: 1,
|
|
2989
3620
|
borderColor: AppColors.grayBorderSecondary,
|
|
2990
|
-
backgroundColor: isLatest
|
|
3621
|
+
backgroundColor: isLatest
|
|
3622
|
+
? AppColors.purpleShade50
|
|
3623
|
+
: AppColors.primaryLight,
|
|
2991
3624
|
padding: 14,
|
|
2992
3625
|
flexDirection: 'row',
|
|
2993
3626
|
alignItems: 'center',
|
|
@@ -2999,23 +3632,23 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
2999
3632
|
shadowRadius: 4,
|
|
3000
3633
|
elevation: 2,
|
|
3001
3634
|
}}>
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3635
|
+
<View style={{ flex: 1, gap: 8 }}>
|
|
3636
|
+
{/* Top row: Title and Badge */}
|
|
3637
|
+
<View style={{
|
|
3005
3638
|
flexDirection: 'row',
|
|
3006
3639
|
alignItems: 'center',
|
|
3007
3640
|
gap: 8,
|
|
3008
3641
|
flexWrap: 'wrap',
|
|
3009
3642
|
}}>
|
|
3010
|
-
|
|
3643
|
+
<Text numberOfLines={1} ellipsizeMode="tail" style={{
|
|
3011
3644
|
fontFamily: AppFonts.interBold,
|
|
3012
3645
|
fontSize: 14,
|
|
3013
3646
|
color: AppColors.primaryBlack,
|
|
3014
3647
|
flexShrink: 1,
|
|
3015
3648
|
}}>
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3649
|
+
{item.title || 'Untitled Page'}
|
|
3650
|
+
</Text>
|
|
3651
|
+
{isLatest && (<View style={{
|
|
3019
3652
|
flexDirection: 'row',
|
|
3020
3653
|
alignItems: 'center',
|
|
3021
3654
|
gap: 4,
|
|
@@ -3024,65 +3657,100 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3024
3657
|
paddingVertical: 3,
|
|
3025
3658
|
borderRadius: 12,
|
|
3026
3659
|
}}>
|
|
3027
|
-
|
|
3660
|
+
<View style={{
|
|
3028
3661
|
width: 6,
|
|
3029
3662
|
height: 6,
|
|
3030
3663
|
borderRadius: 3,
|
|
3031
3664
|
backgroundColor: AppColors.greenBaggageText,
|
|
3032
3665
|
}}/>
|
|
3033
|
-
|
|
3666
|
+
<Text style={{
|
|
3034
3667
|
fontFamily: AppFonts.interBold,
|
|
3035
3668
|
fontSize: 9.5,
|
|
3036
3669
|
color: AppColors.greenBaggageText,
|
|
3037
3670
|
}}>
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3671
|
+
Active
|
|
3672
|
+
</Text>
|
|
3673
|
+
</View>)}
|
|
3674
|
+
</View>
|
|
3042
3675
|
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3676
|
+
{/* Middle row: URL with Globe Icon */}
|
|
3677
|
+
<View style={{
|
|
3678
|
+
flexDirection: 'row',
|
|
3679
|
+
alignItems: 'center',
|
|
3680
|
+
gap: 6,
|
|
3681
|
+
}}>
|
|
3682
|
+
<GlobeIcon size={12} color={AppColors.grayTextWeak}/>
|
|
3683
|
+
<HighlightText text={item.url} search={webViewSearch} numberOfLines={2} ellipsizeMode="tail" style={{
|
|
3047
3684
|
fontFamily: AppFonts.interRegular,
|
|
3048
3685
|
fontSize: 12,
|
|
3049
3686
|
color: AppColors.grayText,
|
|
3050
3687
|
flex: 1,
|
|
3051
3688
|
}} highlightStyle={styles.highlight} detectLinks={true}/>
|
|
3052
|
-
|
|
3689
|
+
</View>
|
|
3053
3690
|
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3691
|
+
{/* Bottom row: Time */}
|
|
3692
|
+
<View style={{
|
|
3693
|
+
flexDirection: 'row',
|
|
3694
|
+
alignItems: 'center',
|
|
3695
|
+
gap: 6,
|
|
3696
|
+
}}>
|
|
3697
|
+
<ClockIcon size={11} color={AppColors.grayTextWeak}/>
|
|
3698
|
+
<Text style={{
|
|
3699
|
+
fontFamily: AppFonts.interRegular,
|
|
3700
|
+
fontSize: 11,
|
|
3701
|
+
color: AppColors.grayTextWeak,
|
|
3702
|
+
}}>
|
|
3703
|
+
{formatNavTime(item.timestamp)}
|
|
3704
|
+
</Text>
|
|
3705
|
+
</View>
|
|
3706
|
+
</View>
|
|
3707
|
+
<CopyButton value={item.url} label="URL"/>
|
|
3708
|
+
</AnimatedEntrance>);
|
|
3064
3709
|
}} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState isSearch={webViewSearch.length > 0}/>} contentContainerStyle={[
|
|
3065
3710
|
styles.listContent,
|
|
3066
|
-
filteredNavHistory.length === 0 && {
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3711
|
+
filteredNavHistory.length === 0 && {
|
|
3712
|
+
flexGrow: 1,
|
|
3713
|
+
},
|
|
3714
|
+
]} keyboardShouldPersistTaps="handled"/>) : webViewSubTab === 'console' ? (<View style={{
|
|
3715
|
+
flex: 1,
|
|
3716
|
+
backgroundColor: AppColors.grayBackground,
|
|
3717
|
+
}}>
|
|
3718
|
+
{webViewLogs.length > 0 ? (<FlatList data={webViewLogs} keyExtractor={(item) => String(item.id)} style={{ flex: 1 }} ListHeaderComponent={<View style={{
|
|
3719
|
+
paddingHorizontal: 16,
|
|
3720
|
+
paddingTop: 12,
|
|
3721
|
+
paddingBottom: 8,
|
|
3722
|
+
flexDirection: 'row',
|
|
3723
|
+
justifyContent: 'space-between',
|
|
3724
|
+
alignItems: 'center',
|
|
3725
|
+
}}>
|
|
3726
|
+
<Text style={styles.resultCount}>
|
|
3727
|
+
Console Logs ({webViewLogs.length})
|
|
3728
|
+
</Text>
|
|
3729
|
+
<TouchableScale onPress={() => clearWebViewData()} style={{
|
|
3730
|
+
padding: 6,
|
|
3731
|
+
borderRadius: 6,
|
|
3732
|
+
backgroundColor: AppColors.primaryLight,
|
|
3733
|
+
borderWidth: 1,
|
|
3734
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
3735
|
+
}}>
|
|
3736
|
+
<TrashIcon color={AppColors.errorColor} size={14}/>
|
|
3737
|
+
</TouchableScale>
|
|
3738
|
+
</View>} renderItem={({ item }) => {
|
|
3739
|
+
const logColor = item.type === 'error'
|
|
3740
|
+
? AppColors.errorColor
|
|
3741
|
+
: item.type === 'warn'
|
|
3742
|
+
? AppColors.warningIconGold
|
|
3743
|
+
: item.type === 'info'
|
|
3744
|
+
? AppColors.skyBlue
|
|
3745
|
+
: AppColors.grayTextWeak;
|
|
3746
|
+
const bgColor = item.type === 'error'
|
|
3747
|
+
? 'rgba(255, 46, 87, 0.06)'
|
|
3748
|
+
: item.type === 'warn'
|
|
3749
|
+
? 'rgba(191, 162, 82, 0.08)'
|
|
3750
|
+
: AppColors.primaryLight;
|
|
3083
3751
|
const d = new Date(item.timestamp);
|
|
3084
3752
|
const timeStr = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
|
|
3085
|
-
return (<
|
|
3753
|
+
return (<AnimatedEntrance index={item.id} distance={8} style={{
|
|
3086
3754
|
marginHorizontal: 12,
|
|
3087
3755
|
marginVertical: 3,
|
|
3088
3756
|
borderRadius: 8,
|
|
@@ -3096,34 +3764,65 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3096
3764
|
gap: 8,
|
|
3097
3765
|
alignItems: 'flex-start',
|
|
3098
3766
|
}}>
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3767
|
+
<View style={{ paddingTop: 1 }}>
|
|
3768
|
+
<TerminalIcon color={logColor} size={11}/>
|
|
3769
|
+
</View>
|
|
3770
|
+
<View style={{ flex: 1, gap: 3 }}>
|
|
3771
|
+
<View style={{
|
|
3772
|
+
flexDirection: 'row',
|
|
3773
|
+
alignItems: 'center',
|
|
3774
|
+
justifyContent: 'space-between',
|
|
3775
|
+
}}>
|
|
3776
|
+
<Text style={{
|
|
3777
|
+
fontFamily: AppFonts.interBold,
|
|
3778
|
+
fontSize: 10,
|
|
3779
|
+
color: logColor,
|
|
3780
|
+
textTransform: 'uppercase',
|
|
3781
|
+
letterSpacing: 0.5,
|
|
3782
|
+
}}>
|
|
3783
|
+
{item.type}
|
|
3784
|
+
</Text>
|
|
3785
|
+
<Text style={{
|
|
3786
|
+
fontFamily: AppFonts.interRegular,
|
|
3787
|
+
fontSize: 10,
|
|
3788
|
+
color: AppColors.grayTextWeak,
|
|
3789
|
+
}}>
|
|
3790
|
+
{timeStr}
|
|
3791
|
+
</Text>
|
|
3792
|
+
</View>
|
|
3793
|
+
<Text style={{
|
|
3794
|
+
fontFamily: AppFonts.interRegular,
|
|
3795
|
+
fontSize: 12,
|
|
3796
|
+
color: AppColors.primaryBlack,
|
|
3797
|
+
lineHeight: 16,
|
|
3798
|
+
}}>
|
|
3799
|
+
{item.message}
|
|
3800
|
+
</Text>
|
|
3801
|
+
</View>
|
|
3802
|
+
</AnimatedEntrance>);
|
|
3803
|
+
}} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={7} contentContainerStyle={[
|
|
3804
|
+
styles.listContent,
|
|
3805
|
+
webViewLogs.length === 0 && { flexGrow: 1 },
|
|
3806
|
+
]}/>) : (<View style={styles.emptyContainer}>
|
|
3807
|
+
<View style={styles.emptyIconWrap}>
|
|
3808
|
+
<TerminalIcon color={AppColors.purple} size={32}/>
|
|
3114
3809
|
</View>
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
</
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3810
|
+
<Text style={styles.emptyTitle}>
|
|
3811
|
+
No Console Logs
|
|
3812
|
+
</Text>
|
|
3813
|
+
<Text style={styles.emptySub}>
|
|
3814
|
+
Console logs from the WebView will appear
|
|
3815
|
+
here.
|
|
3816
|
+
</Text>
|
|
3817
|
+
</View>)}
|
|
3818
|
+
</View>) : (<View style={{
|
|
3819
|
+
flex: 1,
|
|
3820
|
+
backgroundColor: AppColors.grayBackground,
|
|
3821
|
+
}}>
|
|
3822
|
+
{webViewHtml ? (OriginalWebView ? (<OriginalWebView source={{
|
|
3823
|
+
html: webViewHtml,
|
|
3824
|
+
baseUrl: webViewHtmlUrl,
|
|
3825
|
+
}} injectedJavaScript={previewInspectScript} onMessage={(event) => {
|
|
3127
3826
|
try {
|
|
3128
3827
|
const data = JSON.parse(event.nativeEvent.data);
|
|
3129
3828
|
if (data.type === 'preview-inspect') {
|
|
@@ -3138,27 +3837,39 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3138
3837
|
}
|
|
3139
3838
|
}
|
|
3140
3839
|
catch (err) { }
|
|
3141
|
-
}} style={{ flex: 1 }}/>) : (<View style={{
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3840
|
+
}} style={{ flex: 1 }}/>) : (<View style={{
|
|
3841
|
+
flex: 1,
|
|
3842
|
+
justifyContent: 'center',
|
|
3843
|
+
alignItems: 'center',
|
|
3844
|
+
padding: 20,
|
|
3845
|
+
}}>
|
|
3846
|
+
<Text style={{
|
|
3847
|
+
color: AppColors.grayText,
|
|
3848
|
+
textAlign: 'center',
|
|
3849
|
+
fontFamily: AppFonts.interMedium,
|
|
3850
|
+
}}>
|
|
3851
|
+
react-native-webview is not installed in the
|
|
3852
|
+
target project. Install it to enable Preview
|
|
3853
|
+
mode.
|
|
3854
|
+
</Text>
|
|
3855
|
+
</View>)) : (<View style={styles.emptyContainer}>
|
|
3856
|
+
<View style={styles.emptyIconWrap}>
|
|
3857
|
+
<GlobeIcon color={AppColors.purple} size={32}/>
|
|
3858
|
+
</View>
|
|
3859
|
+
<Text style={styles.emptyTitle}>
|
|
3860
|
+
No Preview Available
|
|
3861
|
+
</Text>
|
|
3862
|
+
<Text style={styles.emptySub}>
|
|
3863
|
+
Load a page in the WebView to see its visual
|
|
3864
|
+
preview.
|
|
3865
|
+
</Text>
|
|
3866
|
+
</View>)}
|
|
3867
|
+
</View>)}
|
|
3868
|
+
</View>)) : activeTab === 'redux' ? (renderReduxTab()) : (<View style={{ flex: 1 }}>
|
|
3869
|
+
{/* Non-scrollable details header */}
|
|
3870
|
+
<View style={{ paddingHorizontal: 6, paddingTop: 4 }}>
|
|
3871
|
+
<View style={styles.detailInfoBar}>
|
|
3872
|
+
{(() => {
|
|
3162
3873
|
let hostStr = '';
|
|
3163
3874
|
let pathStr = detailDisplayUrl;
|
|
3164
3875
|
let queryStr = '';
|
|
@@ -3187,31 +3898,29 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3187
3898
|
}
|
|
3188
3899
|
catch (e) { }
|
|
3189
3900
|
return (<>
|
|
3190
|
-
|
|
3191
|
-
|
|
3901
|
+
<View style={styles.detailInfoTop}>
|
|
3902
|
+
<View style={{
|
|
3192
3903
|
flexDirection: 'row',
|
|
3193
3904
|
alignItems: 'center',
|
|
3194
3905
|
gap: 8,
|
|
3195
3906
|
}}>
|
|
3196
|
-
|
|
3907
|
+
<View style={[
|
|
3197
3908
|
styles.methodBadge,
|
|
3198
3909
|
{
|
|
3199
|
-
backgroundColor: `${METHOD_COLORS[selected.method] ??
|
|
3200
|
-
METHOD_COLORS.ALL}15`,
|
|
3910
|
+
backgroundColor: `${METHOD_COLORS[selected.method] ?? METHOD_COLORS.ALL}15`,
|
|
3201
3911
|
},
|
|
3202
3912
|
]}>
|
|
3203
|
-
|
|
3913
|
+
<Text style={[
|
|
3204
3914
|
styles.methodBadgeText,
|
|
3205
3915
|
{
|
|
3206
|
-
color: METHOD_COLORS[selected.method] ??
|
|
3207
|
-
METHOD_COLORS.ALL,
|
|
3916
|
+
color: METHOD_COLORS[selected.method] ?? METHOD_COLORS.ALL,
|
|
3208
3917
|
},
|
|
3209
3918
|
]}>
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3919
|
+
{selected.method}
|
|
3920
|
+
</Text>
|
|
3921
|
+
</View>
|
|
3213
3922
|
|
|
3214
|
-
|
|
3923
|
+
{selected.status != null && (<View style={[
|
|
3215
3924
|
styles.chip,
|
|
3216
3925
|
{
|
|
3217
3926
|
backgroundColor: selected.status === 0
|
|
@@ -3222,10 +3931,10 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3222
3931
|
: `${getStatusColor(selected.status)}40`,
|
|
3223
3932
|
},
|
|
3224
3933
|
]}>
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3934
|
+
{selected.status === 0 ? (<FailIcon size={8} color={AppColors.errorColor}/>) : (<Svg width={6} height={6} viewBox="0 0 10 10" fill="none">
|
|
3935
|
+
<Circle cx="5" cy="5" r="5" fill={getStatusColor(selected.status)}/>
|
|
3936
|
+
</Svg>)}
|
|
3937
|
+
<Text style={[
|
|
3229
3938
|
styles.chipText,
|
|
3230
3939
|
{
|
|
3231
3940
|
color: selected.status === 0
|
|
@@ -3233,29 +3942,38 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3233
3942
|
: getStatusColor(selected.status),
|
|
3234
3943
|
},
|
|
3235
3944
|
]}>
|
|
3236
|
-
|
|
3945
|
+
{selected.status === 0
|
|
3237
3946
|
? 'Failed'
|
|
3238
3947
|
: String(selected.status)}
|
|
3239
|
-
|
|
3240
|
-
|
|
3948
|
+
</Text>
|
|
3949
|
+
</View>)}
|
|
3241
3950
|
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3951
|
+
{selected.duration != null && (<View style={[
|
|
3952
|
+
styles.chip,
|
|
3953
|
+
{
|
|
3954
|
+
backgroundColor: 'rgba(104,75,155,0.08)',
|
|
3955
|
+
borderColor: 'rgba(104,75,155,0.18)',
|
|
3956
|
+
},
|
|
3957
|
+
]}>
|
|
3958
|
+
<Text style={[
|
|
3959
|
+
styles.chipText,
|
|
3960
|
+
{ color: AppColors.purple },
|
|
3961
|
+
]}>
|
|
3962
|
+
{selected.duration}ms
|
|
3963
|
+
</Text>
|
|
3964
|
+
</View>)}
|
|
3965
|
+
</View>
|
|
3966
|
+
<View style={styles.detailInfoRight}>
|
|
3967
|
+
<TouchableScale style={styles.iconSquareBtn} onPress={() => Linking.openURL(detailDisplayUrl)} hitSlop={12}>
|
|
3968
|
+
<GlobeIcon color={AppColors.grayTextWeak} size={14}/>
|
|
3969
|
+
</TouchableScale>
|
|
3970
|
+
<CopyButton value={getFetchCommand(selected)} label="fetch()" iconType="fetch"/>
|
|
3971
|
+
<CopyButton value={getCurlCommand(selected)} label="cURL" iconType="terminal"/>
|
|
3972
|
+
<CopyButton value={detailDisplayUrl} label="URL"/>
|
|
3973
|
+
</View>
|
|
3974
|
+
</View>
|
|
3257
3975
|
|
|
3258
|
-
|
|
3976
|
+
<Pressable style={{
|
|
3259
3977
|
backgroundColor: AppColors.grayBackground,
|
|
3260
3978
|
borderRadius: 10,
|
|
3261
3979
|
borderWidth: 1,
|
|
@@ -3263,28 +3981,59 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3263
3981
|
padding: 10,
|
|
3264
3982
|
marginTop: 6,
|
|
3265
3983
|
}} onPress={() => Linking.openURL(detailDisplayUrl)}>
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3984
|
+
<View style={{
|
|
3985
|
+
flexDirection: 'row',
|
|
3986
|
+
alignItems: 'center',
|
|
3987
|
+
justifyContent: 'space-between',
|
|
3988
|
+
marginBottom: 2,
|
|
3989
|
+
}}>
|
|
3990
|
+
<Text style={{
|
|
3991
|
+
fontFamily: AppFonts.interMedium,
|
|
3992
|
+
fontSize: 10,
|
|
3993
|
+
color: AppColors.grayTextWeak,
|
|
3994
|
+
flex: 1,
|
|
3995
|
+
}} numberOfLines={1}>
|
|
3996
|
+
{hostStr || 'API Endpoint'}
|
|
3997
|
+
</Text>
|
|
3998
|
+
{queryStr ? (<View style={{
|
|
3999
|
+
backgroundColor: 'rgba(104,75,155,0.08)',
|
|
4000
|
+
paddingHorizontal: 5,
|
|
4001
|
+
paddingVertical: 1,
|
|
4002
|
+
borderRadius: 4,
|
|
4003
|
+
}}>
|
|
4004
|
+
<Text style={{
|
|
4005
|
+
fontFamily: AppFonts.interBold,
|
|
4006
|
+
fontSize: 8.5,
|
|
4007
|
+
color: AppColors.purple,
|
|
4008
|
+
}}>
|
|
4009
|
+
Query Params
|
|
4010
|
+
</Text>
|
|
4011
|
+
</View>) : null}
|
|
4012
|
+
</View>
|
|
4013
|
+
<Text selectable={true} style={{
|
|
4014
|
+
fontFamily: AppFonts.interBold,
|
|
4015
|
+
fontSize: 12,
|
|
4016
|
+
color: AppColors.primaryBlack,
|
|
4017
|
+
marginTop: 2,
|
|
4018
|
+
}} numberOfLines={2}>
|
|
4019
|
+
{pathStr}
|
|
4020
|
+
</Text>
|
|
4021
|
+
{queryStr ? (<Text selectable={true} style={{
|
|
4022
|
+
fontFamily: AppFonts.interRegular,
|
|
4023
|
+
fontSize: 10,
|
|
4024
|
+
color: AppColors.grayTextWeak,
|
|
4025
|
+
marginTop: 4,
|
|
4026
|
+
}} numberOfLines={1}>
|
|
4027
|
+
{queryStr}
|
|
4028
|
+
</Text>) : null}
|
|
4029
|
+
</Pressable>
|
|
4030
|
+
</>);
|
|
3282
4031
|
})()}
|
|
3283
|
-
|
|
3284
|
-
|
|
4032
|
+
</View>
|
|
4033
|
+
</View>
|
|
3285
4034
|
|
|
3286
|
-
|
|
3287
|
-
|
|
4035
|
+
{/* Sticky Segment Control */}
|
|
4036
|
+
<View style={{
|
|
3288
4037
|
flexDirection: 'row',
|
|
3289
4038
|
backgroundColor: AppColors.grayBackground,
|
|
3290
4039
|
borderRadius: 10,
|
|
@@ -3295,7 +4044,12 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3295
4044
|
borderWidth: 1,
|
|
3296
4045
|
borderColor: AppColors.dividerColor,
|
|
3297
4046
|
}}>
|
|
3298
|
-
|
|
4047
|
+
{[
|
|
4048
|
+
'metadata',
|
|
4049
|
+
'headers',
|
|
4050
|
+
'request',
|
|
4051
|
+
'response',
|
|
4052
|
+
].map(tab => {
|
|
3299
4053
|
const isActive = apiDetailActiveTab === tab;
|
|
3300
4054
|
if (tab === 'request' && selected.request == null)
|
|
3301
4055
|
return null;
|
|
@@ -3309,7 +4063,9 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3309
4063
|
return 'Response';
|
|
3310
4064
|
};
|
|
3311
4065
|
const getIcon = () => {
|
|
3312
|
-
const iconColor = isActive
|
|
4066
|
+
const iconColor = isActive
|
|
4067
|
+
? '#FFFFFF'
|
|
4068
|
+
: AppColors.grayText;
|
|
3313
4069
|
if (tab === 'metadata')
|
|
3314
4070
|
return <StatusIcon color={iconColor}/>;
|
|
3315
4071
|
if (tab === 'headers')
|
|
@@ -3318,122 +4074,139 @@ const NetworkInspector = ({ enabled = true }) => {
|
|
|
3318
4074
|
return <RequestIcon color={iconColor}/>;
|
|
3319
4075
|
return <ResponseIcon color={iconColor}/>;
|
|
3320
4076
|
};
|
|
3321
|
-
return (<TouchableOpacity key={tab} onPress={() =>
|
|
4077
|
+
return (<TouchableOpacity key={tab} onPress={() => {
|
|
4078
|
+
animateNextLayout();
|
|
4079
|
+
setApiDetailActiveTab(tab);
|
|
4080
|
+
}} style={{
|
|
3322
4081
|
flex: 1,
|
|
3323
4082
|
paddingVertical: 6,
|
|
3324
4083
|
flexDirection: 'row',
|
|
3325
4084
|
alignItems: 'center',
|
|
3326
4085
|
justifyContent: 'center',
|
|
3327
4086
|
borderRadius: 8,
|
|
3328
|
-
backgroundColor: isActive
|
|
4087
|
+
backgroundColor: isActive
|
|
4088
|
+
? AppColors.purple
|
|
4089
|
+
: 'transparent',
|
|
3329
4090
|
gap: 4,
|
|
3330
4091
|
}}>
|
|
3331
|
-
|
|
3332
|
-
|
|
4092
|
+
{getIcon()}
|
|
4093
|
+
<Text style={{
|
|
3333
4094
|
fontFamily: AppFonts.interBold,
|
|
3334
4095
|
fontSize: 10,
|
|
3335
|
-
color: isActive
|
|
4096
|
+
color: isActive
|
|
4097
|
+
? '#FFFFFF'
|
|
4098
|
+
: AppColors.grayText,
|
|
3336
4099
|
}}>
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
4100
|
+
{getLabel()}
|
|
4101
|
+
</Text>
|
|
4102
|
+
</TouchableOpacity>);
|
|
3340
4103
|
})}
|
|
3341
|
-
|
|
4104
|
+
</View>
|
|
3342
4105
|
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
4106
|
+
{/* Scrollable Tab Content */}
|
|
4107
|
+
<ScrollView style={styles.detailScroll} contentContainerStyle={{
|
|
4108
|
+
paddingHorizontal: 6,
|
|
4109
|
+
paddingBottom: 24,
|
|
4110
|
+
}} showsVerticalScrollIndicator={true}>
|
|
4111
|
+
{apiDetailActiveTab === 'metadata' && (<>
|
|
4112
|
+
<MetaAccordion status={selected.status} statusColor={getStatusColor(selected.status)} duration={selected.duration} size={getSize(selected.response)} triggeredAt={formatDateTime(selected.startTime)} method={selected.method} contentType={selected.responseHeaders?.['content-type'] ||
|
|
3347
4113
|
selected.responseHeaders?.['Content-Type']} url={selected.url}/>
|
|
3348
4114
|
|
|
3349
|
-
|
|
4115
|
+
{(() => {
|
|
3350
4116
|
const routeInfo = logRouteMapRef.current.get(selected.id);
|
|
3351
4117
|
if (!routeInfo || routeInfo.path === 'Navigators')
|
|
3352
4118
|
return null;
|
|
3353
4119
|
return <SourcePageCard routeInfo={routeInfo}/>;
|
|
3354
4120
|
})()}
|
|
3355
4121
|
|
|
3356
|
-
|
|
4122
|
+
{(() => {
|
|
3357
4123
|
const cType = selected.responseHeaders?.['content-type'] ||
|
|
3358
4124
|
selected.responseHeaders?.['Content-Type'];
|
|
3359
4125
|
if (cType?.includes('image/')) {
|
|
3360
4126
|
return (<View style={styles.imagePreviewWrapper}>
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
4127
|
+
<Image source={{ uri: selected.url }} style={styles.imagePreview} resizeMode="contain"/>
|
|
4128
|
+
<TouchableScale style={styles.imageDownloadBtn} onPress={() => Linking.openURL(selected.url)} hitSlop={10}>
|
|
4129
|
+
<DownloadIcon color={AppColors.purple} size={18}/>
|
|
4130
|
+
</TouchableScale>
|
|
4131
|
+
</View>);
|
|
3366
4132
|
}
|
|
3367
4133
|
return null;
|
|
3368
4134
|
})()}
|
|
3369
|
-
|
|
4135
|
+
</>)}
|
|
3370
4136
|
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
4137
|
+
{apiDetailActiveTab === 'headers' && (<>
|
|
4138
|
+
<View style={styles.detailSearchRow}>
|
|
4139
|
+
<View style={styles.detailSearchBox}>
|
|
4140
|
+
<TextInput placeholder="Search headers..." placeholderTextColor={AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
4141
|
+
{detailSearch.length > 0 && (<Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
|
|
4142
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
4143
|
+
</Pressable>)}
|
|
4144
|
+
</View>
|
|
4145
|
+
</View>
|
|
3380
4146
|
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
4147
|
+
<HeadersSection title="Request Headers" headers={selected.requestHeaders} search={detailSearch} resetKey={selected.id}/>
|
|
4148
|
+
<HeadersSection title="Response Headers" headers={selected.responseHeaders} search={detailSearch} resetKey={selected.id}/>
|
|
4149
|
+
</>)}
|
|
3384
4150
|
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
4151
|
+
{apiDetailActiveTab === 'request' &&
|
|
4152
|
+
selected.request != null && (<>
|
|
4153
|
+
<View style={styles.detailSearchRow}>
|
|
4154
|
+
<View style={styles.detailSearchBox}>
|
|
4155
|
+
<TextInput placeholder="Search request..." placeholderTextColor={AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
4156
|
+
{detailSearch.length > 0 && (<Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
|
|
4157
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
4158
|
+
</Pressable>)}
|
|
4159
|
+
</View>
|
|
4160
|
+
</View>
|
|
3394
4161
|
|
|
3395
|
-
|
|
3396
|
-
|
|
4162
|
+
<View style={styles.sectionContainer}>
|
|
4163
|
+
<SectionHeader title="Request" value={selected.request} expanded={reqExpanded} onToggleExpand={() => setReqExpanded(v => !v)} showDiff={prevRequestData != null} isDiffing={showReqDiff} onToggleDiff={() => {
|
|
3397
4164
|
setShowReqDiff(v => !v);
|
|
3398
4165
|
if (!reqExpanded && !showReqDiff)
|
|
3399
4166
|
setReqExpanded(true);
|
|
3400
4167
|
}}/>
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
4168
|
+
{showReqDiff ? (<DiffViewer oldData={prevRequestData} newData={selected.request} forceOpen={reqExpanded}/>) : (<JsonViewer data={selected.request} search={detailSearch} forceOpen={reqExpanded}/>)}
|
|
4169
|
+
</View>
|
|
4170
|
+
</>)}
|
|
3404
4171
|
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
4172
|
+
{apiDetailActiveTab === 'response' && (<>
|
|
4173
|
+
<View style={styles.detailSearchRow}>
|
|
4174
|
+
<View style={styles.detailSearchBox}>
|
|
4175
|
+
<TextInput placeholder="Search response..." placeholderTextColor={AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
4176
|
+
{detailSearch.length > 0 && (<Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
|
|
4177
|
+
<ClearIcon color={AppColors.grayTextWeak} size={14}/>
|
|
4178
|
+
</Pressable>)}
|
|
4179
|
+
</View>
|
|
4180
|
+
</View>
|
|
3414
4181
|
|
|
3415
|
-
|
|
3416
|
-
|
|
4182
|
+
<View style={styles.sectionContainer}>
|
|
4183
|
+
<SectionHeader title="Response" value={selected.response} expanded={resExpanded} onToggleExpand={() => setResExpanded(v => !v)} showDiff={prevResponseData != null} isDiffing={showResDiff} onToggleDiff={() => {
|
|
3417
4184
|
setShowResDiff(v => !v);
|
|
3418
4185
|
if (!resExpanded && !showResDiff)
|
|
3419
4186
|
setResExpanded(true);
|
|
3420
4187
|
}}/>
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
4188
|
+
{showResDiff ? (<DiffViewer oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : (<JsonViewer data={selected.response} search={detailSearch} forceOpen={resExpanded}/>)}
|
|
4189
|
+
</View>
|
|
4190
|
+
</>)}
|
|
4191
|
+
</ScrollView>
|
|
4192
|
+
</View>)) : (<View style={styles.empty}>
|
|
4193
|
+
<ActivityIndicator size="large" color={AppColors.purple}/>
|
|
4194
|
+
<Text style={[styles.emptySub, { marginTop: 12 }]}>
|
|
4195
|
+
Loading logs...
|
|
4196
|
+
</Text>
|
|
4197
|
+
</View>)}
|
|
3431
4198
|
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
4199
|
+
{settingsPage !== null && (<View style={[
|
|
4200
|
+
StyleSheet.absoluteFill,
|
|
4201
|
+
{
|
|
4202
|
+
backgroundColor: AppColors.grayBackground,
|
|
4203
|
+
zIndex: 99999,
|
|
4204
|
+
},
|
|
4205
|
+
]}>
|
|
4206
|
+
{renderSettings()}
|
|
4207
|
+
</View>)}
|
|
4208
|
+
</View>
|
|
3435
4209
|
</View>
|
|
3436
|
-
</View>
|
|
3437
4210
|
</ErrorBoundary>)}
|
|
3438
4211
|
</Modal>
|
|
3439
4212
|
</>);
|