react-native-inapp-inspector 1.0.13 → 1.0.15

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