react-native-inapp-inspector 1.1.24 → 1.1.26

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 (114) hide show
  1. package/android/build.gradle +36 -0
  2. package/android/src/main/AndroidManifest.xml +3 -0
  3. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +114 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +28 -0
  5. package/dist/commonjs/components/AnalyticsEventCard.js +94 -88
  6. package/dist/commonjs/components/ConsoleLogCard.js +49 -25
  7. package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
  8. package/dist/commonjs/components/ErrorBoundary.js +9 -145
  9. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
  10. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +1002 -0
  11. package/dist/commonjs/components/Inspector/AnalyticsTab.js +637 -10
  12. package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -1
  13. package/dist/commonjs/components/Inspector/BundleTab.js +826 -406
  14. package/dist/commonjs/components/Inspector/CrashDetail.d.ts +3 -0
  15. package/dist/commonjs/components/Inspector/CrashDetail.js +796 -0
  16. package/dist/commonjs/components/Inspector/CrashFilterModal.d.ts +20 -0
  17. package/dist/commonjs/components/Inspector/CrashFilterModal.js +597 -0
  18. package/dist/commonjs/components/Inspector/CrashTab.d.ts +3 -0
  19. package/dist/commonjs/components/Inspector/CrashTab.js +727 -0
  20. package/dist/commonjs/components/Inspector/InspectorContext.js +6 -1
  21. package/dist/commonjs/components/Inspector/InspectorHeader.js +65 -28
  22. package/dist/commonjs/components/Inspector/LogDetail.js +227 -114
  23. package/dist/commonjs/components/Inspector/MainScreen.js +13 -4
  24. package/dist/commonjs/components/Inspector/NetworkDetail.js +131 -81
  25. package/dist/commonjs/components/Inspector/PerformanceTab.js +20 -10
  26. package/dist/commonjs/components/Inspector/SettingsPanel.js +90 -1
  27. package/dist/commonjs/components/Inspector/TabBar.js +15 -3
  28. package/dist/commonjs/components/NetworkIcons.d.ts +25 -0
  29. package/dist/commonjs/components/NetworkIcons.js +188 -1
  30. package/dist/commonjs/components/SegmentedTabs.js +33 -23
  31. package/dist/commonjs/components/TreeNode.js +13 -12
  32. package/dist/commonjs/constants/version.d.ts +1 -1
  33. package/dist/commonjs/constants/version.js +1 -1
  34. package/dist/commonjs/customHooks/analyticsLogger.js +70 -44
  35. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +5 -1
  36. package/dist/commonjs/customHooks/bundleAnalyzer.js +497 -126
  37. package/dist/commonjs/customHooks/consoleLogger.d.ts +1 -0
  38. package/dist/commonjs/customHooks/consoleLogger.js +153 -51
  39. package/dist/commonjs/customHooks/crashHandler.d.ts +64 -0
  40. package/dist/commonjs/customHooks/crashHandler.js +681 -0
  41. package/dist/commonjs/customHooks/networkLogger.js +74 -49
  42. package/dist/commonjs/customHooks/performanceTracker.d.ts +8 -0
  43. package/dist/commonjs/customHooks/performanceTracker.js +44 -3
  44. package/dist/commonjs/decorators/index.d.ts +49 -0
  45. package/dist/commonjs/decorators/index.js +142 -0
  46. package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +18 -0
  47. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +174 -0
  48. package/dist/commonjs/helpers/index.d.ts +7 -4
  49. package/dist/commonjs/helpers/index.js +102 -64
  50. package/dist/commonjs/i18n/locales/en.json +182 -4
  51. package/dist/commonjs/index.d.ts +6 -0
  52. package/dist/commonjs/index.js +310 -8
  53. package/dist/commonjs/styles/index.d.ts +4 -1
  54. package/dist/commonjs/styles/index.js +22 -19
  55. package/dist/commonjs/types/enums.d.ts +156 -9
  56. package/dist/commonjs/types/enums.js +139 -2
  57. package/dist/commonjs/types/interfaces.d.ts +70 -1
  58. package/dist/esm/components/AnalyticsEventCard.js +95 -89
  59. package/dist/esm/components/ConsoleLogCard.js +49 -25
  60. package/dist/esm/components/ErrorBoundary.d.ts +1 -1
  61. package/dist/esm/components/ErrorBoundary.js +10 -113
  62. package/dist/esm/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
  63. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +964 -0
  64. package/dist/esm/components/Inspector/AnalyticsTab.js +639 -12
  65. package/dist/esm/components/Inspector/BundleTab.d.ts +1 -1
  66. package/dist/esm/components/Inspector/BundleTab.js +827 -407
  67. package/dist/esm/components/Inspector/CrashDetail.d.ts +3 -0
  68. package/dist/esm/components/Inspector/CrashDetail.js +758 -0
  69. package/dist/esm/components/Inspector/CrashFilterModal.d.ts +20 -0
  70. package/dist/esm/components/Inspector/CrashFilterModal.js +557 -0
  71. package/dist/esm/components/Inspector/CrashTab.d.ts +3 -0
  72. package/dist/esm/components/Inspector/CrashTab.js +689 -0
  73. package/dist/esm/components/Inspector/InspectorContext.js +1 -0
  74. package/dist/esm/components/Inspector/InspectorHeader.js +66 -29
  75. package/dist/esm/components/Inspector/LogDetail.js +227 -114
  76. package/dist/esm/components/Inspector/MainScreen.js +14 -5
  77. package/dist/esm/components/Inspector/NetworkDetail.js +132 -49
  78. package/dist/esm/components/Inspector/PerformanceTab.js +20 -10
  79. package/dist/esm/components/Inspector/SettingsPanel.js +91 -2
  80. package/dist/esm/components/Inspector/TabBar.js +16 -4
  81. package/dist/esm/components/NetworkIcons.d.ts +25 -0
  82. package/dist/esm/components/NetworkIcons.js +161 -0
  83. package/dist/esm/components/SegmentedTabs.js +33 -23
  84. package/dist/esm/components/TreeNode.js +13 -12
  85. package/dist/esm/constants/version.d.ts +1 -1
  86. package/dist/esm/constants/version.js +1 -1
  87. package/dist/esm/customHooks/analyticsLogger.js +70 -44
  88. package/dist/esm/customHooks/bundleAnalyzer.d.ts +5 -1
  89. package/dist/esm/customHooks/bundleAnalyzer.js +493 -125
  90. package/dist/esm/customHooks/consoleLogger.d.ts +1 -0
  91. package/dist/esm/customHooks/consoleLogger.js +151 -50
  92. package/dist/esm/customHooks/crashHandler.d.ts +64 -0
  93. package/dist/esm/customHooks/crashHandler.js +659 -0
  94. package/dist/esm/customHooks/networkLogger.js +74 -49
  95. package/dist/esm/customHooks/performanceTracker.d.ts +8 -0
  96. package/dist/esm/customHooks/performanceTracker.js +38 -1
  97. package/dist/esm/decorators/index.d.ts +49 -0
  98. package/dist/esm/decorators/index.js +137 -0
  99. package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +18 -0
  100. package/dist/esm/helpers/gaAnalyticsRegistry.js +169 -0
  101. package/dist/esm/helpers/index.d.ts +7 -4
  102. package/dist/esm/helpers/index.js +100 -63
  103. package/dist/esm/i18n/locales/en.json +182 -4
  104. package/dist/esm/index.d.ts +6 -0
  105. package/dist/esm/index.js +262 -8
  106. package/dist/esm/styles/index.d.ts +4 -1
  107. package/dist/esm/styles/index.js +22 -19
  108. package/dist/esm/types/enums.d.ts +156 -9
  109. package/dist/esm/types/enums.js +138 -3
  110. package/dist/esm/types/interfaces.d.ts +70 -1
  111. package/ios/NetworkInspectorModule.h +6 -0
  112. package/ios/NetworkInspectorModule.m +125 -0
  113. package/package.json +5 -2
  114. package/react-native-inapp-inspector.podspec +18 -0
package/dist/esm/index.js CHANGED
@@ -8,7 +8,7 @@ import ErrorBoundary from './components/ErrorBoundary';
8
8
  import MainScreen from './components/Inspector/MainScreen';
9
9
  import { InspectorContext, animateNextLayout, } from './components/Inspector/InspectorContext';
10
10
  // Helpers
11
- import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, } from './helpers';
11
+ import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, getEventCategory, } from './helpers';
12
12
  // #5 — settings persistence
13
13
  import { loadSettings, saveSettings, setCustomStorage, clearPersistedSettings, } from './helpers/settingsStore';
14
14
  // Network
@@ -16,6 +16,8 @@ import { setupNetworkLogger, clearNetworkLogs, subscribeNetworkLogs, } from './c
16
16
  // Console
17
17
  import { setupConsoleLogger, clearConsoleLogs, subscribeConsoleLogs, } from './customHooks/consoleLogger';
18
18
  import { IGNORED_LOG_PREFIXES } from './customHooks/logFilters';
19
+ // Crash Protection
20
+ import { setupGlobalCrashHandler, subscribeCrashEvents, getCrashRecords, clearCrashRecords, setMaxCrashLogsLimit, } from './customHooks/crashHandler';
19
21
  import { subscribeAnalyticsEvents, clearAnalyticsEvents, autoSetupAnalyticsLogger, } from './customHooks/analyticsLogger';
20
22
  import { getReduxState, subscribeReduxState, setReduxAutoRefresh, getLastActionForReducer, clearActionHistory, } from './customHooks/reduxLogger';
21
23
  import { LIB_VERSION } from './constants';
@@ -89,6 +91,14 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
89
91
  const latestAnalyticsEventsRef = useRef([]);
90
92
  const [lastReadLogsCount, setLastReadLogsCount] = useState(0);
91
93
  const [lastReadApisCount, setLastReadApisCount] = useState(0);
94
+ const [lastReadCrashesCount, setLastReadCrashesCount] = useState(0);
95
+ // ─── Crash state ───────────────────────────────────────────────────────────
96
+ const [crashRecords, setCrashRecords] = useState(() => getCrashRecords());
97
+ const [selectedCrash, setSelectedCrash] = useState(null);
98
+ const [maxCrashLogs, setMaxCrashLogs] = useState(100);
99
+ useEffect(() => {
100
+ setMaxCrashLogsLimit(maxCrashLogs);
101
+ }, [maxCrashLogs]);
92
102
  useEffect(() => {
93
103
  if (visible) {
94
104
  if (activeTab === 'apis') {
@@ -97,6 +107,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
97
107
  if (activeTab === 'logs') {
98
108
  setLastReadLogsCount(consoleLogs.length);
99
109
  }
110
+ if (activeTab === 'crash') {
111
+ setLastReadCrashesCount(crashRecords.length);
112
+ }
100
113
  }
101
114
  }, [visible]);
102
115
  useEffect(() => {
@@ -109,6 +122,11 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
109
122
  setLastReadLogsCount(consoleLogs.length);
110
123
  }
111
124
  }, [activeTab, consoleLogs.length]);
125
+ useEffect(() => {
126
+ if (activeTab === 'crash') {
127
+ setLastReadCrashesCount(crashRecords.length);
128
+ }
129
+ }, [activeTab, crashRecords.length]);
112
130
  const [maxConsoleLogs, setMaxConsoleLogs] = useState(200);
113
131
  const [showConsoleLevels, setShowConsoleLevels] = useState({
114
132
  info: true,
@@ -151,6 +169,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
151
169
  redux: false,
152
170
  bundle: false,
153
171
  performance: false,
172
+ crash: true,
154
173
  });
155
174
  const [maxNetworkLogs, setMaxNetworkLogs] = useState(100);
156
175
  const [reduxAutoRefresh, setReduxAutoRefreshState] = useState(true);
@@ -171,8 +190,10 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
171
190
  redux: false,
172
191
  bundle: false,
173
192
  performance: false,
193
+ crash: true,
174
194
  });
175
195
  setDefaultTab('apis');
196
+ setMaxCrashLogs(100);
176
197
  setMaxNetworkLogs(100);
177
198
  setMaxConsoleLogs(200);
178
199
  setShowConsoleLevels({
@@ -205,6 +226,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
205
226
  ...prev,
206
227
  ...saved.tabVisibility,
207
228
  apis: true, // APIs is always required
229
+ crash: saved.tabVisibility.crash !== undefined
230
+ ? saved.tabVisibility.crash
231
+ : true,
208
232
  }));
209
233
  if (saved.defaultTab)
210
234
  setDefaultTab(saved.defaultTab);
@@ -230,6 +254,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
230
254
  redux: false,
231
255
  bundle: false,
232
256
  performance: false,
257
+ crash: true,
233
258
  },
234
259
  ...(saved.tabVisibility || {}),
235
260
  apis: true,
@@ -332,7 +357,67 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
332
357
  }, []);
333
358
  const [selectedEvent, setSelectedEvent] = useState(null);
334
359
  const [analyticsSearch, setAnalyticsSearch] = useState('');
335
- const [hideScreenView] = useState(true);
360
+ const [analyticsFilters, setAnalyticsFilters] = useState({
361
+ categories: new Set(['all']),
362
+ screens: new Set(),
363
+ sources: new Set(['all']),
364
+ userTypes: new Set(['all']),
365
+ timeWindow: 'all',
366
+ payloadComplexity: 'all',
367
+ hasRevenue: false,
368
+ hasItems: false,
369
+ hasUserProps: false,
370
+ hasParams: false,
371
+ onlyDuplicates: false,
372
+ onlyConversions: false,
373
+ sortBy: 'time_desc',
374
+ });
375
+ const isAnalyticsFilterApplied = useMemo(() => {
376
+ if (analyticsFilters.categories.size > 0 && !analyticsFilters.categories.has('all'))
377
+ return true;
378
+ if (analyticsFilters.screens.size > 0)
379
+ return true;
380
+ if (analyticsFilters.sources.size > 0 && !analyticsFilters.sources.has('all'))
381
+ return true;
382
+ if (analyticsFilters.userTypes.size > 0 && !analyticsFilters.userTypes.has('all'))
383
+ return true;
384
+ if (analyticsFilters.timeWindow !== 'all')
385
+ return true;
386
+ if (analyticsFilters.payloadComplexity !== 'all')
387
+ return true;
388
+ if (analyticsFilters.hasRevenue)
389
+ return true;
390
+ if (analyticsFilters.hasItems)
391
+ return true;
392
+ if (analyticsFilters.hasUserProps)
393
+ return true;
394
+ if (analyticsFilters.hasParams)
395
+ return true;
396
+ if (analyticsFilters.onlyDuplicates)
397
+ return true;
398
+ if (analyticsFilters.onlyConversions)
399
+ return true;
400
+ if (analyticsFilters.sortBy !== 'time_desc')
401
+ return true;
402
+ return false;
403
+ }, [analyticsFilters]);
404
+ const resetAnalyticsFilters = useCallback(() => {
405
+ setAnalyticsFilters({
406
+ categories: new Set(['all']),
407
+ screens: new Set(),
408
+ sources: new Set(['all']),
409
+ userTypes: new Set(['all']),
410
+ timeWindow: 'all',
411
+ payloadComplexity: 'all',
412
+ hasRevenue: false,
413
+ hasItems: false,
414
+ hasUserProps: false,
415
+ hasParams: false,
416
+ onlyDuplicates: false,
417
+ onlyConversions: false,
418
+ sortBy: 'time_desc',
419
+ });
420
+ }, []);
336
421
  const [isAnalyticsLayoutReady, setIsAnalyticsLayoutReady] = useState(false);
337
422
  const [analyticsHeaderExpanded, setAnalyticsHeaderExpanded] = useState(false);
338
423
  const [newEventIds, setNewEventIds] = useState(new Set());
@@ -550,6 +635,22 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
550
635
  clearNetworkLogs();
551
636
  setupConsoleLogger();
552
637
  autoSetupAnalyticsLogger();
638
+ setupGlobalCrashHandler();
639
+ const unsubscribeCrash = subscribeCrashEvents(crashInfo => {
640
+ if (crashInfo.message === '__CLEARED__') {
641
+ setCrashRecords([]);
642
+ setSelectedCrash(null);
643
+ return;
644
+ }
645
+ const updated = getCrashRecords();
646
+ setCrashRecords(updated);
647
+ });
648
+ // Sync crashes recorded before this subscription ran (e.g. a render crash
649
+ // during the very first commit, which fires before effects are mounted).
650
+ const pendingCrashes = getCrashRecords();
651
+ if (pendingCrashes.length > 0) {
652
+ setCrashRecords(pendingCrashes);
653
+ }
553
654
  let timeoutId;
554
655
  let isFirstNetworkCall = true;
555
656
  const unsubscribe = subscribeNetworkLogs((raw) => {
@@ -661,6 +762,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
661
762
  unsubscribeConsole();
662
763
  clearTimeout(consoleTimeoutId);
663
764
  unsubscribeRedux();
765
+ unsubscribeCrash();
664
766
  };
665
767
  }, []);
666
768
  useEffect(() => {
@@ -866,15 +968,110 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
866
968
  const prevResponseData = prevSameRequest ? prevSameRequest.response : null;
867
969
  const filteredAnalyticsEvents = useMemo(() => {
868
970
  let events = analyticsEvents;
869
- if (hideScreenView) {
870
- events = events.filter(e => e.name !== 'screen_view');
871
- }
971
+ // Search query filter
872
972
  if (analyticsSearch) {
873
973
  const s = analyticsSearch.toLowerCase();
874
974
  events = events.filter(e => e.name.toLowerCase().includes(s) ||
875
- JSON.stringify(e.params).toLowerCase().includes(s) ||
975
+ JSON.stringify(e.params || {}).toLowerCase().includes(s) ||
976
+ (e.screenName ?? '').toLowerCase().includes(s) ||
876
977
  (e.pageTitle ?? '').toLowerCase().includes(s));
877
978
  }
979
+ // Category filter
980
+ if (analyticsFilters.categories.size > 0 && !analyticsFilters.categories.has('all')) {
981
+ events = events.filter(e => {
982
+ const cat = getEventCategory(e.name);
983
+ return analyticsFilters.categories.has(cat);
984
+ });
985
+ }
986
+ // Time window filter
987
+ if (analyticsFilters.timeWindow !== 'all') {
988
+ const now = Date.now();
989
+ const cutoff = analyticsFilters.timeWindow === '1m'
990
+ ? now - 60 * 1000
991
+ : analyticsFilters.timeWindow === '5m'
992
+ ? now - 5 * 60 * 1000
993
+ : analyticsFilters.timeWindow === '15m'
994
+ ? now - 15 * 60 * 1000
995
+ : now - 60 * 60 * 1000;
996
+ events = events.filter(e => e.timestamp >= cutoff);
997
+ }
998
+ // Source filter
999
+ if (analyticsFilters.sources.size > 0 && !analyticsFilters.sources.has('all')) {
1000
+ events = events.filter(e => analyticsFilters.sources.has(e.source || 'manual'));
1001
+ }
1002
+ // User identification filter
1003
+ if (analyticsFilters.userTypes.size > 0 && !analyticsFilters.userTypes.has('all')) {
1004
+ events = events.filter(e => {
1005
+ const isIdentified = Boolean(e.userId && e.userId.trim() !== '');
1006
+ if (analyticsFilters.userTypes.has('identified') && isIdentified)
1007
+ return true;
1008
+ if (analyticsFilters.userTypes.has('anonymous') && !isIdentified)
1009
+ return true;
1010
+ return false;
1011
+ });
1012
+ }
1013
+ // Payload complexity filter
1014
+ if (analyticsFilters.payloadComplexity !== 'all') {
1015
+ events = events.filter(e => {
1016
+ const count = e.params ? Object.keys(e.params).length : 0;
1017
+ if (analyticsFilters.payloadComplexity === 'none')
1018
+ return count === 0;
1019
+ if (analyticsFilters.payloadComplexity === 'simple')
1020
+ return count >= 1 && count <= 5;
1021
+ if (analyticsFilters.payloadComplexity === 'heavy')
1022
+ return count > 5;
1023
+ return true;
1024
+ });
1025
+ }
1026
+ // Conversion / Goal events filter
1027
+ if (analyticsFilters.onlyConversions) {
1028
+ const CONVERSION_PATTERNS = [
1029
+ 'purchase',
1030
+ 'item_purchase',
1031
+ 'ecommerce_purchase',
1032
+ 'sign_up',
1033
+ 'login',
1034
+ 'lead',
1035
+ 'generate_lead',
1036
+ 'tutorial_complete',
1037
+ 'add_payment_info',
1038
+ 'begin_checkout',
1039
+ 'spend_virtual_currency',
1040
+ ];
1041
+ events = events.filter(e => CONVERSION_PATTERNS.some(pat => e.name.toLowerCase().includes(pat)));
1042
+ }
1043
+ // Screen filter
1044
+ if (analyticsFilters.screens.size > 0) {
1045
+ events = events.filter(e => {
1046
+ const scr = e.screenName ||
1047
+ e.params?.firebase_screen ||
1048
+ e.params?.screen_name ||
1049
+ e.params?.firebase_screen_class ||
1050
+ e.screenClass ||
1051
+ '';
1052
+ return analyticsFilters.screens.has(scr);
1053
+ });
1054
+ }
1055
+ // Has Revenue filter
1056
+ if (analyticsFilters.hasRevenue) {
1057
+ events = events.filter(e => {
1058
+ const val = e.params?.value ?? e.params?.price;
1059
+ return val !== undefined && val !== null && Number(val) > 0;
1060
+ });
1061
+ }
1062
+ // Has Items filter
1063
+ if (analyticsFilters.hasItems) {
1064
+ events = events.filter(e => Array.isArray(e.params?.items) && e.params.items.length > 0);
1065
+ }
1066
+ // Has User Props filter
1067
+ if (analyticsFilters.hasUserProps) {
1068
+ events = events.filter(e => e.userProperties && Object.keys(e.userProperties).length > 0);
1069
+ }
1070
+ // Has Params filter
1071
+ if (analyticsFilters.hasParams) {
1072
+ events = events.filter(e => e.params && Object.keys(e.params).length > 0);
1073
+ }
1074
+ // Deduplication
878
1075
  const deduplicatedEvents = [];
879
1076
  for (const e of events) {
880
1077
  if (deduplicatedEvents.length === 0) {
@@ -894,8 +1091,27 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
894
1091
  deduplicatedEvents.push({ ...e, count: 1 });
895
1092
  }
896
1093
  }
897
- return deduplicatedEvents;
898
- }, [analyticsEvents, analyticsSearch, hideScreenView]);
1094
+ let result = deduplicatedEvents;
1095
+ // Only duplicates filter
1096
+ if (analyticsFilters.onlyDuplicates) {
1097
+ result = result.filter(e => (e.count || 1) > 1);
1098
+ }
1099
+ // Sorting
1100
+ if (analyticsFilters.sortBy === 'time_asc') {
1101
+ result = [...result].sort((a, b) => a.timestamp - b.timestamp);
1102
+ }
1103
+ else if (analyticsFilters.sortBy === 'revenue_desc') {
1104
+ result = [...result].sort((a, b) => {
1105
+ const valA = Number(a.params?.value ?? a.params?.price ?? 0);
1106
+ const valB = Number(b.params?.value ?? b.params?.price ?? 0);
1107
+ return valB - valA;
1108
+ });
1109
+ }
1110
+ else if (analyticsFilters.sortBy === 'count_desc') {
1111
+ result = [...result].sort((a, b) => (b.count || 1) - (a.count || 1));
1112
+ }
1113
+ return result;
1114
+ }, [analyticsEvents, analyticsSearch, analyticsFilters]);
899
1115
  const filteredConsoleLogs = useMemo(() => {
900
1116
  let result = visibleConsoleLogs;
901
1117
  // Filters check
@@ -1036,6 +1252,21 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1036
1252
  ]);
1037
1253
  return;
1038
1254
  }
1255
+ if (activeTab === 'crash') {
1256
+ Alert.alert('Clear Crash History', 'Are you sure you want to clear all intercepted crash records?', [
1257
+ { text: 'Cancel', style: 'cancel' },
1258
+ {
1259
+ text: 'Clear All',
1260
+ onPress: () => {
1261
+ clearCrashRecords();
1262
+ setCrashRecords([]);
1263
+ setSelectedCrash(null);
1264
+ },
1265
+ style: 'destructive',
1266
+ },
1267
+ ]);
1268
+ return;
1269
+ }
1039
1270
  // Default: APIs tab. Only clears NETWORK logs — never touches the other tabs.
1040
1271
  if (selectedLogs.size > 0) {
1041
1272
  setLogs(prev => prev.filter(l => !selectedLogs.has(l.id)));
@@ -1194,6 +1425,10 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1194
1425
  filteredAnalyticsEvents,
1195
1426
  analyticsSearch,
1196
1427
  setAnalyticsSearch,
1428
+ analyticsFilters,
1429
+ setAnalyticsFilters,
1430
+ isAnalyticsFilterApplied,
1431
+ resetAnalyticsFilters,
1197
1432
  newEventIds,
1198
1433
  isAnalyticsLayoutReady,
1199
1434
  setIsAnalyticsLayoutReady,
@@ -1213,6 +1448,19 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1213
1448
  setSelectedReduxAction,
1214
1449
  reduxActiveSubTab,
1215
1450
  setReduxActiveSubTab,
1451
+ // ─── Crash ───────────────────────────────────────────────────────────
1452
+ crashRecords,
1453
+ setCrashRecords,
1454
+ selectedCrash,
1455
+ setSelectedCrash,
1456
+ lastReadCrashesCount,
1457
+ maxCrashLogs,
1458
+ setMaxCrashLogs,
1459
+ clearAllCrashes: () => {
1460
+ clearCrashRecords();
1461
+ setCrashRecords([]);
1462
+ setSelectedCrash(null);
1463
+ },
1216
1464
  // ─── Settings ───────────────────────────────────────────────────────
1217
1465
  settingsActiveSubTab,
1218
1466
  setSettingsActiveSubTab,
@@ -1256,5 +1504,11 @@ export default NetworkInspectorWrapper;
1256
1504
  export { setupNetworkLogger, clearNetworkLogs, subscribeNetworkLogs, addAxiosInterceptors, } from './customHooks/networkLogger';
1257
1505
  export { setupConsoleLogger, clearConsoleLogs, subscribeConsoleLogs, } from './customHooks/consoleLogger';
1258
1506
  export { setupAnalyticsLogger, logAnalyticsEvent, subscribeAnalyticsEvents, clearAnalyticsEvents, getCurrentUserProperties, getCurrentUserId, getDefaultEventParameters, getCollectionEnabled, } from './customHooks/analyticsLogger';
1507
+ export { setupGlobalCrashHandler, subscribeCrashEvents, emitCrashEvent, getCrashRecords, clearCrashRecords, simulateTestCrash, exportCrashReport, parseCrashStackTrace, recordCustomCrash, addCrashBreadcrumb, recordNavigationBreadcrumb, recordNetworkBreadcrumb, recordReduxBreadcrumb, recordUserActionBreadcrumb, computeCrashFingerprint, } from './customHooks/crashHandler';
1508
+ export { default as CrashTab } from './components/Inspector/CrashTab';
1259
1509
  export { default as ErrorBoundary } from './components/ErrorBoundary';
1260
1510
  export { connectReduxStore, inspectorReduxMiddleware, getReduxState, subscribeReduxState, getActionHistory, clearActionHistory, getLastActionForReducer, } from './customHooks/reduxLogger';
1511
+ export { getEventCategory, registerGAPlugin, } from './helpers/gaAnalyticsRegistry';
1512
+ export { usePerformanceTracker, logPerformanceEvent, clearPerformanceEvents, subscribePerformanceEvents, getPerformanceEvents, } from './customHooks/performanceTracker';
1513
+ export { InspectLog, InspectTrackTime, InspectCatch, } from './decorators';
1514
+ export { ActiveTab, Method, StatusFilter, SortOrder, LocalFilter, ModalAnimationType, SettingsPage, SettingsSubTab, LogFilter, ConsoleLogType, AnalyticsEventSource, GAEventCategory, StackFrameType, DiffResultType, BundleSubTab, PerformanceSubTab, CrashType, CrashExportFormat, CrashDetailSubTab, CrashFilterType, BreadcrumbType, } from './types';
@@ -641,6 +641,10 @@ export declare const getRawStyles: (colors: typeof AppColors) => {
641
641
  fontSize: number;
642
642
  color: string;
643
643
  letterSpacing: number;
644
+ backgroundColor: string;
645
+ paddingHorizontal: number;
646
+ paddingVertical: number;
647
+ borderRadius: number;
644
648
  };
645
649
  slugText: {
646
650
  fontFamily: string;
@@ -1457,7 +1461,6 @@ export declare const getRawStyles: (colors: typeof AppColors) => {
1457
1461
  flexDirection: string;
1458
1462
  justifyContent: string;
1459
1463
  alignItems: string;
1460
- marginBottom: number;
1461
1464
  };
1462
1465
  analyticsHeaderTitle: {
1463
1466
  fontFamily: string;
@@ -574,10 +574,10 @@ export const getRawStyles = (colors) => ({
574
574
  flexDirection: 'row',
575
575
  alignItems: 'center',
576
576
  justifyContent: 'space-between',
577
- backgroundColor: colors.grayBackground,
578
- borderRadius: 7,
577
+ backgroundColor: `${colors.brandPurple}08`,
578
+ borderRadius: 8,
579
579
  borderWidth: 1,
580
- borderColor: colors.grayBorderSecondary,
580
+ borderColor: `${colors.brandPurple}18`,
581
581
  paddingHorizontal: 8,
582
582
  paddingVertical: 5,
583
583
  marginVertical: 5,
@@ -592,12 +592,16 @@ export const getRawStyles = (colors) => ({
592
592
  slugTag: {
593
593
  fontFamily: AppFonts.interBold,
594
594
  fontSize: 8.5,
595
- color: colors.grayTextWeak,
595
+ color: colors.brandPurple,
596
596
  letterSpacing: 0.5,
597
+ backgroundColor: `${colors.brandPurple}15`,
598
+ paddingHorizontal: 4,
599
+ paddingVertical: 1,
600
+ borderRadius: 4,
597
601
  },
598
602
  slugText: {
599
603
  fontFamily: AppFonts.interBold,
600
- fontSize: 12.5,
604
+ fontSize: 12,
601
605
  color: colors.primaryBlack,
602
606
  flexShrink: 1,
603
607
  },
@@ -1333,11 +1337,11 @@ export const getRawStyles = (colors) => ({
1333
1337
  backgroundColor: colors.primaryLight,
1334
1338
  borderRadius: 12,
1335
1339
  borderWidth: 1,
1336
- borderColor: colors.grayBorderSecondary,
1337
- padding: 14,
1338
- marginHorizontal: 12,
1340
+ borderColor: `${colors.brandPurple}20`,
1341
+ padding: 12,
1342
+ marginHorizontal: 10,
1339
1343
  marginTop: 8,
1340
- marginBottom: 8,
1344
+ marginBottom: 6,
1341
1345
  shadowColor: colors.black,
1342
1346
  shadowOpacity: 0.03,
1343
1347
  shadowRadius: 4,
@@ -1348,11 +1352,10 @@ export const getRawStyles = (colors) => ({
1348
1352
  flexDirection: 'row',
1349
1353
  justifyContent: 'space-between',
1350
1354
  alignItems: 'center',
1351
- marginBottom: 10,
1352
1355
  },
1353
1356
  analyticsHeaderTitle: {
1354
1357
  fontFamily: AppFonts.interBold,
1355
- fontSize: 14,
1358
+ fontSize: 13.5,
1356
1359
  color: colors.primaryBlack,
1357
1360
  },
1358
1361
  statusDot: {
@@ -1363,21 +1366,21 @@ export const getRawStyles = (colors) => ({
1363
1366
  analyticsHeaderSubtitle: {
1364
1367
  fontFamily: AppFonts.interMedium,
1365
1368
  fontSize: 11,
1366
- color: colors.grayText,
1369
+ color: colors.grayTextWeak,
1367
1370
  marginTop: 2,
1368
1371
  },
1369
1372
  analyticsHeaderToggle: {
1370
- paddingVertical: 4,
1371
- paddingHorizontal: 8,
1372
- borderRadius: 4,
1373
- backgroundColor: colors.grayBackground,
1373
+ paddingVertical: 4.5,
1374
+ paddingHorizontal: 9,
1375
+ borderRadius: 7,
1376
+ backgroundColor: `${colors.brandPurple}12`,
1374
1377
  borderWidth: 1,
1375
- borderColor: colors.grayBorderSecondary,
1378
+ borderColor: `${colors.brandPurple}25`,
1376
1379
  },
1377
1380
  analyticsHeaderToggleText: {
1378
1381
  fontFamily: AppFonts.interBold,
1379
- fontSize: 10,
1380
- color: colors.purple,
1382
+ fontSize: 10.5,
1383
+ color: colors.brandPurple,
1381
1384
  },
1382
1385
  analyticsStatsRow: {
1383
1386
  flexDirection: 'row',
@@ -1,9 +1,156 @@
1
- export type ActiveTab = 'apis' | 'analytics' | 'logs' | 'redux' | 'bundle' | 'performance';
2
- export type Method = 'ALL' | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
3
- export type StatusFilter = 'ALL' | '2xx' | '3xx' | '4xx' | '5xx' | 'Failed';
4
- export type SortOrder = 'newest' | 'oldest';
5
- export type LocalFilter = 'success' | 'failed' | 'loading';
6
- export type ModalAnimationType = 'slide' | 'fade' | 'none';
7
- export type SettingsPage = 'main' | 'apis' | 'logs' | 'analytics' | 'redux' | 'bundle' | 'performance' | null;
8
- export type SettingsSubTab = 'module' | 'ui';
9
- export type LogFilter = 'all' | 'info' | 'warn' | 'error' | 'user-log' | 'analytics';
1
+ export declare const ActiveTab: {
2
+ readonly Apis: "apis";
3
+ readonly Analytics: "analytics";
4
+ readonly Logs: "logs";
5
+ readonly Redux: "redux";
6
+ readonly Bundle: "bundle";
7
+ readonly Performance: "performance";
8
+ readonly Crash: "crash";
9
+ };
10
+ export type ActiveTab = (typeof ActiveTab)[keyof typeof ActiveTab];
11
+ export declare const Method: {
12
+ readonly All: "ALL";
13
+ readonly Get: "GET";
14
+ readonly Post: "POST";
15
+ readonly Put: "PUT";
16
+ readonly Patch: "PATCH";
17
+ readonly Delete: "DELETE";
18
+ };
19
+ export type Method = (typeof Method)[keyof typeof Method];
20
+ export declare const StatusFilter: {
21
+ readonly All: "ALL";
22
+ readonly TwoXx: "2xx";
23
+ readonly ThreeXx: "3xx";
24
+ readonly FourXx: "4xx";
25
+ readonly FiveXx: "5xx";
26
+ readonly Failed: "Failed";
27
+ };
28
+ export type StatusFilter = (typeof StatusFilter)[keyof typeof StatusFilter];
29
+ export declare const SortOrder: {
30
+ readonly Newest: "newest";
31
+ readonly Oldest: "oldest";
32
+ };
33
+ export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder];
34
+ export declare const LocalFilter: {
35
+ readonly Success: "success";
36
+ readonly Failed: "failed";
37
+ readonly Loading: "loading";
38
+ };
39
+ export type LocalFilter = (typeof LocalFilter)[keyof typeof LocalFilter];
40
+ export declare const ModalAnimationType: {
41
+ readonly Slide: "slide";
42
+ readonly Fade: "fade";
43
+ readonly None: "none";
44
+ };
45
+ export type ModalAnimationType = (typeof ModalAnimationType)[keyof typeof ModalAnimationType];
46
+ export declare const SettingsPage: {
47
+ readonly Main: "main";
48
+ readonly Apis: "apis";
49
+ readonly Logs: "logs";
50
+ readonly Analytics: "analytics";
51
+ readonly Redux: "redux";
52
+ readonly Bundle: "bundle";
53
+ readonly Performance: "performance";
54
+ readonly Crash: "crash";
55
+ };
56
+ export type SettingsPage = (typeof SettingsPage)[keyof typeof SettingsPage] | null;
57
+ export declare const SettingsSubTab: {
58
+ readonly Module: "module";
59
+ readonly Ui: "ui";
60
+ };
61
+ export type SettingsSubTab = (typeof SettingsSubTab)[keyof typeof SettingsSubTab];
62
+ export declare const LogFilter: {
63
+ readonly All: "all";
64
+ readonly Info: "info";
65
+ readonly Warn: "warn";
66
+ readonly Error: "error";
67
+ readonly UserLog: "user-log";
68
+ readonly Analytics: "analytics";
69
+ };
70
+ export type LogFilter = (typeof LogFilter)[keyof typeof LogFilter];
71
+ export declare const ConsoleLogType: {
72
+ readonly Info: "info";
73
+ readonly Warn: "warn";
74
+ readonly Error: "error";
75
+ };
76
+ export type ConsoleLogType = (typeof ConsoleLogType)[keyof typeof ConsoleLogType];
77
+ export declare const AnalyticsEventSource: {
78
+ readonly Firebase: "firebase";
79
+ readonly Manual: "manual";
80
+ };
81
+ export type AnalyticsEventSource = (typeof AnalyticsEventSource)[keyof typeof AnalyticsEventSource];
82
+ export declare const GAEventCategory: {
83
+ readonly PageView: "page_view";
84
+ readonly Ecommerce: "ecommerce";
85
+ readonly System: "system";
86
+ readonly Custom: "custom";
87
+ };
88
+ export type GAEventCategory = (typeof GAEventCategory)[keyof typeof GAEventCategory];
89
+ export declare const StackFrameType: {
90
+ readonly App: "app";
91
+ readonly Dependency: "dependency";
92
+ readonly Runtime: "runtime";
93
+ readonly Native: "native";
94
+ };
95
+ export type StackFrameType = (typeof StackFrameType)[keyof typeof StackFrameType];
96
+ export declare const DiffResultType: {
97
+ readonly Added: "added";
98
+ readonly Removed: "removed";
99
+ readonly Changed: "changed";
100
+ };
101
+ export type DiffResultType = (typeof DiffResultType)[keyof typeof DiffResultType];
102
+ export declare const BundleSubTab: {
103
+ readonly Overview: "overview";
104
+ readonly Production: "production";
105
+ readonly Files: "files";
106
+ readonly Packages: "packages";
107
+ readonly Media: "media";
108
+ readonly Optimizer: "optimizer";
109
+ };
110
+ export type BundleSubTab = (typeof BundleSubTab)[keyof typeof BundleSubTab];
111
+ export declare const PerformanceSubTab: {
112
+ readonly Overview: "overview";
113
+ readonly Renders: "renders";
114
+ readonly Interactions: "interactions";
115
+ readonly Memory: "memory";
116
+ };
117
+ export type PerformanceSubTab = (typeof PerformanceSubTab)[keyof typeof PerformanceSubTab];
118
+ export declare const CrashType: {
119
+ readonly Native: "native";
120
+ readonly Js: "js";
121
+ readonly Promise: "promise";
122
+ readonly Render: "render";
123
+ readonly Custom: "custom";
124
+ };
125
+ export type CrashType = (typeof CrashType)[keyof typeof CrashType];
126
+ export declare const CrashExportFormat: {
127
+ readonly Text: "text";
128
+ readonly Markdown: "markdown";
129
+ readonly Json: "json";
130
+ };
131
+ export type CrashExportFormat = (typeof CrashExportFormat)[keyof typeof CrashExportFormat];
132
+ export declare const CrashDetailSubTab: {
133
+ readonly Stack: "stack";
134
+ readonly Diagnostics: "diagnostics";
135
+ readonly Breadcrumbs: "breadcrumbs";
136
+ readonly Raw: "raw";
137
+ };
138
+ export type CrashDetailSubTab = (typeof CrashDetailSubTab)[keyof typeof CrashDetailSubTab];
139
+ export declare const CrashFilterType: {
140
+ readonly All: "all";
141
+ readonly Fatal: "fatal";
142
+ readonly Js: "js";
143
+ readonly Promise: "promise";
144
+ readonly Render: "render";
145
+ readonly Native: "native";
146
+ };
147
+ export type CrashFilterType = (typeof CrashFilterType)[keyof typeof CrashFilterType];
148
+ export declare const BreadcrumbType: {
149
+ readonly Navigation: "navigation";
150
+ readonly Network: "network";
151
+ readonly Redux: "redux";
152
+ readonly Console: "console";
153
+ readonly User: "user";
154
+ readonly System: "system";
155
+ };
156
+ export type BreadcrumbType = (typeof BreadcrumbType)[keyof typeof BreadcrumbType];