react-native-inapp-inspector 1.1.35 → 2.0.1

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 (104) hide show
  1. package/README.md +123 -101
  2. package/android/build.gradle +13 -1
  3. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +890 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
  5. package/dist/commonjs/components/ConsoleLogCard.js +5 -5
  6. package/dist/commonjs/components/CopyButton.js +3 -0
  7. package/dist/commonjs/components/EndOfListFooter.js +1 -1
  8. package/dist/commonjs/components/ErrorBoundary.js +3 -0
  9. package/dist/commonjs/components/Inspector/AnalyticsTab.js +25 -73
  10. package/dist/commonjs/components/Inspector/BundleTab.js +671 -189
  11. package/dist/commonjs/components/Inspector/ConsoleTab.js +110 -99
  12. package/dist/commonjs/components/Inspector/CrashTab.js +99 -91
  13. package/dist/commonjs/components/Inspector/InspectorHeader.js +107 -20
  14. package/dist/commonjs/components/Inspector/MainScreen.js +111 -68
  15. package/dist/commonjs/components/Inspector/NetworkTab.js +151 -30
  16. package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
  17. package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
  18. package/dist/commonjs/components/Inspector/SettingsPanel.js +1218 -1238
  19. package/dist/commonjs/components/Inspector/TabBar.js +4 -2
  20. package/dist/commonjs/components/JsonViewer.js +9 -4
  21. package/dist/commonjs/components/LogCard.js +31 -1
  22. package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
  23. package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
  24. package/dist/commonjs/components/NetworkIcons.d.ts +3 -0
  25. package/dist/commonjs/components/NetworkIcons.js +15 -1
  26. package/dist/commonjs/components/Slider.d.ts +13 -0
  27. package/dist/commonjs/components/Slider.js +261 -0
  28. package/dist/commonjs/components/TouchableScale.d.ts +1 -0
  29. package/dist/commonjs/components/TouchableScale.js +30 -32
  30. package/dist/commonjs/constants/index.d.ts +1 -2
  31. package/dist/commonjs/constants/index.js +4 -0
  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.d.ts +4 -0
  35. package/dist/commonjs/customHooks/analyticsLogger.js +8 -6
  36. package/dist/commonjs/customHooks/crashHandler.js +8 -1
  37. package/dist/commonjs/helpers/index.d.ts +1 -0
  38. package/dist/commonjs/helpers/index.js +25 -1
  39. package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
  40. package/dist/commonjs/helpers/searchQueryParser.js +236 -0
  41. package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
  42. package/dist/commonjs/helpers/settingsStore.js +59 -3
  43. package/dist/commonjs/index.d.ts +1 -0
  44. package/dist/commonjs/index.js +220 -43
  45. package/dist/commonjs/native/NativeInspector.d.ts +125 -0
  46. package/dist/commonjs/native/NativeInspector.js +313 -0
  47. package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
  48. package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
  49. package/dist/commonjs/styles/index.js +41 -41
  50. package/dist/commonjs/types/enums.d.ts +1 -1
  51. package/dist/commonjs/types/interfaces.d.ts +9 -0
  52. package/dist/esm/components/ConsoleLogCard.js +5 -5
  53. package/dist/esm/components/CopyButton.js +3 -0
  54. package/dist/esm/components/EndOfListFooter.js +2 -2
  55. package/dist/esm/components/ErrorBoundary.js +3 -0
  56. package/dist/esm/components/Inspector/AnalyticsTab.js +27 -75
  57. package/dist/esm/components/Inspector/BundleTab.js +671 -189
  58. package/dist/esm/components/Inspector/ConsoleTab.js +111 -100
  59. package/dist/esm/components/Inspector/CrashTab.js +99 -91
  60. package/dist/esm/components/Inspector/InspectorHeader.js +108 -21
  61. package/dist/esm/components/Inspector/MainScreen.js +113 -70
  62. package/dist/esm/components/Inspector/NetworkTab.js +152 -31
  63. package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
  64. package/dist/esm/components/Inspector/ReduxTab.js +18 -10
  65. package/dist/esm/components/Inspector/SettingsPanel.js +1222 -1242
  66. package/dist/esm/components/Inspector/TabBar.js +4 -2
  67. package/dist/esm/components/JsonViewer.js +9 -4
  68. package/dist/esm/components/LogCard.js +32 -2
  69. package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
  70. package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
  71. package/dist/esm/components/NetworkIcons.d.ts +3 -0
  72. package/dist/esm/components/NetworkIcons.js +11 -0
  73. package/dist/esm/components/Slider.d.ts +13 -0
  74. package/dist/esm/components/Slider.js +222 -0
  75. package/dist/esm/components/TouchableScale.d.ts +1 -0
  76. package/dist/esm/components/TouchableScale.js +31 -33
  77. package/dist/esm/constants/index.d.ts +1 -2
  78. package/dist/esm/constants/index.js +4 -0
  79. package/dist/esm/constants/version.d.ts +1 -1
  80. package/dist/esm/constants/version.js +1 -1
  81. package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
  82. package/dist/esm/customHooks/analyticsLogger.js +6 -5
  83. package/dist/esm/customHooks/crashHandler.js +8 -1
  84. package/dist/esm/helpers/index.d.ts +1 -0
  85. package/dist/esm/helpers/index.js +11 -1
  86. package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
  87. package/dist/esm/helpers/searchQueryParser.js +233 -0
  88. package/dist/esm/helpers/settingsStore.d.ts +9 -0
  89. package/dist/esm/helpers/settingsStore.js +58 -3
  90. package/dist/esm/index.d.ts +1 -0
  91. package/dist/esm/index.js +207 -44
  92. package/dist/esm/native/NativeInspector.d.ts +125 -0
  93. package/dist/esm/native/NativeInspector.js +289 -0
  94. package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
  95. package/dist/esm/native/NativeNetworkInspector.js +2 -0
  96. package/dist/esm/styles/index.js +41 -41
  97. package/dist/esm/types/enums.d.ts +1 -1
  98. package/dist/esm/types/interfaces.d.ts +9 -0
  99. package/ios/NetworkInspectorModule.h +6 -0
  100. package/ios/NetworkInspectorModule.m +760 -5
  101. package/package.json +13 -2
  102. package/react-native-inapp-inspector.podspec +7 -2
  103. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
  104. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +0 -28
package/dist/esm/index.js CHANGED
@@ -8,9 +8,10 @@ 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, getEventCategory, } from './helpers';
11
+ import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, getEventCategory, matchNetworkLogQuery, } from './helpers';
12
12
  // #5 — settings persistence
13
- import { loadSettings, saveSettings, setCustomStorage, clearPersistedSettings, } from './helpers/settingsStore';
13
+ import { loadSettings, saveSettings, setCustomStorage, clearPersistedSettings, calculateRamBasedLimits, } from './helpers/settingsStore';
14
+ import { getNativeSystemMetrics, pushNativeLogRecord, fetchNativeCachedPage, } from './native/NativeInspector';
14
15
  // Network
15
16
  import { setupNetworkLogger, clearNetworkLogs, subscribeNetworkLogs, setNetworkModuleEnabled, } from './customHooks/networkLogger';
16
17
  // Console
@@ -22,6 +23,7 @@ import { subscribeAnalyticsEvents, clearAnalyticsEvents, autoSetupAnalyticsLogge
22
23
  import { getReduxState, subscribeReduxState, setReduxAutoRefresh, getLastActionForReducer, clearActionHistory, isReduxConnected, setReduxModuleEnabled, } from './customHooks/reduxLogger';
23
24
  import { setPerformanceModuleEnabled } from './customHooks/performanceTracker';
24
25
  import { setBundleModuleEnabled } from './customHooks/bundleAnalyzer';
26
+ import { showNativeFloatingButton, hideNativeFloatingButton, setNativeFloatingButtonBadge, subscribeNativeFloatingButtonPress, subscribeNativeDeviceShake, isNativeModuleAvailable, } from './native/NativeInspector';
25
27
  import { LIB_VERSION } from './constants';
26
28
  // Stylesheet
27
29
  import { toggleGlobalTheme } from './styles';
@@ -97,7 +99,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
97
99
  // ─── Crash state ───────────────────────────────────────────────────────────
98
100
  const [crashRecords, setCrashRecords] = useState(() => getCrashRecords());
99
101
  const [selectedCrash, setSelectedCrash] = useState(null);
100
- const [maxCrashLogs, setMaxCrashLogs] = useState(100);
102
+ const [maxCrashLogs, setMaxCrashLogs] = useState(50);
101
103
  useEffect(() => {
102
104
  setMaxCrashLogsLimit(maxCrashLogs);
103
105
  }, [maxCrashLogs]);
@@ -129,7 +131,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
129
131
  setLastReadCrashesCount(crashRecords.length);
130
132
  }
131
133
  }, [activeTab, crashRecords.length]);
132
- const [maxConsoleLogs, setMaxConsoleLogs] = useState(200);
134
+ const [maxConsoleLogs, setMaxConsoleLogs] = useState(100);
133
135
  const [showConsoleLevels, setShowConsoleLevels] = useState({
134
136
  info: true,
135
137
  warn: false,
@@ -174,6 +176,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
174
176
  crash: false,
175
177
  });
176
178
  const [maxNetworkLogs, setMaxNetworkLogs] = useState(100);
179
+ const [maxAnalyticsEventsLimit, setMaxAnalyticsEventsLimit] = useState(75);
180
+ const [isAutoRamLimitEnabled, setIsAutoRamLimitEnabled] = useState(true);
181
+ const [deviceFreeRamMb, setDeviceFreeRamMb] = useState(1800);
177
182
  const [reduxAutoRefresh, setReduxAutoRefreshState] = useState(true);
178
183
  const [reduxExpandDepth, setReduxExpandDepth] = useState(1);
179
184
  // #6 — tab the inspector opens on. Shown with a DEFAULT badge in Settings.
@@ -189,6 +194,25 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
189
194
  setCrashModuleEnabled(!!tabVisibility.crash);
190
195
  setBundleModuleEnabled(!!tabVisibility.bundle);
191
196
  }, [tabVisibility]);
197
+ // Query native hardware RAM and auto-tune limits if auto-RAM is active
198
+ useEffect(() => {
199
+ getNativeSystemMetrics()
200
+ .then(metrics => {
201
+ if (metrics) {
202
+ const freeRam = metrics.totalPhysicalRamMb - metrics.residentRamMb;
203
+ const freeMb = Math.max(200, Math.round(freeRam > 0 ? freeRam : 1500));
204
+ setDeviceFreeRamMb(freeMb);
205
+ if (isAutoRamLimitEnabled) {
206
+ const profile = calculateRamBasedLimits(freeMb);
207
+ setMaxNetworkLogs(profile.maxNetworkLogs);
208
+ setMaxConsoleLogs(profile.maxConsoleLogs);
209
+ setMaxAnalyticsEventsLimit(profile.maxAnalyticsEvents);
210
+ setMaxCrashLogs(profile.maxCrashRecords);
211
+ }
212
+ }
213
+ })
214
+ .catch(() => { });
215
+ }, [isAutoRamLimitEnabled]);
192
216
  const resetToDefaults = async () => {
193
217
  await clearPersistedSettings();
194
218
  setIsDark(false);
@@ -205,9 +229,12 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
205
229
  crash: false,
206
230
  });
207
231
  setDefaultTab('apis');
208
- setMaxCrashLogs(100);
209
- setMaxNetworkLogs(100);
210
- setMaxConsoleLogs(200);
232
+ setIsAutoRamLimitEnabled(true);
233
+ const profile = calculateRamBasedLimits(deviceFreeRamMb);
234
+ setMaxCrashLogs(profile.maxCrashRecords);
235
+ setMaxNetworkLogs(profile.maxNetworkLogs);
236
+ setMaxConsoleLogs(profile.maxConsoleLogs);
237
+ setMaxAnalyticsEventsLimit(profile.maxAnalyticsEvents);
211
238
  setShowConsoleLevels({
212
239
  info: true,
213
240
  warn: true,
@@ -241,10 +268,16 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
241
268
  }));
242
269
  if (saved.defaultTab)
243
270
  setDefaultTab(saved.defaultTab);
271
+ if (saved.isAutoRamLimitEnabled != null)
272
+ setIsAutoRamLimitEnabled(saved.isAutoRamLimitEnabled);
244
273
  if (saved.maxNetworkLogs != null)
245
274
  setMaxNetworkLogs(saved.maxNetworkLogs);
246
275
  if (saved.maxConsoleLogs != null)
247
276
  setMaxConsoleLogs(saved.maxConsoleLogs);
277
+ if (saved.maxAnalyticsEventsLimit != null)
278
+ setMaxAnalyticsEventsLimit(saved.maxAnalyticsEventsLimit);
279
+ if (saved.maxCrashLogs != null)
280
+ setMaxCrashLogs(saved.maxCrashLogs);
248
281
  if (saved.showConsoleLevels)
249
282
  setShowConsoleLevels(saved.showConsoleLevels);
250
283
  if (saved.reduxAutoRefresh != null)
@@ -287,6 +320,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
287
320
  defaultTab,
288
321
  maxNetworkLogs,
289
322
  maxConsoleLogs,
323
+ maxAnalyticsEventsLimit,
324
+ maxCrashLogs,
325
+ isAutoRamLimitEnabled,
290
326
  showConsoleLevels,
291
327
  reduxAutoRefresh,
292
328
  reduxExpandDepth,
@@ -300,6 +336,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
300
336
  defaultTab,
301
337
  maxNetworkLogs,
302
338
  maxConsoleLogs,
339
+ maxAnalyticsEventsLimit,
340
+ maxCrashLogs,
341
+ isAutoRamLimitEnabled,
303
342
  showConsoleLevels,
304
343
  reduxAutoRefresh,
305
344
  reduxExpandDepth,
@@ -374,13 +413,43 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
374
413
  return newVisibility;
375
414
  });
376
415
  };
416
+ const loadNativePage = useCallback(async (tabKey, query = '') => {
417
+ if (tabKey === 'apis' || tabKey === 'logs' || tabKey === 'analytics' || tabKey === 'crash') {
418
+ const pageData = await fetchNativeCachedPage(tabKey, 0, 100, query);
419
+ if (pageData && pageData.items && pageData.items.length > 0) {
420
+ if (tabKey === 'apis')
421
+ setLogs(pageData.items);
422
+ else if (tabKey === 'logs')
423
+ setConsoleLogs(pageData.items);
424
+ else if (tabKey === 'analytics')
425
+ setAnalyticsEvents(pageData.items);
426
+ else if (tabKey === 'crash')
427
+ setCrashRecords(pageData.items);
428
+ }
429
+ }
430
+ }, []);
377
431
  const switchActiveTab = useCallback((key) => {
378
432
  if (key === 'redux' && !isReduxConnected())
379
433
  return;
380
434
  if (key === 'analytics' && !isAnalyticsConnected())
381
435
  return;
382
- setActiveTab(key);
383
- }, []);
436
+ setSelected(null);
437
+ setSelectedEvent(null);
438
+ setSelectedLog(null);
439
+ setSelectedReduxSlice(null);
440
+ setSelectedReduxAction(null);
441
+ setSelectedCrash(null);
442
+ if (typeof React.startTransition === 'function') {
443
+ React.startTransition(() => {
444
+ setActiveTab(key);
445
+ loadNativePage(key);
446
+ });
447
+ }
448
+ else {
449
+ setActiveTab(key);
450
+ loadNativePage(key);
451
+ }
452
+ }, [loadNativePage]);
384
453
  const [selectedEvent, setSelectedEvent] = useState(null);
385
454
  const [analyticsSearch, setAnalyticsSearch] = useState('');
386
455
  const [analyticsFilters, setAnalyticsFilters] = useState({
@@ -628,6 +697,53 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
628
697
  loop.start();
629
698
  return () => loop.stop();
630
699
  }, [unreadPulseAnim]);
700
+ const isNativeModule = useMemo(() => isNativeModuleAvailable(), []);
701
+ const useNativeFab = (Platform.OS === 'ios' || Platform.OS === 'android') && isNativeModule;
702
+ // 100% Native Main-Thread Floating Button Lifecycle
703
+ useEffect(() => {
704
+ if (!useNativeFab || !isEnabled || !enabled) {
705
+ if (useNativeFab) {
706
+ hideNativeFloatingButton();
707
+ }
708
+ return;
709
+ }
710
+ if (visible) {
711
+ hideNativeFloatingButton();
712
+ }
713
+ else {
714
+ showNativeFloatingButton();
715
+ setNativeFloatingButtonBadge(logs.length > 0 || analyticsEvents.length > 0);
716
+ }
717
+ }, [
718
+ useNativeFab,
719
+ isEnabled,
720
+ enabled,
721
+ visible,
722
+ logs.length,
723
+ analyticsEvents.length,
724
+ ]);
725
+ // Subscribe to native UI-thread floating button tap events
726
+ useEffect(() => {
727
+ if (!useNativeFab)
728
+ return;
729
+ const unsubscribe = subscribeNativeFloatingButtonPress(() => {
730
+ setVisible(true);
731
+ });
732
+ return () => {
733
+ unsubscribe();
734
+ };
735
+ }, [useNativeFab]);
736
+ // Subscribe to physical hardware shake events (or Cmd+Ctrl+Z on iOS simulator)
737
+ useEffect(() => {
738
+ if (!useNativeFab)
739
+ return;
740
+ const unsubscribe = subscribeNativeDeviceShake(() => {
741
+ setVisible(prev => !prev);
742
+ });
743
+ return () => {
744
+ unsubscribe();
745
+ };
746
+ }, [useNativeFab]);
631
747
  const isVisibleRefObj = useRef(visible);
632
748
  // #6 — every time the inspector is opened, land on chosen default tab & sync latest logs
633
749
  useEffect(() => {
@@ -694,6 +810,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
694
810
  return;
695
811
  }
696
812
  const updated = getCrashRecords();
813
+ if (updated.length > 0) {
814
+ pushNativeLogRecord('crash', JSON.stringify(updated[0]));
815
+ }
697
816
  if (isVisibleRef.current) {
698
817
  setCrashRecords(updated);
699
818
  }
@@ -702,12 +821,16 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
702
821
  // during the very first commit, which fires before effects are mounted).
703
822
  const pendingCrashes = getCrashRecords();
704
823
  if (pendingCrashes.length > 0) {
824
+ pendingCrashes.forEach(c => pushNativeLogRecord('crash', JSON.stringify(c)));
705
825
  setCrashRecords(pendingCrashes);
706
826
  }
707
827
  let timeoutId;
708
828
  let isFirstNetworkCall = true;
709
829
  const unsubscribe = subscribeNetworkLogs((raw) => {
710
830
  latestNetworkLogsRef.current = raw;
831
+ if (raw.length > 0) {
832
+ pushNativeLogRecord('apis', JSON.stringify(raw[0]));
833
+ }
711
834
  if (isNetworkPausedRef.current)
712
835
  return;
713
836
  if (!isVisibleRef.current)
@@ -749,6 +872,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
749
872
  let isFirstAnalyticsCall = true;
750
873
  const unsubscribeAnalytics = subscribeAnalyticsEvents((raw) => {
751
874
  latestAnalyticsEventsRef.current = raw;
875
+ if (raw.length > 0) {
876
+ pushNativeLogRecord('analytics', JSON.stringify(raw[0]));
877
+ }
752
878
  if (isAnalyticsPausedRef.current)
753
879
  return;
754
880
  if (!isVisibleRef.current)
@@ -788,6 +914,9 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
788
914
  let isFirstConsoleCall = true;
789
915
  const unsubscribeConsole = subscribeConsoleLogs((raw) => {
790
916
  latestConsoleLogsRef.current = raw;
917
+ if (raw.length > 0) {
918
+ pushNativeLogRecord('logs', JSON.stringify(raw[0]));
919
+ }
791
920
  if (isConsolePausedRef.current)
792
921
  return;
793
922
  if (!isVisibleRef.current)
@@ -858,6 +987,10 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
858
987
  return true;
859
988
  if (f === 'Failed')
860
989
  return log.status === 0 || log.status == null;
990
+ const codeNum = parseInt(f, 10);
991
+ if (!isNaN(codeNum)) {
992
+ return Number(log.status) === codeNum;
993
+ }
861
994
  return String(log.status)[0] === f[0];
862
995
  });
863
996
  if (!matched)
@@ -873,9 +1006,13 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
873
1006
  if (!matchedMethod)
874
1007
  return false;
875
1008
  }
876
- // Search Bar Check
877
- if (search && !log.url?.toLowerCase().includes(search.toLowerCase()))
878
- return false;
1009
+ // Advanced Search Query Engine Check (Supports method:POST, is:error, slow:>1s, status:200, headers, body, etc.)
1010
+ if (search && search.trim().length > 0) {
1011
+ const routePath = logRouteMapRef.current.get(log.id)?.path || '';
1012
+ const isMatch = matchNetworkLogQuery(log, search, routePath);
1013
+ if (!isMatch)
1014
+ return false;
1015
+ }
879
1016
  return true;
880
1017
  });
881
1018
  if (sortOrder === 'oldest') {
@@ -1030,12 +1167,20 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1030
1167
  const filteredAnalyticsEvents = useMemo(() => {
1031
1168
  let events = analyticsEvents;
1032
1169
  // Search query filter
1033
- if (analyticsSearch) {
1034
- const s = analyticsSearch.toLowerCase();
1035
- events = events.filter(e => e.name.toLowerCase().includes(s) ||
1036
- JSON.stringify(e.params || {}).toLowerCase().includes(s) ||
1037
- (e.screenName ?? '').toLowerCase().includes(s) ||
1038
- (e.pageTitle ?? '').toLowerCase().includes(s));
1170
+ if (analyticsSearch && analyticsSearch.trim().length > 0) {
1171
+ const queryTokens = analyticsSearch.trim().toLowerCase().split(/\s+/).filter(Boolean);
1172
+ events = events.filter(e => {
1173
+ const searchTarget = [
1174
+ e.name || '',
1175
+ JSON.stringify(e.params || ''),
1176
+ JSON.stringify(e.userProperties || ''),
1177
+ e.screenName || '',
1178
+ e.pageTitle || '',
1179
+ e.userId || '',
1180
+ e.source || '',
1181
+ ].join(' ').toLowerCase();
1182
+ return queryTokens.every(token => searchTarget.includes(token));
1183
+ });
1039
1184
  }
1040
1185
  // Category filter
1041
1186
  if (analyticsFilters.categories.size > 0 && !analyticsFilters.categories.has('all')) {
@@ -1073,16 +1218,15 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1073
1218
  }
1074
1219
  // Payload complexity filter
1075
1220
  if (analyticsFilters.payloadComplexity !== 'all') {
1076
- events = events.filter(e => {
1077
- const count = e.params ? Object.keys(e.params).length : 0;
1078
- if (analyticsFilters.payloadComplexity === 'none')
1079
- return count === 0;
1080
- if (analyticsFilters.payloadComplexity === 'simple')
1081
- return count >= 1 && count <= 5;
1082
- if (analyticsFilters.payloadComplexity === 'heavy')
1083
- return count > 5;
1084
- return true;
1085
- });
1221
+ if (analyticsFilters.payloadComplexity === 'none') {
1222
+ events = events.filter(e => !e.params || Object.keys(e.params).length === 0);
1223
+ }
1224
+ else if (analyticsFilters.payloadComplexity === 'simple') {
1225
+ events = events.filter(e => e.params && Object.keys(e.params).length <= 3);
1226
+ }
1227
+ else if (analyticsFilters.payloadComplexity === 'heavy') {
1228
+ events = events.filter(e => e.params && Object.keys(e.params).length > 3);
1229
+ }
1086
1230
  }
1087
1231
  // Conversion / Goal events filter
1088
1232
  if (analyticsFilters.onlyConversions) {
@@ -1115,10 +1259,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1115
1259
  }
1116
1260
  // Has Revenue filter
1117
1261
  if (analyticsFilters.hasRevenue) {
1118
- events = events.filter(e => {
1119
- const val = e.params?.value ?? e.params?.price;
1120
- return val !== undefined && val !== null && Number(val) > 0;
1121
- });
1262
+ events = events.filter(e => (e.params?.value != null && !isNaN(Number(e.params.value))) ||
1263
+ (e.params?.price != null && !isNaN(Number(e.params.price))));
1122
1264
  }
1123
1265
  // Has Items filter
1124
1266
  if (analyticsFilters.hasItems) {
@@ -1171,8 +1313,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1171
1313
  else if (analyticsFilters.sortBy === 'count_desc') {
1172
1314
  result = [...result].sort((a, b) => (b.count || 1) - (a.count || 1));
1173
1315
  }
1174
- return result;
1175
- }, [analyticsEvents, analyticsSearch, analyticsFilters]);
1316
+ return result.slice(0, maxAnalyticsEventsLimit);
1317
+ }, [analyticsEvents, analyticsSearch, analyticsFilters, maxAnalyticsEventsLimit]);
1176
1318
  const filteredConsoleLogs = useMemo(() => {
1177
1319
  let result = visibleConsoleLogs;
1178
1320
  // Filters check
@@ -1183,16 +1325,23 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1183
1325
  if (logFilters.has('user-log') && log.sourceMethod === 'log')
1184
1326
  return true;
1185
1327
  if (logFilters.has('analytics') &&
1186
- log.message.toLowerCase().includes('[analytics error]'))
1328
+ log.message?.toLowerCase().includes('[analytics error]'))
1187
1329
  return true;
1188
1330
  return false;
1189
1331
  });
1190
1332
  }
1191
- // Search bar check
1192
- if (logSearch) {
1193
- const s = logSearch.toLowerCase();
1194
- result = result.filter(log => log.message.toLowerCase().includes(s) ||
1195
- (log.caller ?? '').toLowerCase().includes(s));
1333
+ // Comprehensive Search bar check
1334
+ if (logSearch && logSearch.trim().length > 0) {
1335
+ const queryTokens = logSearch.trim().toLowerCase().split(/\s+/).filter(Boolean);
1336
+ result = result.filter(log => {
1337
+ const searchTarget = [
1338
+ log.message || '',
1339
+ log.caller || '',
1340
+ log.type || '',
1341
+ log.sourceMethod || '',
1342
+ ].join(' ').toLowerCase();
1343
+ return queryTokens.every(token => searchTarget.includes(token));
1344
+ });
1196
1345
  }
1197
1346
  // #7 — apply sort order (newest/oldest first)
1198
1347
  result = [...result].sort((a, b) => logSortOrder === 'newest'
@@ -1229,10 +1378,17 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1229
1378
  ]);
1230
1379
  const logCounts = useMemo(() => {
1231
1380
  let searchedLogs = visibleConsoleLogs;
1232
- if (logSearch) {
1233
- const s = logSearch.toLowerCase();
1234
- searchedLogs = visibleConsoleLogs.filter(log => log.message.toLowerCase().includes(s) ||
1235
- (log.caller ?? '').toLowerCase().includes(s));
1381
+ if (logSearch && logSearch.trim().length > 0) {
1382
+ const queryTokens = logSearch.trim().toLowerCase().split(/\s+/).filter(Boolean);
1383
+ searchedLogs = visibleConsoleLogs.filter(log => {
1384
+ const searchTarget = [
1385
+ log.message || '',
1386
+ log.caller || '',
1387
+ log.type || '',
1388
+ log.sourceMethod || '',
1389
+ ].join(' ').toLowerCase();
1390
+ return queryTokens.every(token => searchTarget.includes(token));
1391
+ });
1236
1392
  }
1237
1393
  const total = visibleConsoleLogs.length;
1238
1394
  return {
@@ -1426,6 +1582,7 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1426
1582
  unreadPulseAnim,
1427
1583
  runClearAllWithAnimation,
1428
1584
  // ─── FAB / launcher ─────────────────────────────────────────────────
1585
+ useNativeFab,
1429
1586
  fabPan,
1430
1587
  fabPanResponder,
1431
1588
  fabDraggedRef,
@@ -1543,6 +1700,11 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
1543
1700
  setMaxNetworkLogs,
1544
1701
  maxConsoleLogs,
1545
1702
  setMaxConsoleLogs,
1703
+ maxAnalyticsEventsLimit,
1704
+ setMaxAnalyticsEventsLimit,
1705
+ isAutoRamLimitEnabled,
1706
+ setIsAutoRamLimitEnabled,
1707
+ deviceFreeRamMb,
1546
1708
  reduxAutoRefresh,
1547
1709
  setReduxAutoRefreshState,
1548
1710
  reduxExpandDepth,
@@ -1576,4 +1738,5 @@ export { connectReduxStore, inspectorReduxMiddleware, getReduxState, subscribeRe
1576
1738
  export { getEventCategory, registerGAPlugin, } from './helpers/gaAnalyticsRegistry';
1577
1739
  export { usePerformanceTracker, useComponentProfiler, useNavigationProfiler, trackComponentRender, trackNavigationTransition, trackHeavyTask, measureAsync, getHermesMemoryStats, registerComponentProfile, subscribeRenderProfiles, getRenderProfiles, logPerformanceEvent, clearPerformanceEvents, subscribePerformanceEvents, getPerformanceEvents, getInitialRenderProfiles, getInitialPerformanceEvents, generateFixSnippet, } from './customHooks/performanceTracker';
1578
1740
  export { InspectLog, InspectTrackTime, InspectCatch, } from './decorators';
1741
+ export { getNativeDeviceMetrics, enableNativeCrashProtection, subscribeNativeCrashes, showNativeFloatingButton, hideNativeFloatingButton, setNativeFloatingButtonBadge, subscribeNativeFloatingButtonPress, subscribeNativeDeviceShake, startNativeFpsMonitoring, stopNativeFpsMonitoring, getNativeFpsMetrics, getNativeStorageItem, setNativeStorageItem, isNativeModuleAvailable, } from './native/NativeInspector';
1579
1742
  export { ActiveTab, Method, StatusFilter, SortOrder, LocalFilter, ModalAnimationType, SettingsPage, SettingsSubTab, LogFilter, ConsoleLogType, AnalyticsEventSource, GAEventCategory, StackFrameType, DiffResultType, BundleSubTab, PerformanceSubTab, CrashType, CrashExportFormat, CrashDetailSubTab, CrashFilterType, BreadcrumbType, } from './types';
@@ -0,0 +1,125 @@
1
+ export interface NativeDeviceMetrics {
2
+ totalRAM?: number;
3
+ freeRAM?: number;
4
+ usedRAM?: number;
5
+ residentMemory?: number;
6
+ virtualMemory?: number;
7
+ isLowMemory?: boolean;
8
+ nativeHeapAllocated?: number;
9
+ nativeHeapSize?: number;
10
+ nativeHeapFree?: number;
11
+ freeStorage?: number;
12
+ totalStorage?: number;
13
+ batteryPercent?: number;
14
+ isCharging?: boolean;
15
+ deviceModel?: string;
16
+ deviceBrand?: string;
17
+ osVersion?: string;
18
+ apiLevel?: number;
19
+ cpuAbi?: string;
20
+ }
21
+ export interface NativeCrashEvent {
22
+ platform: 'android' | 'ios';
23
+ error: string;
24
+ name?: string;
25
+ stack?: string;
26
+ threadName?: string;
27
+ timestamp: number;
28
+ }
29
+ export declare const isNativeModuleAvailable: () => boolean;
30
+ /**
31
+ * Retrieves low-level native hardware and system metrics (RAM, Heap, Disk, Battery, CPU).
32
+ */
33
+ export declare const getNativeDeviceMetrics: () => Promise<NativeDeviceMetrics | null>;
34
+ /**
35
+ * Enables native signal and uncaught exception protection in the iOS / Android runtime.
36
+ * Automatically ensures the native floating icon is shown and available before UI renders.
37
+ */
38
+ export declare const enableNativeCrashProtection: (options?: {
39
+ showFloatingButton?: boolean;
40
+ }) => Promise<boolean>;
41
+ /**
42
+ * Subscribes to fatal native crash events caught by the iOS / Kotlin exception handlers.
43
+ */
44
+ export declare const subscribeNativeCrashes: (callback: (event: NativeCrashEvent) => void) => (() => void);
45
+ export interface FloatingButtonOptions {
46
+ size?: number;
47
+ x?: number;
48
+ y?: number;
49
+ }
50
+ /**
51
+ * Displays the 100% native main-thread floating overlay button.
52
+ * Dragging & touches run on the native UI thread, completely isolated from JS thread stalls.
53
+ */
54
+ export declare const showNativeFloatingButton: (options?: FloatingButtonOptions) => Promise<boolean>;
55
+ /**
56
+ * Hides the native floating overlay button.
57
+ */
58
+ export declare const hideNativeFloatingButton: () => Promise<boolean>;
59
+ /**
60
+ * Updates the badge/status dot on the native floating overlay button.
61
+ */
62
+ export declare const setNativeFloatingButtonBadge: (hasBadge: boolean) => Promise<boolean>;
63
+ /**
64
+ * Subscribes to tap events on the native floating button.
65
+ */
66
+ export declare const subscribeNativeFloatingButtonPress: (callback: () => void) => (() => void);
67
+ /**
68
+ * Starts hardware-accurate native UI thread FPS tracking (CADisplayLink / Choreographer).
69
+ */
70
+ export declare const startNativeFpsMonitoring: () => Promise<boolean>;
71
+ /**
72
+ * Stops native FPS tracking.
73
+ */
74
+ export declare const stopNativeFpsMonitoring: () => Promise<boolean>;
75
+ export interface NativeFpsMetrics {
76
+ fps: number;
77
+ targetFps: number;
78
+ }
79
+ /**
80
+ * Reads the latest live hardware FPS from CADisplayLink (iOS) or Choreographer (Android).
81
+ */
82
+ export declare const getNativeFpsMetrics: () => Promise<NativeFpsMetrics>;
83
+ /**
84
+ * Subscribes to physical hardware shake events (or Cmd+Ctrl+Z on iOS simulator).
85
+ */
86
+ export declare const subscribeNativeDeviceShake: (callback: () => void) => (() => void);
87
+ /**
88
+ * Reads a persisted value synchronously from native NSUserDefaults / SharedPreferences.
89
+ */
90
+ export declare const getNativeStorageItem: (key: string) => Promise<string | null>;
91
+ /**
92
+ * Persists a key-value pair to native NSUserDefaults / SharedPreferences with 0ms latency.
93
+ */
94
+ export declare const setNativeStorageItem: (key: string, value: string | null) => Promise<boolean>;
95
+ export type HapticStyle = 'light' | 'medium' | 'heavy' | 'success' | 'warning' | 'error';
96
+ /**
97
+ * Triggers hardware native haptic feedback (iOS UIFeedbackGenerator / Android VibrationEffect).
98
+ */
99
+ export declare const triggerNativeHaptic: (style?: HapticStyle) => Promise<boolean>;
100
+ export interface NativeSystemMetrics {
101
+ thermalState: 'nominal' | 'fair' | 'serious' | 'critical';
102
+ residentRamMb: number;
103
+ totalPhysicalRamMb: number;
104
+ fps: number;
105
+ activeCpuCores: number;
106
+ }
107
+ /**
108
+ * Retrieves live system thermal state and RAM telemetry directly from native layer.
109
+ */
110
+ export declare const getNativeSystemMetrics: () => Promise<NativeSystemMetrics | null>;
111
+ /**
112
+ * Pushes a log payload to native background worker queues for instant native page caching.
113
+ */
114
+ export declare const pushNativeLogRecord: (pageKey: "apis" | "logs" | "analytics" | "crash", jsonPayload: string) => Promise<boolean>;
115
+ export interface NativeCachedPageResult<T = any> {
116
+ pageKey: string;
117
+ total: number;
118
+ offset: number;
119
+ items: T[];
120
+ }
121
+ /**
122
+ * Fetches pre-indexed, pre-sliced page data directly from native background memory queues.
123
+ * Delivers instantaneous 0ms page loading without blocking JS render thread.
124
+ */
125
+ export declare const fetchNativeCachedPage: <T = any>(pageKey: "apis" | "logs" | "analytics" | "crash", offset?: number, limit?: number, query?: string) => Promise<NativeCachedPageResult<T> | null>;