react-native-inapp-inspector 2.3.4 → 2.3.6

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 (229) hide show
  1. package/dist/commonjs/analytics.d.ts +0 -4
  2. package/dist/commonjs/analytics.js +0 -4
  3. package/dist/commonjs/bundle.d.ts +0 -4
  4. package/dist/commonjs/bundle.js +0 -4
  5. package/dist/commonjs/components/AnalyticsDetail.js +18 -27
  6. package/dist/commonjs/components/AnalyticsEventCard.js +9 -12
  7. package/dist/commonjs/components/AnalyticsGraph.js +10 -15
  8. package/dist/commonjs/components/AppHeaderLogo.js +0 -3
  9. package/dist/commonjs/components/BrandCircleIcon.js +15 -15
  10. package/dist/commonjs/components/BrandSquareIcon.js +20 -20
  11. package/dist/commonjs/components/CodeSnippet.js +6 -19
  12. package/dist/commonjs/components/ConsoleLogCard.js +0 -1
  13. package/dist/commonjs/components/CopyButton.js +0 -4
  14. package/dist/commonjs/components/DiffViewer.js +0 -2
  15. package/dist/commonjs/components/DomainHeader.js +0 -4
  16. package/dist/commonjs/components/EmptyState.js +0 -3
  17. package/dist/commonjs/components/ErrorBoundary.js +5 -10
  18. package/dist/commonjs/components/HeadersSection.js +0 -5
  19. package/dist/commonjs/components/HighlightText.js +1 -4
  20. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +11 -26
  21. package/dist/commonjs/components/Inspector/AnalyticsTab.js +34 -40
  22. package/dist/commonjs/components/Inspector/BundleTab.js +56 -84
  23. package/dist/commonjs/components/Inspector/ConsoleTab.js +7 -7
  24. package/dist/commonjs/components/Inspector/CrashDetail.js +18 -20
  25. package/dist/commonjs/components/Inspector/CrashFilterModal.js +0 -1
  26. package/dist/commonjs/components/Inspector/CrashTab.js +11 -20
  27. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +12 -24
  28. package/dist/commonjs/components/Inspector/FabLauncher.js +1 -1
  29. package/dist/commonjs/components/Inspector/InspectorContext.js +0 -2
  30. package/dist/commonjs/components/Inspector/InspectorHeader.js +7 -8
  31. package/dist/commonjs/components/Inspector/LogDetail.js +27 -29
  32. package/dist/commonjs/components/Inspector/MainScreen.js +168 -9
  33. package/dist/commonjs/components/Inspector/NetworkDetail.js +10 -11
  34. package/dist/commonjs/components/Inspector/NetworkTab.js +14 -14
  35. package/dist/commonjs/components/Inspector/NpmUpdateToast.js +6 -9
  36. package/dist/commonjs/components/Inspector/PerformanceTab.js +30 -43
  37. package/dist/commonjs/components/Inspector/ReduxDetail.js +18 -34
  38. package/dist/commonjs/components/Inspector/ReduxTab.js +11 -20
  39. package/dist/commonjs/components/Inspector/SettingsPanel.js +32 -36
  40. package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +6 -6
  41. package/dist/commonjs/components/Inspector/StorageTab.js +14 -26
  42. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +5 -6
  43. package/dist/commonjs/components/JsonViewer.js +3 -10
  44. package/dist/commonjs/components/LogCard.js +7 -7
  45. package/dist/commonjs/components/MetaAccordion.js +1 -7
  46. package/dist/commonjs/components/NetworkIcons.js +12 -16
  47. package/dist/commonjs/components/SectionHeader.js +0 -4
  48. package/dist/commonjs/components/SkeletonPlaceholder.js +6 -6
  49. package/dist/commonjs/components/Slider.js +6 -6
  50. package/dist/commonjs/components/SourcePageCard.js +0 -4
  51. package/dist/commonjs/components/TreeNode.js +0 -4
  52. package/dist/commonjs/console.d.ts +0 -4
  53. package/dist/commonjs/console.js +0 -4
  54. package/dist/commonjs/constants/index.js +6 -9
  55. package/dist/commonjs/constants/telemetryConfig.d.ts +7 -0
  56. package/dist/commonjs/constants/telemetryConfig.js +10 -0
  57. package/dist/commonjs/constants/version.d.ts +1 -1
  58. package/dist/commonjs/constants/version.js +1 -3
  59. package/dist/commonjs/crash.d.ts +0 -4
  60. package/dist/commonjs/crash.js +0 -4
  61. package/dist/commonjs/customHooks/analyticsLogger.d.ts +0 -7
  62. package/dist/commonjs/customHooks/analyticsLogger.js +3 -59
  63. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +0 -9
  64. package/dist/commonjs/customHooks/bundleAnalyzer.js +3 -86
  65. package/dist/commonjs/customHooks/consoleLogger.js +0 -16
  66. package/dist/commonjs/customHooks/crashHandler.d.ts +0 -28
  67. package/dist/commonjs/customHooks/crashHandler.js +0 -55
  68. package/dist/commonjs/customHooks/logFilters.d.ts +0 -4
  69. package/dist/commonjs/customHooks/logFilters.js +0 -11
  70. package/dist/commonjs/customHooks/networkLogger.js +2 -13
  71. package/dist/commonjs/customHooks/performanceTracker.d.ts +0 -27
  72. package/dist/commonjs/customHooks/performanceTracker.js +0 -31
  73. package/dist/commonjs/customHooks/reduxLogger.d.ts +0 -12
  74. package/dist/commonjs/customHooks/reduxLogger.js +0 -51
  75. package/dist/commonjs/customHooks/storageInspector.d.ts +0 -40
  76. package/dist/commonjs/customHooks/storageInspector.js +1 -56
  77. package/dist/commonjs/decorators/index.d.ts +0 -37
  78. package/dist/commonjs/decorators/index.js +0 -42
  79. package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +0 -10
  80. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +0 -26
  81. package/dist/commonjs/helpers/index.d.ts +0 -7
  82. package/dist/commonjs/helpers/index.js +1 -42
  83. package/dist/commonjs/helpers/memoryManager.d.ts +0 -11
  84. package/dist/commonjs/helpers/memoryManager.js +0 -13
  85. package/dist/commonjs/helpers/searchQueryParser.d.ts +0 -4
  86. package/dist/commonjs/helpers/searchQueryParser.js +0 -18
  87. package/dist/commonjs/helpers/settingsStore.js +0 -8
  88. package/dist/commonjs/helpers/telemetry.d.ts +2 -0
  89. package/dist/commonjs/helpers/telemetry.js +302 -0
  90. package/dist/commonjs/i18n/index.d.ts +0 -9
  91. package/dist/commonjs/i18n/index.js +0 -15
  92. package/dist/commonjs/index.d.ts +0 -1
  93. package/dist/commonjs/index.js +18 -102
  94. package/dist/commonjs/native/NativeInspector.d.ts +0 -54
  95. package/dist/commonjs/native/NativeInspector.js +0 -56
  96. package/dist/commonjs/network.d.ts +0 -4
  97. package/dist/commonjs/network.js +0 -4
  98. package/dist/commonjs/performance.d.ts +0 -4
  99. package/dist/commonjs/performance.js +0 -4
  100. package/dist/commonjs/redux.d.ts +0 -4
  101. package/dist/commonjs/redux.js +0 -4
  102. package/dist/commonjs/storage.d.ts +0 -4
  103. package/dist/commonjs/storage.js +0 -4
  104. package/dist/commonjs/styles/AppColors.d.ts +0 -3
  105. package/dist/commonjs/styles/AppColors.js +15 -30
  106. package/dist/commonjs/styles/AppFonts.d.ts +0 -4
  107. package/dist/commonjs/styles/AppFonts.js +0 -4
  108. package/dist/commonjs/styles/common.js +0 -11
  109. package/dist/commonjs/styles/index.js +0 -8
  110. package/dist/commonjs/types/enums.js +0 -3
  111. package/dist/commonjs/types/interfaces.d.ts +3 -3
  112. package/dist/esm/analytics.d.ts +0 -4
  113. package/dist/esm/analytics.js +0 -4
  114. package/dist/esm/bundle.d.ts +0 -4
  115. package/dist/esm/bundle.js +0 -4
  116. package/dist/esm/components/AnalyticsDetail.js +18 -27
  117. package/dist/esm/components/AnalyticsEventCard.js +9 -12
  118. package/dist/esm/components/AnalyticsGraph.js +10 -15
  119. package/dist/esm/components/AppHeaderLogo.js +0 -3
  120. package/dist/esm/components/BrandCircleIcon.js +15 -15
  121. package/dist/esm/components/BrandSquareIcon.js +20 -20
  122. package/dist/esm/components/CodeSnippet.js +6 -19
  123. package/dist/esm/components/ConsoleLogCard.js +0 -1
  124. package/dist/esm/components/CopyButton.js +0 -4
  125. package/dist/esm/components/DiffViewer.js +0 -2
  126. package/dist/esm/components/DomainHeader.js +0 -4
  127. package/dist/esm/components/EmptyState.js +0 -3
  128. package/dist/esm/components/ErrorBoundary.js +5 -10
  129. package/dist/esm/components/HeadersSection.js +0 -5
  130. package/dist/esm/components/HighlightText.js +1 -4
  131. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +11 -26
  132. package/dist/esm/components/Inspector/AnalyticsTab.js +34 -40
  133. package/dist/esm/components/Inspector/BundleTab.js +56 -84
  134. package/dist/esm/components/Inspector/ConsoleTab.js +7 -7
  135. package/dist/esm/components/Inspector/CrashDetail.js +18 -20
  136. package/dist/esm/components/Inspector/CrashFilterModal.js +0 -1
  137. package/dist/esm/components/Inspector/CrashTab.js +11 -20
  138. package/dist/esm/components/Inspector/DeviceInfoTab.js +12 -24
  139. package/dist/esm/components/Inspector/FabLauncher.js +1 -1
  140. package/dist/esm/components/Inspector/InspectorContext.js +0 -2
  141. package/dist/esm/components/Inspector/InspectorHeader.js +7 -8
  142. package/dist/esm/components/Inspector/LogDetail.js +27 -29
  143. package/dist/esm/components/Inspector/MainScreen.js +168 -9
  144. package/dist/esm/components/Inspector/NetworkDetail.js +10 -11
  145. package/dist/esm/components/Inspector/NetworkTab.js +14 -14
  146. package/dist/esm/components/Inspector/NpmUpdateToast.js +6 -9
  147. package/dist/esm/components/Inspector/PerformanceTab.js +30 -43
  148. package/dist/esm/components/Inspector/ReduxDetail.js +18 -34
  149. package/dist/esm/components/Inspector/ReduxTab.js +11 -20
  150. package/dist/esm/components/Inspector/SettingsPanel.js +32 -36
  151. package/dist/esm/components/Inspector/SkeletonPlaceholder.js +6 -6
  152. package/dist/esm/components/Inspector/StorageTab.js +14 -26
  153. package/dist/esm/components/Inspector/UpdateAvailableModal.js +5 -6
  154. package/dist/esm/components/JsonViewer.js +3 -10
  155. package/dist/esm/components/LogCard.js +7 -7
  156. package/dist/esm/components/MetaAccordion.js +1 -7
  157. package/dist/esm/components/NetworkIcons.js +12 -16
  158. package/dist/esm/components/SectionHeader.js +0 -4
  159. package/dist/esm/components/SkeletonPlaceholder.js +6 -6
  160. package/dist/esm/components/Slider.js +6 -6
  161. package/dist/esm/components/SourcePageCard.js +0 -4
  162. package/dist/esm/components/TreeNode.js +0 -4
  163. package/dist/esm/console.d.ts +0 -4
  164. package/dist/esm/console.js +0 -4
  165. package/dist/esm/constants/index.js +6 -9
  166. package/dist/esm/constants/telemetryConfig.d.ts +7 -0
  167. package/dist/esm/constants/telemetryConfig.js +7 -0
  168. package/dist/esm/constants/version.d.ts +1 -1
  169. package/dist/esm/constants/version.js +1 -3
  170. package/dist/esm/crash.d.ts +0 -4
  171. package/dist/esm/crash.js +0 -4
  172. package/dist/esm/customHooks/analyticsLogger.d.ts +0 -7
  173. package/dist/esm/customHooks/analyticsLogger.js +3 -59
  174. package/dist/esm/customHooks/bundleAnalyzer.d.ts +0 -9
  175. package/dist/esm/customHooks/bundleAnalyzer.js +3 -86
  176. package/dist/esm/customHooks/consoleLogger.js +0 -16
  177. package/dist/esm/customHooks/crashHandler.d.ts +0 -28
  178. package/dist/esm/customHooks/crashHandler.js +0 -55
  179. package/dist/esm/customHooks/logFilters.d.ts +0 -4
  180. package/dist/esm/customHooks/logFilters.js +0 -11
  181. package/dist/esm/customHooks/networkLogger.js +2 -13
  182. package/dist/esm/customHooks/performanceTracker.d.ts +0 -27
  183. package/dist/esm/customHooks/performanceTracker.js +0 -31
  184. package/dist/esm/customHooks/reduxLogger.d.ts +0 -12
  185. package/dist/esm/customHooks/reduxLogger.js +0 -51
  186. package/dist/esm/customHooks/storageInspector.d.ts +0 -40
  187. package/dist/esm/customHooks/storageInspector.js +1 -56
  188. package/dist/esm/decorators/index.d.ts +0 -37
  189. package/dist/esm/decorators/index.js +0 -42
  190. package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +0 -10
  191. package/dist/esm/helpers/gaAnalyticsRegistry.js +0 -26
  192. package/dist/esm/helpers/index.d.ts +0 -7
  193. package/dist/esm/helpers/index.js +1 -42
  194. package/dist/esm/helpers/memoryManager.d.ts +0 -11
  195. package/dist/esm/helpers/memoryManager.js +0 -13
  196. package/dist/esm/helpers/searchQueryParser.d.ts +0 -4
  197. package/dist/esm/helpers/searchQueryParser.js +0 -18
  198. package/dist/esm/helpers/settingsStore.js +0 -8
  199. package/dist/esm/helpers/telemetry.d.ts +2 -0
  200. package/dist/esm/helpers/telemetry.js +298 -0
  201. package/dist/esm/i18n/index.d.ts +0 -9
  202. package/dist/esm/i18n/index.js +0 -15
  203. package/dist/esm/index.d.ts +0 -1
  204. package/dist/esm/index.js +15 -98
  205. package/dist/esm/native/NativeInspector.d.ts +0 -54
  206. package/dist/esm/native/NativeInspector.js +0 -56
  207. package/dist/esm/network.d.ts +0 -4
  208. package/dist/esm/network.js +0 -4
  209. package/dist/esm/performance.d.ts +0 -4
  210. package/dist/esm/performance.js +0 -4
  211. package/dist/esm/redux.d.ts +0 -4
  212. package/dist/esm/redux.js +0 -4
  213. package/dist/esm/storage.d.ts +0 -4
  214. package/dist/esm/storage.js +0 -4
  215. package/dist/esm/styles/AppColors.d.ts +0 -3
  216. package/dist/esm/styles/AppColors.js +15 -30
  217. package/dist/esm/styles/AppFonts.d.ts +0 -4
  218. package/dist/esm/styles/AppFonts.js +0 -4
  219. package/dist/esm/styles/common.js +0 -11
  220. package/dist/esm/styles/index.js +0 -8
  221. package/dist/esm/types/enums.js +0 -3
  222. package/dist/esm/types/interfaces.d.ts +3 -3
  223. package/package.json +2 -2
  224. package/src/components/Inspector/MainScreen.tsx +188 -2
  225. package/src/constants/telemetryConfig.ts +16 -0
  226. package/src/constants/version.ts +1 -1
  227. package/src/helpers/telemetry.ts +341 -0
  228. package/src/index.tsx +15 -2
  229. package/src/types/interfaces.ts +3 -0
@@ -34,7 +34,6 @@ export const NpmUpdateToast = () => {
34
34
  useEffect(() => {
35
35
  if (showUpdateToast && updateAvailable && latestNpmVersion && !dismissed) {
36
36
  setVisible(true);
37
- // Slide and fade in
38
37
  Animated.parallel([
39
38
  Animated.spring(translateYAnim, {
40
39
  toValue: 0,
@@ -48,14 +47,12 @@ export const NpmUpdateToast = () => {
48
47
  useNativeDriver: true,
49
48
  }),
50
49
  ]).start();
51
- // Progress bar countdown from 1 to 0
52
50
  progressAnim.setValue(1);
53
51
  Animated.timing(progressAnim, {
54
52
  toValue: 0,
55
53
  duration: TOAST_TIMEOUT_MS,
56
54
  useNativeDriver: false,
57
55
  }).start();
58
- // Auto-hide after timeout
59
56
  timerRef.current = setTimeout(() => {
60
57
  handleDismiss();
61
58
  }, TOAST_TIMEOUT_MS);
@@ -109,12 +106,12 @@ export const NpmUpdateToast = () => {
109
106
  },
110
107
  ]}>
111
108
  <View style={styles.contentRow}>
112
- {/* Left NPM Badge Icon */}
109
+
113
110
  <View style={styles.npmIconContainer}>
114
111
  <NpmIcon size={15} color="#CB3837"/>
115
112
  </View>
116
113
 
117
- {/* Text Details */}
114
+
118
115
  <View style={styles.textContainer}>
119
116
  <View style={styles.titleRow}>
120
117
  <Text style={styles.titleText}>Update Available</Text>
@@ -127,7 +124,7 @@ export const NpmUpdateToast = () => {
127
124
  </Text>
128
125
  </View>
129
126
 
130
- {/* Copy command quick button */}
127
+
131
128
  <TouchableOpacity style={styles.copyButton} onPress={handleCopyCommand} hitSlop={6} activeOpacity={0.75}>
132
129
  {copied ? <CheckSvg size={11} color="#10B981"/> : <CopySvg size={11} color="#94A3B8"/>}
133
130
  <Text style={[styles.copyButtonText, copied && { color: '#10B981' }]}>
@@ -135,19 +132,19 @@ export const NpmUpdateToast = () => {
135
132
  </Text>
136
133
  </TouchableOpacity>
137
134
 
138
- {/* Action Button: View */}
135
+
139
136
  <TouchableOpacity style={styles.actionButton} onPress={handleOpenNpm} activeOpacity={0.8}>
140
137
  <Text style={styles.actionButtonText}>View</Text>
141
138
  <ExternalLinkSvg size={10} color="#FFFFFF"/>
142
139
  </TouchableOpacity>
143
140
 
144
- {/* Close Button */}
141
+
145
142
  <TouchableOpacity style={styles.closeButton} onPress={handleDismiss} hitSlop={8} activeOpacity={0.7}>
146
143
  <CloseSvg size={12} color="#94A3B8"/>
147
144
  </TouchableOpacity>
148
145
  </View>
149
146
 
150
- {/* Animated Linear Timeout Progress Bar */}
147
+
151
148
  <View style={styles.progressBarTrack}>
152
149
  <Animated.View style={[styles.progressBarFill, { width: progressWidth }]}/>
153
150
  </View>
@@ -14,7 +14,6 @@ import { getPerformanceEvents, subscribePerformanceEvents, logPerformanceEvent,
14
14
  import { startNativeFpsMonitoring, stopNativeFpsMonitoring, getNativeFpsMetrics, getNativeSystemMetrics, isNativeModuleAvailable, } from '../../native/NativeInspector';
15
15
  const PerformanceTab = React.memo(() => {
16
16
  const { t } = useTranslation();
17
- // ─── Real-Time FPS Tracking ────────────────────────────────────────────────
18
17
  const [isRecording, setIsRecording] = useState(true);
19
18
  const [currentFps, setCurrentFps] = useState(60);
20
19
  const [minFps, setMinFps] = useState(57);
@@ -23,7 +22,6 @@ const PerformanceTab = React.memo(() => {
23
22
  const [totalFrames, setTotalFrames] = useState(4820);
24
23
  const [jankyFrameCount, setJankyFrameCount] = useState(4);
25
24
  const [jsLagMs, setJsLagMs] = useState(1.2);
26
- // Expanded Event Card IDs
27
25
  const [expandedEventIds, setExpandedEventIds] = useState({
28
26
  'perf-1': true,
29
27
  });
@@ -33,11 +31,9 @@ const PerformanceTab = React.memo(() => {
33
31
  [id]: !prev[id],
34
32
  }));
35
33
  };
36
- // FPS history for sparkline
37
34
  const [fpsHistory, setFpsHistory] = useState([
38
35
  60, 59, 60, 60, 58, 60, 59, 60, 60, 60, 57, 60, 59, 60, 60, 58, 60, 60, 59, 60,
39
36
  ]);
40
- // Performance Log Events (Dynamic live subscription)
41
37
  const [events, setEvents] = useState(() => getPerformanceEvents());
42
38
  const [filterCategory, setFilterCategory] = useState('ALL');
43
39
  const [search, setSearch] = useState('');
@@ -47,7 +43,6 @@ const PerformanceTab = React.memo(() => {
47
43
  });
48
44
  return unsub;
49
45
  }, []);
50
- // ─── Live Frame Measurement Loop (1-Second Batch Interval) ────────────────
51
46
  const lastFrameTimeRef = useRef(Date.now());
52
47
  const rafIdRef = useRef(null);
53
48
  const [systemMetrics, setSystemMetrics] = useState(null);
@@ -87,13 +82,11 @@ const PerformanceTab = React.memo(() => {
87
82
  const now = Date.now();
88
83
  const delta = now - lastFrameTimeRef.current;
89
84
  lastFrameTimeRef.current = now;
90
- // Track peak JS event loop lag during this 1s interval (without triggering re-renders)
91
85
  const lag = Math.max(0, delta - 16.67);
92
86
  if (lag > maxLagInSecond) {
93
87
  maxLagInSecond = lag;
94
88
  }
95
89
  frameCount++;
96
- // Update React state ONCE every 1 second (1000ms) to prevent UI shaking/re-rendering
97
90
  if (now - lastSecond >= 1000) {
98
91
  const elapsed = now - lastSecond;
99
92
  let measuredFps = Math.min(120, Math.max(0, Math.round((frameCount * 1000) / elapsed)));
@@ -120,7 +113,6 @@ const PerformanceTab = React.memo(() => {
120
113
  setAvgFps(Math.round(sum / next.length));
121
114
  return next;
122
115
  });
123
- // Trigger log if noticeable frame drop
124
116
  if (measuredFps < 50) {
125
117
  const durationStr = (1000 / measuredFps).toFixed(1);
126
118
  logPerformanceEvent({
@@ -153,7 +145,6 @@ const PerformanceTab = React.memo(() => {
153
145
  cancelAnimationFrame(rafIdRef.current);
154
146
  };
155
147
  }, [isRecording]);
156
- // Filtered Events
157
148
  const filteredEvents = useMemo(() => {
158
149
  return events.filter(e => {
159
150
  const matchSearch = !search ||
@@ -174,7 +165,6 @@ const PerformanceTab = React.memo(() => {
174
165
  return matchSearch && matchFilter;
175
166
  });
176
167
  }, [events, search, filterCategory]);
177
- // Overall Performance Score
178
168
  const performanceScore = useMemo(() => {
179
169
  if (avgFps >= 58) {
180
170
  return {
@@ -199,7 +189,6 @@ const PerformanceTab = React.memo(() => {
199
189
  bg: AppColors.errorCardBg,
200
190
  };
201
191
  }, [avgFps, t]);
202
- // ─── Dynamic Runtime Environment & Engine Diagnostics ──────────────────────
203
192
  const runtimeDiagnostics = useMemo(() => {
204
193
  const raw = getRuntimeDiagnostics();
205
194
  const engineNameMap = {
@@ -229,7 +218,6 @@ const PerformanceTab = React.memo(() => {
229
218
  totalAllocMb: raw.totalAllocMb,
230
219
  };
231
220
  }, [t]);
232
- // ─── Dynamic 16.67ms Frame Budget Utilization ─────────────────────────────
233
221
  const frameBudgetStats = useMemo(() => {
234
222
  const frameDuration = avgFps > 0 ? 1000 / avgFps : 16.67;
235
223
  const jsTime = Number(Math.max(1.0, Math.min(frameDuration * 0.45, 2.0 + jsLagMs)).toFixed(1));
@@ -246,7 +234,6 @@ const PerformanceTab = React.memo(() => {
246
234
  headroomPercent,
247
235
  };
248
236
  }, [avgFps, jsLagMs]);
249
- // ─── Dynamic SVG FPS Area & Trend Curve Data ────────────────────────────
250
237
  const [selectedFpsPointIdx, setSelectedFpsPointIdx] = useState(null);
251
238
  const svgGraphWidth = 320;
252
239
  const svgGraphHeight = 64;
@@ -329,7 +316,7 @@ const PerformanceTab = React.memo(() => {
329
316
  ? fpsGraphData.coords[selectedFpsPointIdx]
330
317
  : null;
331
318
  return (<View style={perfStyles.container}>
332
- {/* Search & Live Control Header */}
319
+
333
320
  <View style={perfStyles.headerBar}>
334
321
  <View style={perfStyles.searchBox}>
335
322
  <SearchIcon color={AppColors.grayTextWeak} size={15}/>
@@ -339,7 +326,7 @@ const PerformanceTab = React.memo(() => {
339
326
  </TouchableScale>) : null}
340
327
  </View>
341
328
 
342
- {/* Live FPS Telemetry Recorder Toggle */}
329
+
343
330
  <TouchableScale onPress={() => setIsRecording(prev => !prev)} style={[
344
331
  perfStyles.recordToggleBtn,
345
332
  isRecording
@@ -369,7 +356,7 @@ const PerformanceTab = React.memo(() => {
369
356
  </TouchableScale>
370
357
  </View>
371
358
 
372
- {/* Filter Category Tabs Carousel */}
359
+
373
360
  <View style={perfStyles.categoryScrollWrapper}>
374
361
  <ScrollView horizontal showsHorizontalScrollIndicator={false} style={perfStyles.categoryScrollView} contentContainerStyle={perfStyles.categoryScroll}>
375
362
  {[
@@ -423,9 +410,9 @@ const PerformanceTab = React.memo(() => {
423
410
  </ScrollView>
424
411
  </View>
425
412
 
426
- {/* Main Content Scroll View */}
413
+
427
414
  <ScrollView style={perfStyles.scrollBody} contentContainerStyle={perfStyles.scrollContent} showsVerticalScrollIndicator={false}>
428
- {/* ── 1. REAL-TIME FPS SCORECARD & SMOOTH AREA GRAPH ── */}
415
+
429
416
  <View style={perfStyles.heroCard}>
430
417
  <View style={perfStyles.heroHeaderRow}>
431
418
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
@@ -440,7 +427,7 @@ const PerformanceTab = React.memo(() => {
440
427
  </View>
441
428
  </View>
442
429
 
443
- {/* Health Grade Score Pill */}
430
+
444
431
  <View style={[
445
432
  perfStyles.scorePill,
446
433
  { backgroundColor: performanceScore.bg },
@@ -454,7 +441,7 @@ const PerformanceTab = React.memo(() => {
454
441
  </View>
455
442
  </View>
456
443
 
457
- {/* Primary Gauge Counter */}
444
+
458
445
  <View style={perfStyles.primaryFpsRow}>
459
446
  <View style={perfStyles.fpsBigNumberBox}>
460
447
  <Text style={[
@@ -515,7 +502,7 @@ const PerformanceTab = React.memo(() => {
515
502
  </View>
516
503
  </View>
517
504
 
518
- {/* Interactive Scrub Tooltip */}
505
+
519
506
  {activeScrubPoint && (<View style={perfStyles.graphScrubTooltip}>
520
507
  <Text style={perfStyles.graphScrubTooltipText}>
521
508
  {activeScrubPoint.val} FPS •{' '}
@@ -524,7 +511,7 @@ const PerformanceTab = React.memo(() => {
524
511
  </Text>
525
512
  </View>)}
526
513
 
527
- {/* Real-Time SVG Smooth Area & Trend Wave Graph */}
514
+
528
515
  <View style={perfStyles.svgGraphContainer}>
529
516
  <Svg width="100%" height={svgGraphHeight} viewBox={`0 0 ${svgGraphWidth} ${svgGraphHeight}`} preserveAspectRatio="none">
530
517
  <Defs>
@@ -542,23 +529,23 @@ const PerformanceTab = React.memo(() => {
542
529
  </LinearGradient>
543
530
  </Defs>
544
531
 
545
- {/* 60 FPS Target Baseline */}
532
+
546
533
  <Line x1="0" y1="7" x2={svgGraphWidth} y2="7" stroke={AppColors.emerald500} strokeWidth="1" strokeDasharray="4,4" opacity="0.4"/>
547
534
 
548
- {/* 30 FPS Warning Baseline */}
535
+
549
536
  <Line x1="0" y1={svgGraphHeight / 2} x2={svgGraphWidth} y2={svgGraphHeight / 2} stroke={AppColors.amber500} strokeWidth="0.8" strokeDasharray="3,3" opacity="0.3"/>
550
537
 
551
- {/* Shaded Area Under Curve */}
538
+
552
539
  {fpsGraphData.areaPath ? (<Path d={fpsGraphData.areaPath} fill="url(#fpsAreaGradient)"/>) : null}
553
540
 
554
- {/* Bezier Trend Line */}
541
+
555
542
  {fpsGraphData.linePath ? (<Path d={fpsGraphData.linePath} fill="none" stroke={avgFps >= 55
556
543
  ? AppColors.emerald600
557
544
  : avgFps >= 40
558
545
  ? AppColors.amber600
559
546
  : AppColors.errorColor} strokeWidth="2.2"/>) : null}
560
547
 
561
- {/* Sample Nodes */}
548
+
562
549
  {fpsGraphData.coords.map((c, idx) => {
563
550
  const isSelected = selectedFpsPointIdx === idx;
564
551
  const isDip = c.val < 50;
@@ -573,7 +560,7 @@ const PerformanceTab = React.memo(() => {
573
560
  })}
574
561
  </Svg>
575
562
 
576
- {/* Invisible Touch Column Targets for Interactive Inspection */}
563
+
577
564
  <View style={perfStyles.svgTouchOverlay}>
578
565
  {fpsGraphData.coords.map((_, idx) => (<TouchableOpacity key={idx} style={perfStyles.svgTouchCol} activeOpacity={0.7} onPress={() => setSelectedFpsPointIdx(selectedFpsPointIdx === idx ? null : idx)}/>))}
579
566
  </View>
@@ -589,7 +576,7 @@ const PerformanceTab = React.memo(() => {
589
576
  </View>
590
577
  </View>
591
578
 
592
- {/* ── 1.5 NATIVE HARDWARE HEALTH & SYSTEM TELEMETRY CARD ── */}
579
+
593
580
  <View style={perfStyles.budgetCard}>
594
581
  <View style={perfStyles.budgetHeader}>
595
582
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
@@ -646,7 +633,7 @@ const PerformanceTab = React.memo(() => {
646
633
  </View>
647
634
  </View>
648
635
 
649
- {/* ── 2. FRAME LATENCY DISTRIBUTION HISTOGRAM CARD ── */}
636
+
650
637
  <View style={perfStyles.budgetCard}>
651
638
  <View style={perfStyles.budgetHeader}>
652
639
  <View>
@@ -693,7 +680,7 @@ const PerformanceTab = React.memo(() => {
693
680
  </View>
694
681
  </View>
695
682
 
696
- {/* ── 3. FRAME BUDGET BREAKDOWN CARD ── */}
683
+
697
684
  <View style={perfStyles.budgetCard}>
698
685
  <View style={perfStyles.budgetHeader}>
699
686
  <Text style={perfStyles.budgetTitle}>{t('performance.budgetUsage')}</Text>
@@ -705,7 +692,7 @@ const PerformanceTab = React.memo(() => {
705
692
  </Text>
706
693
  </View>
707
694
 
708
- {/* Multi-colored segmented frame budget bar */}
695
+
709
696
  <View style={perfStyles.budgetBarContainer}>
710
697
  <View style={[
711
698
  perfStyles.budgetBarSegment,
@@ -753,7 +740,7 @@ const PerformanceTab = React.memo(() => {
753
740
  </View>
754
741
  </View>
755
742
 
756
- {/* ── 3. RUNTIME ENGINE & MEMORY SUMMARY ── */}
743
+
757
744
  <View style={perfStyles.engineSummaryGrid}>
758
745
  <View style={perfStyles.engineSummaryCard}>
759
746
  <Text style={perfStyles.engineSummaryLabel}>{t('performance.jsEngine')}</Text>
@@ -774,7 +761,7 @@ const PerformanceTab = React.memo(() => {
774
761
  </View>
775
762
  </View>
776
763
 
777
- {/* ── 4. PERFORMANCE LOGS & DETAILED EVENTS ── */}
764
+
778
765
  <View style={perfStyles.logsHeaderRow}>
779
766
  <Text style={perfStyles.logsSectionHeading}>
780
767
  {t('performance.recordedEvents')} ({filteredEvents.length})
@@ -813,7 +800,7 @@ const PerformanceTab = React.memo(() => {
813
800
  </Text>
814
801
  </View>
815
802
 
816
- {/* Dropped Frames Badge */}
803
+
817
804
  <View style={[
818
805
  perfStyles.droppedBadge,
819
806
  (event.droppedFrames ?? Math.max(0, 60 - event.fps)) > 0
@@ -832,7 +819,7 @@ const PerformanceTab = React.memo(() => {
832
819
  </Text>
833
820
  </View>
834
821
 
835
- {/* Bottleneck Thread Tag */}
822
+
836
823
  {event.bottleneckThread && (<View style={[perfStyles.bottleneckTag, { flexDirection: 'row', alignItems: 'center', gap: 3 }]}>
837
824
  {event.bottleneckThread === 'JS Thread' && (<BoltIcon size={10} color={AppColors.warningIconGold}/>)}
838
825
  <Text style={perfStyles.bottleneckTagText}>
@@ -851,7 +838,7 @@ const PerformanceTab = React.memo(() => {
851
838
  </View>
852
839
  </View>
853
840
 
854
- {/* Event Label & Meta */}
841
+
855
842
  <View style={{ marginTop: 4 }}>
856
843
  <HighlightText text={event.label} search={search} style={perfStyles.eventLabel} highlightStyle={perfStyles.searchHighlight}/>
857
844
  <View style={perfStyles.eventMetaRow}>
@@ -876,7 +863,7 @@ const PerformanceTab = React.memo(() => {
876
863
  </View>
877
864
  </View>
878
865
 
879
- {/* Visual Frame Time Budget Bar */}
866
+
880
867
  <View style={perfStyles.frameBarTrack}>
881
868
  <View style={[
882
869
  perfStyles.frameBarFill,
@@ -889,9 +876,9 @@ const PerformanceTab = React.memo(() => {
889
876
 
890
877
  <HighlightText text={event.detail} search={search} style={perfStyles.eventDetail} highlightStyle={perfStyles.searchHighlight}/>
891
878
 
892
- {/* ── EXPANDABLE IN-DEPTH METRICS ACCORDION ── */}
879
+
893
880
  {isExpanded && (<View style={perfStyles.expandedDetailBox}>
894
- {/* Screen / Component Context */}
881
+
895
882
  {(event.screenName || event.source) && (<View style={perfStyles.sourceRow}>
896
883
  <Text style={perfStyles.sourceTag}>{t('performance.screenContext')}</Text>
897
884
  <Text style={perfStyles.sourceText} numberOfLines={1}>
@@ -899,7 +886,7 @@ const PerformanceTab = React.memo(() => {
899
886
  </Text>
900
887
  </View>)}
901
888
 
902
- {/* Frame Metrics Grid */}
889
+
903
890
  <View style={perfStyles.fpsMetricsGrid}>
904
891
  <View style={perfStyles.fpsMetricItem}>
905
892
  <Text style={perfStyles.fpsMetricLabel}>{t('performance.target60Fps', { fps: event.fps })}</Text>
@@ -930,7 +917,7 @@ const PerformanceTab = React.memo(() => {
930
917
  </View>
931
918
  </View>
932
919
 
933
- {/* Thread Timing Breakdown */}
920
+
934
921
  {event.breakdown && (<View style={perfStyles.breakdownGrid}>
935
922
  <View style={perfStyles.breakdownCol}>
936
923
  <Text style={perfStyles.breakdownLabel}>{t('performance.jsThread')}</Text>
@@ -961,7 +948,7 @@ const PerformanceTab = React.memo(() => {
961
948
  </View>)}
962
949
  </View>)}
963
950
 
964
- {/* Actionable Optimization Tip */}
951
+
965
952
  {event.advice && (<View style={perfStyles.adviceCard}>
966
953
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
967
954
  <LightbulbIcon color={AppColors.purpleShade700} size={12}/>
@@ -62,22 +62,16 @@ const getOriginBadge = (originType) => {
62
62
  const ReduxDetail = React.memo(() => {
63
63
  const { t } = useTranslation();
64
64
  const { reduxState, reduxLastActionMap, selectedReduxSlice, selectedReduxAction, setSelectedReduxSlice, } = useInspector();
65
- // Search filter within details
66
65
  const [detailSearch, setDetailSearch] = useState('');
67
- // Sub-tabs for Slice & Action
68
66
  const [sliceTab, setSliceTab] = useState('live');
69
67
  const [actionTab, setActionTab] = useState('payload');
70
68
  const [viewMode, setViewMode] = useState('pretty');
71
- // Selected Action inside Timeline
72
69
  const [expandedActionId, setExpandedActionId] = useState(null);
73
- // Persistence data for active slice
74
70
  const [isPersisted, setIsPersisted] = useState(false);
75
71
  const [persistedData, setPersistedData] = useState(null);
76
- // Fetch Action History
77
72
  const allActionHistory = useMemo(() => {
78
73
  return getActionHistory();
79
74
  }, [reduxLastActionMap]);
80
- // Slices-filtered actions
81
75
  const sliceActions = useMemo(() => {
82
76
  if (!selectedReduxSlice)
83
77
  return allActionHistory;
@@ -87,7 +81,6 @@ const ReduxDetail = React.memo(() => {
87
81
  return action.affectedSlices.includes(selectedReduxSlice);
88
82
  });
89
83
  }, [allActionHistory, selectedReduxSlice]);
90
- // Filtered slice actions by search query in timeline tab
91
84
  const filteredTimelineActions = useMemo(() => {
92
85
  if (!detailSearch.trim())
93
86
  return sliceActions;
@@ -138,7 +131,6 @@ const ReduxDetail = React.memo(() => {
138
131
  }
139
132
  }
140
133
  catch (e) {
141
- // silent catch
142
134
  }
143
135
  setIsPersisted(false);
144
136
  setPersistedData(null);
@@ -181,9 +173,6 @@ const ReduxDetail = React.memo(() => {
181
173
  },
182
174
  ]);
183
175
  };
184
- // ══════════════════════════════════════════════════════════════════════════
185
- // ── 1. RENDER SLICE DETAIL VIEW ───────────────────────────────────────────
186
- // ══════════════════════════════════════════════════════════════════════════
187
176
  if (selectedReduxSlice != null) {
188
177
  const sliceData = reduxState?.[selectedReduxSlice];
189
178
  const fieldsCount = sliceData && typeof sliceData === 'object'
@@ -217,7 +206,7 @@ const ReduxDetail = React.memo(() => {
217
206
  },
218
207
  ];
219
208
  return (<View style={{ flex: 1, backgroundColor: AppColors.grayBackground }}>
220
- {/* Info Header Bar */}
209
+
221
210
  <View style={reduxDetailStyles.infoBar}>
222
211
  <View style={reduxDetailStyles.infoTopRow}>
223
212
  <View style={{
@@ -257,11 +246,11 @@ const ReduxDetail = React.memo(() => {
257
246
  </View>)}
258
247
  </View>
259
248
 
260
- {/* Copy Button */}
249
+
261
250
  <CopyButton value={() => (sliceTab === 'live' ? sliceData : persistedData)} label={t('redux.sliceJson', 'Slice JSON')}/>
262
251
  </View>
263
252
 
264
- {/* Sub Stats Row */}
253
+
265
254
  <View style={reduxDetailStyles.subStatsRow}>
266
255
  <View style={[
267
256
  reduxDetailStyles.statPill,
@@ -350,11 +339,11 @@ const ReduxDetail = React.memo(() => {
350
339
  </View>)}
351
340
  </View>
352
341
 
353
- {/* Sub-Tabs */}
342
+
354
343
  <SegmentedTabs tabs={sliceTabs} activeKey={sliceTab} onChange={key => setSliceTab(key)} style={{ marginTop: 10 }}/>
355
344
  </View>
356
345
 
357
- {/* Search Bar within slice (for Live, Timeline, Persisted) */}
346
+
358
347
  {sliceTab !== 'metadata' && (<View style={reduxDetailStyles.searchContainer}>
359
348
  <SearchIcon color={AppColors.grayTextWeak} size={14}/>
360
349
  <TextInput placeholder={sliceTab === 'timeline'
@@ -365,7 +354,7 @@ const ReduxDetail = React.memo(() => {
365
354
  </Pressable>)}
366
355
  </View>)}
367
356
 
368
- {/* Content Body */}
357
+
369
358
  {sliceTab === 'timeline' ? (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 12, paddingBottom: 40 }} keyboardShouldPersistTaps="handled">
370
359
  {filteredTimelineActions.length === 0 ? (<View style={reduxDetailStyles.emptyBox}>
371
360
  <TimelineIcon color={AppColors.grayTextWeak} size={28}/>
@@ -396,7 +385,7 @@ const ReduxDetail = React.memo(() => {
396
385
  #{action.id}
397
386
  </Text>
398
387
  </View>
399
- {/* Origin Badge */}
388
+
400
389
  <View style={{
401
390
  flexDirection: 'row',
402
391
  alignItems: 'center',
@@ -430,7 +419,7 @@ const ReduxDetail = React.memo(() => {
430
419
  </View>
431
420
  </View>
432
421
 
433
- {/* Trigger caller preview row */}
422
+
434
423
  {action.callerFile && (<View style={{
435
424
  flexDirection: 'row',
436
425
  alignItems: 'center',
@@ -488,9 +477,9 @@ const ReduxDetail = React.memo(() => {
488
477
  </Pressable>
489
478
  </View>)}
490
479
 
491
- {/* Expanded Payload, Diff Viewer & Call Stack */}
480
+
492
481
  {isExpanded ? (<View style={reduxDetailStyles.expandedContent}>
493
- {/* Call Stack Trace Box */}
482
+
494
483
  {action.stack ? (<View style={{ marginBottom: 12 }}>
495
484
  <Text style={reduxDetailStyles.expandedSectionTitle}>
496
485
  {t('redux.callStack', 'Call Stack Trace')}:
@@ -656,16 +645,11 @@ const ReduxDetail = React.memo(() => {
656
645
  State exists purely in active JavaScript memory.
657
646
  </Text>
658
647
  </View>)}
659
- </View>) : (
660
- /* Live State JsonViewer: Direct flex: 1 with fullHeight to prevent nested scroll conflicts */
661
- <View style={{ flex: 1, padding: 10 }}>
648
+ </View>) : (<View style={{ flex: 1, padding: 10 }}>
662
649
  <JsonViewer data={sliceData} search={detailSearch} forceOpen={detailSearch.length > 0 ? true : undefined} mode={viewMode} onModeChange={setViewMode} fullHeight={true} wrap={true}/>
663
650
  </View>)}
664
651
  </View>);
665
652
  }
666
- // ══════════════════════════════════════════════════════════════════════════
667
- // ── 2. RENDER ACTION DETAIL VIEW (when an action is selected directly) ────
668
- // ══════════════════════════════════════════════════════════════════════════
669
653
  if (selectedReduxAction != null) {
670
654
  const originMeta = getOriginBadge(selectedReduxAction.originType);
671
655
  const callerBasename = selectedReduxAction.callerFile
@@ -694,7 +678,7 @@ const ReduxDetail = React.memo(() => {
694
678
  },
695
679
  ];
696
680
  return (<View style={{ flex: 1, backgroundColor: AppColors.grayBackground }}>
697
- {/* Top Info Bar */}
681
+
698
682
  <View style={reduxDetailStyles.infoBar}>
699
683
  <View style={reduxDetailStyles.infoTopRow}>
700
684
  <View style={{
@@ -710,7 +694,7 @@ const ReduxDetail = React.memo(() => {
710
694
  #{selectedReduxAction.id}
711
695
  </Text>
712
696
  </View>
713
- {/* Origin Badge */}
697
+
714
698
  <View style={{
715
699
  flexDirection: 'row',
716
700
  alignItems: 'center',
@@ -743,11 +727,11 @@ const ReduxDetail = React.memo(() => {
743
727
  </View>)}
744
728
  </View>
745
729
 
746
- {/* Copy Button */}
730
+
747
731
  <CopyButton value={() => selectedReduxAction} label="Copy Action"/>
748
732
  </View>
749
733
 
750
- {/* Sub Stats Row */}
734
+
751
735
  <View style={reduxDetailStyles.subStatsRow}>
752
736
  {selectedReduxAction.affectedSlices &&
753
737
  selectedReduxAction.affectedSlices.length > 0 && (<View style={[
@@ -793,7 +777,7 @@ const ReduxDetail = React.memo(() => {
793
777
  </View>
794
778
  </View>
795
779
 
796
- {/* Triggered from caller preview row */}
780
+
797
781
  {selectedReduxAction.callerFile && (<View style={{
798
782
  flexDirection: 'row',
799
783
  alignItems: 'center',
@@ -850,11 +834,11 @@ const ReduxDetail = React.memo(() => {
850
834
  </Pressable>
851
835
  </View>)}
852
836
 
853
- {/* Sub-Tabs */}
837
+
854
838
  <SegmentedTabs tabs={actionTabs} activeKey={actionTab} onChange={key => setActionTab(key)} style={{ marginTop: 10 }}/>
855
839
  </View>
856
840
 
857
- {/* Content Body */}
841
+
858
842
  {actionTab === 'payload' ? (<View style={{ flex: 1, padding: 10 }}>
859
843
  {selectedReduxAction.payload !== undefined ? (<JsonViewer data={selectedReduxAction.payload} search={detailSearch} forceOpen={true} fullHeight={true} wrap={true}/>) : (<View style={reduxDetailStyles.emptyBox}>
860
844
  <Text style={reduxDetailStyles.emptyBoxText}>