react-native-inapp-inspector 1.1.1 → 1.1.3

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.
Files changed (45) hide show
  1. package/README.md +14 -0
  2. package/dist/commonjs/components/ConsoleLogCard.js +18 -0
  3. package/dist/commonjs/components/JsonViewer.d.ts +2 -1
  4. package/dist/commonjs/components/JsonViewer.js +6 -4
  5. package/dist/commonjs/components/LogCard.js +17 -0
  6. package/dist/commonjs/components/MetaAccordion.js +26 -6
  7. package/dist/commonjs/components/NetworkIcons.d.ts +9 -2
  8. package/dist/commonjs/components/NetworkIcons.js +59 -3
  9. package/dist/commonjs/components/ReduxTreeView.js +80 -5
  10. package/dist/commonjs/constants/version.d.ts +1 -1
  11. package/dist/commonjs/constants/version.js +1 -1
  12. package/dist/commonjs/customHooks/reduxLogger.d.ts +21 -7
  13. package/dist/commonjs/customHooks/reduxLogger.js +147 -48
  14. package/dist/commonjs/customHooks/webViewLogger.js +13 -8
  15. package/dist/commonjs/helpers/settingsStore.d.ts +24 -0
  16. package/dist/commonjs/helpers/settingsStore.js +74 -0
  17. package/dist/commonjs/index.d.ts +1 -1
  18. package/dist/commonjs/index.js +897 -170
  19. package/dist/commonjs/styles/index.d.ts +40 -0
  20. package/dist/commonjs/styles/index.js +45 -2
  21. package/dist/commonjs/types/index.d.ts +4 -0
  22. package/dist/esm/components/ConsoleLogCard.js +18 -0
  23. package/dist/esm/components/JsonViewer.d.ts +2 -1
  24. package/dist/esm/components/JsonViewer.js +6 -4
  25. package/dist/esm/components/LogCard.js +17 -0
  26. package/dist/esm/components/MetaAccordion.js +27 -7
  27. package/dist/esm/components/NetworkIcons.d.ts +9 -2
  28. package/dist/esm/components/NetworkIcons.js +51 -2
  29. package/dist/esm/components/ReduxTreeView.js +81 -6
  30. package/dist/esm/constants/version.d.ts +1 -1
  31. package/dist/esm/constants/version.js +1 -1
  32. package/dist/esm/customHooks/reduxLogger.d.ts +21 -7
  33. package/dist/esm/customHooks/reduxLogger.js +145 -47
  34. package/dist/esm/customHooks/webViewLogger.js +13 -8
  35. package/dist/esm/helpers/settingsStore.d.ts +24 -0
  36. package/dist/esm/helpers/settingsStore.js +67 -0
  37. package/dist/esm/index.d.ts +1 -1
  38. package/dist/esm/index.js +896 -172
  39. package/dist/esm/styles/index.d.ts +40 -0
  40. package/dist/esm/styles/index.js +45 -2
  41. package/dist/esm/types/index.d.ts +4 -0
  42. package/example/App.tsx +199 -61
  43. package/example/ios/example.xcodeproj/project.pbxproj +0 -8
  44. package/example/package-lock.json +4 -3
  45. package/package.json +1 -1
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.subscribeReduxState = exports.getReduxState = exports.connectReduxStore = exports.ErrorBoundary = exports.subscribeWebView = exports.clearWebViewData = exports.getWebViewHtmlUrl = exports.getWebViewJs = exports.getWebViewCss = exports.getWebViewHtml = exports.getWebViewNavHistory = exports.getWebViewLogs = exports.WebView = exports.clearAnalyticsEvents = exports.subscribeAnalyticsEvents = exports.logAnalyticsEvent = exports.setupAnalyticsLogger = exports.subscribeConsoleLogs = exports.clearConsoleLogs = exports.setupConsoleLogger = exports.addAxiosInterceptors = exports.subscribeNetworkLogs = exports.clearNetworkLogs = exports.setupNetworkLogger = void 0;
39
+ exports.clearActionHistory = exports.getActionHistory = exports.subscribeReduxState = exports.getReduxState = exports.inspectorReduxMiddleware = exports.connectReduxStore = exports.ErrorBoundary = exports.subscribeWebView = exports.clearWebViewData = exports.getWebViewHtmlUrl = exports.getWebViewJs = exports.getWebViewCss = exports.getWebViewHtml = exports.getWebViewNavHistory = exports.getWebViewLogs = exports.WebView = exports.clearAnalyticsEvents = exports.subscribeAnalyticsEvents = exports.logAnalyticsEvent = exports.setupAnalyticsLogger = exports.subscribeConsoleLogs = exports.clearConsoleLogs = exports.setupConsoleLogger = exports.addAxiosInterceptors = exports.subscribeNetworkLogs = exports.clearNetworkLogs = exports.setupNetworkLogger = void 0;
40
40
  const react_1 = __importStar(require("react"));
41
41
  const react_native_1 = require("react-native");
42
42
  const react_native_svg_1 = __importStar(require("react-native-svg"));
@@ -62,6 +62,8 @@ const CodeSnippet_1 = __importDefault(require("./components/CodeSnippet"));
62
62
  const AnimatedEntrance_1 = __importDefault(require("./components/AnimatedEntrance"));
63
63
  // Helpers
64
64
  const helpers_1 = require("./helpers");
65
+ // #5 — settings persistence
66
+ const settingsStore_1 = require("./helpers/settingsStore");
65
67
  // Assets
66
68
  const NetworkIcons_1 = require("./components/NetworkIcons");
67
69
  const ErrorBoundary_1 = __importDefault(require("./components/ErrorBoundary"));
@@ -189,6 +191,8 @@ const NetworkInspector = ({ enabled = true, }) => {
189
191
  const [showNetworkMenu, setShowNetworkMenu] = (0, react_1.useState)(false);
190
192
  const [showUiMenu, setShowUiMenu] = (0, react_1.useState)(false);
191
193
  const [sortOrder, setSortOrder] = (0, react_1.useState)('newest');
194
+ // #7 — sort order for the Logs (console) tab
195
+ const [logSortOrder, setLogSortOrder] = (0, react_1.useState)('newest');
192
196
  const [reqExpanded, setReqExpanded] = (0, react_1.useState)(undefined);
193
197
  const [resExpanded, setResExpanded] = (0, react_1.useState)(undefined);
194
198
  const [showReqDiff, setShowReqDiff] = (0, react_1.useState)(false);
@@ -274,6 +278,141 @@ const NetworkInspector = ({ enabled = true, }) => {
274
278
  const [reduxExpandDepth, setReduxExpandDepth] = (0, react_1.useState)(1);
275
279
  const [slowRequestThreshold, setSlowRequestThreshold] = (0, react_1.useState)(1000);
276
280
  const [insightsShowConsoleAlerts, setInsightsShowConsoleAlerts] = (0, react_1.useState)(true);
281
+ // #6 — tab the inspector opens on. Shown with a DEFAULT badge in Settings.
282
+ const [defaultTab, setDefaultTab] = (0, react_1.useState)('apis');
283
+ // #9 — when false (default), consecutive identical entries in the API and
284
+ // Console lists are collapsed into one row with a ×N counter.
285
+ const [showDuplicateLogs, setShowDuplicateLogs] = (0, react_1.useState)(false);
286
+ // #5 — hydrate persisted settings once, then auto-save on any change.
287
+ const settingsHydratedRef = (0, react_1.useRef)(false);
288
+ (0, react_1.useEffect)(() => {
289
+ let cancelled = false;
290
+ (0, settingsStore_1.loadSettings)().then(saved => {
291
+ if (cancelled)
292
+ return;
293
+ if (saved.isDark != null) {
294
+ setIsDark(saved.isDark);
295
+ (0, styles_1.toggleGlobalTheme)(saved.isDark);
296
+ }
297
+ if (saved.modalHeightPercent != null)
298
+ setModalHeightPercent(saved.modalHeightPercent);
299
+ if (saved.tabVisibility)
300
+ setTabVisibility(prev => ({
301
+ ...prev,
302
+ ...saved.tabVisibility,
303
+ apis: true, // APIs is always required
304
+ }));
305
+ if (saved.defaultTab)
306
+ setDefaultTab(saved.defaultTab);
307
+ if (saved.maxNetworkLogs != null)
308
+ setMaxNetworkLogs(saved.maxNetworkLogs);
309
+ if (saved.maxConsoleLogs != null)
310
+ setMaxConsoleLogs(saved.maxConsoleLogs);
311
+ if (saved.showConsoleLevels)
312
+ setShowConsoleLevels(saved.showConsoleLevels);
313
+ if (saved.webViewCaptureCssJs != null)
314
+ setWebViewCaptureCssJs(saved.webViewCaptureCssJs);
315
+ if (saved.reduxAutoRefresh != null)
316
+ setReduxAutoRefreshState(saved.reduxAutoRefresh);
317
+ if (saved.reduxExpandDepth != null)
318
+ setReduxExpandDepth(saved.reduxExpandDepth);
319
+ if (saved.slowRequestThreshold != null)
320
+ setSlowRequestThreshold(saved.slowRequestThreshold);
321
+ if (saved.insightsShowConsoleAlerts != null)
322
+ setInsightsShowConsoleAlerts(saved.insightsShowConsoleAlerts);
323
+ if (saved.showDuplicateLogs != null)
324
+ setShowDuplicateLogs(saved.showDuplicateLogs);
325
+ if (saved.defaultTab) {
326
+ const dt = saved.defaultTab;
327
+ const vis = {
328
+ ...{
329
+ insights: true,
330
+ apis: true,
331
+ logs: true,
332
+ analytics: true,
333
+ webview: true,
334
+ redux: true,
335
+ },
336
+ ...(saved.tabVisibility || {}),
337
+ apis: true,
338
+ };
339
+ setActiveTab(vis[dt] ? dt : 'apis');
340
+ }
341
+ settingsHydratedRef.current = true;
342
+ });
343
+ return () => {
344
+ cancelled = true;
345
+ };
346
+ }, []);
347
+ (0, react_1.useEffect)(() => {
348
+ if (!settingsHydratedRef.current)
349
+ return;
350
+ (0, settingsStore_1.saveSettings)({
351
+ isDark,
352
+ modalHeightPercent,
353
+ tabVisibility,
354
+ defaultTab,
355
+ maxNetworkLogs,
356
+ maxConsoleLogs,
357
+ showConsoleLevels,
358
+ webViewCaptureCssJs,
359
+ reduxAutoRefresh,
360
+ reduxExpandDepth,
361
+ slowRequestThreshold,
362
+ insightsShowConsoleAlerts,
363
+ showDuplicateLogs,
364
+ });
365
+ }, [
366
+ isDark,
367
+ modalHeightPercent,
368
+ tabVisibility,
369
+ defaultTab,
370
+ maxNetworkLogs,
371
+ maxConsoleLogs,
372
+ showConsoleLevels,
373
+ webViewCaptureCssJs,
374
+ reduxAutoRefresh,
375
+ reduxExpandDepth,
376
+ slowRequestThreshold,
377
+ insightsShowConsoleAlerts,
378
+ showDuplicateLogs,
379
+ ]);
380
+ // #1 — check NPM for a newer published version; surfaces an animated dot
381
+ // in the header next to the npm chip when an update is available.
382
+ const [latestNpmVersion, setLatestNpmVersion] = (0, react_1.useState)(null);
383
+ const updateAvailable = (0, react_1.useMemo)(() => {
384
+ if (!latestNpmVersion)
385
+ return false;
386
+ const parse = (v) => v
387
+ .replace(/^v/, '')
388
+ .split('.')
389
+ .map(n => parseInt(n, 10) || 0);
390
+ const cur = parse(constants_1.LIB_VERSION);
391
+ const latest = parse(latestNpmVersion);
392
+ for (let i = 0; i < 3; i++) {
393
+ if ((latest[i] || 0) > (cur[i] || 0))
394
+ return true;
395
+ if ((latest[i] || 0) < (cur[i] || 0))
396
+ return false;
397
+ }
398
+ return false;
399
+ }, [latestNpmVersion]);
400
+ (0, react_1.useEffect)(() => {
401
+ let cancelled = false;
402
+ fetch('https://registry.npmjs.org/react-native-inapp-inspector/latest')
403
+ .then(res => (res.ok ? res.json() : null))
404
+ .then(data => {
405
+ if (!cancelled && data && typeof data.version === 'string') {
406
+ setLatestNpmVersion(data.version);
407
+ }
408
+ })
409
+ .catch(() => {
410
+ // Offline / blocked — silently skip the update check.
411
+ });
412
+ return () => {
413
+ cancelled = true;
414
+ };
415
+ }, []);
277
416
  (0, react_1.useEffect)(() => {
278
417
  (0, reduxLogger_1.setReduxAutoRefresh)(reduxAutoRefresh);
279
418
  }, [reduxAutoRefresh]);
@@ -287,6 +426,10 @@ const NetworkInspector = ({ enabled = true, }) => {
287
426
  animateNextLayout();
288
427
  setActiveTab('apis');
289
428
  }
429
+ // #6 — a hidden module can't be the default landing tab.
430
+ if (!nextVal && defaultTab === key) {
431
+ setDefaultTab('apis');
432
+ }
290
433
  return newVisibility;
291
434
  });
292
435
  };
@@ -368,6 +511,68 @@ const NetworkInspector = ({ enabled = true, }) => {
368
511
  const badgeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
369
512
  const activePulseAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0.4)).current;
370
513
  const unreadPulseAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
514
+ // #4 — diagonal light streak sweeping across the floating launcher
515
+ const fabShineAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
516
+ // #11 — header "clear all" icon spin/scale animation
517
+ const clearAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
518
+ // #4 — draggable floating launcher (drag anywhere on screen)
519
+ const fabPan = (0, react_1.useRef)(new react_native_1.Animated.ValueXY({ x: 0, y: 0 })).current;
520
+ const fabPanRef = (0, react_1.useRef)({ x: 0, y: 0 });
521
+ (0, react_1.useEffect)(() => {
522
+ const idX = fabPan.x.addListener(v => (fabPanRef.current.x = v.value));
523
+ const idY = fabPan.y.addListener(v => (fabPanRef.current.y = v.value));
524
+ return () => {
525
+ fabPan.x.removeListener(idX);
526
+ fabPan.y.removeListener(idY);
527
+ };
528
+ }, [fabPan]);
529
+ const fabDraggedRef = (0, react_1.useRef)(false);
530
+ const fabPanResponder = (0, react_1.useRef)(react_native_1.PanResponder.create({
531
+ // Let taps fall through to the launcher; only hijack once the
532
+ // finger actually moves, so onPress still fires on a tap.
533
+ onStartShouldSetPanResponder: () => false,
534
+ onMoveShouldSetPanResponder: (_e, g) => Math.abs(g.dx) > 4 || Math.abs(g.dy) > 4,
535
+ onPanResponderGrant: () => {
536
+ fabDraggedRef.current = true;
537
+ fabPan.setOffset({
538
+ x: fabPanRef.current.x,
539
+ y: fabPanRef.current.y,
540
+ });
541
+ fabPan.setValue({ x: 0, y: 0 });
542
+ },
543
+ onPanResponderMove: react_native_1.Animated.event([null, { dx: fabPan.x, dy: fabPan.y }], {
544
+ useNativeDriver: false,
545
+ }),
546
+ onPanResponderRelease: () => {
547
+ fabPan.flattenOffset();
548
+ // small delay so the trailing tap (if any) is ignored
549
+ setTimeout(() => {
550
+ fabDraggedRef.current = false;
551
+ }, 50);
552
+ },
553
+ onPanResponderTerminate: () => {
554
+ fabPan.flattenOffset();
555
+ fabDraggedRef.current = false;
556
+ },
557
+ })).current;
558
+ // #2 — scroll-to-top button for the main APIs list, always visible at the
559
+ // bottom right of the list.
560
+ const apisListRef = (0, react_1.useRef)(null);
561
+ const runClearAllWithAnimation = (0, react_1.useCallback)(() => {
562
+ react_native_1.Animated.sequence([
563
+ react_native_1.Animated.timing(clearAnim, {
564
+ toValue: 1,
565
+ duration: 320,
566
+ useNativeDriver: true,
567
+ }),
568
+ react_native_1.Animated.timing(clearAnim, {
569
+ toValue: 0,
570
+ duration: 0,
571
+ useNativeDriver: true,
572
+ }),
573
+ ]).start();
574
+ handleClearAll();
575
+ }, [clearAnim]);
371
576
  (0, react_1.useEffect)(() => {
372
577
  if (react_native_1.Platform.OS === 'android') {
373
578
  react_native_1.UIManager.setLayoutAnimationEnabledExperimental?.(true);
@@ -389,6 +594,24 @@ const NetworkInspector = ({ enabled = true, }) => {
389
594
  loop.start();
390
595
  return () => loop.stop();
391
596
  }, [pulseAnim]);
597
+ // #4 — sweep the shine streak across the launcher, pause, repeat.
598
+ (0, react_1.useEffect)(() => {
599
+ const loop = react_native_1.Animated.loop(react_native_1.Animated.sequence([
600
+ react_native_1.Animated.timing(fabShineAnim, {
601
+ toValue: 1,
602
+ duration: 1100,
603
+ useNativeDriver: true,
604
+ }),
605
+ react_native_1.Animated.delay(1600),
606
+ react_native_1.Animated.timing(fabShineAnim, {
607
+ toValue: 0,
608
+ duration: 0,
609
+ useNativeDriver: true,
610
+ }),
611
+ ]));
612
+ loop.start();
613
+ return () => loop.stop();
614
+ }, [fabShineAnim]);
392
615
  (0, react_1.useEffect)(() => {
393
616
  const loop = react_native_1.Animated.loop(react_native_1.Animated.sequence([
394
617
  react_native_1.Animated.timing(activePulseAnim, {
@@ -432,6 +655,16 @@ const NetworkInspector = ({ enabled = true, }) => {
432
655
  }).start();
433
656
  }
434
657
  }, [newLogIds]);
658
+ // #6 — every time the inspector is opened, land on the chosen default tab.
659
+ (0, react_1.useEffect)(() => {
660
+ if (visible) {
661
+ const target = defaultTab === 'apis' || tabVisibility[defaultTab]
662
+ ? defaultTab
663
+ : 'apis';
664
+ setActiveTab(target);
665
+ }
666
+ // eslint-disable-next-line react-hooks/exhaustive-deps
667
+ }, [visible]);
435
668
  (0, react_1.useEffect)(() => {
436
669
  if (visible) {
437
670
  const task = react_native_1.InteractionManager.runAfterInteractions(() => {
@@ -585,8 +818,38 @@ const NetworkInspector = ({ enabled = true, }) => {
585
818
  if (sortOrder === 'oldest') {
586
819
  result = [...result].reverse();
587
820
  }
821
+ // #9 — collapse consecutive identical requests (same method + url +
822
+ // status) into one row carrying a ×N counter, unless the user opted in
823
+ // to seeing every duplicate via Settings → "Show Duplicate Logs".
824
+ if (!showDuplicateLogs) {
825
+ const collapsed = [];
826
+ for (const log of result) {
827
+ const last = collapsed[collapsed.length - 1];
828
+ if (last &&
829
+ last.method === log.method &&
830
+ last.url === log.url &&
831
+ last.status === log.status) {
832
+ collapsed[collapsed.length - 1] = {
833
+ ...last,
834
+ duplicateCount: (last.duplicateCount || 1) + 1,
835
+ };
836
+ }
837
+ else {
838
+ collapsed.push({ ...log, duplicateCount: 1 });
839
+ }
840
+ }
841
+ result = collapsed;
842
+ }
588
843
  return result.slice(0, maxNetworkLogs);
589
- }, [logs, search, statusFilters, methodFilters, sortOrder, maxNetworkLogs]);
844
+ }, [
845
+ logs,
846
+ search,
847
+ statusFilters,
848
+ methodFilters,
849
+ sortOrder,
850
+ maxNetworkLogs,
851
+ showDuplicateLogs,
852
+ ]);
590
853
  const availableMethods = (0, react_1.useMemo)(() => {
591
854
  const methods = new Set();
592
855
  logs.forEach(log => {
@@ -792,8 +1055,39 @@ const NetworkInspector = ({ enabled = true, }) => {
792
1055
  result = result.filter(log => log.message.toLowerCase().includes(s) ||
793
1056
  (log.caller ?? '').toLowerCase().includes(s));
794
1057
  }
1058
+ // #7 — apply sort order (newest/oldest first)
1059
+ result = [...result].sort((a, b) => logSortOrder === 'newest'
1060
+ ? b.timestamp - a.timestamp
1061
+ : a.timestamp - b.timestamp);
1062
+ // #9 — collapse consecutive identical messages into one row with a ×N
1063
+ // counter unless duplicates are explicitly enabled in Settings.
1064
+ if (!showDuplicateLogs) {
1065
+ const collapsed = [];
1066
+ for (const log of result) {
1067
+ const last = collapsed[collapsed.length - 1];
1068
+ if (last &&
1069
+ last.type === log.type &&
1070
+ last.sourceMethod === log.sourceMethod &&
1071
+ last.message === log.message) {
1072
+ collapsed[collapsed.length - 1] = {
1073
+ ...last,
1074
+ duplicateCount: (last.duplicateCount || 1) + 1,
1075
+ };
1076
+ }
1077
+ else {
1078
+ collapsed.push({ ...log, duplicateCount: 1 });
1079
+ }
1080
+ }
1081
+ result = collapsed;
1082
+ }
795
1083
  return result;
796
- }, [visibleConsoleLogs, logFilters, logSearch]);
1084
+ }, [
1085
+ visibleConsoleLogs,
1086
+ logFilters,
1087
+ logSearch,
1088
+ logSortOrder,
1089
+ showDuplicateLogs,
1090
+ ]);
797
1091
  const filteredWebViewLogs = (0, react_1.useMemo)(() => {
798
1092
  let result = webViewLogs;
799
1093
  if (webViewSearch) {
@@ -919,6 +1213,22 @@ const NetworkInspector = ({ enabled = true, }) => {
919
1213
  ]);
920
1214
  return;
921
1215
  }
1216
+ if (activeTab === 'redux') {
1217
+ react_native_1.Alert.alert('Clear Redux Timeline', 'Are you sure you want to clear the dispatched action history?', [
1218
+ { text: 'Cancel', style: 'cancel' },
1219
+ {
1220
+ text: 'Clear All',
1221
+ onPress: () => {
1222
+ (0, reduxLogger_1.clearActionHistory)();
1223
+ setReduxActionHistory([]);
1224
+ setReduxLastActionMap({});
1225
+ },
1226
+ style: 'destructive',
1227
+ },
1228
+ ]);
1229
+ return;
1230
+ }
1231
+ // Default: APIs tab. Only clears NETWORK logs — never touches the other tabs.
922
1232
  if (selectedLogs.size > 0) {
923
1233
  setLogs(prev => prev.filter(l => !selectedLogs.has(l.id)));
924
1234
  setSelectedLogs(new Set());
@@ -926,10 +1236,26 @@ const NetworkInspector = ({ enabled = true, }) => {
926
1236
  else {
927
1237
  react_native_1.Alert.alert('Clear Logs', 'Are you sure you want to clear all network logs?', [
928
1238
  { text: 'Cancel', style: 'cancel' },
929
- { text: 'Clear All', onPress: handleClearAll, style: 'destructive' },
1239
+ {
1240
+ text: 'Clear All',
1241
+ onPress: clearNetworkOnly,
1242
+ style: 'destructive',
1243
+ },
930
1244
  ]);
931
1245
  }
932
1246
  }
1247
+ // Clears ONLY network logs + their derived selection/filter state.
1248
+ function clearNetworkOnly() {
1249
+ (0, networkLogger_1.clearNetworkLogs)();
1250
+ setLogs([]);
1251
+ setSelectedLogs(new Set());
1252
+ setSectionFilters({});
1253
+ setCollapsedSections(new Set());
1254
+ setStatusFilters(new Set());
1255
+ setMethodFilters(new Set());
1256
+ prevLogIdsRef.current = new Set();
1257
+ logRouteMapRef.current = new Map();
1258
+ }
933
1259
  const detailTitle = (0, react_1.useMemo)(() => {
934
1260
  if (!selected)
935
1261
  return '';
@@ -1158,7 +1484,8 @@ const NetworkInspector = ({ enabled = true, }) => {
1158
1484
  }}>
1159
1485
  {tab.label}
1160
1486
  </react_native_1.Text>
1161
- {isLocked && (<react_native_1.View style={{
1487
+ {/* #6 badge marks the configured default tab */}
1488
+ {tab.key === defaultTab && (<react_native_1.View style={{
1162
1489
  flexDirection: 'row',
1163
1490
  alignItems: 'center',
1164
1491
  backgroundColor: 'rgba(104,75,155,0.08)',
@@ -1263,7 +1590,7 @@ const NetworkInspector = ({ enabled = true, }) => {
1263
1590
  })}
1264
1591
  </react_native_1.View>
1265
1592
 
1266
- {/* Preferences Section */}
1593
+ {/* UI Preferences Section */}
1267
1594
  <react_native_1.View style={{ marginTop: 8 }}>
1268
1595
  <react_native_1.Text style={{
1269
1596
  fontFamily: AppFonts_1.AppFonts.interBold,
@@ -1272,7 +1599,7 @@ const NetworkInspector = ({ enabled = true, }) => {
1272
1599
  letterSpacing: 0.6,
1273
1600
  marginBottom: 8,
1274
1601
  }}>
1275
- PREFERENCES
1602
+ UI PREFERENCES
1276
1603
  </react_native_1.Text>
1277
1604
  <react_native_1.View style={{
1278
1605
  backgroundColor: AppColors_1.AppColors.primaryLight,
@@ -1426,6 +1753,169 @@ const NetworkInspector = ({ enabled = true, }) => {
1426
1753
  })}
1427
1754
  </react_native_1.View>
1428
1755
  </react_native_1.View>
1756
+
1757
+ {/* Divider */}
1758
+ <react_native_1.View style={{
1759
+ height: 1,
1760
+ backgroundColor: AppColors_1.AppColors.dividerColor,
1761
+ }}/>
1762
+
1763
+ {/* #6 — Default Tab */}
1764
+ <react_native_1.View style={{
1765
+ paddingVertical: 12,
1766
+ paddingHorizontal: 14,
1767
+ }}>
1768
+ <react_native_1.View style={{
1769
+ flexDirection: 'row',
1770
+ alignItems: 'center',
1771
+ gap: 8,
1772
+ }}>
1773
+ <react_native_1.View style={{
1774
+ width: 20,
1775
+ height: 20,
1776
+ borderRadius: 6,
1777
+ backgroundColor: AppColors_1.AppColors.purpleShade50,
1778
+ borderWidth: 1,
1779
+ borderColor: 'rgba(104,75,155,0.2)',
1780
+ alignItems: 'center',
1781
+ justifyContent: 'center',
1782
+ }}>
1783
+ <NetworkIcons_1.LayersIcon color={AppColors_1.AppColors.purple} size={11}/>
1784
+ </react_native_1.View>
1785
+ <react_native_1.View style={{ flex: 1 }}>
1786
+ <react_native_1.Text style={{
1787
+ fontFamily: AppFonts_1.AppFonts.interBold,
1788
+ fontSize: 13,
1789
+ color: AppColors_1.AppColors.primaryBlack,
1790
+ }}>
1791
+ Default Tab
1792
+ </react_native_1.Text>
1793
+ <react_native_1.Text style={{
1794
+ fontFamily: AppFonts_1.AppFonts.interRegular,
1795
+ fontSize: 11,
1796
+ color: AppColors_1.AppColors.grayText,
1797
+ marginTop: 1,
1798
+ }}>
1799
+ Tab shown when the inspector opens
1800
+ </react_native_1.Text>
1801
+ </react_native_1.View>
1802
+ </react_native_1.View>
1803
+
1804
+ {/* Segmented picker — only visible tabs are offered */}
1805
+ <react_native_1.View style={{
1806
+ flexDirection: 'row',
1807
+ flexWrap: 'wrap',
1808
+ backgroundColor: AppColors_1.AppColors.grayBackground,
1809
+ borderRadius: 8,
1810
+ padding: 2.5,
1811
+ marginTop: 10,
1812
+ borderWidth: 1,
1813
+ borderColor: AppColors_1.AppColors.dividerColor,
1814
+ gap: 2,
1815
+ }}>
1816
+ {settingsTabs
1817
+ .filter(tab => tab.key === 'apis' || tabVisibility[tab.key])
1818
+ .map(tab => {
1819
+ const isActive = defaultTab === tab.key;
1820
+ return (<TouchableScale_1.default key={tab.key} onPress={() => setDefaultTab(tab.key)} style={{
1821
+ paddingVertical: 6,
1822
+ paddingHorizontal: 10,
1823
+ alignItems: 'center',
1824
+ borderRadius: 6,
1825
+ backgroundColor: isActive
1826
+ ? AppColors_1.AppColors.purple
1827
+ : 'transparent',
1828
+ }}>
1829
+ <react_native_1.Text style={{
1830
+ fontFamily: AppFonts_1.AppFonts.interBold,
1831
+ fontSize: 11,
1832
+ color: isActive
1833
+ ? '#FFFFFF'
1834
+ : AppColors_1.AppColors.grayText,
1835
+ }}>
1836
+ {tab.label}
1837
+ </react_native_1.Text>
1838
+ </TouchableScale_1.default>);
1839
+ })}
1840
+ </react_native_1.View>
1841
+ </react_native_1.View>
1842
+
1843
+ {/* Divider */}
1844
+ <react_native_1.View style={{
1845
+ height: 1,
1846
+ backgroundColor: AppColors_1.AppColors.dividerColor,
1847
+ }}/>
1848
+
1849
+ {/* #9 — Show Duplicate Logs */}
1850
+ <react_native_1.View style={{
1851
+ flexDirection: 'row',
1852
+ alignItems: 'center',
1853
+ paddingVertical: 12,
1854
+ paddingHorizontal: 14,
1855
+ gap: 12,
1856
+ }}>
1857
+ <react_native_1.View style={{
1858
+ flex: 1,
1859
+ flexDirection: 'row',
1860
+ alignItems: 'center',
1861
+ gap: 8,
1862
+ }}>
1863
+ <react_native_1.View style={{
1864
+ width: 20,
1865
+ height: 20,
1866
+ borderRadius: 6,
1867
+ backgroundColor: AppColors_1.AppColors.purpleShade50,
1868
+ borderWidth: 1,
1869
+ borderColor: 'rgba(104,75,155,0.2)',
1870
+ alignItems: 'center',
1871
+ justifyContent: 'center',
1872
+ }}>
1873
+ <NetworkIcons_1.EyeIcon color={AppColors_1.AppColors.purple} size={11}/>
1874
+ </react_native_1.View>
1875
+ <react_native_1.View style={{ flex: 1 }}>
1876
+ <react_native_1.Text style={{
1877
+ fontFamily: AppFonts_1.AppFonts.interBold,
1878
+ fontSize: 13,
1879
+ color: AppColors_1.AppColors.primaryBlack,
1880
+ }}>
1881
+ Show Duplicate Logs
1882
+ </react_native_1.Text>
1883
+ <react_native_1.Text style={{
1884
+ fontFamily: AppFonts_1.AppFonts.interRegular,
1885
+ fontSize: 11,
1886
+ color: AppColors_1.AppColors.grayText,
1887
+ marginTop: 1,
1888
+ }}>
1889
+ Off: repeated identical entries collapse into one row
1890
+ with a ×N count
1891
+ </react_native_1.Text>
1892
+ </react_native_1.View>
1893
+ </react_native_1.View>
1894
+
1895
+ {/* Toggle Switch */}
1896
+ <TouchableScale_1.default onPress={() => setShowDuplicateLogs(prev => !prev)} style={{
1897
+ width: 38,
1898
+ height: 22,
1899
+ borderRadius: 11,
1900
+ backgroundColor: showDuplicateLogs
1901
+ ? AppColors_1.AppColors.purple
1902
+ : AppColors_1.AppColors.grayBorderSecondary,
1903
+ padding: 2,
1904
+ justifyContent: 'center',
1905
+ alignItems: showDuplicateLogs ? 'flex-end' : 'flex-start',
1906
+ }}>
1907
+ <react_native_1.View style={{
1908
+ width: 18,
1909
+ height: 18,
1910
+ borderRadius: 9,
1911
+ backgroundColor: '#FFFFFF',
1912
+ shadowColor: '#000',
1913
+ shadowOpacity: 0.15,
1914
+ shadowRadius: 1.5,
1915
+ shadowOffset: { width: 0, height: 1 },
1916
+ }}/>
1917
+ </TouchableScale_1.default>
1918
+ </react_native_1.View>
1429
1919
  </react_native_1.View>
1430
1920
  </react_native_1.View>
1431
1921
  </react_native_1.ScrollView>
@@ -2528,50 +3018,6 @@ const NetworkInspector = ({ enabled = true, }) => {
2528
3018
  const lastActionMap = reduxLastActionMap;
2529
3019
  const actionHistory = reduxActionHistory;
2530
3020
  return (<react_native_1.ScrollView style={styles_1.default.detailScroll} contentContainerStyle={{ paddingBottom: 24 }}>
2531
- {/* Top Summary Card */}
2532
- <react_native_1.View style={{
2533
- backgroundColor: AppColors_1.AppColors.primaryLight,
2534
- borderRadius: 12,
2535
- borderWidth: 1,
2536
- borderColor: AppColors_1.AppColors.grayBorderSecondary,
2537
- padding: 14,
2538
- marginHorizontal: 16,
2539
- marginTop: 12,
2540
- marginBottom: 12,
2541
- flexDirection: 'row',
2542
- alignItems: 'center',
2543
- gap: 12,
2544
- }}>
2545
- <react_native_1.View style={{
2546
- width: 44,
2547
- height: 44,
2548
- borderRadius: 10,
2549
- backgroundColor: AppColors_1.AppColors.purpleShade50,
2550
- alignItems: 'center',
2551
- justifyContent: 'center',
2552
- }}>
2553
- <NetworkIcons_1.TerminalIcon color={AppColors_1.AppColors.purple} size={20}/>
2554
- </react_native_1.View>
2555
- <react_native_1.View style={{ flex: 1 }}>
2556
- <react_native_1.Text style={{
2557
- fontFamily: AppFonts_1.AppFonts.interBold,
2558
- fontSize: 13,
2559
- color: AppColors_1.AppColors.primaryBlack,
2560
- }}>
2561
- Redux Store Snapshot
2562
- </react_native_1.Text>
2563
- <react_native_1.Text style={{
2564
- fontFamily: AppFonts_1.AppFonts.interRegular,
2565
- fontSize: 11,
2566
- color: AppColors_1.AppColors.grayText,
2567
- marginTop: 2,
2568
- }}>
2569
- Total size: {(0, helpers_1.getSize)(reduxState)} • {reducerKeys.length} Reducers
2570
- </react_native_1.Text>
2571
- </react_native_1.View>
2572
- <CopyButton_1.default value={() => reduxState} label="Overall Store"/>
2573
- </react_native_1.View>
2574
-
2575
3021
  {/* Tab View Selection Segments */}
2576
3022
  <react_native_1.View style={{
2577
3023
  flexDirection: 'row',
@@ -2579,6 +3025,7 @@ const NetworkInspector = ({ enabled = true, }) => {
2579
3025
  borderRadius: 10,
2580
3026
  padding: 3,
2581
3027
  marginHorizontal: 16,
3028
+ marginTop: 12,
2582
3029
  marginBottom: 12,
2583
3030
  borderWidth: 1,
2584
3031
  borderColor: AppColors_1.AppColors.dividerColor,
@@ -2614,6 +3061,27 @@ const NetworkInspector = ({ enabled = true, }) => {
2614
3061
  }}>
2615
3062
  Action Timeline
2616
3063
  </react_native_1.Text>
3064
+ <react_native_1.View style={{
3065
+ minWidth: 18,
3066
+ paddingHorizontal: 5,
3067
+ height: 16,
3068
+ borderRadius: 8,
3069
+ alignItems: 'center',
3070
+ justifyContent: 'center',
3071
+ backgroundColor: reduxActiveSubTab === 'timeline'
3072
+ ? 'rgba(255,255,255,0.28)'
3073
+ : AppColors_1.AppColors.dividerColor,
3074
+ }}>
3075
+ <react_native_1.Text style={{
3076
+ fontFamily: AppFonts_1.AppFonts.interBold,
3077
+ fontSize: 9,
3078
+ color: reduxActiveSubTab === 'timeline'
3079
+ ? '#FFFFFF'
3080
+ : AppColors_1.AppColors.grayText,
3081
+ }}>
3082
+ {actionHistory.length}
3083
+ </react_native_1.Text>
3084
+ </react_native_1.View>
2617
3085
  </react_native_1.View>
2618
3086
  </react_native_1.TouchableOpacity>
2619
3087
  <react_native_1.TouchableOpacity onPress={() => {
@@ -2643,6 +3111,27 @@ const NetworkInspector = ({ enabled = true, }) => {
2643
3111
  }}>
2644
3112
  Store Tree
2645
3113
  </react_native_1.Text>
3114
+ <react_native_1.View style={{
3115
+ minWidth: 18,
3116
+ paddingHorizontal: 5,
3117
+ height: 16,
3118
+ borderRadius: 8,
3119
+ alignItems: 'center',
3120
+ justifyContent: 'center',
3121
+ backgroundColor: reduxActiveSubTab === 'tree'
3122
+ ? 'rgba(255,255,255,0.28)'
3123
+ : AppColors_1.AppColors.dividerColor,
3124
+ }}>
3125
+ <react_native_1.Text style={{
3126
+ fontFamily: AppFonts_1.AppFonts.interBold,
3127
+ fontSize: 9,
3128
+ color: reduxActiveSubTab === 'tree'
3129
+ ? '#FFFFFF'
3130
+ : AppColors_1.AppColors.grayText,
3131
+ }}>
3132
+ {reducerKeys.length}
3133
+ </react_native_1.Text>
3134
+ </react_native_1.View>
2646
3135
  </react_native_1.View>
2647
3136
  </react_native_1.TouchableOpacity>
2648
3137
  </react_native_1.View>
@@ -2689,21 +3178,50 @@ const NetworkInspector = ({ enabled = true, }) => {
2689
3178
  };
2690
3179
  return (<>
2691
3180
  {hasNavigationContext && (<NavigationTracker onStateChange={setNavState}/>)}
2692
- <TouchableScale_1.default style={styles_1.default.fabWrapper} onPress={() => setVisible(true)} hitSlop={10}>
2693
- <react_native_1.Animated.View style={[styles_1.default.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
2694
- <NetworkIcons_1.BrandCircleIcon size={62}/>
2695
- {(logs.length > 0 || analyticsEvents.length > 0) && (<react_native_1.Animated.View style={[
3181
+ <react_native_1.Animated.View style={[styles_1.default.fabWrapper, { transform: fabPan.getTranslateTransform() }]} {...fabPanResponder.panHandlers}>
3182
+ <TouchableScale_1.default style={{ alignItems: 'center', justifyContent: 'center' }} onPress={() => {
3183
+ if (fabDraggedRef.current)
3184
+ return;
3185
+ setVisible(true);
3186
+ }} hitSlop={10}>
3187
+ <react_native_1.Animated.View style={[styles_1.default.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
3188
+ <NetworkIcons_1.BrandCircleIcon size={62}/>
3189
+ {/* #4 — shining sweep, clipped inside the circular launcher */}
3190
+ <react_native_1.View pointerEvents="none" style={styles_1.default.fabShineClip}>
3191
+ <react_native_1.Animated.View style={[
3192
+ styles_1.default.fabShineStreak,
3193
+ {
3194
+ transform: [
3195
+ {
3196
+ translateX: fabShineAnim.interpolate({
3197
+ inputRange: [0, 1],
3198
+ outputRange: [-48, 96],
3199
+ }),
3200
+ },
3201
+ { rotate: '25deg' },
3202
+ ],
3203
+ },
3204
+ ]}>
3205
+ <react_native_linear_gradient_1.default colors={[
3206
+ 'rgba(255,255,255,0)',
3207
+ 'rgba(255,255,255,0.55)',
3208
+ 'rgba(255,255,255,0)',
3209
+ ]} start={{ x: 0, y: 0.5 }} end={{ x: 1, y: 0.5 }} style={{ flex: 1 }}/>
3210
+ </react_native_1.Animated.View>
3211
+ </react_native_1.View>
3212
+ {(logs.length > 0 || analyticsEvents.length > 0) && (<react_native_1.Animated.View style={[
2696
3213
  styles_1.default.fabBadge,
2697
3214
  hasErrors ? styles_1.default.fabBadgeError : styles_1.default.fabBadgeNormal,
2698
3215
  { transform: [{ scale: badgeAnim }] },
2699
3216
  ]}>
2700
- <react_native_1.Text style={styles_1.default.fabBadgeText}>
2701
- {logs.length + analyticsEvents.length > 99
3217
+ <react_native_1.Text style={styles_1.default.fabBadgeText}>
3218
+ {logs.length + analyticsEvents.length > 99
2702
3219
  ? '99+'
2703
3220
  : logs.length + analyticsEvents.length}
2704
- </react_native_1.Text>
2705
- </react_native_1.Animated.View>)}
2706
- </TouchableScale_1.default>
3221
+ </react_native_1.Text>
3222
+ </react_native_1.Animated.View>)}
3223
+ </TouchableScale_1.default>
3224
+ </react_native_1.Animated.View>
2707
3225
 
2708
3226
  <react_native_1.Modal visible={visible} animationType="slide" transparent>
2709
3227
  {visible && (<ErrorBoundary_1.default onClose={closeModal}>
@@ -2733,10 +3251,27 @@ const NetworkInspector = ({ enabled = true, }) => {
2733
3251
  setSelectedEvent(null);
2734
3252
  });
2735
3253
  }} hitSlop={15} style={[
2736
- styles_1.default.iconBtnMinimal,
3254
+ {
3255
+ width: 38,
3256
+ height: 38,
3257
+ borderRadius: 19,
3258
+ alignItems: 'center',
3259
+ justifyContent: 'center',
3260
+ backgroundColor: 'rgba(255,255,255,0.18)',
3261
+ borderWidth: 1,
3262
+ borderColor: 'rgba(255,255,255,0.30)',
3263
+ },
2737
3264
  selected == null &&
2738
3265
  selectedEvent == null && { display: 'none' },
2739
3266
  ]}>
3267
+ {/* Soft outer glow to fake a blurred circle */}
3268
+ <react_native_1.View style={{
3269
+ position: 'absolute',
3270
+ width: 48,
3271
+ height: 48,
3272
+ borderRadius: 24,
3273
+ backgroundColor: 'rgba(255,255,255,0.10)',
3274
+ }}/>
2740
3275
  <NetworkIcons_1.WhiteBackNavigation />
2741
3276
  </TouchableScale_1.default>
2742
3277
 
@@ -2747,8 +3282,8 @@ const NetworkInspector = ({ enabled = true, }) => {
2747
3282
  flex: 1,
2748
3283
  }}>
2749
3284
  <react_native_1.View style={{
2750
- width: 42,
2751
- height: 42,
3285
+ width: 50,
3286
+ height: 50,
2752
3287
  borderRadius: 10,
2753
3288
  backgroundColor: 'rgba(255,255,255,0.13)',
2754
3289
  borderWidth: 1.5,
@@ -2760,13 +3295,10 @@ const NetworkInspector = ({ enabled = true, }) => {
2760
3295
  shadowRadius: 4,
2761
3296
  shadowOffset: { width: 0, height: 2 },
2762
3297
  }}>
2763
- <NetworkIcons_1.BrandSquareIcon size={36}/>
3298
+ <NetworkIcons_1.BrandSquareIcon size={45}/>
2764
3299
  </react_native_1.View>
2765
3300
  <react_native_1.View style={{ gap: 3 }}>
2766
- <react_native_1.Text style={[
2767
- styles_1.default.headerTitle,
2768
- { fontSize: 17, letterSpacing: 0.2 },
2769
- ]}>
3301
+ <react_native_1.Text style={[styles_1.default.headerTitle]}>
2770
3302
  RN InApp Inspector
2771
3303
  </react_native_1.Text>
2772
3304
  <react_native_1.View style={{
@@ -2849,6 +3381,29 @@ const NetworkInspector = ({ enabled = true, }) => {
2849
3381
  </react_native_1.Text>
2850
3382
  </react_native_1.View>
2851
3383
  </react_native_1.View>
3384
+
3385
+ {/* #1 — pulsing dot when a newer version is on NPM */}
3386
+ {updateAvailable && (<react_native_1.Pressable hitSlop={10} onPress={() => react_native_1.Alert.alert('Update Available', `react-native-inapp-inspector v${latestNpmVersion} is available on NPM (installed: v${constants_1.LIB_VERSION}).`, [
3387
+ { text: 'Later', style: 'cancel' },
3388
+ {
3389
+ text: 'View on NPM',
3390
+ onPress: () => react_native_1.Linking.openURL('https://www.npmjs.com/package/react-native-inapp-inspector').catch(() => { }),
3391
+ },
3392
+ ])} style={{
3393
+ alignItems: 'center',
3394
+ justifyContent: 'center',
3395
+ }}>
3396
+ <react_native_1.Animated.View style={{
3397
+ width: 8,
3398
+ height: 8,
3399
+ borderRadius: 4,
3400
+ backgroundColor: '#4ADE80',
3401
+ borderWidth: 1,
3402
+ borderColor: 'rgba(255,255,255,0.9)',
3403
+ opacity: activePulseAnim,
3404
+ transform: [{ scale: unreadPulseAnim }],
3405
+ }}/>
3406
+ </react_native_1.Pressable>)}
2852
3407
  </react_native_1.View>
2853
3408
  </react_native_1.View>
2854
3409
  </react_native_1.View>) : null}
@@ -2873,21 +3428,48 @@ const NetworkInspector = ({ enabled = true, }) => {
2873
3428
  </react_native_1.Text>
2874
3429
  </react_native_1.View>
2875
3430
  <react_native_1.View style={styles_1.default.headerDetailSubRow}>
2876
- <react_native_1.View style={[
3431
+ <react_native_1.View style={{
3432
+ flexDirection: 'row',
3433
+ alignItems: 'center',
3434
+ gap: 5,
3435
+ paddingHorizontal: 8,
3436
+ paddingVertical: 3,
3437
+ borderRadius: 20,
3438
+ backgroundColor: `${(0, helpers_1.getStatusColor)(selected.status)}26`,
3439
+ borderWidth: 1,
3440
+ borderColor: `${(0, helpers_1.getStatusColor)(selected.status)}55`,
3441
+ }}>
3442
+ <react_native_1.View style={[
2877
3443
  styles_1.default.headerStatusDot,
2878
3444
  {
2879
3445
  backgroundColor: (0, helpers_1.getStatusColor)(selected.status),
2880
3446
  },
2881
3447
  ]}/>
2882
- <react_native_1.Text style={styles_1.default.headerSubTitle}>
2883
- {selected.status === 0
3448
+ <react_native_1.Text style={[
3449
+ styles_1.default.headerSubTitle,
3450
+ { fontFamily: AppFonts_1.AppFonts.interBold },
3451
+ ]}>
3452
+ {selected.status === 0
2884
3453
  ? 'Failed'
2885
- : selected.status ?? 'Pending'}{' '}
2886
- •{' '}
2887
- {selected.duration != null
3454
+ : selected.status ?? 'Pending'}
3455
+ </react_native_1.Text>
3456
+ </react_native_1.View>
3457
+ <react_native_1.View style={{
3458
+ flexDirection: 'row',
3459
+ alignItems: 'center',
3460
+ gap: 4,
3461
+ paddingHorizontal: 8,
3462
+ paddingVertical: 3,
3463
+ borderRadius: 20,
3464
+ backgroundColor: 'rgba(255,255,255,0.16)',
3465
+ }}>
3466
+ <NetworkIcons_1.ClockIcon color="#FFFFFF" size={11}/>
3467
+ <react_native_1.Text style={styles_1.default.headerSubTitle}>
3468
+ {selected.duration != null
2888
3469
  ? `${selected.duration}ms`
2889
- : '-'}
2890
- </react_native_1.Text>
3470
+ : ''}
3471
+ </react_native_1.Text>
3472
+ </react_native_1.View>
2891
3473
  </react_native_1.View>
2892
3474
  </react_native_1.View>) : selectedEvent != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
2893
3475
  <react_native_1.View style={styles_1.default.headerDetailRow}>
@@ -2930,7 +3512,50 @@ const NetworkInspector = ({ enabled = true, }) => {
2930
3512
  </react_native_1.View>) : null}
2931
3513
  </react_native_1.View>
2932
3514
 
2933
- <react_native_1.View style={styles_1.default.headerRight}>
3515
+ <react_native_1.View style={[
3516
+ styles_1.default.headerRight,
3517
+ selected == null &&
3518
+ selectedEvent == null && {
3519
+ flexShrink: 0,
3520
+ minWidth: 116,
3521
+ },
3522
+ ]}>
3523
+ {selected == null && selectedEvent == null && (<TouchableScale_1.default onPress={() => {
3524
+ react_native_1.Alert.alert('Clear Everything', 'This clears all tabs — APIs, Logs, Analytics, WebView and Redux timeline. Continue?', [
3525
+ { text: 'Cancel', style: 'cancel' },
3526
+ {
3527
+ text: 'Clear All',
3528
+ onPress: runClearAllWithAnimation,
3529
+ style: 'destructive',
3530
+ },
3531
+ ]);
3532
+ }} hitSlop={15} style={[
3533
+ styles_1.default.closeButtonSquare,
3534
+ {
3535
+ marginRight: 8,
3536
+ backgroundColor: 'rgba(255,255,255,0.15)',
3537
+ },
3538
+ ]}>
3539
+ <react_native_1.Animated.View style={{
3540
+ transform: [
3541
+ {
3542
+ rotate: clearAnim.interpolate({
3543
+ inputRange: [0, 1],
3544
+ outputRange: ['0deg', '-25deg'],
3545
+ }),
3546
+ },
3547
+ {
3548
+ scale: clearAnim.interpolate({
3549
+ inputRange: [0, 0.5, 1],
3550
+ outputRange: [1, 1.25, 1],
3551
+ }),
3552
+ },
3553
+ ],
3554
+ }}>
3555
+ <NetworkIcons_1.WipeIcon color="#FFFFFF" size={16}/>
3556
+ </react_native_1.Animated.View>
3557
+ </TouchableScale_1.default>)}
3558
+
2934
3559
  {selected == null && selectedEvent == null && (<TouchableScale_1.default onPress={() => setSettingsPage('main')} hitSlop={15} style={[
2935
3560
  styles_1.default.closeButtonSquare,
2936
3561
  {
@@ -3107,7 +3732,16 @@ const NetworkInspector = ({ enabled = true, }) => {
3107
3732
  animateNextLayout();
3108
3733
  setAnalyticsSubTab('ga_events');
3109
3734
  }}>
3110
- <react_native_1.Text style={[
3735
+ <react_native_1.View style={{
3736
+ flexDirection: 'row',
3737
+ alignItems: 'center',
3738
+ gap: 6,
3739
+ }}>
3740
+ {/* #7 */}
3741
+ <NetworkIcons_1.AnalyticsIcon size={13} color={analyticsSubTab === 'ga_events'
3742
+ ? AppColors_1.AppColors.purple
3743
+ : AppColors_1.AppColors.grayTextStrong}/>
3744
+ <react_native_1.Text style={[
3111
3745
  {
3112
3746
  fontFamily: AppFonts_1.AppFonts.interMedium,
3113
3747
  fontSize: 13,
@@ -3118,12 +3752,13 @@ const NetworkInspector = ({ enabled = true, }) => {
3118
3752
  color: AppColors_1.AppColors.purple,
3119
3753
  },
3120
3754
  ]}>
3121
- GA Events (
3122
- {analyticsSearch
3755
+ GA Events (
3756
+ {analyticsSearch
3123
3757
  ? filteredAnalyticsEvents.length
3124
3758
  : analyticsEvents.length}
3125
- )
3126
- </react_native_1.Text>
3759
+ )
3760
+ </react_native_1.Text>
3761
+ </react_native_1.View>
3127
3762
  </react_native_1.Pressable>
3128
3763
  <react_native_1.Pressable style={[
3129
3764
  {
@@ -3144,7 +3779,16 @@ const NetworkInspector = ({ enabled = true, }) => {
3144
3779
  animateNextLayout();
3145
3780
  setAnalyticsSubTab('top_events');
3146
3781
  }}>
3147
- <react_native_1.Text style={[
3782
+ <react_native_1.View style={{
3783
+ flexDirection: 'row',
3784
+ alignItems: 'center',
3785
+ gap: 6,
3786
+ }}>
3787
+ {/* #7 */}
3788
+ <NetworkIcons_1.TrendingUpIcon size={13} color={analyticsSubTab === 'top_events'
3789
+ ? AppColors_1.AppColors.purple
3790
+ : AppColors_1.AppColors.grayTextStrong}/>
3791
+ <react_native_1.Text style={[
3148
3792
  {
3149
3793
  fontFamily: AppFonts_1.AppFonts.interMedium,
3150
3794
  fontSize: 13,
@@ -3155,8 +3799,9 @@ const NetworkInspector = ({ enabled = true, }) => {
3155
3799
  color: AppColors_1.AppColors.purple,
3156
3800
  },
3157
3801
  ]}>
3158
- Top Events ({topEventsArray.length})
3159
- </react_native_1.Text>
3802
+ Top Events ({topEventsArray.length})
3803
+ </react_native_1.Text>
3804
+ </react_native_1.View>
3160
3805
  </react_native_1.Pressable>
3161
3806
  </react_native_1.View>
3162
3807
  </react_native_1.View>)}
@@ -3265,50 +3910,53 @@ const NetworkInspector = ({ enabled = true, }) => {
3265
3910
  filteredAnalyticsEvents.length === 0 && {
3266
3911
  flexGrow: 1,
3267
3912
  },
3268
- ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'apis' && selected == null ? (<react_native_1.FlatList data={groupedData} keyExtractor={item => item?.id?.toString()} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<react_native_1.View style={{ marginTop: 8 }}>
3269
- <react_native_1.View style={styles_1.default.toolbarRow}>
3270
- <react_native_1.View style={styles_1.default.searchContainer}>
3271
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
3272
- <react_native_1.TextInput placeholder="Search endpoints..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
3273
- {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
3274
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
3275
- </react_native_1.Pressable>)}
3276
- </react_native_1.View>
3913
+ ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'apis' && selected == null ? (<react_native_1.View style={{ flex: 1 }}>
3914
+ <react_native_1.FlatList ref={apisListRef} data={groupedData} keyExtractor={item => item?.id?.toString()} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<react_native_1.View style={{ marginTop: 8 }}>
3915
+ <react_native_1.View style={styles_1.default.toolbarRow}>
3916
+ <react_native_1.View style={styles_1.default.searchContainer}>
3917
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
3918
+ <react_native_1.TextInput placeholder="Search endpoints..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
3919
+ {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
3920
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
3921
+ </react_native_1.Pressable>)}
3922
+ </react_native_1.View>
3277
3923
 
3278
- <react_native_1.View style={styles_1.default.toolbarRight}>
3279
- <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
3280
- <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
3281
- {selectedLogs.size > 0 && (<react_native_1.View style={styles_1.default.trashBadge}>
3282
- <react_native_1.Text style={styles_1.default.trashBadgeText}>
3283
- {selectedLogs.size}
3284
- </react_native_1.Text>
3285
- </react_native_1.View>)}
3286
- </TouchableScale_1.default>
3924
+ <react_native_1.View style={styles_1.default.toolbarRight}>
3925
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
3926
+ <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
3927
+ {selectedLogs.size > 0 && (<react_native_1.View style={styles_1.default.trashBadge}>
3928
+ <react_native_1.Text style={styles_1.default.trashBadgeText}>
3929
+ {selectedLogs.size}
3930
+ </react_native_1.Text>
3931
+ </react_native_1.View>)}
3932
+ </TouchableScale_1.default>
3287
3933
 
3288
- <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
3289
- <NetworkIcons_1.SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors_1.AppColors.grayTextStrong} size={18}/>
3290
- </TouchableScale_1.default>
3934
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
3935
+ <NetworkIcons_1.SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors_1.AppColors.grayTextStrong} size={18}/>
3936
+ </TouchableScale_1.default>
3291
3937
 
3292
- <TouchableScale_1.default style={[
3938
+ <TouchableScale_1.default style={[
3293
3939
  styles_1.default.toolbarBtn,
3294
3940
  filtersAccordion.isOpen &&
3295
3941
  styles_1.default.toolbarBtnActive,
3296
3942
  ]} onPress={filtersAccordion.toggleOpen} hitSlop={10}>
3297
- <NetworkIcons_1.FilterIcon color={filtersAccordion.isOpen
3943
+ <NetworkIcons_1.FilterIcon color={filtersAccordion.isOpen
3298
3944
  ? AppColors_1.AppColors.purple
3299
3945
  : AppColors_1.AppColors.grayTextStrong} size={18}/>
3300
- </TouchableScale_1.default>
3946
+ </TouchableScale_1.default>
3947
+ </react_native_1.View>
3301
3948
  </react_native_1.View>
3302
- </react_native_1.View>
3303
3949
 
3304
- <react_native_1.Animated.View style={[
3950
+ <react_native_1.Animated.View style={[
3305
3951
  filtersAccordion.bodyStyle,
3306
3952
  { overflow: 'hidden' },
3307
3953
  ]}>
3308
- <react_native_1.View style={styles_1.default.filtersContainer}>
3309
- <react_native_1.Text style={styles_1.default.filtersHeading}>STATUS</react_native_1.Text>
3310
- <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
3311
- {constants_1.STATUS_FILTERS.map(filter => {
3954
+ <react_native_1.View style={styles_1.default.filtersContainer}>
3955
+ <react_native_1.Text style={styles_1.default.filtersHeading}>
3956
+ STATUS
3957
+ </react_native_1.Text>
3958
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
3959
+ {constants_1.STATUS_FILTERS.map(filter => {
3312
3960
  const isAll = filter === 'ALL';
3313
3961
  const active = isAll
3314
3962
  ? statusFilters.size === 0
@@ -3327,38 +3975,38 @@ const NetworkInspector = ({ enabled = true, }) => {
3327
3975
  });
3328
3976
  }
3329
3977
  }} hitSlop={10}>
3330
- {active ? (<react_native_1.View style={[
3978
+ {active ? (<react_native_1.View style={[
3331
3979
  styles_1.default.statusFilterChip,
3332
3980
  styles_1.default.statusFilterActive,
3333
3981
  { overflow: 'hidden' },
3334
3982
  ]}>
3335
- <react_native_linear_gradient_1.default colors={[
3983
+ <react_native_linear_gradient_1.default colors={[
3336
3984
  AppColors_1.AppColors.purpleShade50,
3337
3985
  '#EAE5FF',
3338
3986
  ]} style={react_native_1.StyleSheet.absoluteFill} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}/>
3339
- <react_native_1.Text style={[
3987
+ <react_native_1.Text style={[
3340
3988
  styles_1.default.statusFilterText,
3341
3989
  { color: AppColors_1.AppColors.purple },
3342
3990
  ]}>
3343
- {filter}
3344
- </react_native_1.Text>
3345
- </react_native_1.View>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
3346
- <react_native_1.Text style={styles_1.default.statusFilterText}>
3347
- {filter}
3348
- </react_native_1.Text>
3349
- </react_native_1.View>)}
3350
- </TouchableScale_1.default>);
3991
+ {filter}
3992
+ </react_native_1.Text>
3993
+ </react_native_1.View>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
3994
+ <react_native_1.Text style={styles_1.default.statusFilterText}>
3995
+ {filter}
3996
+ </react_native_1.Text>
3997
+ </react_native_1.View>)}
3998
+ </TouchableScale_1.default>);
3351
3999
  })}
3352
- </react_native_1.ScrollView>
4000
+ </react_native_1.ScrollView>
3353
4001
 
3354
- <react_native_1.Text style={[
4002
+ <react_native_1.Text style={[
3355
4003
  styles_1.default.filtersHeading,
3356
4004
  { marginTop: 16 },
3357
4005
  ]}>
3358
- METHOD
3359
- </react_native_1.Text>
3360
- <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
3361
- {availableMethods.map(filter => {
4006
+ METHOD
4007
+ </react_native_1.Text>
4008
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
4009
+ {availableMethods.map(filter => {
3362
4010
  const isAll = filter === 'ALL';
3363
4011
  const active = isAll
3364
4012
  ? methodFilters.size === 0
@@ -3377,43 +4025,55 @@ const NetworkInspector = ({ enabled = true, }) => {
3377
4025
  });
3378
4026
  }
3379
4027
  }} hitSlop={10}>
3380
- {active ? (<react_native_1.View style={[
4028
+ {active ? (<react_native_1.View style={[
3381
4029
  styles_1.default.statusFilterChip,
3382
4030
  styles_1.default.statusFilterActive,
3383
4031
  { overflow: 'hidden' },
3384
4032
  ]}>
3385
- <react_native_linear_gradient_1.default colors={[
4033
+ <react_native_linear_gradient_1.default colors={[
3386
4034
  AppColors_1.AppColors.purpleShade50,
3387
4035
  '#EAE5FF',
3388
4036
  ]} style={react_native_1.StyleSheet.absoluteFill} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}/>
3389
- <react_native_1.Text style={[
4037
+ <react_native_1.Text style={[
3390
4038
  styles_1.default.statusFilterText,
3391
4039
  { color: AppColors_1.AppColors.purple },
3392
4040
  ]}>
3393
- {filter}
3394
- </react_native_1.Text>
3395
- </react_native_1.View>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
3396
- <react_native_1.Text style={styles_1.default.statusFilterText}>
3397
- {filter}
3398
- </react_native_1.Text>
3399
- </react_native_1.View>)}
3400
- </TouchableScale_1.default>);
4041
+ {filter}
4042
+ </react_native_1.Text>
4043
+ </react_native_1.View>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
4044
+ <react_native_1.Text style={styles_1.default.statusFilterText}>
4045
+ {filter}
4046
+ </react_native_1.Text>
4047
+ </react_native_1.View>)}
4048
+ </TouchableScale_1.default>);
3401
4049
  })}
3402
- </react_native_1.ScrollView>
3403
- </react_native_1.View>
3404
- </react_native_1.Animated.View>
4050
+ </react_native_1.ScrollView>
4051
+ </react_native_1.View>
4052
+ </react_native_1.Animated.View>
3405
4053
 
3406
- {(search ||
4054
+ {(search ||
3407
4055
  statusFilters.size > 0 ||
3408
4056
  methodFilters.size > 0) && (<react_native_1.Text style={styles_1.default.resultCount}>
3409
- {filteredLogs.length === logs.length
4057
+ {filteredLogs.length === logs.length
3410
4058
  ? `${logs.length} requests`
3411
4059
  : `${filteredLogs.length} of ${logs.length} filtered requests`}
3412
- </react_native_1.Text>)}
3413
- </react_native_1.View>} ListEmptyComponent={<EmptyState_1.default isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
4060
+ </react_native_1.Text>)}
4061
+ </react_native_1.View>} ListEmptyComponent={<EmptyState_1.default isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
3414
4062
  styles_1.default.listContent,
3415
4063
  filteredLogs.length === 0 && { flexGrow: 1 },
3416
- ]} keyboardShouldPersistTaps="handled"/>) : activeTab === 'logs' ? (<react_native_1.View style={{ flex: 1 }}>
4064
+ ]} keyboardShouldPersistTaps="handled"/>
4065
+ {/* #2 — always-visible scroll-to-top, bottom right */}
4066
+ <TouchableScale_1.default onPress={() => {
4067
+ apisListRef.current?.scrollToOffset({
4068
+ offset: 0,
4069
+ animated: true,
4070
+ });
4071
+ }} hitSlop={10} style={styles_1.default.scrollTopBtn}>
4072
+ <react_native_1.View style={{ transform: [{ rotate: '180deg' }] }}>
4073
+ <NetworkIcons_1.ChevronIcon color="#FFFFFF" size={18}/>
4074
+ </react_native_1.View>
4075
+ </TouchableScale_1.default>
4076
+ </react_native_1.View>) : activeTab === 'logs' ? (<react_native_1.View style={{ flex: 1 }}>
3417
4077
  <react_native_1.View style={{
3418
4078
  backgroundColor: '#FFFFFF',
3419
4079
  borderBottomWidth: 1,
@@ -3433,6 +4093,9 @@ const NetworkInspector = ({ enabled = true, }) => {
3433
4093
  </react_native_1.View>
3434
4094
 
3435
4095
  <react_native_1.View style={styles_1.default.toolbarRight}>
4096
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setLogSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
4097
+ <NetworkIcons_1.SortArrowIcon color={AppColors_1.AppColors.grayTextStrong} size={18} direction={logSortOrder === 'newest' ? 'down' : 'up'}/>
4098
+ </TouchableScale_1.default>
3436
4099
  <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
3437
4100
  <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
3438
4101
  </TouchableScale_1.default>
@@ -3458,15 +4121,25 @@ const NetworkInspector = ({ enabled = true, }) => {
3458
4121
  backgroundColor: '#F4EBFF',
3459
4122
  },
3460
4123
  ]}>
3461
- <react_native_1.Text numberOfLines={1} style={[
4124
+ {/* #7 */}
4125
+ <react_native_1.View style={{
4126
+ flexDirection: 'row',
4127
+ alignItems: 'center',
4128
+ gap: 5,
4129
+ }}>
4130
+ <NetworkIcons_1.LayersIcon size={12} color={active
4131
+ ? AppColors_1.AppColors.purpleShade700
4132
+ : AppColors_1.AppColors.grayTextStrong}/>
4133
+ <react_native_1.Text numberOfLines={1} style={[
3462
4134
  styles_1.default.statusFilterText,
3463
4135
  active && {
3464
4136
  color: AppColors_1.AppColors.purpleShade700,
3465
4137
  fontFamily: AppFonts_1.AppFonts.interBold,
3466
4138
  },
3467
4139
  ]}>
3468
- All ({logCounts.all})
3469
- </react_native_1.Text>
4140
+ All ({logCounts.all})
4141
+ </react_native_1.Text>
4142
+ </react_native_1.View>
3470
4143
  </react_native_1.View>
3471
4144
  </TouchableScale_1.default>);
3472
4145
  })()}
@@ -3492,15 +4165,25 @@ const NetworkInspector = ({ enabled = true, }) => {
3492
4165
  backgroundColor: '#F1F5F9',
3493
4166
  },
3494
4167
  ]}>
3495
- <react_native_1.Text numberOfLines={1} style={[
4168
+ {/* #7 */}
4169
+ <react_native_1.View style={{
4170
+ flexDirection: 'row',
4171
+ alignItems: 'center',
4172
+ gap: 5,
4173
+ }}>
4174
+ <NetworkIcons_1.UserIcon size={12} color={active
4175
+ ? '#334155'
4176
+ : AppColors_1.AppColors.grayTextStrong}/>
4177
+ <react_native_1.Text numberOfLines={1} style={[
3496
4178
  styles_1.default.statusFilterText,
3497
4179
  active && {
3498
4180
  color: '#334155',
3499
4181
  fontFamily: AppFonts_1.AppFonts.interBold,
3500
4182
  },
3501
4183
  ]}>
3502
- User Log ({logCounts['user-log']})
3503
- </react_native_1.Text>
4184
+ User Log ({logCounts['user-log']})
4185
+ </react_native_1.Text>
4186
+ </react_native_1.View>
3504
4187
  </react_native_1.View>
3505
4188
  </TouchableScale_1.default>);
3506
4189
  })()}
@@ -3526,15 +4209,25 @@ const NetworkInspector = ({ enabled = true, }) => {
3526
4209
  backgroundColor: AppColors_1.AppColors.purpleShade50,
3527
4210
  },
3528
4211
  ]}>
3529
- <react_native_1.Text numberOfLines={1} style={[
4212
+ {/* #7 */}
4213
+ <react_native_1.View style={{
4214
+ flexDirection: 'row',
4215
+ alignItems: 'center',
4216
+ gap: 5,
4217
+ }}>
4218
+ <NetworkIcons_1.InfoCircleIcon size={12} color={active
4219
+ ? AppColors_1.AppColors.purple
4220
+ : AppColors_1.AppColors.grayTextStrong}/>
4221
+ <react_native_1.Text numberOfLines={1} style={[
3530
4222
  styles_1.default.statusFilterText,
3531
4223
  active && {
3532
4224
  color: AppColors_1.AppColors.purple,
3533
4225
  fontFamily: AppFonts_1.AppFonts.interBold,
3534
4226
  },
3535
4227
  ]}>
3536
- Info ({logCounts.info})
3537
- </react_native_1.Text>
4228
+ Info ({logCounts.info})
4229
+ </react_native_1.Text>
4230
+ </react_native_1.View>
3538
4231
  </react_native_1.View>
3539
4232
  </TouchableScale_1.default>);
3540
4233
  })()}
@@ -3560,7 +4253,17 @@ const NetworkInspector = ({ enabled = true, }) => {
3560
4253
  backgroundColor: '#FFFDF6',
3561
4254
  },
3562
4255
  ]}>
3563
- <react_native_1.Text numberOfLines={1} style={[
4256
+ {/* #7 */}
4257
+ <react_native_1.View style={{
4258
+ flexDirection: 'row',
4259
+ alignItems: 'center',
4260
+ gap: 5,
4261
+ }}>
4262
+ <NetworkIcons_1.WarningTriangleIcon size={12} color={active
4263
+ ? AppColors_1.AppColors.darkOrange ||
4264
+ AppColors_1.AppColors.lightOrange
4265
+ : AppColors_1.AppColors.grayTextStrong}/>
4266
+ <react_native_1.Text numberOfLines={1} style={[
3564
4267
  styles_1.default.statusFilterText,
3565
4268
  active && {
3566
4269
  color: AppColors_1.AppColors.darkOrange ||
@@ -3568,8 +4271,9 @@ const NetworkInspector = ({ enabled = true, }) => {
3568
4271
  fontFamily: AppFonts_1.AppFonts.interBold,
3569
4272
  },
3570
4273
  ]}>
3571
- Warning ({logCounts.warn})
3572
- </react_native_1.Text>
4274
+ Warning ({logCounts.warn})
4275
+ </react_native_1.Text>
4276
+ </react_native_1.View>
3573
4277
  </react_native_1.View>
3574
4278
  </TouchableScale_1.default>);
3575
4279
  })()}
@@ -3595,15 +4299,25 @@ const NetworkInspector = ({ enabled = true, }) => {
3595
4299
  backgroundColor: '#FFF5F6',
3596
4300
  },
3597
4301
  ]}>
3598
- <react_native_1.Text numberOfLines={1} style={[
4302
+ {/* #7 */}
4303
+ <react_native_1.View style={{
4304
+ flexDirection: 'row',
4305
+ alignItems: 'center',
4306
+ gap: 5,
4307
+ }}>
4308
+ <NetworkIcons_1.ErrorCircleIcon size={12} color={active
4309
+ ? AppColors_1.AppColors.errorColor
4310
+ : AppColors_1.AppColors.grayTextStrong}/>
4311
+ <react_native_1.Text numberOfLines={1} style={[
3599
4312
  styles_1.default.statusFilterText,
3600
4313
  active && {
3601
4314
  color: AppColors_1.AppColors.errorColor,
3602
4315
  fontFamily: AppFonts_1.AppFonts.interBold,
3603
4316
  },
3604
4317
  ]}>
3605
- Error ({logCounts.error})
3606
- </react_native_1.Text>
4318
+ Error ({logCounts.error})
4319
+ </react_native_1.Text>
4320
+ </react_native_1.View>
3607
4321
  </react_native_1.View>
3608
4322
  </TouchableScale_1.default>);
3609
4323
  })()}
@@ -3629,15 +4343,25 @@ const NetworkInspector = ({ enabled = true, }) => {
3629
4343
  backgroundColor: `${AppColors_1.AppColors.skyBlue}15`,
3630
4344
  },
3631
4345
  ]}>
3632
- <react_native_1.Text numberOfLines={1} style={[
4346
+ {/* #7 */}
4347
+ <react_native_1.View style={{
4348
+ flexDirection: 'row',
4349
+ alignItems: 'center',
4350
+ gap: 5,
4351
+ }}>
4352
+ <NetworkIcons_1.AnalyticsIcon size={12} color={active
4353
+ ? AppColors_1.AppColors.skyBlue
4354
+ : AppColors_1.AppColors.grayTextStrong}/>
4355
+ <react_native_1.Text numberOfLines={1} style={[
3633
4356
  styles_1.default.statusFilterText,
3634
4357
  active && {
3635
4358
  color: AppColors_1.AppColors.skyBlue,
3636
4359
  fontFamily: AppFonts_1.AppFonts.interBold,
3637
4360
  },
3638
4361
  ]}>
3639
- Analytics ({logCounts.analytics})
3640
- </react_native_1.Text>
4362
+ Analytics ({logCounts.analytics})
4363
+ </react_native_1.Text>
4364
+ </react_native_1.View>
3641
4365
  </react_native_1.View>
3642
4366
  </TouchableScale_1.default>);
3643
4367
  })()}
@@ -4672,7 +5396,7 @@ const NetworkInspector = ({ enabled = true, }) => {
4672
5396
  if (!resExpanded && !showResDiff)
4673
5397
  setResExpanded(true);
4674
5398
  }}/>
4675
- {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : (<JsonViewer_1.default data={selected.response} search={detailSearch} forceOpen={resExpanded}/>)}
5399
+ {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : (<JsonViewer_1.default data={selected.response} search={detailSearch} forceOpen={resExpanded} wrap/>)}
4676
5400
  </react_native_1.View>
4677
5401
  </>)}
4678
5402
  </react_native_1.ScrollView>
@@ -4733,5 +5457,8 @@ var ErrorBoundary_2 = require("./components/ErrorBoundary");
4733
5457
  Object.defineProperty(exports, "ErrorBoundary", { enumerable: true, get: function () { return __importDefault(ErrorBoundary_2).default; } });
4734
5458
  var reduxLogger_2 = require("./customHooks/reduxLogger");
4735
5459
  Object.defineProperty(exports, "connectReduxStore", { enumerable: true, get: function () { return reduxLogger_2.connectReduxStore; } });
5460
+ Object.defineProperty(exports, "inspectorReduxMiddleware", { enumerable: true, get: function () { return reduxLogger_2.inspectorReduxMiddleware; } });
4736
5461
  Object.defineProperty(exports, "getReduxState", { enumerable: true, get: function () { return reduxLogger_2.getReduxState; } });
4737
5462
  Object.defineProperty(exports, "subscribeReduxState", { enumerable: true, get: function () { return reduxLogger_2.subscribeReduxState; } });
5463
+ Object.defineProperty(exports, "getActionHistory", { enumerable: true, get: function () { return reduxLogger_2.getActionHistory; } });
5464
+ Object.defineProperty(exports, "clearActionHistory", { enumerable: true, get: function () { return reduxLogger_2.clearActionHistory; } });