react-native-inapp-inspector 1.0.3 → 1.0.5

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 (47) hide show
  1. package/README.md +3 -3
  2. package/dist/commonjs/components/AnalyticsEventCard.js +10 -10
  3. package/dist/commonjs/components/CodeSnippet.js +233 -10
  4. package/dist/commonjs/components/ConsoleLogCard.js +55 -9
  5. package/dist/commonjs/components/CopyButton.js +2 -1
  6. package/dist/commonjs/components/ErrorBoundary.d.ts +20 -0
  7. package/dist/commonjs/components/ErrorBoundary.js +332 -0
  8. package/dist/commonjs/components/NetworkIcons.d.ts +5 -0
  9. package/dist/commonjs/components/NetworkIcons.js +45 -1
  10. package/dist/commonjs/customHooks/reduxLogger.d.ts +4 -0
  11. package/dist/commonjs/customHooks/reduxLogger.js +30 -0
  12. package/dist/commonjs/customHooks/webViewLogger.d.ts +2 -0
  13. package/dist/commonjs/customHooks/webViewLogger.js +281 -246
  14. package/dist/commonjs/helpers/index.js +2 -1
  15. package/dist/commonjs/index.d.ts +5 -3
  16. package/dist/commonjs/index.js +685 -911
  17. package/dist/commonjs/styles/AppColors.d.ts +29 -1
  18. package/dist/commonjs/styles/AppColors.js +38 -2
  19. package/dist/commonjs/styles/index.d.ts +438 -229
  20. package/dist/commonjs/styles/index.js +448 -209
  21. package/dist/commonjs/types/index.d.ts +2 -2
  22. package/dist/esm/components/AnalyticsEventCard.js +10 -10
  23. package/dist/esm/components/CodeSnippet.js +232 -12
  24. package/dist/esm/components/ConsoleLogCard.js +55 -9
  25. package/dist/esm/components/CopyButton.js +2 -1
  26. package/dist/esm/components/ErrorBoundary.d.ts +20 -0
  27. package/dist/esm/components/ErrorBoundary.js +295 -0
  28. package/dist/esm/components/NetworkIcons.d.ts +5 -0
  29. package/dist/esm/components/NetworkIcons.js +39 -0
  30. package/dist/esm/customHooks/reduxLogger.d.ts +4 -0
  31. package/dist/esm/customHooks/reduxLogger.js +23 -0
  32. package/dist/esm/customHooks/webViewLogger.d.ts +2 -0
  33. package/dist/esm/customHooks/webViewLogger.js +281 -246
  34. package/dist/esm/helpers/index.js +2 -1
  35. package/dist/esm/index.d.ts +5 -3
  36. package/dist/esm/index.js +683 -914
  37. package/dist/esm/styles/AppColors.d.ts +29 -1
  38. package/dist/esm/styles/AppColors.js +35 -1
  39. package/dist/esm/styles/index.d.ts +438 -229
  40. package/dist/esm/styles/index.js +412 -209
  41. package/dist/esm/types/index.d.ts +2 -2
  42. package/example/App.tsx +351 -127
  43. package/example/ios/Podfile.lock +26 -0
  44. package/example/metro.config.js +1 -1
  45. package/example/package-lock.json +20 -4
  46. package/example/package.json +4 -3
  47. 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.subscribeWebView = exports.clearWebViewData = exports.getWebViewHtmlUrl = exports.getWebViewJs = exports.getWebViewCss = exports.getWebViewHtml = exports.getWebViewNavHistory = exports.getWebViewLogs = exports.clearAnalyticsEvents = exports.subscribeAnalyticsEvents = exports.logAnalyticsEvent = exports.setupAnalyticsLogger = exports.subscribeConsoleLogs = exports.clearConsoleLogs = exports.setupConsoleLogger = exports.subscribeNetworkLogs = exports.clearNetworkLogs = exports.setupNetworkLogger = void 0;
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.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"));
@@ -47,8 +47,6 @@ const TouchableScale_1 = __importDefault(require("./components/TouchableScale"))
47
47
  const useAccordion_1 = __importDefault(require("./customHooks/useAccordion"));
48
48
  const MetaAccordion_1 = __importDefault(require("./components/MetaAccordion"));
49
49
  const CopyButton_1 = __importDefault(require("./components/CopyButton"));
50
- const MiniBarChart_1 = __importDefault(require("./components/MiniBarChart"));
51
- const MiniLineChart_1 = __importDefault(require("./components/MiniLineChart"));
52
50
  const SectionHeader_1 = __importDefault(require("./components/SectionHeader"));
53
51
  const EmptyState_1 = __importDefault(require("./components/EmptyState"));
54
52
  const JsonViewer_1 = __importDefault(require("./components/JsonViewer"));
@@ -64,10 +62,11 @@ const CodeSnippet_1 = __importDefault(require("./components/CodeSnippet"));
64
62
  const helpers_1 = require("./helpers");
65
63
  // Assets
66
64
  const NetworkIcons_1 = require("./components/NetworkIcons");
65
+ const ErrorBoundary_1 = __importDefault(require("./components/ErrorBoundary"));
67
66
  // Stylesheet
68
67
  const AppColors_1 = require("./styles/AppColors");
69
68
  const AppFonts_1 = require("./styles/AppFonts");
70
- const styles_1 = __importDefault(require("./styles"));
69
+ const styles_1 = __importStar(require("./styles"));
71
70
  // Network
72
71
  const networkLogger_1 = require("./customHooks/networkLogger");
73
72
  // Console
@@ -78,6 +77,7 @@ const AnalyticsEventCard_1 = __importStar(require("./components/AnalyticsEventCa
78
77
  const AnalyticsDetail_1 = __importDefault(require("./components/AnalyticsDetail"));
79
78
  // WebView
80
79
  const webViewLogger_1 = require("./customHooks/webViewLogger");
80
+ const reduxLogger_1 = require("./customHooks/reduxLogger");
81
81
  const constants_1 = require("./constants");
82
82
  const NavigationTracker = ({ onStateChange }) => {
83
83
  const navState = (0, native_1.useNavigationState)(state => state);
@@ -87,6 +87,9 @@ const NavigationTracker = ({ onStateChange }) => {
87
87
  return null;
88
88
  };
89
89
  const NetworkInspector = () => {
90
+ const [isDark, setIsDark] = (0, react_1.useState)(false);
91
+ const [reduxState, setReduxState] = (0, react_1.useState)(null);
92
+ const [expandedReducers, setExpandedReducers] = (0, react_1.useState)({});
90
93
  const [logs, setLogs] = (0, react_1.useState)([]);
91
94
  const [visible, setVisible] = (0, react_1.useState)(false);
92
95
  const [isReady, setIsReady] = (0, react_1.useState)(false);
@@ -94,6 +97,14 @@ const NetworkInspector = () => {
94
97
  const [selectedLogs, setSelectedLogs] = (0, react_1.useState)(new Set());
95
98
  const [search, setSearch] = (0, react_1.useState)('');
96
99
  const [detailSearch, setDetailSearch] = (0, react_1.useState)('');
100
+ const [reduxSearch, setReduxSearch] = (0, react_1.useState)('');
101
+ const [apiDetailActiveTab, setApiDetailActiveTab] = (0, react_1.useState)('metadata');
102
+ (0, react_1.useEffect)(() => {
103
+ if (selected) {
104
+ setApiDetailActiveTab('metadata');
105
+ setDetailSearch('');
106
+ }
107
+ }, [selected]);
97
108
  const [statusFilters, setStatusFilters] = (0, react_1.useState)(new Set());
98
109
  const [methodFilters, setMethodFilters] = (0, react_1.useState)(new Set());
99
110
  const [sectionFilters, setSectionFilters] = (0, react_1.useState)({});
@@ -135,20 +146,23 @@ const NetworkInspector = () => {
135
146
  const [webViewNavHistory, setWebViewNavHistory] = (0, react_1.useState)([]);
136
147
  const [webViewSubTab, setWebViewSubTab] = (0, react_1.useState)('html');
137
148
  const [webViewSearch, setWebViewSearch] = (0, react_1.useState)('');
138
- const [htmlSearch, setHtmlSearch] = (0, react_1.useState)('');
139
- const [cssSearch, setCssSearch] = (0, react_1.useState)('');
140
- const [jsSearch, setJsSearch] = (0, react_1.useState)('');
141
149
  const [webViewHtml, setWebViewHtml] = (0, react_1.useState)('');
142
150
  const [webViewCss, setWebViewCss] = (0, react_1.useState)('');
143
151
  const [webViewJs, setWebViewJs] = (0, react_1.useState)('');
144
152
  const [webViewHtmlUrl, setWebViewHtmlUrl] = (0, react_1.useState)('');
145
153
  const [htmlSubTab, setHtmlSubTab] = (0, react_1.useState)('html');
154
+ const [isHtmlTabReady, setIsHtmlTabReady] = (0, react_1.useState)(true);
155
+ (0, react_1.useEffect)(() => {
156
+ setIsHtmlTabReady(false);
157
+ const timer = setTimeout(() => {
158
+ setIsHtmlTabReady(true);
159
+ }, 120);
160
+ return () => clearTimeout(timer);
161
+ }, [htmlSubTab, webViewSubTab, activeTab]);
146
162
  const [selectedEvent, setSelectedEvent] = (0, react_1.useState)(null);
147
163
  const [analyticsSearch, setAnalyticsSearch] = (0, react_1.useState)('');
148
164
  const [hideScreenView, setHideScreenView] = (0, react_1.useState)(true);
149
165
  const [analyticsSubTab, setAnalyticsSubTab] = (0, react_1.useState)('ga_events');
150
- const [groupByScreen, setGroupByScreen] = (0, react_1.useState)(false);
151
- const [expandedScreens, setExpandedScreens] = (0, react_1.useState)(new Set());
152
166
  const [topEventsExpanded, setTopEventsExpanded] = (0, react_1.useState)(true);
153
167
  const [newEventIds, setNewEventIds] = (0, react_1.useState)(new Set());
154
168
  const prevEventIdsRef = (0, react_1.useRef)(new Set());
@@ -288,6 +302,10 @@ const NetworkInspector = () => {
288
302
  setWebViewHtmlUrl((0, webViewLogger_1.getWebViewHtmlUrl)());
289
303
  }, 200);
290
304
  });
305
+ setReduxState((0, reduxLogger_1.getReduxState)());
306
+ const unsubscribeRedux = (0, reduxLogger_1.subscribeReduxState)(() => {
307
+ setReduxState((0, reduxLogger_1.getReduxState)());
308
+ });
291
309
  return () => {
292
310
  unsubscribe();
293
311
  clearTimeout(timeoutId);
@@ -297,6 +315,7 @@ const NetworkInspector = () => {
297
315
  clearTimeout(consoleTimeoutId);
298
316
  unsubscribeWebView();
299
317
  clearTimeout(webViewTimeoutId);
318
+ unsubscribeRedux();
300
319
  };
301
320
  }, []);
302
321
  (0, react_1.useEffect)(() => {
@@ -581,39 +600,6 @@ const NetworkInspector = () => {
581
600
  analytics: `${searchedLogs.filter(l => l.message.toLowerCase().includes('[analytics error]')).length}/${total}`,
582
601
  };
583
602
  }, [visibleConsoleLogs, logSearch]);
584
- const groupedAnalyticsEvents = (0, react_1.useMemo)(() => {
585
- if (!groupByScreen)
586
- return [];
587
- const map = new Map();
588
- for (const e of filteredAnalyticsEvents) {
589
- const routeInfo = logRouteMapRef.current.get(e.id + 1000000);
590
- let screenName = e.screenName ||
591
- e.screenClass ||
592
- e.pageTitle ||
593
- e.pageLocation ||
594
- e.params?.firebase_screen ||
595
- e.params?.screen_name ||
596
- e.params?.firebase_screen_class ||
597
- e.params?.screen_class;
598
- if (!screenName) {
599
- if (routeInfo && routeInfo.path !== 'Navigators') {
600
- const parts = routeInfo.path.split(' ➔ ');
601
- screenName = parts[parts.length - 1];
602
- }
603
- else {
604
- screenName = 'Unknown Component';
605
- }
606
- }
607
- if (!map.has(screenName))
608
- map.set(screenName, []);
609
- map.get(screenName).push(e);
610
- }
611
- const sections = [];
612
- for (const [title, data] of map.entries()) {
613
- sections.push({ title, data });
614
- }
615
- return sections;
616
- }, [groupByScreen, filteredAnalyticsEvents]);
617
603
  const topEventsArray = (0, react_1.useMemo)(() => {
618
604
  const freq = {};
619
605
  filteredAnalyticsEvents.forEach(e => {
@@ -623,51 +609,6 @@ const NetworkInspector = () => {
623
609
  });
624
610
  return Object.entries(freq).sort((a, b) => b[1] - a[1]);
625
611
  }, [filteredAnalyticsEvents]);
626
- const groupedNetworkLogs = (0, react_1.useMemo)(() => {
627
- if (!groupByScreen)
628
- return [];
629
- const map = new Map();
630
- for (const l of filteredLogs) {
631
- const routeInfo = logRouteMapRef.current.get(l.id);
632
- let screenName = 'Unknown Origin';
633
- if (routeInfo && routeInfo.path !== 'Navigators') {
634
- const parts = routeInfo.path.split(' ➔ ');
635
- screenName = parts[parts.length - 1];
636
- }
637
- if (!map.has(screenName))
638
- map.set(screenName, []);
639
- map.get(screenName).push(l);
640
- }
641
- const sections = [];
642
- for (const [title, data] of map.entries()) {
643
- sections.push({ title, data });
644
- }
645
- return sections;
646
- }, [groupByScreen, filteredLogs]);
647
- const toggleScreenAccordion = (0, react_1.useCallback)((title) => {
648
- setExpandedScreens(prev => {
649
- const next = new Set(prev);
650
- if (next.has(title))
651
- next.delete(title);
652
- else
653
- next.add(title);
654
- return next;
655
- });
656
- }, []);
657
- const renderScreenSectionHeader = (0, react_1.useCallback)(({ section: { title, data } }) => {
658
- const isExpanded = expandedScreens.has(title);
659
- return (<react_native_1.Pressable onPress={() => toggleScreenAccordion(title)} style={styles_1.default.screenSectionHeader}>
660
- <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
661
- <react_native_1.View style={{
662
- transform: [{ rotate: isExpanded ? '180deg' : '0deg' }],
663
- }}>
664
- <NetworkIcons_1.ExpandCollapseIcon color={AppColors_1.AppColors.primaryBlack} size={14} isExpanded={false}/>
665
- </react_native_1.View>
666
- <react_native_1.Text style={styles_1.default.screenSectionTitle}>{title}</react_native_1.Text>
667
- </react_native_1.View>
668
- <react_native_1.Text style={styles_1.default.screenSectionCount}>{data.length} logs</react_native_1.Text>
669
- </react_native_1.Pressable>);
670
- }, [expandedScreens, toggleScreenAccordion]);
671
612
  function closeModal() {
672
613
  setVisible(false);
673
614
  setSelected(null);
@@ -814,12 +755,317 @@ const NetworkInspector = () => {
814
755
  toggleSectionFilter,
815
756
  toggleSectionCollapse,
816
757
  ]);
758
+ const renderInsightsDashboard = () => {
759
+ const apiTotal = logs.length;
760
+ const apiErrors = logs.filter(l => (l.status != null && l.status >= 400) || l.status === 0 || l.status == null).length;
761
+ const apiSuccess = apiTotal - apiErrors;
762
+ const apiSuccessRate = apiTotal > 0 ? Math.round((apiSuccess / apiTotal) * 100) : 100;
763
+ const durations = logs.filter(l => l.duration != null).map(l => l.duration);
764
+ const avgTime = durations.length > 0
765
+ ? Math.round(durations.reduce((a, b) => a + b, 0) / durations.length)
766
+ : null;
767
+ const logTotal = visibleConsoleLogs.length;
768
+ const logErrors = visibleConsoleLogs.filter(l => l.type === 'error').length;
769
+ const logWarns = visibleConsoleLogs.filter(l => l.type === 'warn').length;
770
+ const logInfos = visibleConsoleLogs.filter(l => l.type === 'info').length;
771
+ const analyticsTotal = analyticsEvents.length;
772
+ const uniqueEvents = new Set(analyticsEvents.map(e => e.name)).size;
773
+ const screenViews = analyticsEvents.filter(e => e.name === 'screen_view' || e.name === 'page_view' || e.name === 'firebase_screen_class').length;
774
+ const webviewTotal = webViewNavHistory.length;
775
+ return (<react_native_1.View style={styles_1.default.dashboardContainer}>
776
+ {/* Module 1: APIs */}
777
+ <TouchableScale_1.default style={styles_1.default.dashboardModuleCard} onPress={() => setActiveTab('apis')}>
778
+ <react_native_1.View style={styles_1.default.dashboardModuleHeader}>
779
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
780
+ <NetworkIcons_1.SignalIcon color={AppColors_1.AppColors.purple} size={18}/>
781
+ <react_native_1.Text style={styles_1.default.dashboardModuleTitle}>APIs & Network</react_native_1.Text>
782
+ </react_native_1.View>
783
+ <react_native_1.Text style={styles_1.default.dashboardModuleGoText}>View Details →</react_native_1.Text>
784
+ </react_native_1.View>
785
+ <react_native_1.View style={styles_1.default.dashboardModuleGrid}>
786
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
787
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>{apiTotal}</react_native_1.Text>
788
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Requests</react_native_1.Text>
789
+ </react_native_1.View>
790
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
791
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, apiSuccessRate < 90 && { color: AppColors_1.AppColors.warningIconGold }]}>
792
+ {apiSuccessRate}%
793
+ </react_native_1.Text>
794
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Success Rate</react_native_1.Text>
795
+ </react_native_1.View>
796
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
797
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, apiErrors > 0 && { color: AppColors_1.AppColors.errorColor }]}>
798
+ {apiErrors}
799
+ </react_native_1.Text>
800
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Errors</react_native_1.Text>
801
+ </react_native_1.View>
802
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
803
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>
804
+ {avgTime != null ? `${avgTime}ms` : '—'}
805
+ </react_native_1.Text>
806
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Avg Latency</react_native_1.Text>
807
+ </react_native_1.View>
808
+ </react_native_1.View>
809
+ </TouchableScale_1.default>
810
+
811
+ {/* Module 2: Logs */}
812
+ <TouchableScale_1.default style={styles_1.default.dashboardModuleCard} onPress={() => setActiveTab('logs')}>
813
+ <react_native_1.View style={styles_1.default.dashboardModuleHeader}>
814
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
815
+ <NetworkIcons_1.TerminalIcon color="#0D9488" size={18}/>
816
+ <react_native_1.Text style={styles_1.default.dashboardModuleTitle}>Console Logs</react_native_1.Text>
817
+ </react_native_1.View>
818
+ <react_native_1.Text style={styles_1.default.dashboardModuleGoText}>View Details →</react_native_1.Text>
819
+ </react_native_1.View>
820
+ <react_native_1.View style={styles_1.default.dashboardModuleGrid}>
821
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
822
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>{logTotal}</react_native_1.Text>
823
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Total Logs</react_native_1.Text>
824
+ </react_native_1.View>
825
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
826
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, { color: '#0D9488' }]}>{logInfos}</react_native_1.Text>
827
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Info</react_native_1.Text>
828
+ </react_native_1.View>
829
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
830
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, logWarns > 0 && { color: AppColors_1.AppColors.warningIconGold }]}>
831
+ {logWarns}
832
+ </react_native_1.Text>
833
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Warnings</react_native_1.Text>
834
+ </react_native_1.View>
835
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
836
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, logErrors > 0 && { color: AppColors_1.AppColors.errorColor }]}>
837
+ {logErrors}
838
+ </react_native_1.Text>
839
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Errors</react_native_1.Text>
840
+ </react_native_1.View>
841
+ </react_native_1.View>
842
+ </TouchableScale_1.default>
843
+
844
+ {/* Module 3: Analytics */}
845
+ <TouchableScale_1.default style={styles_1.default.dashboardModuleCard} onPress={() => setActiveTab('analytics')}>
846
+ <react_native_1.View style={styles_1.default.dashboardModuleHeader}>
847
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
848
+ <NetworkIcons_1.AnalyticsIcon color="#EA580C" size={18}/>
849
+ <react_native_1.Text style={styles_1.default.dashboardModuleTitle}>Analytics Events</react_native_1.Text>
850
+ </react_native_1.View>
851
+ <react_native_1.Text style={styles_1.default.dashboardModuleGoText}>View Details →</react_native_1.Text>
852
+ </react_native_1.View>
853
+ <react_native_1.View style={styles_1.default.dashboardModuleGrid}>
854
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
855
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>{analyticsTotal}</react_native_1.Text>
856
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Total Events</react_native_1.Text>
857
+ </react_native_1.View>
858
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
859
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, { color: '#EA580C' }]}>{uniqueEvents}</react_native_1.Text>
860
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Unique Names</react_native_1.Text>
861
+ </react_native_1.View>
862
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
863
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>{screenViews}</react_native_1.Text>
864
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Screen Views</react_native_1.Text>
865
+ </react_native_1.View>
866
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
867
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>
868
+ {analyticsTotal > 0 ? Math.round(analyticsTotal / Math.max(1, logs.length / 5)) : 0}
869
+ </react_native_1.Text>
870
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Events Ratio</react_native_1.Text>
871
+ </react_native_1.View>
872
+ </react_native_1.View>
873
+ </TouchableScale_1.default>
874
+
875
+ {/* Module 4: WebView */}
876
+ <TouchableScale_1.default style={styles_1.default.dashboardModuleCard} onPress={() => setActiveTab('webview')}>
877
+ <react_native_1.View style={styles_1.default.dashboardModuleHeader}>
878
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
879
+ <NetworkIcons_1.GlobeIcon color="#2563EB" size={18}/>
880
+ <react_native_1.Text style={styles_1.default.dashboardModuleTitle}>WebView Captures</react_native_1.Text>
881
+ </react_native_1.View>
882
+ <react_native_1.Text style={styles_1.default.dashboardModuleGoText}>View Details →</react_native_1.Text>
883
+ </react_native_1.View>
884
+ <react_native_1.View style={styles_1.default.dashboardModuleGrid}>
885
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
886
+ <react_native_1.Text style={styles_1.default.dashboardGridVal}>{webviewTotal}</react_native_1.Text>
887
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>History Size</react_native_1.Text>
888
+ </react_native_1.View>
889
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
890
+ <react_native_1.Text style={[styles_1.default.dashboardGridVal, { color: '#16A34A' }]}>Active</react_native_1.Text>
891
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Status</react_native_1.Text>
892
+ </react_native_1.View>
893
+ <react_native_1.View style={styles_1.default.dashboardGridItem}>
894
+ <react_native_1.Text numberOfLines={1} style={styles_1.default.dashboardGridVal}>
895
+ {webviewTotal > 0 ? `${webViewNavHistory[0]?.title?.substring(0, 10) ?? ''}...` : '—'}
896
+ </react_native_1.Text>
897
+ <react_native_1.Text style={styles_1.default.dashboardGridLbl}>Last URL</react_native_1.Text>
898
+ </react_native_1.View>
899
+ </react_native_1.View>
900
+ </TouchableScale_1.default>
901
+
902
+ {/* Module 5: Redux Store */}
903
+ <TouchableScale_1.default style={styles_1.default.dashboardModuleCard} onPress={() => setActiveTab('redux')}>
904
+ <react_native_1.View style={styles_1.default.dashboardModuleHeader}>
905
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
906
+ <NetworkIcons_1.TerminalIcon color={AppColors_1.AppColors.purple} size={18}/>
907
+ <react_native_1.Text style={styles_1.default.dashboardModuleTitle}>Redux Store State</react_native_1.Text>
908
+ </react_native_1.View>
909
+ <react_native_1.Text style={styles_1.default.dashboardModuleGoText}>View Details →</react_native_1.Text>
910
+ </react_native_1.View>
911
+ {reduxState ? (<react_native_1.View style={{ paddingHorizontal: 12, paddingBottom: 12, gap: 6 }}>
912
+ <react_native_1.View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 4 }}>
913
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interBold, fontSize: 10, color: AppColors_1.AppColors.grayTextWeak, letterSpacing: 0.5 }}>
914
+ REDUCER NAME
915
+ </react_native_1.Text>
916
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interBold, fontSize: 10, color: AppColors_1.AppColors.grayTextWeak, letterSpacing: 0.5 }}>
917
+ SIZE / FIELDS
918
+ </react_native_1.Text>
919
+ </react_native_1.View>
920
+ {Object.keys(reduxState).map(key => {
921
+ const val = reduxState[key];
922
+ const fieldsCount = typeof val === 'object' && val !== null ? Object.keys(val).length : 0;
923
+ const sizeStr = (0, helpers_1.getSize)(val);
924
+ return (<react_native_1.View key={key} style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 2 }}>
925
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interMedium, fontSize: 12, color: AppColors_1.AppColors.grayTextStrong }}>
926
+ {key}
927
+ </react_native_1.Text>
928
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interRegular, fontSize: 11, color: AppColors_1.AppColors.grayTextWeak }}>
929
+ {sizeStr} ({fieldsCount} fields)
930
+ </react_native_1.Text>
931
+ </react_native_1.View>);
932
+ })}
933
+ </react_native_1.View>) : (<react_native_1.View style={{ padding: 12, alignItems: 'center' }}>
934
+ <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interRegular, fontSize: 12, color: AppColors_1.AppColors.grayTextWeak }}>
935
+ No connected Redux store.
936
+ </react_native_1.Text>
937
+ </react_native_1.View>)}
938
+ </TouchableScale_1.default>
939
+ </react_native_1.View>);
940
+ };
941
+ const renderReduxTab = () => {
942
+ if (!reduxState) {
943
+ return (<react_native_1.View style={styles_1.default.emptyContainer}>
944
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
945
+ <NetworkIcons_1.TerminalIcon color={AppColors_1.AppColors.purple} size={32}/>
946
+ </react_native_1.View>
947
+ <react_native_1.Text style={styles_1.default.emptyTitle}>No Redux Store</react_native_1.Text>
948
+ <react_native_1.Text style={styles_1.default.emptySub}>
949
+ To inspect Redux store, call connectReduxStore(store) at app start.
950
+ </react_native_1.Text>
951
+ </react_native_1.View>);
952
+ }
953
+ const reducerKeys = Object.keys(reduxState);
954
+ if (reducerKeys.length === 0) {
955
+ return (<react_native_1.View style={styles_1.default.emptyContainer}>
956
+ <react_native_1.Text style={styles_1.default.emptyTitle}>Empty Store</react_native_1.Text>
957
+ <react_native_1.Text style={styles_1.default.emptySub}>Connected store state is empty.</react_native_1.Text>
958
+ </react_native_1.View>);
959
+ }
960
+ return (<react_native_1.ScrollView style={styles_1.default.detailScroll} contentContainerStyle={{ paddingBottom: 24 }}>
961
+ <react_native_1.View style={{
962
+ flexDirection: 'row',
963
+ alignItems: 'center',
964
+ justifyContent: 'space-between',
965
+ paddingHorizontal: 16,
966
+ paddingVertical: 12,
967
+ borderBottomWidth: 1,
968
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
969
+ backgroundColor: AppColors_1.AppColors.primaryLight,
970
+ }}>
971
+ <react_native_1.Text style={{
972
+ fontFamily: AppFonts_1.AppFonts.interBold,
973
+ color: AppColors_1.AppColors.grayTextStrong,
974
+ fontSize: 12,
975
+ textTransform: 'uppercase',
976
+ letterSpacing: 0.6,
977
+ }}>
978
+ Redux Store ({reducerKeys.length} Reducers)
979
+ </react_native_1.Text>
980
+ <CopyButton_1.default value={() => reduxState} label="Overall Store"/>
981
+ </react_native_1.View>
982
+
983
+ <react_native_1.View style={{
984
+ flexDirection: 'row',
985
+ alignItems: 'center',
986
+ backgroundColor: AppColors_1.AppColors.grayBackground,
987
+ borderRadius: 8,
988
+ marginHorizontal: 16,
989
+ marginTop: 12,
990
+ marginBottom: 8,
991
+ paddingHorizontal: 10,
992
+ borderWidth: 1,
993
+ borderColor: AppColors_1.AppColors.dividerColor,
994
+ height: 36,
995
+ }}>
996
+ <react_native_1.TextInput placeholder="Search Redux keys or values..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={reduxSearch} onChangeText={setReduxSearch} style={{
997
+ flex: 1,
998
+ fontFamily: AppFonts_1.AppFonts.interRegular,
999
+ fontSize: 12,
1000
+ color: AppColors_1.AppColors.grayTextStrong,
1001
+ padding: 0,
1002
+ }} autoCorrect={false} autoCapitalize="none"/>
1003
+ {reduxSearch.length > 0 && (<react_native_1.Pressable onPress={() => setReduxSearch('')} hitSlop={10}>
1004
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1005
+ </react_native_1.Pressable>)}
1006
+ </react_native_1.View>
1007
+
1008
+ {reducerKeys.map(key => {
1009
+ const isExpanded = expandedReducers[key];
1010
+ const val = reduxState[key];
1011
+ return (<react_native_1.View key={key} style={{
1012
+ backgroundColor: AppColors_1.AppColors.primaryLight,
1013
+ borderBottomWidth: 1,
1014
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
1015
+ }}>
1016
+ <react_native_1.Pressable onPress={() => {
1017
+ setExpandedReducers(prev => ({
1018
+ ...prev,
1019
+ [key]: !prev[key],
1020
+ }));
1021
+ }} style={{
1022
+ flexDirection: 'row',
1023
+ alignItems: 'center',
1024
+ justifyContent: 'space-between',
1025
+ paddingHorizontal: 16,
1026
+ paddingVertical: 12,
1027
+ }}>
1028
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, flex: 1 }}>
1029
+ <react_native_1.Animated.View style={{ transform: [{ rotate: isExpanded ? '0deg' : '-90deg' }] }}>
1030
+ <NetworkIcons_1.ChevronIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1031
+ </react_native_1.Animated.View>
1032
+ <react_native_1.Text style={{
1033
+ fontFamily: AppFonts_1.AppFonts.interBold,
1034
+ fontSize: 13,
1035
+ color: AppColors_1.AppColors.purple,
1036
+ }}>
1037
+ {key}
1038
+ </react_native_1.Text>
1039
+ <react_native_1.Text style={{
1040
+ fontFamily: AppFonts_1.AppFonts.interRegular,
1041
+ fontSize: 11,
1042
+ color: AppColors_1.AppColors.grayTextWeak,
1043
+ }}>
1044
+ ({typeof val === 'object' && val !== null ? `${Object.keys(val).length} fields` : typeof val})
1045
+ </react_native_1.Text>
1046
+ </react_native_1.View>
1047
+ <CopyButton_1.default value={() => val} label={`${key} Reducer`}/>
1048
+ </react_native_1.Pressable>
1049
+
1050
+ {isExpanded && (<react_native_1.View style={{
1051
+ backgroundColor: AppColors_1.AppColors.grayBackground,
1052
+ paddingHorizontal: 12,
1053
+ paddingVertical: 8,
1054
+ borderTopWidth: 1,
1055
+ borderTopColor: AppColors_1.AppColors.dividerColor,
1056
+ }}>
1057
+ <JsonViewer_1.default data={val} search={reduxSearch}/>
1058
+ </react_native_1.View>)}
1059
+ </react_native_1.View>);
1060
+ })}
1061
+ </react_native_1.ScrollView>);
1062
+ };
817
1063
  return (<>
818
1064
  {hasNavigationContext && (<NavigationTracker onStateChange={setNavState}/>)}
819
1065
  <TouchableScale_1.default style={styles_1.default.fabWrapper} onPress={() => setVisible(true)} hitSlop={10}>
820
1066
  <react_native_1.Animated.View style={[styles_1.default.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
821
1067
  <react_native_linear_gradient_1.default colors={[AppColors_1.AppColors.purple, '#8F6EFF']} style={styles_1.default.fab}>
822
- <react_native_1.Text style={styles_1.default.fabText}>API</react_native_1.Text>
1068
+ <NetworkIcons_1.DebugIcon color="#FFFFFF" size={28}/>
823
1069
  </react_native_linear_gradient_1.default>
824
1070
  {(logs.length > 0 || analyticsEvents.length > 0) && (<react_native_1.Animated.View style={[
825
1071
  styles_1.default.fabBadge,
@@ -835,23 +1081,24 @@ const NetworkInspector = () => {
835
1081
  </TouchableScale_1.default>
836
1082
 
837
1083
  <react_native_1.Modal visible={visible} animationType="slide" transparent>
838
- {visible && (<react_native_1.View style={{ flex: 1, backgroundColor: AppColors_1.AppColors.grayBackground }}>
839
- <react_native_1.StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
1084
+ {visible && (<ErrorBoundary_1.default onClose={closeModal}>
1085
+ <react_native_1.View style={styles_1.default.modalBackdrop}>
1086
+ <react_native_1.Pressable style={styles_1.default.modalBackdropPressable} onPress={closeModal}/>
1087
+ <react_native_1.View style={styles_1.default.modalContentCard}>
1088
+ <react_native_1.StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
840
1089
 
841
- <react_native_linear_gradient_1.default colors={[AppColors_1.AppColors.purple, '#6B4EFF']} style={styles_1.default.headerGradient}>
842
- <react_native_1.View style={[
843
- styles_1.default.header,
1090
+ <react_native_linear_gradient_1.default colors={[AppColors_1.AppColors.purple, '#6B4EFF']} style={styles_1.default.headerGradient}>
1091
+ <react_native_1.View style={styles_1.default.header}>
1092
+ <react_native_1.View style={[
1093
+ styles_1.default.headerLeft,
844
1094
  {
845
- paddingTop: react_native_1.Platform.OS === 'android'
846
- ? (react_native_1.StatusBar.currentHeight ?? 24) + 16
847
- : 54,
1095
+ flexDirection: 'row',
1096
+ alignItems: 'center',
1097
+ gap: 16,
1098
+ flex: (selected == null && selectedEvent == null) ? 5 : 1,
848
1099
  },
849
1100
  ]}>
850
- <react_native_1.View style={[
851
- styles_1.default.headerLeft,
852
- { flexDirection: 'row', alignItems: 'center', gap: 16 },
853
- ]}>
854
- <TouchableScale_1.default onPress={() => {
1101
+ <TouchableScale_1.default onPress={() => {
855
1102
  requestAnimationFrame(() => {
856
1103
  setSelected(null);
857
1104
  setSelectedEvent(null);
@@ -861,100 +1108,48 @@ const NetworkInspector = () => {
861
1108
  selected == null &&
862
1109
  selectedEvent == null && { display: 'none' },
863
1110
  ]}>
864
- <NetworkIcons_1.WhiteBackNavigation />
865
- </TouchableScale_1.default>
866
-
867
- {selected == null && selectedEvent == null ? (<react_native_1.View style={styles_1.default.headerButtonGroup}>
868
- {/* Network Dropdown */}
869
- <react_native_1.Pressable onPress={() => {
870
- setShowNetworkMenu(prev => !prev);
871
- setShowUiMenu(false);
872
- }} style={[
873
- styles_1.default.headerGroupButton,
874
- ['apis', 'analytics', 'logs'].includes(activeTab) &&
875
- styles_1.default.headerGroupButtonActive,
876
- ]}>
877
- <react_native_1.Text style={[
878
- styles_1.default.headerGroupButtonText,
879
- ['apis', 'analytics', 'logs'].includes(activeTab) && { color: '#FFFFFF' },
880
- ]}>
881
- APIs
882
- </react_native_1.Text>
883
- <react_native_1.View style={{
884
- transform: [
885
- { rotate: showNetworkMenu ? '180deg' : '0deg' },
886
- ],
887
- }}>
888
- <NetworkIcons_1.ChevronIcon color={['apis', 'analytics', 'logs'].includes(activeTab)
889
- ? '#FFFFFF'
890
- : 'rgba(255, 255, 255, 0.6)'} size={10}/>
891
- </react_native_1.View>
892
- </react_native_1.Pressable>
1111
+ <NetworkIcons_1.WhiteBackNavigation />
1112
+ </TouchableScale_1.default>
893
1113
 
894
- {/* UI Dropdown */}
895
- <react_native_1.Pressable onPress={() => {
896
- setShowUiMenu(prev => !prev);
897
- setShowNetworkMenu(false);
898
- }} style={[
899
- styles_1.default.headerGroupButton,
900
- activeTab === 'webview' &&
901
- styles_1.default.headerGroupButtonActive,
902
- ]}>
903
- <react_native_1.Text style={[
904
- styles_1.default.headerGroupButtonText,
905
- activeTab === 'webview' && { color: '#FFFFFF' },
906
- ]}>
907
- UI
908
- </react_native_1.Text>
909
- <react_native_1.View style={{
910
- transform: [
911
- { rotate: showUiMenu ? '180deg' : '0deg' },
912
- ],
913
- }}>
914
- <NetworkIcons_1.ChevronIcon color={activeTab === 'webview'
915
- ? '#FFFFFF'
916
- : 'rgba(255, 255, 255, 0.6)'} size={10}/>
917
- </react_native_1.View>
918
- </react_native_1.Pressable>
919
- </react_native_1.View>) : null}
920
- </react_native_1.View>
1114
+ {selected == null && selectedEvent == null ? (<react_native_1.Text style={styles_1.default.headerTitle}>RN-InApp-Inspector</react_native_1.Text>) : null}
1115
+ </react_native_1.View>
921
1116
 
922
- <react_native_1.View style={styles_1.default.headerCenter}>
923
- {selected != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
924
- <react_native_1.View style={styles_1.default.headerDetailRow}>
925
- <react_native_1.View style={[
1117
+ <react_native_1.View style={styles_1.default.headerCenter}>
1118
+ {selected != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
1119
+ <react_native_1.View style={styles_1.default.headerDetailRow}>
1120
+ <react_native_1.View style={[
926
1121
  styles_1.default.headerMethodBadge,
927
1122
  {
928
1123
  backgroundColor: constants_1.METHOD_COLORS[selected.method] ??
929
1124
  AppColors_1.AppColors.grayText,
930
1125
  },
931
1126
  ]}>
932
- <react_native_1.Text style={styles_1.default.headerMethodText}>
933
- {selected.method}
1127
+ <react_native_1.Text style={styles_1.default.headerMethodText}>
1128
+ {selected.method}
1129
+ </react_native_1.Text>
1130
+ </react_native_1.View>
1131
+ <react_native_1.Text style={styles_1.default.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
1132
+ {detailTitle}
934
1133
  </react_native_1.Text>
935
1134
  </react_native_1.View>
936
- <react_native_1.Text style={styles_1.default.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
937
- {detailTitle}
938
- </react_native_1.Text>
939
- </react_native_1.View>
940
- <react_native_1.View style={styles_1.default.headerDetailSubRow}>
941
- <react_native_1.View style={[
1135
+ <react_native_1.View style={styles_1.default.headerDetailSubRow}>
1136
+ <react_native_1.View style={[
942
1137
  styles_1.default.headerStatusDot,
943
1138
  { backgroundColor: (0, helpers_1.getStatusColor)(selected.status) },
944
1139
  ]}/>
945
- <react_native_1.Text style={styles_1.default.headerSubTitle}>
946
- {selected.status === 0
1140
+ <react_native_1.Text style={styles_1.default.headerSubTitle}>
1141
+ {selected.status === 0
947
1142
  ? 'Failed'
948
1143
  : selected.status ?? 'Pending'}{' '}
949
- •{' '}
950
- {selected.duration != null
1144
+ •{' '}
1145
+ {selected.duration != null
951
1146
  ? `${selected.duration}ms`
952
1147
  : '-'}
953
- </react_native_1.Text>
954
- </react_native_1.View>
955
- </react_native_1.View>) : selectedEvent != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
956
- <react_native_1.View style={styles_1.default.headerDetailRow}>
957
- <react_native_1.View style={[
1148
+ </react_native_1.Text>
1149
+ </react_native_1.View>
1150
+ </react_native_1.View>) : selectedEvent != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
1151
+ <react_native_1.View style={styles_1.default.headerDetailRow}>
1152
+ <react_native_1.View style={[
958
1153
  styles_1.default.headerMethodBadge,
959
1154
  {
960
1155
  backgroundColor: selectedEvent.source === 'firebase'
@@ -962,16 +1157,16 @@ const NetworkInspector = () => {
962
1157
  : 'rgba(124,92,191,0.3)',
963
1158
  },
964
1159
  ]}>
965
- <react_native_1.Text style={styles_1.default.headerMethodText}>
966
- {selectedEvent.source === 'firebase' ? 'FB' : 'MAN'}
1160
+ <react_native_1.Text style={styles_1.default.headerMethodText}>
1161
+ {selectedEvent.source === 'firebase' ? 'FB' : 'MAN'}
1162
+ </react_native_1.Text>
1163
+ </react_native_1.View>
1164
+ <react_native_1.Text style={styles_1.default.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
1165
+ {selectedEvent.name}
967
1166
  </react_native_1.Text>
968
1167
  </react_native_1.View>
969
- <react_native_1.Text style={styles_1.default.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
970
- {selectedEvent.name}
971
- </react_native_1.Text>
972
- </react_native_1.View>
973
- <react_native_1.View style={styles_1.default.headerDetailSubRow}>
974
- <react_native_1.View style={[
1168
+ <react_native_1.View style={styles_1.default.headerDetailSubRow}>
1169
+ <react_native_1.View style={[
975
1170
  styles_1.default.headerStatusDot,
976
1171
  {
977
1172
  backgroundColor: selectedEvent.source === 'firebase'
@@ -979,133 +1174,76 @@ const NetworkInspector = () => {
979
1174
  : AppColors_1.AppColors.purple,
980
1175
  },
981
1176
  ]}/>
982
- <react_native_1.Text style={styles_1.default.headerSubTitle}>
983
- {Object.keys(selectedEvent.params).length} param
984
- {Object.keys(selectedEvent.params).length !== 1
1177
+ <react_native_1.Text style={styles_1.default.headerSubTitle}>
1178
+ {Object.keys(selectedEvent.params).length} param
1179
+ {Object.keys(selectedEvent.params).length !== 1
985
1180
  ? 's'
986
1181
  : ''}
987
- {' · '}
988
- {selectedEvent.source}
989
- </react_native_1.Text>
990
- </react_native_1.View>
991
- </react_native_1.View>) : (<react_native_1.View style={styles_1.default.headerCountBadge}>
992
- <react_native_1.Text style={styles_1.default.headerCountText}>
993
- {activeTab === 'apis'
994
- ? `${logs.length} API${logs.length !== 1 ? 's' : ''}`
995
- : activeTab === 'logs'
996
- ? `${visibleConsoleLogs.length} log${visibleConsoleLogs.length !== 1 ? 's' : ''}`
997
- : activeTab === 'analytics'
998
- ? `${analyticsEvents.length} event${analyticsEvents.length !== 1 ? 's' : ''}`
999
- : `${webViewLogs.length} log${webViewLogs.length !== 1 ? 's' : ''}`}
1000
- </react_native_1.Text>
1001
- </react_native_1.View>)}
1002
- </react_native_1.View>
1003
-
1004
- <react_native_1.View style={styles_1.default.headerRight}>
1005
- <TouchableScale_1.default onPress={closeModal} hitSlop={15} style={styles_1.default.iconBtnMinimal}>
1006
- <NetworkIcons_1.CloseWhite />
1007
- </TouchableScale_1.default>
1008
- </react_native_1.View>
1009
- </react_native_1.View>
1010
- </react_native_linear_gradient_1.default>
1182
+ {' · '}
1183
+ {selectedEvent.source}
1184
+ </react_native_1.Text>
1185
+ </react_native_1.View>
1186
+ </react_native_1.View>) : null}
1187
+ </react_native_1.View>
1011
1188
 
1012
- {(showNetworkMenu || showUiMenu) && selected == null && (<react_native_1.Pressable style={{
1013
- position: 'absolute',
1014
- top: 0,
1015
- left: 0,
1016
- right: 0,
1017
- bottom: 0,
1018
- zIndex: 99,
1019
- }} onPress={() => {
1020
- setShowNetworkMenu(false);
1021
- setShowUiMenu(false);
1022
- }}/>)}
1189
+ <react_native_1.View style={styles_1.default.headerRight}>
1190
+ <TouchableScale_1.default onPress={() => {
1191
+ const newTheme = !isDark;
1192
+ setIsDark(newTheme);
1193
+ (0, styles_1.toggleGlobalTheme)(newTheme);
1194
+ }} hitSlop={15} style={[styles_1.default.closeButtonCircle, { marginRight: 8 }]}>
1195
+ {isDark ? (<NetworkIcons_1.SunIcon color="#FFFFFF" size={16}/>) : (<NetworkIcons_1.MoonIcon color="#FFFFFF" size={16}/>)}
1196
+ </TouchableScale_1.default>
1023
1197
 
1024
- {selected == null && selectedEvent == null && (<react_native_1.View style={{
1025
- paddingHorizontal: 16,
1026
- paddingTop: 10,
1027
- paddingBottom: 2,
1028
- }}>
1029
- <react_native_1.Text style={{
1030
- fontFamily: AppFonts_1.AppFonts.interMedium,
1031
- fontSize: 11.5,
1032
- color: AppColors_1.AppColors.grayTextWeak,
1033
- }}>
1034
- {['apis', 'analytics', 'logs'].includes(activeTab)
1035
- ? 'APIs'
1036
- : 'UI'}
1037
- {' ➔ '}
1038
- <react_native_1.Text style={{
1039
- color: AppColors_1.AppColors.purple,
1040
- fontFamily: AppFonts_1.AppFonts.interBold,
1041
- }}>
1042
- {activeTab === 'apis'
1043
- ? 'APIs'
1044
- : activeTab === 'analytics'
1045
- ? 'Analytics'
1046
- : activeTab === 'logs'
1047
- ? 'Logs'
1048
- : 'WebView'}
1049
- </react_native_1.Text>
1050
- </react_native_1.Text>
1051
- </react_native_1.View>)}
1198
+ <TouchableScale_1.default onPress={closeModal} hitSlop={15} style={styles_1.default.closeButtonCircle}>
1199
+ <NetworkIcons_1.CloseWhite size={16}/>
1200
+ </TouchableScale_1.default>
1201
+ </react_native_1.View>
1202
+ </react_native_1.View>
1203
+ </react_native_linear_gradient_1.default>
1052
1204
 
1053
- {showNetworkMenu && selected == null && selectedEvent == null && (<react_native_1.View style={[styles_1.default.menuDropdown, { left: 16 }]}>
1054
- {['apis', 'analytics', 'logs'].map(tab => {
1055
- const label = tab === 'apis'
1056
- ? 'APIs'
1057
- : tab === 'analytics'
1058
- ? 'Analytics'
1059
- : 'Logs';
1060
- const count = tab === 'apis'
1061
- ? logs.length
1062
- : tab === 'analytics'
1063
- ? analyticsEvents.length
1064
- : visibleConsoleLogs.length;
1065
- const isActive = activeTab === tab;
1066
- return (<react_native_1.Pressable key={tab} style={[
1067
- styles_1.default.dropdownItem,
1068
- isActive && { backgroundColor: `${AppColors_1.AppColors.purple}12` },
1069
- ]} onPress={() => {
1070
- setActiveTab(tab);
1071
- setShowNetworkMenu(false);
1072
- }} hitSlop={10}>
1073
- <react_native_1.Text style={{
1074
- fontFamily: AppFonts_1.AppFonts.interMedium,
1075
- color: isActive
1076
- ? AppColors_1.AppColors.purple
1077
- : AppColors_1.AppColors.primaryBlack,
1078
- }}>
1079
- {label} {count > 0 ? `(${count})` : ''}
1080
- </react_native_1.Text>
1081
- </react_native_1.Pressable>);
1205
+ {/* ─── Horizontal Scrollable Tab Bar inside Content ─── */}
1206
+ {selected == null && selectedEvent == null ? (<react_native_1.View style={styles_1.default.tabBarContainer}>
1207
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ paddingRight: 16 }}>
1208
+ {[
1209
+ { key: 'insights', label: 'Insights', count: 0, icon: 'insights' },
1210
+ { key: 'apis', label: 'APIs', count: logs.length, icon: 'apis' },
1211
+ { key: 'logs', label: 'Logs', count: consoleLogs.length, icon: 'logs' },
1212
+ { key: 'analytics', label: 'Analytics', count: analyticsEvents.length, icon: 'analytics' },
1213
+ { key: 'webview', label: 'WebView', count: webViewNavHistory.length, icon: 'webview' },
1214
+ { key: 'redux', label: 'Redux', count: 0, icon: 'redux' },
1215
+ ].map(tab => {
1216
+ const isActive = activeTab === tab.key;
1217
+ const iconColor = isActive ? '#FFFFFF' : AppColors_1.AppColors.grayText;
1218
+ const countLabel = tab.count > 9 ? '9+' : String(tab.count);
1219
+ return (<TouchableScale_1.default key={tab.key} onPress={() => {
1220
+ requestAnimationFrame(() => {
1221
+ setActiveTab(tab.key);
1222
+ });
1223
+ }} style={[
1224
+ styles_1.default.contentTabButton,
1225
+ isActive && styles_1.default.contentTabButtonActive,
1226
+ ]}>
1227
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
1228
+ {tab.icon === 'insights' && <NetworkIcons_1.InsightsIcon color={iconColor} size={14}/>}
1229
+ {tab.icon === 'apis' && <NetworkIcons_1.SignalIcon color={iconColor} size={14}/>}
1230
+ {tab.icon === 'logs' && <NetworkIcons_1.TerminalIcon color={iconColor} size={14}/>}
1231
+ {tab.icon === 'analytics' && <NetworkIcons_1.AnalyticsIcon color={iconColor} size={14}/>}
1232
+ {tab.icon === 'webview' && <NetworkIcons_1.GlobeIcon color={iconColor} size={14}/>}
1233
+ {tab.icon === 'redux' && <NetworkIcons_1.TerminalIcon color={iconColor} size={14}/>}
1234
+ <react_native_1.Text numberOfLines={1} ellipsizeMode="tail" style={[
1235
+ styles_1.default.contentTabButtonText,
1236
+ isActive && styles_1.default.contentTabButtonTextActive,
1237
+ ]}>
1238
+ {tab.label} {tab.count > 0 ? `(${countLabel})` : ''}
1239
+ </react_native_1.Text>
1240
+ </react_native_1.View>
1241
+ </TouchableScale_1.default>);
1082
1242
  })}
1083
- </react_native_1.View>)}
1243
+ </react_native_1.ScrollView>
1244
+ </react_native_1.View>) : null}
1245
+
1084
1246
 
1085
- {showUiMenu && selected == null && selectedEvent == null && (<react_native_1.View style={[styles_1.default.menuDropdown, { left: 120 }]}>
1086
- {['webview'].map(tab => {
1087
- const isActive = activeTab === tab;
1088
- return (<react_native_1.Pressable key={tab} style={[
1089
- styles_1.default.dropdownItem,
1090
- isActive && { backgroundColor: `${AppColors_1.AppColors.purple}12` },
1091
- ]} onPress={() => {
1092
- setActiveTab(tab);
1093
- setShowUiMenu(false);
1094
- }} hitSlop={10}>
1095
- <react_native_1.Text style={{
1096
- fontFamily: AppFonts_1.AppFonts.interMedium,
1097
- color: isActive
1098
- ? AppColors_1.AppColors.purple
1099
- : AppColors_1.AppColors.primaryBlack,
1100
- }}>
1101
- WebView{' '}
1102
- {webViewLogs.length > 0
1103
- ? `(${webViewLogs.length})`
1104
- : ''}
1105
- </react_native_1.Text>
1106
- </react_native_1.Pressable>);
1107
- })}
1108
- </react_native_1.View>)}
1109
1247
 
1110
1248
  {/* ─── Secondary Tab Bar for Analytics ──────────────────────── */}
1111
1249
  {isReady && activeTab === 'analytics' && selectedEvent == null && (<react_native_1.View>
@@ -1119,14 +1257,6 @@ const NetworkInspector = () => {
1119
1257
  </react_native_1.Pressable>)}
1120
1258
  </react_native_1.View>
1121
1259
  {analyticsSubTab === 'ga_events' && (<react_native_1.View style={styles_1.default.toolbarRight}>
1122
- <TouchableScale_1.default style={[
1123
- styles_1.default.toolbarBtn,
1124
- groupByScreen && styles_1.default.toolbarBtnActive,
1125
- ]} onPress={() => setGroupByScreen(prev => !prev)} hitSlop={10}>
1126
- <NetworkIcons_1.MapPinIcon color={groupByScreen
1127
- ? AppColors_1.AppColors.purple
1128
- : AppColors_1.AppColors.grayTextStrong} size={18}/>
1129
- </TouchableScale_1.default>
1130
1260
  <TouchableScale_1.default style={[
1131
1261
  styles_1.default.toolbarBtn,
1132
1262
  !hideScreenView && styles_1.default.toolbarBtnActive,
@@ -1220,17 +1350,19 @@ const NetworkInspector = () => {
1220
1350
  </react_native_1.View>
1221
1351
  </react_native_1.View>)}
1222
1352
 
1223
- {isReady ? (activeTab === 'analytics' ? (selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<react_native_1.FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
1353
+ {isReady ? (activeTab === 'insights' ? (<react_native_1.ScrollView style={styles_1.default.insightsContainer} contentContainerStyle={styles_1.default.insightsContent} showsVerticalScrollIndicator={false}>
1354
+ {renderInsightsDashboard()}
1355
+ </react_native_1.ScrollView>) : activeTab === 'analytics' ? (selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<react_native_1.FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
1224
1356
  styles_1.default.listContent,
1225
1357
  { paddingHorizontal: 16, paddingTop: 16 },
1226
1358
  ]} renderItem={({ item: [name, count] }) => {
1227
1359
  const maxCount = topEventsArray[0]?.[1] || 1;
1228
1360
  const color = (0, AnalyticsEventCard_1.getEventColor)(name);
1229
1361
  return (<react_native_1.View style={[
1230
- analyticsListStyles.topEventsCard,
1362
+ styles_1.default.analyticsTopEventsCard,
1231
1363
  { marginBottom: 12, paddingVertical: 16 },
1232
1364
  ]}>
1233
- <react_native_1.View style={analyticsListStyles.topEventRow}>
1365
+ <react_native_1.View style={styles_1.default.analyticsTopEventRow}>
1234
1366
  <react_native_1.View style={{
1235
1367
  flexDirection: 'row',
1236
1368
  alignItems: 'center',
@@ -1238,7 +1370,7 @@ const NetworkInspector = () => {
1238
1370
  flex: 1,
1239
1371
  }}>
1240
1372
  <react_native_1.View style={[
1241
- analyticsListStyles.iconCircle,
1373
+ styles_1.default.analyticsIconCircle,
1242
1374
  { backgroundColor: `${color}1A` },
1243
1375
  ]}>
1244
1376
  <react_native_svg_1.default width={14} height={14} viewBox="0 0 24 24" fill={color}>
@@ -1246,19 +1378,19 @@ const NetworkInspector = () => {
1246
1378
  <react_native_svg_1.Path d="M7 14l3-3 4 4 6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
1247
1379
  </react_native_svg_1.default>
1248
1380
  </react_native_1.View>
1249
- <react_native_1.Text style={analyticsListStyles.topEventName} numberOfLines={2}>
1381
+ <react_native_1.Text style={styles_1.default.analyticsTopEventName} numberOfLines={2}>
1250
1382
  {name}
1251
1383
  </react_native_1.Text>
1252
1384
  </react_native_1.View>
1253
- <react_native_1.View style={analyticsListStyles.topEventBarWrap}>
1385
+ <react_native_1.View style={styles_1.default.analyticsTopEventBarWrap}>
1254
1386
  <react_native_linear_gradient_1.default colors={[color, `${color}99`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={[
1255
- analyticsListStyles.topEventBar,
1387
+ styles_1.default.analyticsTopEventBar,
1256
1388
  {
1257
1389
  width: `${Math.max(6, (count / maxCount) * 100)}%`,
1258
1390
  },
1259
1391
  ]}/>
1260
1392
  </react_native_1.View>
1261
- <react_native_1.Text style={analyticsListStyles.topEventCount}>
1393
+ <react_native_1.Text style={styles_1.default.analyticsTopEventCount}>
1262
1394
  {count}
1263
1395
  </react_native_1.Text>
1264
1396
  </react_native_1.View>
@@ -1268,39 +1400,7 @@ const NetworkInspector = () => {
1268
1400
  <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
1269
1401
  </react_native_1.View>
1270
1402
  <react_native_1.Text style={styles_1.default.emptyTitle}>No Top Events</react_native_1.Text>
1271
- </react_native_1.View>}/>) : groupByScreen ? (<react_native_1.SectionList sections={groupedAnalyticsEvents} keyExtractor={item => item.id.toString()} renderSectionHeader={renderScreenSectionHeader} renderItem={({ item, index, section }) => {
1272
- if (expandedScreens.has(section.title))
1273
- return null;
1274
- const events = section.data;
1275
- const prev = events[index + 1];
1276
- const next = events[index - 1];
1277
- const msSincePrev = prev
1278
- ? item.timestamp - prev.timestamp
1279
- : undefined;
1280
- const thisMin = Math.floor(item.timestamp / 60000);
1281
- const nextMin = next
1282
- ? Math.floor(next.timestamp / 60000)
1283
- : -1;
1284
- const showTimestamp = index === 0 || thisMin !== nextMin;
1285
- return (<AnalyticsEventCard_1.default event={item} onPress={() => setSelectedEvent(item)} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === events.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={section.title}/>);
1286
- }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListHeaderComponent={null} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1287
- <react_native_1.View style={styles_1.default.emptyIconWrap}>
1288
- <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
1289
- </react_native_1.View>
1290
- <react_native_1.Text style={styles_1.default.emptyTitle}>
1291
- {analyticsSearch.length > 0
1292
- ? 'No matching events'
1293
- : 'No analytics events yet'}
1294
- </react_native_1.Text>
1295
- <react_native_1.Text style={styles_1.default.emptySub}>
1296
- {analyticsSearch.length > 0
1297
- ? 'Try adjusting your search.'
1298
- : 'Call setupAnalyticsLogger(analytics()) at app start.'}
1299
- </react_native_1.Text>
1300
- </react_native_1.View>} contentContainerStyle={[
1301
- styles_1.default.listContent,
1302
- filteredAnalyticsEvents.length === 0 && { flexGrow: 1 },
1303
- ]} keyboardShouldPersistTaps="handled"/>) : (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
1403
+ </react_native_1.View>}/>) : (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
1304
1404
  const prev = filteredAnalyticsEvents[index + 1];
1305
1405
  const next = filteredAnalyticsEvents[index - 1];
1306
1406
  const msSincePrev = prev
@@ -1330,7 +1430,7 @@ const NetworkInspector = () => {
1330
1430
  }
1331
1431
  return screenName;
1332
1432
  })()}/>);
1333
- }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListHeaderComponent={null} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1433
+ }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1334
1434
  <react_native_1.View style={styles_1.default.emptyIconWrap}>
1335
1435
  <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
1336
1436
  </react_native_1.View>
@@ -1347,84 +1447,7 @@ const NetworkInspector = () => {
1347
1447
  </react_native_1.View>} contentContainerStyle={[
1348
1448
  styles_1.default.listContent,
1349
1449
  filteredAnalyticsEvents.length === 0 && { flexGrow: 1 },
1350
- ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'apis' && selected == null ? (groupByScreen ? (<react_native_1.SectionList sections={groupedNetworkLogs} keyExtractor={item => item?.id?.toString()} renderSectionHeader={renderScreenSectionHeader} renderItem={({ item, section }) => {
1351
- if (expandedScreens.has(section.title))
1352
- return null;
1353
- return renderItem({
1354
- item: {
1355
- type: 'log',
1356
- log: item,
1357
- color: AppColors_1.AppColors.purple,
1358
- },
1359
- });
1360
- }} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<react_native_1.View style={{ marginTop: 8 }}>
1361
- {logs.length > 0 && (<react_native_1.View style={styles_1.default.dashboardCard}>
1362
- <react_native_1.View style={styles_1.default.dashboardStatsRow}>
1363
- <react_native_1.View style={styles_1.default.statBox}>
1364
- <react_native_1.Text style={styles_1.default.statValue}>
1365
- {stats.filtered < stats.total
1366
- ? stats.filtered
1367
- : stats.total}
1368
- </react_native_1.Text>
1369
- <react_native_1.Text style={styles_1.default.statLabel}>
1370
- {stats.filtered < stats.total
1371
- ? `of ${stats.total} Req`
1372
- : 'Requests'}
1373
- </react_native_1.Text>
1374
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1375
- <MiniBarChart_1.default data={stats.reqTrend} color={AppColors_1.AppColors.purple}/>
1376
- </react_native_1.View>
1377
- </react_native_1.View>
1378
- <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1379
- <react_native_1.View style={styles_1.default.statBox}>
1380
- <react_native_1.Text style={[
1381
- styles_1.default.statValue,
1382
- stats.errors > 0 && {
1383
- color: AppColors_1.AppColors.errorColor,
1384
- },
1385
- ]}>
1386
- {stats.errors}
1387
- </react_native_1.Text>
1388
- <react_native_1.Text style={styles_1.default.statLabel}>Errors</react_native_1.Text>
1389
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1390
- <MiniBarChart_1.default data={stats.errorTrend} color={AppColors_1.AppColors.errorColor} maxVal={1}/>
1391
- </react_native_1.View>
1392
- </react_native_1.View>
1393
- <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1394
- <react_native_1.View style={styles_1.default.statBox}>
1395
- <react_native_1.Text style={[
1396
- styles_1.default.statValue,
1397
- stats.avgDuration != null
1398
- ? {
1399
- color: (0, helpers_1.getDurationColor)(stats.avgDuration),
1400
- }
1401
- : null,
1402
- ]}>
1403
- {stats.avgDuration != null
1404
- ? `${stats.avgDuration}ms`
1405
- : '—'}
1406
- </react_native_1.Text>
1407
- <react_native_1.Text style={styles_1.default.statLabel}>Avg Time</react_native_1.Text>
1408
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1409
- <MiniLineChart_1.default data={stats.durationTrend} color={AppColors_1.AppColors.darkOrange}/>
1410
- </react_native_1.View>
1411
- </react_native_1.View>
1412
- <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1413
- <react_native_1.View style={styles_1.default.statBox}>
1414
- <react_native_1.Text style={[
1415
- styles_1.default.statValue,
1416
- { color: AppColors_1.AppColors.skyBlue },
1417
- ]}>
1418
- {stats.size}
1419
- </react_native_1.Text>
1420
- <react_native_1.Text style={styles_1.default.statLabel}>Payload</react_native_1.Text>
1421
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1422
- <MiniBarChart_1.default data={stats.sizeTrend} color={AppColors_1.AppColors.skyBlue}/>
1423
- </react_native_1.View>
1424
- </react_native_1.View>
1425
- </react_native_1.View>
1426
- </react_native_1.View>)}
1427
-
1450
+ ]} 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 }}>
1428
1451
  <react_native_1.View style={styles_1.default.toolbarRow}>
1429
1452
  <react_native_1.View style={styles_1.default.searchContainer}>
1430
1453
  <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
@@ -1444,14 +1467,6 @@ const NetworkInspector = () => {
1444
1467
  </react_native_1.View>)}
1445
1468
  </TouchableScale_1.default>
1446
1469
 
1447
- <TouchableScale_1.default style={[
1448
- styles_1.default.toolbarBtn,
1449
- groupByScreen && styles_1.default.toolbarBtnActive,
1450
- ]} onPress={() => setGroupByScreen(prev => !prev)} hitSlop={10}>
1451
- <NetworkIcons_1.MapPinIcon color={groupByScreen
1452
- ? AppColors_1.AppColors.purple
1453
- : AppColors_1.AppColors.grayTextStrong} size={18}/>
1454
- </TouchableScale_1.default>
1455
1470
 
1456
1471
  <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
1457
1472
  <NetworkIcons_1.SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors_1.AppColors.grayTextStrong} size={18}/>
@@ -1495,237 +1510,22 @@ const NetworkInspector = () => {
1495
1510
  });
1496
1511
  }
1497
1512
  }} hitSlop={10}>
1498
- {active ? (<react_native_linear_gradient_1.default colors={[
1499
- AppColors_1.AppColors.purpleShade50,
1500
- '#EAE5FF',
1501
- ]} style={[
1502
- styles_1.default.statusFilterChip,
1503
- styles_1.default.statusFilterActive,
1504
- ]}>
1505
- <react_native_1.Text style={[
1506
- styles_1.default.statusFilterText,
1507
- { color: AppColors_1.AppColors.purple },
1508
- ]}>
1509
- {filter}
1510
- </react_native_1.Text>
1511
- </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1512
- <react_native_1.Text style={styles_1.default.statusFilterText}>
1513
- {filter}
1514
- </react_native_1.Text>
1515
- </react_native_1.View>)}
1516
- </TouchableScale_1.default>);
1517
- })}
1518
- </react_native_1.ScrollView>
1519
-
1520
- <react_native_1.Text style={[styles_1.default.filtersHeading, { marginTop: 16 }]}>
1521
- METHOD
1522
- </react_native_1.Text>
1523
- <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
1524
- {availableMethods.map(filter => {
1525
- const isAll = filter === 'ALL';
1526
- const active = isAll
1527
- ? methodFilters.size === 0
1528
- : methodFilters.has(filter);
1529
- return (<TouchableScale_1.default key={filter} style={styles_1.default.statusFilterWrap} onPress={() => {
1530
- if (isAll) {
1531
- setMethodFilters(new Set());
1532
- }
1533
- else {
1534
- setMethodFilters(prev => {
1535
- const next = new Set(prev);
1536
- next.has(filter)
1537
- ? next.delete(filter)
1538
- : next.add(filter);
1539
- return next;
1540
- });
1541
- }
1542
- }} hitSlop={10}>
1543
- {active ? (<react_native_linear_gradient_1.default colors={[
1544
- AppColors_1.AppColors.purpleShade50,
1545
- '#EAE5FF',
1546
- ]} style={[
1513
+ {active ? (<react_native_1.View style={[
1547
1514
  styles_1.default.statusFilterChip,
1548
1515
  styles_1.default.statusFilterActive,
1516
+ { overflow: 'hidden' },
1549
1517
  ]}>
1550
- <react_native_1.Text style={[
1551
- styles_1.default.statusFilterText,
1552
- { color: AppColors_1.AppColors.purple },
1553
- ]}>
1554
- {filter}
1555
- </react_native_1.Text>
1556
- </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1557
- <react_native_1.Text style={styles_1.default.statusFilterText}>
1558
- {filter}
1559
- </react_native_1.Text>
1560
- </react_native_1.View>)}
1561
- </TouchableScale_1.default>);
1562
- })}
1563
- </react_native_1.ScrollView>
1564
- </react_native_1.View>
1565
- </react_native_1.Animated.View>
1566
-
1567
- {(search ||
1568
- statusFilters.size > 0 ||
1569
- methodFilters.size > 0) && (<react_native_1.Text style={styles_1.default.resultCount}>
1570
- {filteredLogs.length === logs.length
1571
- ? `${logs.length} requests`
1572
- : `${filteredLogs.length} of ${logs.length} filtered requests`}
1573
- </react_native_1.Text>)}
1574
- </react_native_1.View>} ListEmptyComponent={<EmptyState_1.default isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
1575
- styles_1.default.listContent,
1576
- filteredLogs.length === 0 && { flexGrow: 1 },
1577
- ]} keyboardShouldPersistTaps="handled"/>) : (<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 }}>
1578
- {logs.length > 0 && (<react_native_1.View style={styles_1.default.dashboardCard}>
1579
- <react_native_1.View style={styles_1.default.dashboardStatsRow}>
1580
- <react_native_1.View style={styles_1.default.statBox}>
1581
- <react_native_1.Text style={styles_1.default.statValue}>
1582
- {stats.filtered < stats.total
1583
- ? stats.filtered
1584
- : stats.total}
1585
- </react_native_1.Text>
1586
- <react_native_1.Text style={styles_1.default.statLabel}>
1587
- {stats.filtered < stats.total
1588
- ? `of ${stats.total} Req`
1589
- : 'Requests'}
1590
- </react_native_1.Text>
1591
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1592
- <MiniBarChart_1.default data={stats.reqTrend} color={AppColors_1.AppColors.purple}/>
1593
- </react_native_1.View>
1594
- </react_native_1.View>
1595
- <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1596
- <react_native_1.View style={styles_1.default.statBox}>
1597
- <react_native_1.Text style={[
1598
- styles_1.default.statValue,
1599
- stats.errors > 0 && {
1600
- color: AppColors_1.AppColors.errorColor,
1601
- },
1602
- ]}>
1603
- {stats.errors}
1604
- </react_native_1.Text>
1605
- <react_native_1.Text style={styles_1.default.statLabel}>Errors</react_native_1.Text>
1606
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1607
- <MiniBarChart_1.default data={stats.errorTrend} color={AppColors_1.AppColors.errorColor} maxVal={1}/>
1608
- </react_native_1.View>
1609
- </react_native_1.View>
1610
- <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1611
- <react_native_1.View style={styles_1.default.statBox}>
1612
- <react_native_1.Text style={[
1613
- styles_1.default.statValue,
1614
- stats.avgDuration != null
1615
- ? {
1616
- color: (0, helpers_1.getDurationColor)(stats.avgDuration),
1617
- }
1618
- : null,
1619
- ]}>
1620
- {stats.avgDuration != null
1621
- ? `${stats.avgDuration}ms`
1622
- : '—'}
1623
- </react_native_1.Text>
1624
- <react_native_1.Text style={styles_1.default.statLabel}>Avg Time</react_native_1.Text>
1625
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1626
- <MiniLineChart_1.default data={stats.durationTrend} color={AppColors_1.AppColors.darkOrange}/>
1627
- </react_native_1.View>
1628
- </react_native_1.View>
1629
- <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1630
- <react_native_1.View style={styles_1.default.statBox}>
1631
- <react_native_1.Text style={[
1632
- styles_1.default.statValue,
1633
- { color: AppColors_1.AppColors.skyBlue },
1634
- ]}>
1635
- {stats.size}
1636
- </react_native_1.Text>
1637
- <react_native_1.Text style={styles_1.default.statLabel}>Payload</react_native_1.Text>
1638
- <react_native_1.View style={styles_1.default.miniGraphWrap}>
1639
- <MiniBarChart_1.default data={stats.sizeTrend} color={AppColors_1.AppColors.skyBlue}/>
1640
- </react_native_1.View>
1641
- </react_native_1.View>
1642
- </react_native_1.View>
1643
- </react_native_1.View>)}
1644
-
1645
- <react_native_1.View style={styles_1.default.toolbarRow}>
1646
- <react_native_1.View style={styles_1.default.searchContainer}>
1647
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
1648
- <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"/>
1649
- {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
1650
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1651
- </react_native_1.Pressable>)}
1652
- </react_native_1.View>
1653
-
1654
- <react_native_1.View style={styles_1.default.toolbarRight}>
1655
- <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
1656
- <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1657
- {selectedLogs.size > 0 && (<react_native_1.View style={styles_1.default.trashBadge}>
1658
- <react_native_1.Text style={styles_1.default.trashBadgeText}>
1659
- {selectedLogs.size}
1660
- </react_native_1.Text>
1661
- </react_native_1.View>)}
1662
- </TouchableScale_1.default>
1663
-
1664
- <TouchableScale_1.default style={[
1665
- styles_1.default.toolbarBtn,
1666
- groupByScreen && styles_1.default.toolbarBtnActive,
1667
- ]} onPress={() => setGroupByScreen(prev => !prev)} hitSlop={10}>
1668
- <NetworkIcons_1.MapPinIcon color={groupByScreen
1669
- ? AppColors_1.AppColors.purple
1670
- : AppColors_1.AppColors.grayTextStrong} size={18}/>
1671
- </TouchableScale_1.default>
1672
-
1673
- <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
1674
- <NetworkIcons_1.SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1675
- </TouchableScale_1.default>
1676
-
1677
- <TouchableScale_1.default style={[
1678
- styles_1.default.toolbarBtn,
1679
- filtersAccordion.isOpen &&
1680
- styles_1.default.toolbarBtnActive,
1681
- ]} onPress={filtersAccordion.toggleOpen} hitSlop={10}>
1682
- <NetworkIcons_1.FilterIcon color={filtersAccordion.isOpen
1683
- ? AppColors_1.AppColors.purple
1684
- : AppColors_1.AppColors.grayTextStrong} size={18}/>
1685
- </TouchableScale_1.default>
1686
- </react_native_1.View>
1687
- </react_native_1.View>
1688
-
1689
- <react_native_1.Animated.View style={[
1690
- filtersAccordion.bodyStyle,
1691
- { overflow: 'hidden' },
1692
- ]}>
1693
- <react_native_1.View style={styles_1.default.filtersContainer}>
1694
- <react_native_1.Text style={styles_1.default.filtersHeading}>STATUS</react_native_1.Text>
1695
- <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
1696
- {constants_1.STATUS_FILTERS.map(filter => {
1697
- const isAll = filter === 'ALL';
1698
- const active = isAll
1699
- ? statusFilters.size === 0
1700
- : statusFilters.has(filter);
1701
- return (<TouchableScale_1.default key={filter} style={styles_1.default.statusFilterWrap} onPress={() => {
1702
- if (isAll) {
1703
- setStatusFilters(new Set());
1704
- }
1705
- else {
1706
- setStatusFilters(prev => {
1707
- const next = new Set(prev);
1708
- next.has(filter)
1709
- ? next.delete(filter)
1710
- : next.add(filter);
1711
- return next;
1712
- });
1713
- }
1714
- }} hitSlop={10}>
1715
- {active ? (<react_native_linear_gradient_1.default colors={[
1518
+ <react_native_linear_gradient_1.default colors={[
1716
1519
  AppColors_1.AppColors.purpleShade50,
1717
1520
  '#EAE5FF',
1718
- ]} style={[
1719
- styles_1.default.statusFilterChip,
1720
- styles_1.default.statusFilterActive,
1721
- ]}>
1521
+ ]} style={react_native_1.StyleSheet.absoluteFill} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}/>
1722
1522
  <react_native_1.Text style={[
1723
1523
  styles_1.default.statusFilterText,
1724
1524
  { color: AppColors_1.AppColors.purple },
1725
1525
  ]}>
1726
1526
  {filter}
1727
1527
  </react_native_1.Text>
1728
- </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1528
+ </react_native_1.View>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1729
1529
  <react_native_1.Text style={styles_1.default.statusFilterText}>
1730
1530
  {filter}
1731
1531
  </react_native_1.Text>
@@ -1757,20 +1557,22 @@ const NetworkInspector = () => {
1757
1557
  });
1758
1558
  }
1759
1559
  }} hitSlop={10}>
1760
- {active ? (<react_native_linear_gradient_1.default colors={[
1761
- AppColors_1.AppColors.purpleShade50,
1762
- '#EAE5FF',
1763
- ]} style={[
1560
+ {active ? (<react_native_1.View style={[
1764
1561
  styles_1.default.statusFilterChip,
1765
1562
  styles_1.default.statusFilterActive,
1563
+ { overflow: 'hidden' },
1766
1564
  ]}>
1565
+ <react_native_linear_gradient_1.default colors={[
1566
+ AppColors_1.AppColors.purpleShade50,
1567
+ '#EAE5FF',
1568
+ ]} style={react_native_1.StyleSheet.absoluteFill} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}/>
1767
1569
  <react_native_1.Text style={[
1768
1570
  styles_1.default.statusFilterText,
1769
1571
  { color: AppColors_1.AppColors.purple },
1770
1572
  ]}>
1771
1573
  {filter}
1772
1574
  </react_native_1.Text>
1773
- </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1575
+ </react_native_1.View>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1774
1576
  <react_native_1.Text style={styles_1.default.statusFilterText}>
1775
1577
  {filter}
1776
1578
  </react_native_1.Text>
@@ -1791,7 +1593,7 @@ const NetworkInspector = () => {
1791
1593
  </react_native_1.View>} ListEmptyComponent={<EmptyState_1.default isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
1792
1594
  styles_1.default.listContent,
1793
1595
  filteredLogs.length === 0 && { flexGrow: 1 },
1794
- ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'logs' ? (<react_native_1.View style={{ flex: 1 }}>
1596
+ ]} keyboardShouldPersistTaps="handled"/>) : activeTab === 'logs' ? (<react_native_1.View style={{ flex: 1 }}>
1795
1597
  <react_native_1.View style={{
1796
1598
  backgroundColor: '#FFFFFF',
1797
1599
  borderBottomWidth: 1,
@@ -2238,78 +2040,23 @@ const NetworkInspector = () => {
2238
2040
  })}
2239
2041
  </react_native_1.View>
2240
2042
  <react_native_1.View style={{ flex: 1, padding: 12 }}>
2241
- {htmlSubTab === 'html' ? (webViewHtml ? (<react_native_1.View style={{ flex: 1 }}>
2242
- <react_native_1.View style={{
2243
- flexDirection: 'row',
2244
- alignItems: 'center',
2245
- marginBottom: 8,
2246
- gap: 8,
2247
- }}>
2248
- <react_native_1.View style={[
2249
- styles_1.default.searchContainer,
2250
- { flex: 1 },
2251
- ]}>
2252
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
2253
- <react_native_1.TextInput placeholder="Search HTML..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={htmlSearch} onChangeText={setHtmlSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
2254
- {htmlSearch.length > 0 && (<react_native_1.Pressable onPress={() => setHtmlSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
2255
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2256
- </react_native_1.Pressable>)}
2257
- </react_native_1.View>
2258
- <CopyButton_1.default value={webViewHtml} label="HTML Source"/>
2259
- </react_native_1.View>
2260
- <CodeSnippet_1.default code={webViewHtml} language="html" search={htmlSearch}/>
2261
- </react_native_1.View>) : (<react_native_1.Text style={{
2043
+ {!isHtmlTabReady ? (<react_native_1.View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', minHeight: 200 }}>
2044
+ <react_native_1.ActivityIndicator size="large" color={AppColors_1.AppColors.purple}/>
2045
+ </react_native_1.View>) : htmlSubTab === 'html' ? (webViewHtml ? (<CodeSnippet_1.default code={webViewHtml} language="html"/>) : (<react_native_1.Text style={{
2262
2046
  fontFamily: 'monospace',
2263
2047
  fontSize: 11,
2264
2048
  color: '#94A3B8',
2265
2049
  padding: 12,
2266
2050
  }}>
2267
2051
  No HTML content captured.
2268
- </react_native_1.Text>)) : htmlSubTab === 'css' ? (webViewCss ? (<react_native_1.View style={{ flex: 1 }}>
2269
- <react_native_1.View style={{
2270
- flexDirection: 'row',
2271
- alignItems: 'center',
2272
- marginBottom: 8,
2273
- gap: 8,
2274
- }}>
2275
- <react_native_1.View style={[
2276
- styles_1.default.searchContainer,
2277
- { flex: 1 },
2278
- ]}>
2279
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
2280
- <react_native_1.TextInput placeholder="Search CSS..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={cssSearch} onChangeText={setCssSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
2281
- {cssSearch.length > 0 && (<react_native_1.Pressable onPress={() => setCssSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
2282
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2283
- </react_native_1.Pressable>)}
2284
- </react_native_1.View>
2285
- <CopyButton_1.default value={webViewCss} label="CSS Source"/>
2286
- </react_native_1.View>
2287
- <CodeSnippet_1.default code={webViewCss} language="css" search={cssSearch}/>
2288
- </react_native_1.View>) : (<react_native_1.Text style={{
2052
+ </react_native_1.Text>)) : htmlSubTab === 'css' ? (webViewCss ? (<CodeSnippet_1.default code={webViewCss} language="css"/>) : (<react_native_1.Text style={{
2289
2053
  fontFamily: 'monospace',
2290
2054
  fontSize: 11,
2291
2055
  color: '#94A3B8',
2292
2056
  padding: 12,
2293
2057
  }}>
2294
2058
  No CSS styles detected on this page.
2295
- </react_native_1.Text>)) : webViewJs ? (<react_native_1.View style={{ flex: 1 }}>
2296
- <react_native_1.View style={{
2297
- flexDirection: 'row',
2298
- alignItems: 'center',
2299
- marginBottom: 8,
2300
- gap: 8,
2301
- }}>
2302
- <react_native_1.View style={[styles_1.default.searchContainer, { flex: 1 }]}>
2303
- <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
2304
- <react_native_1.TextInput placeholder="Search Javascript..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={jsSearch} onChangeText={setJsSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
2305
- {jsSearch.length > 0 && (<react_native_1.Pressable onPress={() => setJsSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
2306
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2307
- </react_native_1.Pressable>)}
2308
- </react_native_1.View>
2309
- <CopyButton_1.default value={webViewJs} label="JS Source"/>
2310
- </react_native_1.View>
2311
- <CodeSnippet_1.default code={webViewJs} language="javascript" search={jsSearch}/>
2312
- </react_native_1.View>) : (<react_native_1.Text style={{
2059
+ </react_native_1.Text>)) : webViewJs ? (<CodeSnippet_1.default code={webViewJs} language="javascript"/>) : (<react_native_1.Text style={{
2313
2060
  fontFamily: 'monospace',
2314
2061
  fontSize: 11,
2315
2062
  color: '#94A3B8',
@@ -2405,60 +2152,89 @@ const NetworkInspector = () => {
2405
2152
  styles_1.default.listContent,
2406
2153
  filteredNavHistory.length === 0 && { flexGrow: 1 },
2407
2154
  ]} keyboardShouldPersistTaps="handled"/>)}
2408
- </react_native_1.View>) : (<react_native_1.ScrollView style={styles_1.default.detailScroll} contentContainerStyle={styles_1.default.detailContent} showsVerticalScrollIndicator={true}>
2409
- {(() => {
2155
+ </react_native_1.View>) : activeTab === 'redux' ? (renderReduxTab()) : (<react_native_1.View style={{ flex: 1 }}>
2156
+ {/* Non-scrollable details header */}
2157
+ <react_native_1.View style={{ paddingHorizontal: 6, paddingTop: 4 }}>
2158
+ {(() => {
2410
2159
  const routeInfo = logRouteMapRef.current.get(selected.id);
2411
2160
  const screenPath = routeInfo && routeInfo.path !== 'Navigators'
2412
2161
  ? routeInfo.path.split(' ➔ ')
2413
2162
  : [];
2414
- const parts = ['APIs', 'APIs', ...screenPath];
2415
- return (<react_native_1.View style={{ marginBottom: 12, marginTop: 4 }}>
2416
- <react_native_1.Text style={{
2417
- fontFamily: AppFonts_1.AppFonts.interMedium,
2418
- fontSize: 11.5,
2419
- color: AppColors_1.AppColors.grayTextWeak,
2163
+ const parts = ['APIs', ...screenPath];
2164
+ return (<react_native_1.View style={{
2165
+ flexDirection: 'row',
2166
+ alignItems: 'center',
2167
+ backgroundColor: AppColors_1.AppColors.primaryLight,
2168
+ borderRadius: 8,
2169
+ paddingVertical: 8,
2170
+ paddingHorizontal: 12,
2171
+ borderWidth: 1,
2172
+ borderColor: AppColors_1.AppColors.dividerColor,
2173
+ marginBottom: 12,
2174
+ marginTop: 4,
2420
2175
  }}>
2421
- {parts.map((part, index) => (<react_1.default.Fragment key={index}>
2422
- {index > 0 && ''}
2423
- <react_native_1.Text style={index === parts.length - 1
2424
- ? {
2425
- color: AppColors_1.AppColors.purple,
2426
- fontFamily: AppFonts_1.AppFonts.interBold,
2427
- }
2428
- : undefined}>
2429
- {part}
2430
- </react_native_1.Text>
2431
- </react_1.default.Fragment>))}
2432
- </react_native_1.Text>
2433
- </react_native_1.View>);
2176
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
2177
+ flexDirection: 'row',
2178
+ alignItems: 'center',
2179
+ gap: 6,
2180
+ }}>
2181
+ {parts.map((part, index) => {
2182
+ const isLast = index === parts.length - 1;
2183
+ return (<react_1.default.Fragment key={index}>
2184
+ {index > 0 && (<react_native_1.Text style={{ color: AppColors_1.AppColors.grayTextWeak, fontSize: 11, marginHorizontal: 2 }}>
2185
+ /
2186
+ </react_native_1.Text>)}
2187
+ <react_native_1.View style={isLast
2188
+ ? {
2189
+ backgroundColor: `${AppColors_1.AppColors.purple}12`,
2190
+ paddingHorizontal: 8,
2191
+ paddingVertical: 3,
2192
+ borderRadius: 6,
2193
+ }
2194
+ : {
2195
+ paddingHorizontal: 4,
2196
+ paddingVertical: 2,
2197
+ }}>
2198
+ <react_native_1.Text style={{
2199
+ fontFamily: isLast ? AppFonts_1.AppFonts.interBold : AppFonts_1.AppFonts.interMedium,
2200
+ fontSize: 11.5,
2201
+ color: isLast ? AppColors_1.AppColors.purple : AppColors_1.AppColors.grayText,
2202
+ }}>
2203
+ {part}
2204
+ </react_native_1.Text>
2205
+ </react_native_1.View>
2206
+ </react_1.default.Fragment>);
2207
+ })}
2208
+ </react_native_1.ScrollView>
2209
+ </react_native_1.View>);
2434
2210
  })()}
2435
2211
 
2436
- <react_native_1.View style={styles_1.default.detailInfoBar}>
2437
- <react_native_1.View style={styles_1.default.detailInfoTop}>
2438
- <react_native_1.View style={{
2212
+ <react_native_1.View style={styles_1.default.detailInfoBar}>
2213
+ <react_native_1.View style={styles_1.default.detailInfoTop}>
2214
+ <react_native_1.View style={{
2439
2215
  flexDirection: 'row',
2440
2216
  alignItems: 'center',
2441
2217
  gap: 10,
2442
2218
  }}>
2443
- <react_native_1.View style={[
2219
+ <react_native_1.View style={[
2444
2220
  styles_1.default.methodBadge,
2445
2221
  {
2446
2222
  backgroundColor: `${constants_1.METHOD_COLORS[selected.method] ??
2447
2223
  constants_1.METHOD_COLORS.ALL}15`,
2448
2224
  },
2449
2225
  ]}>
2450
- <react_native_1.Text style={[
2226
+ <react_native_1.Text style={[
2451
2227
  styles_1.default.methodBadgeText,
2452
2228
  {
2453
2229
  color: constants_1.METHOD_COLORS[selected.method] ??
2454
2230
  constants_1.METHOD_COLORS.ALL,
2455
2231
  },
2456
2232
  ]}>
2457
- {selected.method}
2458
- </react_native_1.Text>
2459
- </react_native_1.View>
2233
+ {selected.method}
2234
+ </react_native_1.Text>
2235
+ </react_native_1.View>
2460
2236
 
2461
- {selected.status != null && (<react_native_1.View style={[
2237
+ {selected.status != null && (<react_native_1.View style={[
2462
2238
  styles_1.default.chip,
2463
2239
  {
2464
2240
  backgroundColor: selected.status === 0
@@ -2469,10 +2245,10 @@ const NetworkInspector = () => {
2469
2245
  : `${(0, helpers_1.getStatusColor)(selected.status)}40`,
2470
2246
  },
2471
2247
  ]}>
2472
- {selected.status === 0 ? (<NetworkIcons_1.FailIcon size={8} color={AppColors_1.AppColors.errorColor}/>) : (<react_native_svg_1.default width={6} height={6} viewBox="0 0 10 10" fill="none">
2473
- <react_native_svg_1.Circle cx="5" cy="5" r="5" fill={(0, helpers_1.getStatusColor)(selected.status)}/>
2474
- </react_native_svg_1.default>)}
2475
- <react_native_1.Text style={[
2248
+ {selected.status === 0 ? (<NetworkIcons_1.FailIcon size={8} color={AppColors_1.AppColors.errorColor}/>) : (<react_native_svg_1.default width={6} height={6} viewBox="0 0 10 10" fill="none">
2249
+ <react_native_svg_1.Circle cx="5" cy="5" r="5" fill={(0, helpers_1.getStatusColor)(selected.status)}/>
2250
+ </react_native_svg_1.default>)}
2251
+ <react_native_1.Text style={[
2476
2252
  styles_1.default.chipText,
2477
2253
  {
2478
2254
  color: selected.status === 0
@@ -2480,181 +2256,172 @@ const NetworkInspector = () => {
2480
2256
  : (0, helpers_1.getStatusColor)(selected.status),
2481
2257
  },
2482
2258
  ]}>
2483
- {selected.status === 0
2259
+ {selected.status === 0
2484
2260
  ? 'Failed'
2485
2261
  : String(selected.status)}
2486
- </react_native_1.Text>
2487
- </react_native_1.View>)}
2488
- </react_native_1.View>
2489
- <react_native_1.View style={styles_1.default.detailInfoRight}>
2490
- <TouchableScale_1.default style={styles_1.default.iconSquareBtn} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)} hitSlop={12}>
2491
- <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2492
- </TouchableScale_1.default>
2493
- <CopyButton_1.default value={(0, helpers_1.getFetchCommand)(selected)} label="fetch()" iconType="fetch"/>
2494
- <CopyButton_1.default value={(0, helpers_1.getCurlCommand)(selected)} label="cURL" iconType="terminal"/>
2495
- <CopyButton_1.default value={detailDisplayUrl} label="URL"/>
2262
+ </react_native_1.Text>
2263
+ </react_native_1.View>)}
2264
+ </react_native_1.View>
2265
+ <react_native_1.View style={styles_1.default.detailInfoRight}>
2266
+ <TouchableScale_1.default style={styles_1.default.iconSquareBtn} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)} hitSlop={12}>
2267
+ <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2268
+ </TouchableScale_1.default>
2269
+ <CopyButton_1.default value={(0, helpers_1.getFetchCommand)(selected)} label="fetch()" iconType="fetch"/>
2270
+ <CopyButton_1.default value={(0, helpers_1.getCurlCommand)(selected)} label="cURL" iconType="terminal"/>
2271
+ <CopyButton_1.default value={detailDisplayUrl} label="URL"/>
2272
+ </react_native_1.View>
2496
2273
  </react_native_1.View>
2274
+
2275
+ <react_native_1.Pressable style={styles_1.default.detailUrlContainer} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)}>
2276
+ <react_native_1.Text selectable={true} style={styles_1.default.detailUrl}>
2277
+ {detailDisplayUrl}
2278
+ </react_native_1.Text>
2279
+ </react_native_1.Pressable>
2497
2280
  </react_native_1.View>
2281
+ </react_native_1.View>
2498
2282
 
2499
- <react_native_1.Pressable style={styles_1.default.detailUrlContainer} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)}>
2500
- <react_native_1.Text selectable={true} style={styles_1.default.detailUrl}>
2501
- {detailDisplayUrl}
2502
- </react_native_1.Text>
2503
- </react_native_1.Pressable>
2283
+ {/* Sticky Segment Control */}
2284
+ <react_native_1.View style={{
2285
+ flexDirection: 'row',
2286
+ backgroundColor: AppColors_1.AppColors.grayBackground,
2287
+ borderRadius: 10,
2288
+ padding: 3,
2289
+ marginHorizontal: 6,
2290
+ marginBottom: 10,
2291
+ marginTop: 6,
2292
+ borderWidth: 1,
2293
+ borderColor: AppColors_1.AppColors.dividerColor,
2294
+ }}>
2295
+ {['metadata', 'headers', 'request', 'response'].map(tab => {
2296
+ const isActive = apiDetailActiveTab === tab;
2297
+ if (tab === 'request' && selected.request == null)
2298
+ return null;
2299
+ const getLabel = () => {
2300
+ if (tab === 'metadata')
2301
+ return 'Metadata';
2302
+ if (tab === 'headers')
2303
+ return 'Headers';
2304
+ if (tab === 'request')
2305
+ return 'Request';
2306
+ return 'Response';
2307
+ };
2308
+ return (<react_native_1.TouchableOpacity key={tab} onPress={() => setApiDetailActiveTab(tab)} style={{
2309
+ flex: 1,
2310
+ paddingVertical: 6,
2311
+ alignItems: 'center',
2312
+ borderRadius: 8,
2313
+ backgroundColor: isActive ? AppColors_1.AppColors.purple : 'transparent',
2314
+ }}>
2315
+ <react_native_1.Text style={{
2316
+ fontFamily: AppFonts_1.AppFonts.interBold,
2317
+ fontSize: 11,
2318
+ color: isActive ? '#FFFFFF' : AppColors_1.AppColors.grayText,
2319
+ }}>
2320
+ {getLabel()}
2321
+ </react_native_1.Text>
2322
+ </react_native_1.TouchableOpacity>);
2323
+ })}
2504
2324
  </react_native_1.View>
2505
2325
 
2506
- <MetaAccordion_1.default status={selected.status} statusColor={(0, helpers_1.getStatusColor)(selected.status)} duration={selected.duration} size={(0, helpers_1.getSize)(selected.response)} triggeredAt={(0, helpers_1.formatDateTime)(selected.startTime)}/>
2326
+ {/* Scrollable Tab Content */}
2327
+ <react_native_1.ScrollView style={styles_1.default.detailScroll} contentContainerStyle={{ paddingHorizontal: 6, paddingBottom: 24 }} showsVerticalScrollIndicator={true}>
2328
+ {apiDetailActiveTab === 'metadata' && (<>
2329
+ <MetaAccordion_1.default status={selected.status} statusColor={(0, helpers_1.getStatusColor)(selected.status)} duration={selected.duration} size={(0, helpers_1.getSize)(selected.response)} triggeredAt={(0, helpers_1.formatDateTime)(selected.startTime)}/>
2507
2330
 
2508
- {(() => {
2509
- const routeInfo = logRouteMapRef.current.get(selected.id);
2510
- if (!routeInfo || routeInfo.path === 'Navigators')
2511
- return null;
2512
- return <SourcePageCard_1.default routeInfo={routeInfo}/>;
2513
- })()}
2331
+ {(() => {
2332
+ const routeInfo = logRouteMapRef.current.get(selected.id);
2333
+ if (!routeInfo || routeInfo.path === 'Navigators')
2334
+ return null;
2335
+ return <SourcePageCard_1.default routeInfo={routeInfo}/>;
2336
+ })()}
2514
2337
 
2515
- <react_native_1.View style={styles_1.default.seperator}/>
2338
+ {(() => {
2339
+ const cType = selected.responseHeaders?.['content-type'] ||
2340
+ selected.responseHeaders?.['Content-Type'];
2341
+ if (cType?.includes('image/')) {
2342
+ return (<react_native_1.View style={styles_1.default.imagePreviewWrapper}>
2343
+ <react_native_1.Image source={{ uri: selected.url }} style={styles_1.default.imagePreview} resizeMode="contain"/>
2344
+ <TouchableScale_1.default style={styles_1.default.imageDownloadBtn} onPress={() => react_native_1.Linking.openURL(selected.url)} hitSlop={10}>
2345
+ <NetworkIcons_1.DownloadIcon color={AppColors_1.AppColors.purple} size={18}/>
2346
+ </TouchableScale_1.default>
2347
+ </react_native_1.View>);
2348
+ }
2349
+ return null;
2350
+ })()}
2351
+ </>)}
2516
2352
 
2517
- {(() => {
2518
- const cType = selected.responseHeaders?.['content-type'] ||
2519
- selected.responseHeaders?.['Content-Type'];
2520
- if (cType?.includes('image/')) {
2521
- return (<react_native_1.View style={styles_1.default.imagePreviewWrapper}>
2522
- <react_native_1.Image source={{ uri: selected.url }} style={styles_1.default.imagePreview} resizeMode="contain"/>
2523
- <TouchableScale_1.default style={styles_1.default.imageDownloadBtn} onPress={() => react_native_1.Linking.openURL(selected.url)} hitSlop={10}>
2524
- <NetworkIcons_1.DownloadIcon color={AppColors_1.AppColors.purple} size={18}/>
2525
- </TouchableScale_1.default>
2526
- </react_native_1.View>);
2527
- }
2528
- return null;
2529
- })()}
2353
+ {apiDetailActiveTab === 'headers' && (<>
2354
+ <react_native_1.View style={styles_1.default.detailSearchRow}>
2355
+ <react_native_1.View style={styles_1.default.detailSearchBox}>
2356
+ <react_native_1.TextInput placeholder="Search headers..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles_1.default.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
2357
+ {detailSearch.length > 0 && (<react_native_1.Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
2358
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2359
+ </react_native_1.Pressable>)}
2360
+ </react_native_1.View>
2361
+ </react_native_1.View>
2530
2362
 
2531
- <react_native_1.View style={styles_1.default.detailSearchRow}>
2532
- <react_native_1.View style={styles_1.default.detailSearchBox}>
2533
- <react_native_1.TextInput placeholder="Search in request / response..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles_1.default.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
2534
- {detailSearch.length > 0 && (<react_native_1.Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
2535
- <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2536
- </react_native_1.Pressable>)}
2537
- </react_native_1.View>
2538
- <TouchableScale_1.default style={[styles_1.default.iconSquareBtn, { marginLeft: 8 }]} onPress={() => {
2539
- const next = reqExpanded === true || resExpanded === true
2540
- ? false
2541
- : true;
2542
- setReqExpanded(next);
2543
- setResExpanded(next);
2544
- }} hitSlop={10}>
2545
- <NetworkIcons_1.ExpandCollapseIcon isExpanded={reqExpanded === true || resExpanded === true} color={reqExpanded === true || resExpanded === true
2546
- ? AppColors_1.AppColors.purple
2547
- : AppColors_1.AppColors.grayTextWeak} size={14}/>
2548
- </TouchableScale_1.default>
2549
- </react_native_1.View>
2363
+ <HeadersSection_1.default title="Request Headers" headers={selected.requestHeaders} search={detailSearch} resetKey={selected.id}/>
2364
+ <HeadersSection_1.default title="Response Headers" headers={selected.responseHeaders} search={detailSearch} resetKey={selected.id}/>
2365
+ </>)}
2550
2366
 
2551
- <HeadersSection_1.default title="Request Headers" headers={selected.requestHeaders} search={detailSearch} resetKey={selected.id}/>
2552
- <HeadersSection_1.default title="Response Headers" headers={selected.responseHeaders} search={detailSearch} resetKey={selected.id}/>
2367
+ {apiDetailActiveTab === 'request' && selected.request != null && (<>
2368
+ <react_native_1.View style={styles_1.default.detailSearchRow}>
2369
+ <react_native_1.View style={styles_1.default.detailSearchBox}>
2370
+ <react_native_1.TextInput placeholder="Search request..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles_1.default.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
2371
+ {detailSearch.length > 0 && (<react_native_1.Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
2372
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2373
+ </react_native_1.Pressable>)}
2374
+ </react_native_1.View>
2375
+ </react_native_1.View>
2553
2376
 
2554
- {selected.request != null && selected.method !== 'GET' && (<react_native_1.View style={styles_1.default.sectionContainer}>
2555
- <SectionHeader_1.default title="Request" value={selected.request} expanded={reqExpanded} onToggleExpand={() => setReqExpanded(v => !v)} showDiff={prevRequestData != null} isDiffing={showReqDiff} onToggleDiff={() => {
2377
+ <react_native_1.View style={styles_1.default.sectionContainer}>
2378
+ <SectionHeader_1.default title="Request" value={selected.request} expanded={reqExpanded} onToggleExpand={() => setReqExpanded(v => !v)} showDiff={prevRequestData != null} isDiffing={showReqDiff} onToggleDiff={() => {
2556
2379
  setShowReqDiff(v => !v);
2557
2380
  if (!reqExpanded && !showReqDiff)
2558
2381
  setReqExpanded(true);
2559
2382
  }}/>
2560
- {showReqDiff ? (<DiffViewer_1.default oldData={prevRequestData} newData={selected.request} forceOpen={reqExpanded}/>) : (<JsonViewer_1.default data={selected.request} search={detailSearch} forceOpen={reqExpanded}/>)}
2561
- </react_native_1.View>)}
2383
+ {showReqDiff ? (<DiffViewer_1.default oldData={prevRequestData} newData={selected.request} forceOpen={reqExpanded}/>) : (<JsonViewer_1.default data={selected.request} search={detailSearch} forceOpen={reqExpanded}/>)}
2384
+ </react_native_1.View>
2385
+ </>)}
2562
2386
 
2563
- <react_native_1.View style={styles_1.default.sectionContainer}>
2564
- <SectionHeader_1.default title="Response" value={selected.response} expanded={resExpanded} onToggleExpand={() => setResExpanded(v => !v)} showDiff={prevResponseData != null} isDiffing={showResDiff} onToggleDiff={() => {
2565
- setShowResDiff(v => !v);
2566
- if (!resExpanded && !showResDiff)
2567
- setResExpanded(true);
2568
- }}/>
2569
- {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : (<JsonViewer_1.default data={selected.response} search={detailSearch} forceOpen={resExpanded}/>)}
2570
- </react_native_1.View>
2571
- </react_native_1.ScrollView>)) : (<react_native_1.View style={styles_1.default.empty}>
2387
+ {apiDetailActiveTab === 'response' && (<>
2388
+ <react_native_1.View style={styles_1.default.detailSearchRow}>
2389
+ <react_native_1.View style={styles_1.default.detailSearchBox}>
2390
+ <react_native_1.TextInput placeholder="Search response..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles_1.default.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
2391
+ {detailSearch.length > 0 && (<react_native_1.Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
2392
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2393
+ </react_native_1.Pressable>)}
2394
+ </react_native_1.View>
2395
+ </react_native_1.View>
2396
+
2397
+ <react_native_1.View style={styles_1.default.sectionContainer}>
2398
+ <SectionHeader_1.default title="Response" value={selected.response} expanded={resExpanded} onToggleExpand={() => setResExpanded(v => !v)} showDiff={prevResponseData != null} isDiffing={showResDiff} onToggleDiff={() => {
2399
+ setShowResDiff(v => !v);
2400
+ if (!resExpanded && !showResDiff)
2401
+ setResExpanded(true);
2402
+ }}/>
2403
+ {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : (<JsonViewer_1.default data={selected.response} search={detailSearch} forceOpen={resExpanded}/>)}
2404
+ </react_native_1.View>
2405
+ </>)}
2406
+ </react_native_1.ScrollView>
2407
+ </react_native_1.View>)) : (<react_native_1.View style={styles_1.default.empty}>
2572
2408
  <react_native_1.ActivityIndicator size="large" color={AppColors_1.AppColors.purple}/>
2573
2409
  <react_native_1.Text style={[styles_1.default.emptySub, { marginTop: 12 }]}>
2574
2410
  Loading logs...
2575
2411
  </react_native_1.Text>
2576
2412
  </react_native_1.View>)}
2577
- </react_native_1.View>)}
2413
+ </react_native_1.View>
2414
+ </react_native_1.View>
2415
+ </ErrorBoundary_1.default>)}
2578
2416
  </react_native_1.Modal>
2579
2417
  </>);
2580
2418
  };
2581
- exports.default = NetworkInspector;
2582
- // ─── Analytics list styles (Firebase DebugView look) ─────────────────────────
2583
- const analyticsListStyles = react_native_1.StyleSheet.create({
2584
- cardRow: {},
2585
- // ── Top Events summary card (mirrors Firebase DebugView right panel) ────────
2586
- topEventsCard: {
2587
- marginHorizontal: 16,
2588
- marginBottom: 12,
2589
- backgroundColor: AppColors_1.AppColors.primaryLight,
2590
- borderRadius: 12,
2591
- borderWidth: 1,
2592
- borderColor: AppColors_1.AppColors.grayBorderSecondary,
2593
- paddingHorizontal: 16,
2594
- paddingVertical: 12,
2595
- shadowColor: '#000',
2596
- shadowOpacity: 0.04,
2597
- shadowRadius: 4,
2598
- shadowOffset: { width: 0, height: 1 },
2599
- elevation: 1,
2600
- },
2601
- topEventsHeaderRow: {
2602
- flexDirection: 'row',
2603
- alignItems: 'center',
2604
- justifyContent: 'space-between',
2605
- marginBottom: 12,
2606
- },
2607
- topEventsTitle: {
2608
- fontFamily: AppFonts_1.AppFonts.interBold,
2609
- fontSize: 10,
2610
- color: AppColors_1.AppColors.grayTextWeak,
2611
- letterSpacing: 0.8,
2612
- textTransform: 'uppercase',
2613
- },
2614
- topEventsSubtitle: {
2615
- fontFamily: AppFonts_1.AppFonts.interMedium,
2616
- fontSize: 9,
2617
- color: AppColors_1.AppColors.grayTextWeak,
2618
- letterSpacing: 0.4,
2619
- },
2620
- topEventRow: {
2621
- flexDirection: 'row',
2622
- alignItems: 'center',
2623
- marginBottom: 8,
2624
- gap: 8,
2625
- },
2626
- topEventName: {
2627
- fontFamily: AppFonts_1.AppFonts.interMedium,
2628
- fontSize: 12,
2629
- color: AppColors_1.AppColors.primaryBlack,
2630
- flex: 1,
2631
- },
2632
- topEventBarWrap: {
2633
- flex: 0.8,
2634
- height: 3,
2635
- backgroundColor: AppColors_1.AppColors.grayBackground,
2636
- borderRadius: 2,
2637
- overflow: 'hidden',
2638
- },
2639
- topEventBar: {
2640
- height: '100%',
2641
- borderRadius: 2,
2642
- },
2643
- topEventCount: {
2644
- fontFamily: AppFonts_1.AppFonts.interBold,
2645
- fontSize: 11,
2646
- color: AppColors_1.AppColors.grayText,
2647
- width: 24,
2648
- textAlign: 'right',
2649
- },
2650
- iconCircle: {
2651
- width: 24,
2652
- height: 24,
2653
- borderRadius: 12,
2654
- alignItems: 'center',
2655
- justifyContent: 'center',
2656
- },
2657
- });
2419
+ const NetworkInspectorWrapper = (props) => {
2420
+ return (<ErrorBoundary_1.default fallbackType="inline">
2421
+ <NetworkInspector {...props}/>
2422
+ </ErrorBoundary_1.default>);
2423
+ };
2424
+ exports.default = NetworkInspectorWrapper;
2658
2425
  // Re-export public APIs
2659
2426
  var networkLogger_2 = require("./customHooks/networkLogger");
2660
2427
  Object.defineProperty(exports, "setupNetworkLogger", { enumerable: true, get: function () { return networkLogger_2.setupNetworkLogger; } });
@@ -2670,6 +2437,7 @@ Object.defineProperty(exports, "logAnalyticsEvent", { enumerable: true, get: fun
2670
2437
  Object.defineProperty(exports, "subscribeAnalyticsEvents", { enumerable: true, get: function () { return analyticsLogger_2.subscribeAnalyticsEvents; } });
2671
2438
  Object.defineProperty(exports, "clearAnalyticsEvents", { enumerable: true, get: function () { return analyticsLogger_2.clearAnalyticsEvents; } });
2672
2439
  var webViewLogger_2 = require("./customHooks/webViewLogger");
2440
+ Object.defineProperty(exports, "WebView", { enumerable: true, get: function () { return webViewLogger_2.WebView; } });
2673
2441
  Object.defineProperty(exports, "getWebViewLogs", { enumerable: true, get: function () { return webViewLogger_2.getWebViewLogs; } });
2674
2442
  Object.defineProperty(exports, "getWebViewNavHistory", { enumerable: true, get: function () { return webViewLogger_2.getWebViewNavHistory; } });
2675
2443
  Object.defineProperty(exports, "getWebViewHtml", { enumerable: true, get: function () { return webViewLogger_2.getWebViewHtml; } });
@@ -2678,3 +2446,9 @@ Object.defineProperty(exports, "getWebViewJs", { enumerable: true, get: function
2678
2446
  Object.defineProperty(exports, "getWebViewHtmlUrl", { enumerable: true, get: function () { return webViewLogger_2.getWebViewHtmlUrl; } });
2679
2447
  Object.defineProperty(exports, "clearWebViewData", { enumerable: true, get: function () { return webViewLogger_2.clearWebViewData; } });
2680
2448
  Object.defineProperty(exports, "subscribeWebView", { enumerable: true, get: function () { return webViewLogger_2.subscribeWebView; } });
2449
+ var ErrorBoundary_2 = require("./components/ErrorBoundary");
2450
+ Object.defineProperty(exports, "ErrorBoundary", { enumerable: true, get: function () { return __importDefault(ErrorBoundary_2).default; } });
2451
+ var reduxLogger_2 = require("./customHooks/reduxLogger");
2452
+ Object.defineProperty(exports, "connectReduxStore", { enumerable: true, get: function () { return reduxLogger_2.connectReduxStore; } });
2453
+ Object.defineProperty(exports, "getReduxState", { enumerable: true, get: function () { return reduxLogger_2.getReduxState; } });
2454
+ Object.defineProperty(exports, "subscribeReduxState", { enumerable: true, get: function () { return reduxLogger_2.subscribeReduxState; } });