react-native-inapp-inspector 2.3.18 → 2.3.20

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 (358) hide show
  1. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +57 -0
  2. package/dist/commonjs/analytics.js +1 -24
  3. package/dist/commonjs/bundle.js +1 -16
  4. package/dist/commonjs/capture.d.ts +2 -0
  5. package/dist/commonjs/capture.js +1 -32
  6. package/dist/commonjs/components/AnalyticsDetail.js +92 -623
  7. package/dist/commonjs/components/AnalyticsEventCard.js +54 -350
  8. package/dist/commonjs/components/AnalyticsGraph.js +70 -370
  9. package/dist/commonjs/components/AnimatedEntrance.js +1 -11
  10. package/dist/commonjs/components/AppHeaderLogo.js +7 -134
  11. package/dist/commonjs/components/BrandCircleIcon.js +73 -118
  12. package/dist/commonjs/components/BrandSquareIcon.js +63 -108
  13. package/dist/commonjs/components/CodeSnippet.js +48 -623
  14. package/dist/commonjs/components/ConsoleLogCard.js +63 -537
  15. package/dist/commonjs/components/CopyButton.js +3 -89
  16. package/dist/commonjs/components/DiffViewer.js +19 -83
  17. package/dist/commonjs/components/DomainHeader.js +27 -127
  18. package/dist/commonjs/components/EmptyState.d.ts +1 -0
  19. package/dist/commonjs/components/EmptyState.js +10 -87
  20. package/dist/commonjs/components/EndOfListFooter.js +7 -81
  21. package/dist/commonjs/components/ErrorBoundary.js +72 -566
  22. package/dist/commonjs/components/HeadersSection.js +31 -110
  23. package/dist/commonjs/components/HighlightText.js +17 -58
  24. package/dist/commonjs/components/Inspector/AboutModal.d.ts +6 -0
  25. package/dist/commonjs/components/Inspector/AboutModal.js +351 -0
  26. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +98 -797
  27. package/dist/commonjs/components/Inspector/AnalyticsTab.js +284 -930
  28. package/dist/commonjs/components/Inspector/BundleTab.js +551 -2918
  29. package/dist/commonjs/components/Inspector/ConsoleTab.js +79 -492
  30. package/dist/commonjs/components/Inspector/CrashDetail.js +123 -672
  31. package/dist/commonjs/components/Inspector/CrashFilterModal.js +66 -498
  32. package/dist/commonjs/components/Inspector/CrashTab.js +98 -670
  33. package/dist/commonjs/components/Inspector/DebuggingTab.js +64 -871
  34. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +143 -907
  35. package/dist/commonjs/components/Inspector/FabLauncher.js +85 -54
  36. package/dist/commonjs/components/Inspector/FeatureUnderDevNotice.js +6 -99
  37. package/dist/commonjs/components/Inspector/FeedbackModal.d.ts +9 -0
  38. package/dist/commonjs/components/Inspector/FeedbackModal.js +167 -521
  39. package/dist/commonjs/components/Inspector/InspectorContext.js +1 -21
  40. package/dist/commonjs/components/Inspector/InspectorHeader.js +219 -1093
  41. package/dist/commonjs/components/Inspector/LogDetail.js +168 -994
  42. package/dist/commonjs/components/Inspector/MainScreen.js +60 -332
  43. package/dist/commonjs/components/Inspector/MediaGalleryTab.js +136 -278
  44. package/dist/commonjs/components/Inspector/MediaPreviewModal.js +134 -361
  45. package/dist/commonjs/components/Inspector/NavigationTracker.js +1 -12
  46. package/dist/commonjs/components/Inspector/NetworkDetail.js +96 -432
  47. package/dist/commonjs/components/Inspector/NetworkFilterModal.js +60 -576
  48. package/dist/commonjs/components/Inspector/NetworkTab.js +84 -514
  49. package/dist/commonjs/components/Inspector/NpmStarPrompt.js +17 -433
  50. package/dist/commonjs/components/Inspector/NpmUpdateToast.js +25 -298
  51. package/dist/commonjs/components/Inspector/PerformanceTab.js +182 -1397
  52. package/dist/commonjs/components/Inspector/ReduxDetail.js +188 -1089
  53. package/dist/commonjs/components/Inspector/ReduxTab.js +85 -701
  54. package/dist/commonjs/components/Inspector/SettingsPanel.js +431 -3431
  55. package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +11 -180
  56. package/dist/commonjs/components/Inspector/StorageTab.js +93 -826
  57. package/dist/commonjs/components/Inspector/TabBar.js +47 -183
  58. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +34 -408
  59. package/dist/commonjs/components/JsonViewer.js +168 -380
  60. package/dist/commonjs/components/LogCard.js +57 -567
  61. package/dist/commonjs/components/LogSyntaxHighlighter.js +11 -130
  62. package/dist/commonjs/components/MetaAccordion.js +69 -238
  63. package/dist/commonjs/components/MiniBarChart.js +3 -56
  64. package/dist/commonjs/components/MiniLineChart.js +3 -58
  65. package/dist/commonjs/components/NetworkIcons.d.ts +7 -0
  66. package/dist/commonjs/components/NetworkIcons.js +479 -997
  67. package/dist/commonjs/components/QRCodeView.js +5 -79
  68. package/dist/commonjs/components/SectionHeader.js +15 -37
  69. package/dist/commonjs/components/SegmentedTabs.js +7 -61
  70. package/dist/commonjs/components/SkeletonPlaceholder.js +11 -180
  71. package/dist/commonjs/components/Slider.js +15 -243
  72. package/dist/commonjs/components/SourcePageCard.js +30 -89
  73. package/dist/commonjs/components/Toast.js +5 -147
  74. package/dist/commonjs/components/TouchableScale.js +3 -24
  75. package/dist/commonjs/components/TreeNode.js +55 -130
  76. package/dist/commonjs/console.js +1 -16
  77. package/dist/commonjs/constants/index.js +1 -32
  78. package/dist/commonjs/constants/telemetryConfig.js +1 -6
  79. package/dist/commonjs/constants/version.d.ts +1 -1
  80. package/dist/commonjs/constants/version.js +1 -4
  81. package/dist/commonjs/crash.js +1 -23
  82. package/dist/commonjs/customHooks/analyticsLogger.js +1 -250
  83. package/dist/commonjs/customHooks/bundleAnalyzer.js +1 -957
  84. package/dist/commonjs/customHooks/consoleLogger.js +6 -445
  85. package/dist/commonjs/customHooks/crashHandler.js +7 -656
  86. package/dist/commonjs/customHooks/logFilters.js +1 -23
  87. package/dist/commonjs/customHooks/networkLogger.js +2 -536
  88. package/dist/commonjs/customHooks/performanceTracker.js +63 -750
  89. package/dist/commonjs/customHooks/reduxLogger.js +2 -313
  90. package/dist/commonjs/customHooks/storageInspector.js +1 -435
  91. package/dist/commonjs/customHooks/useAccordion.js +1 -18
  92. package/dist/commonjs/decorators/index.js +1 -100
  93. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +1 -148
  94. package/dist/commonjs/helpers/index.js +8 -921
  95. package/dist/commonjs/helpers/memoryManager.js +1 -99
  96. package/dist/commonjs/helpers/qrGenerator.js +1 -367
  97. package/dist/commonjs/helpers/remoteConfig.js +1 -165
  98. package/dist/commonjs/helpers/searchQueryParser.js +1 -62
  99. package/dist/commonjs/helpers/settingsStore.js +1 -144
  100. package/dist/commonjs/helpers/telemetry.js +1 -501
  101. package/dist/commonjs/helpers/toast.js +1 -20
  102. package/dist/commonjs/i18n/index.js +1 -90
  103. package/dist/commonjs/i18n/locales/en.json +1 -1122
  104. package/dist/commonjs/index.js +5 -2153
  105. package/dist/commonjs/metro.js +6 -468
  106. package/dist/commonjs/native/NativeInspector.d.ts +3 -0
  107. package/dist/commonjs/native/NativeInspector.js +1 -402
  108. package/dist/commonjs/native/NativeNetworkInspector.d.ts +1 -0
  109. package/dist/commonjs/native/NativeNetworkInspector.js +1 -4
  110. package/dist/commonjs/network.js +1 -13
  111. package/dist/commonjs/performance.js +1 -29
  112. package/dist/commonjs/redux.js +1 -20
  113. package/dist/commonjs/storage.js +1 -14
  114. package/dist/commonjs/styles/AppColors.js +1 -423
  115. package/dist/commonjs/styles/AppFonts.js +1 -17
  116. package/dist/commonjs/styles/common.js +1 -190
  117. package/dist/commonjs/styles/index.d.ts +6 -0
  118. package/dist/commonjs/styles/index.js +1 -1589
  119. package/dist/commonjs/types/enums.d.ts +2 -1
  120. package/dist/commonjs/types/enums.js +1 -150
  121. package/dist/commonjs/types/index.js +1 -18
  122. package/dist/commonjs/types/interfaces.d.ts +7 -0
  123. package/dist/commonjs/types/interfaces.js +1 -2
  124. package/dist/esm/analytics.js +1 -2
  125. package/dist/esm/bundle.js +1 -2
  126. package/dist/esm/capture.d.ts +2 -0
  127. package/dist/esm/capture.js +1 -29
  128. package/dist/esm/components/AnalyticsDetail.js +171 -664
  129. package/dist/esm/components/AnalyticsEventCard.js +77 -335
  130. package/dist/esm/components/AnalyticsGraph.js +95 -357
  131. package/dist/esm/components/AnimatedEntrance.js +1 -6
  132. package/dist/esm/components/AppHeaderLogo.js +7 -94
  133. package/dist/esm/components/BrandCircleIcon.js +114 -119
  134. package/dist/esm/components/BrandSquareIcon.js +73 -78
  135. package/dist/esm/components/CodeSnippet.js +58 -595
  136. package/dist/esm/components/ConsoleLogCard.js +91 -526
  137. package/dist/esm/components/CopyButton.js +3 -51
  138. package/dist/esm/components/DiffViewer.js +22 -48
  139. package/dist/esm/components/DomainHeader.js +43 -138
  140. package/dist/esm/components/EmptyState.d.ts +1 -0
  141. package/dist/esm/components/EmptyState.js +17 -56
  142. package/dist/esm/components/EndOfListFooter.js +15 -83
  143. package/dist/esm/components/ErrorBoundary.js +125 -582
  144. package/dist/esm/components/HeadersSection.js +52 -93
  145. package/dist/esm/components/HighlightText.js +17 -53
  146. package/dist/esm/components/Inspector/AboutModal.d.ts +6 -0
  147. package/dist/esm/components/Inspector/AboutModal.js +351 -0
  148. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +225 -886
  149. package/dist/esm/components/Inspector/AnalyticsTab.js +296 -904
  150. package/dist/esm/components/Inspector/BundleTab.js +1175 -3502
  151. package/dist/esm/components/Inspector/ConsoleTab.js +113 -488
  152. package/dist/esm/components/Inspector/CrashDetail.js +236 -747
  153. package/dist/esm/components/Inspector/CrashFilterModal.js +149 -541
  154. package/dist/esm/components/Inspector/CrashTab.js +177 -711
  155. package/dist/esm/components/Inspector/DebuggingTab.js +156 -923
  156. package/dist/esm/components/Inspector/DeviceInfoTab.js +199 -924
  157. package/dist/esm/components/Inspector/FabLauncher.js +85 -49
  158. package/dist/esm/components/Inspector/FeatureUnderDevNotice.js +14 -70
  159. package/dist/esm/components/Inspector/FeedbackModal.d.ts +9 -0
  160. package/dist/esm/components/Inspector/FeedbackModal.js +182 -499
  161. package/dist/esm/components/Inspector/InspectorContext.js +1 -12
  162. package/dist/esm/components/Inspector/InspectorHeader.js +309 -1145
  163. package/dist/esm/components/Inspector/LogDetail.js +235 -1023
  164. package/dist/esm/components/Inspector/MainScreen.js +86 -320
  165. package/dist/esm/components/Inspector/MediaGalleryTab.js +157 -259
  166. package/dist/esm/components/Inspector/MediaPreviewModal.js +153 -340
  167. package/dist/esm/components/Inspector/NavigationTracker.js +1 -10
  168. package/dist/esm/components/Inspector/NetworkDetail.js +141 -472
  169. package/dist/esm/components/Inspector/NetworkFilterModal.js +122 -597
  170. package/dist/esm/components/Inspector/NetworkTab.js +125 -517
  171. package/dist/esm/components/Inspector/NpmStarPrompt.js +58 -434
  172. package/dist/esm/components/Inspector/NpmUpdateToast.js +45 -281
  173. package/dist/esm/components/Inspector/PerformanceTab.js +393 -1570
  174. package/dist/esm/components/Inspector/ReduxDetail.js +307 -1170
  175. package/dist/esm/components/Inspector/ReduxTab.js +144 -722
  176. package/dist/esm/components/Inspector/SettingsPanel.js +647 -3609
  177. package/dist/esm/components/Inspector/SkeletonPlaceholder.js +30 -163
  178. package/dist/esm/components/Inspector/StorageTab.js +172 -866
  179. package/dist/esm/components/Inspector/TabBar.js +52 -183
  180. package/dist/esm/components/Inspector/UpdateAvailableModal.js +79 -416
  181. package/dist/esm/components/JsonViewer.js +179 -353
  182. package/dist/esm/components/LogCard.js +93 -565
  183. package/dist/esm/components/LogSyntaxHighlighter.js +11 -123
  184. package/dist/esm/components/MetaAccordion.js +136 -267
  185. package/dist/esm/components/MiniBarChart.js +3 -18
  186. package/dist/esm/components/MiniLineChart.js +3 -20
  187. package/dist/esm/components/NetworkIcons.d.ts +7 -0
  188. package/dist/esm/components/NetworkIcons.js +481 -817
  189. package/dist/esm/components/QRCodeView.js +8 -45
  190. package/dist/esm/components/SectionHeader.js +22 -39
  191. package/dist/esm/components/SegmentedTabs.js +8 -57
  192. package/dist/esm/components/SkeletonPlaceholder.js +30 -163
  193. package/dist/esm/components/Slider.js +24 -213
  194. package/dist/esm/components/SourcePageCard.js +65 -86
  195. package/dist/esm/components/Toast.js +10 -117
  196. package/dist/esm/components/TouchableScale.js +3 -19
  197. package/dist/esm/components/TreeNode.js +58 -95
  198. package/dist/esm/console.js +1 -2
  199. package/dist/esm/constants/index.js +1 -28
  200. package/dist/esm/constants/telemetryConfig.js +1 -3
  201. package/dist/esm/constants/version.d.ts +1 -1
  202. package/dist/esm/constants/version.js +1 -1
  203. package/dist/esm/crash.js +1 -2
  204. package/dist/esm/customHooks/analyticsLogger.js +1 -230
  205. package/dist/esm/customHooks/bundleAnalyzer.js +1 -944
  206. package/dist/esm/customHooks/consoleLogger.js +6 -432
  207. package/dist/esm/customHooks/crashHandler.js +7 -630
  208. package/dist/esm/customHooks/logFilters.js +1 -20
  209. package/dist/esm/customHooks/networkLogger.js +2 -519
  210. package/dist/esm/customHooks/performanceTracker.js +63 -723
  211. package/dist/esm/customHooks/reduxLogger.js +2 -293
  212. package/dist/esm/customHooks/storageInspector.js +1 -418
  213. package/dist/esm/customHooks/useAccordion.js +1 -16
  214. package/dist/esm/decorators/index.js +1 -95
  215. package/dist/esm/helpers/gaAnalyticsRegistry.js +1 -143
  216. package/dist/esm/helpers/index.js +8 -861
  217. package/dist/esm/helpers/memoryManager.js +1 -91
  218. package/dist/esm/helpers/qrGenerator.js +1 -364
  219. package/dist/esm/helpers/remoteConfig.js +1 -160
  220. package/dist/esm/helpers/searchQueryParser.js +1 -59
  221. package/dist/esm/helpers/settingsStore.js +1 -134
  222. package/dist/esm/helpers/telemetry.js +1 -489
  223. package/dist/esm/helpers/toast.js +1 -15
  224. package/dist/esm/i18n/index.js +1 -78
  225. package/dist/esm/i18n/locales/en.json +1 -1122
  226. package/dist/esm/index.js +7 -1967
  227. package/dist/esm/metro.js +6 -459
  228. package/dist/esm/native/NativeInspector.d.ts +3 -0
  229. package/dist/esm/native/NativeInspector.js +1 -370
  230. package/dist/esm/native/NativeNetworkInspector.d.ts +1 -0
  231. package/dist/esm/native/NativeNetworkInspector.js +1 -2
  232. package/dist/esm/network.js +1 -1
  233. package/dist/esm/performance.js +1 -2
  234. package/dist/esm/redux.js +1 -1
  235. package/dist/esm/storage.js +1 -1
  236. package/dist/esm/styles/AppColors.js +1 -417
  237. package/dist/esm/styles/AppFonts.js +1 -13
  238. package/dist/esm/styles/common.js +1 -186
  239. package/dist/esm/styles/index.d.ts +6 -0
  240. package/dist/esm/styles/index.js +1 -1551
  241. package/dist/esm/types/enums.d.ts +2 -1
  242. package/dist/esm/types/enums.js +1 -147
  243. package/dist/esm/types/index.js +1 -2
  244. package/dist/esm/types/interfaces.d.ts +7 -0
  245. package/dist/esm/types/interfaces.js +1 -1
  246. package/ios/NetworkInspectorModule.mm +253 -136
  247. package/package.json +5 -3
  248. package/react-native-inapp-inspector.podspec +1 -1
  249. package/src/native/NativeInspector.ts +17 -0
  250. package/src/native/NativeNetworkInspector.ts +1 -0
  251. package/src/analytics.ts +0 -35
  252. package/src/bundle.ts +0 -25
  253. package/src/capture.ts +0 -101
  254. package/src/components/AnalyticsDetail.tsx +0 -870
  255. package/src/components/AnalyticsEventCard.tsx +0 -444
  256. package/src/components/AnalyticsGraph.tsx +0 -583
  257. package/src/components/AnimatedEntrance.tsx +0 -20
  258. package/src/components/AppHeaderLogo.tsx +0 -143
  259. package/src/components/BrandCircleIcon.tsx +0 -144
  260. package/src/components/BrandSquareIcon.tsx +0 -184
  261. package/src/components/CodeSnippet.tsx +0 -725
  262. package/src/components/ConsoleLogCard.tsx +0 -679
  263. package/src/components/CopyButton.tsx +0 -87
  264. package/src/components/DiffViewer.tsx +0 -82
  265. package/src/components/DomainHeader.tsx +0 -224
  266. package/src/components/EmptyState.tsx +0 -95
  267. package/src/components/EndOfListFooter.tsx +0 -100
  268. package/src/components/ErrorBoundary.tsx +0 -688
  269. package/src/components/HeadersSection.tsx +0 -172
  270. package/src/components/HighlightText.tsx +0 -100
  271. package/src/components/Inspector/AnalyticsFilterModal.tsx +0 -1250
  272. package/src/components/Inspector/AnalyticsTab.tsx +0 -1362
  273. package/src/components/Inspector/BundleTab.tsx +0 -4768
  274. package/src/components/Inspector/ConsoleTab.tsx +0 -726
  275. package/src/components/Inspector/CrashDetail.tsx +0 -997
  276. package/src/components/Inspector/CrashFilterModal.tsx +0 -721
  277. package/src/components/Inspector/CrashTab.tsx +0 -933
  278. package/src/components/Inspector/DebuggingTab.tsx +0 -1103
  279. package/src/components/Inspector/DeviceInfoTab.tsx +0 -1397
  280. package/src/components/Inspector/FabLauncher.tsx +0 -80
  281. package/src/components/Inspector/FeatureUnderDevNotice.tsx +0 -94
  282. package/src/components/Inspector/FeedbackModal.tsx +0 -626
  283. package/src/components/Inspector/InspectorContext.tsx +0 -28
  284. package/src/components/Inspector/InspectorHeader.tsx +0 -1545
  285. package/src/components/Inspector/LogDetail.tsx +0 -1431
  286. package/src/components/Inspector/MainScreen.tsx +0 -459
  287. package/src/components/Inspector/MediaGalleryTab.tsx +0 -355
  288. package/src/components/Inspector/MediaPreviewModal.tsx +0 -435
  289. package/src/components/Inspector/NavigationTracker.tsx +0 -13
  290. package/src/components/Inspector/NetworkDetail.tsx +0 -795
  291. package/src/components/Inspector/NetworkFilterModal.tsx +0 -730
  292. package/src/components/Inspector/NetworkTab.tsx +0 -820
  293. package/src/components/Inspector/NpmStarPrompt.tsx +0 -532
  294. package/src/components/Inspector/NpmUpdateToast.tsx +0 -387
  295. package/src/components/Inspector/PerformanceTab.tsx +0 -1967
  296. package/src/components/Inspector/ReduxDetail.tsx +0 -1651
  297. package/src/components/Inspector/ReduxTab.tsx +0 -987
  298. package/src/components/Inspector/SettingsPanel.tsx +0 -4580
  299. package/src/components/Inspector/SkeletonPlaceholder.tsx +0 -206
  300. package/src/components/Inspector/StorageTab.tsx +0 -1159
  301. package/src/components/Inspector/TabBar.tsx +0 -263
  302. package/src/components/Inspector/UpdateAvailableModal.tsx +0 -555
  303. package/src/components/JsonViewer.tsx +0 -547
  304. package/src/components/LogCard.tsx +0 -694
  305. package/src/components/LogSyntaxHighlighter.tsx +0 -178
  306. package/src/components/MetaAccordion.tsx +0 -355
  307. package/src/components/MiniBarChart.tsx +0 -42
  308. package/src/components/MiniLineChart.tsx +0 -33
  309. package/src/components/NetworkIcons.tsx +0 -2599
  310. package/src/components/QRCodeView.tsx +0 -75
  311. package/src/components/SectionHeader.tsx +0 -101
  312. package/src/components/SegmentedTabs.tsx +0 -83
  313. package/src/components/SkeletonPlaceholder.tsx +0 -206
  314. package/src/components/Slider.tsx +0 -300
  315. package/src/components/SourcePageCard.tsx +0 -150
  316. package/src/components/Toast.tsx +0 -131
  317. package/src/components/TouchableScale.tsx +0 -61
  318. package/src/components/TreeNode.tsx +0 -171
  319. package/src/console.ts +0 -24
  320. package/src/constants/index.ts +0 -41
  321. package/src/constants/telemetryConfig.ts +0 -4
  322. package/src/constants/version.ts +0 -3
  323. package/src/crash.ts +0 -32
  324. package/src/customHooks/analyticsLogger.ts +0 -336
  325. package/src/customHooks/bundleAnalyzer.ts +0 -1256
  326. package/src/customHooks/consoleLogger.ts +0 -530
  327. package/src/customHooks/crashHandler.ts +0 -944
  328. package/src/customHooks/logFilters.ts +0 -32
  329. package/src/customHooks/networkLogger.ts +0 -624
  330. package/src/customHooks/performanceTracker.ts +0 -1014
  331. package/src/customHooks/reduxLogger.ts +0 -406
  332. package/src/customHooks/storageInspector.ts +0 -513
  333. package/src/customHooks/useAccordion.tsx +0 -27
  334. package/src/decorators/index.ts +0 -184
  335. package/src/helpers/gaAnalyticsRegistry.ts +0 -204
  336. package/src/helpers/index.ts +0 -1092
  337. package/src/helpers/memoryManager.ts +0 -138
  338. package/src/helpers/qrGenerator.ts +0 -430
  339. package/src/helpers/remoteConfig.ts +0 -212
  340. package/src/helpers/searchQueryParser.ts +0 -84
  341. package/src/helpers/settingsStore.ts +0 -171
  342. package/src/helpers/telemetry.ts +0 -568
  343. package/src/helpers/toast.ts +0 -17
  344. package/src/i18n/index.ts +0 -104
  345. package/src/i18n/locales/en.json +0 -1125
  346. package/src/index.tsx +0 -2635
  347. package/src/metro.ts +0 -598
  348. package/src/network.ts +0 -22
  349. package/src/performance.ts +0 -38
  350. package/src/redux.ts +0 -23
  351. package/src/storage.ts +0 -18
  352. package/src/styles/AppColors.ts +0 -455
  353. package/src/styles/AppFonts.ts +0 -26
  354. package/src/styles/common.ts +0 -209
  355. package/src/styles/index.ts +0 -1606
  356. package/src/types/enums.ts +0 -208
  357. package/src/types/index.ts +0 -34
  358. package/src/types/interfaces.ts +0 -530
@@ -1,1631 +1,454 @@
1
- import React, { useState, useEffect, useMemo, useRef } from 'react';
2
- import { ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native';
3
- import Svg, { Path, Defs, LinearGradient, Stop, Line, Circle, G, } from 'react-native-svg';
4
- import TouchableScale from '../TouchableScale';
5
- import CopyButton from '../CopyButton';
6
- import HighlightText from '../HighlightText';
7
- import EndOfListFooter from '../EndOfListFooter';
8
- import FeatureUnderDevNotice from './FeatureUnderDevNotice';
9
- import { AppColors } from '../../styles/AppColors';
10
- import { AppFonts } from '../../styles/AppFonts';
11
- import { useTranslation } from '../../i18n';
12
- import { getRuntimeDiagnostics } from '../../helpers';
13
- import { SearchIcon, CircleXIcon, CircleAlertIcon, PerformanceIcon, BoltIcon, LightbulbIcon, MapIcon, AtomIcon, BrainIcon, GlobeIcon, ChevronIcon, } from '../NetworkIcons';
14
- import { getPerformanceEvents, subscribePerformanceEvents, logPerformanceEvent, clearPerformanceEvents, } from '../../customHooks/performanceTracker';
15
- import { startNativeFpsMonitoring, stopNativeFpsMonitoring, getNativeFpsMetrics, getNativeSystemMetrics, isNativeModuleAvailable, } from '../../native/NativeInspector';
16
- import { trackInspectorScreenRecord } from '../../helpers/telemetry';
17
- const PerformanceTab = React.memo(() => {
18
- const { t } = useTranslation();
19
- const [isRecording, setIsRecording] = useState(true);
20
- const [currentFps, setCurrentFps] = useState(60);
21
- const [minFps, setMinFps] = useState(57);
22
- const [maxFps, setMaxFps] = useState(60);
23
- const [avgFps, setAvgFps] = useState(59);
24
- const [totalFrames, setTotalFrames] = useState(4820);
25
- const [jankyFrameCount, setJankyFrameCount] = useState(4);
26
- const [jsLagMs, setJsLagMs] = useState(1.2);
27
- const [expandedEventIds, setExpandedEventIds] = useState({
28
- 'perf-1': true,
29
- });
30
- const toggleEventExpand = (id) => {
31
- setExpandedEventIds(prev => ({
32
- ...prev,
33
- [id]: !prev[id],
34
- }));
35
- };
36
- const [fpsHistory, setFpsHistory] = useState([
37
- 60, 59, 60, 60, 58, 60, 59, 60, 60, 60, 57, 60, 59, 60, 60, 58, 60, 60, 59, 60,
38
- ]);
39
- const [events, setEvents] = useState(() => getPerformanceEvents());
40
- const [filterCategory, setFilterCategory] = useState('ALL');
41
- const [search, setSearch] = useState('');
42
- useEffect(() => {
43
- const unsub = subscribePerformanceEvents(liveEvents => {
44
- setEvents(liveEvents);
45
- });
46
- return unsub;
47
- }, []);
48
- const lastFrameTimeRef = useRef(Date.now());
49
- const rafIdRef = useRef(null);
50
- const [systemMetrics, setSystemMetrics] = useState(null);
51
- useEffect(() => {
52
- let isMounted = true;
53
- const fetchMetrics = async () => {
54
- const metrics = await getNativeSystemMetrics();
55
- if (isMounted && metrics) {
56
- setSystemMetrics(metrics);
57
- }
58
- };
59
- fetchMetrics();
60
- const interval = setInterval(fetchMetrics, 2000);
61
- return () => {
62
- isMounted = false;
63
- clearInterval(interval);
64
- };
65
- }, []);
66
- useEffect(() => {
67
- if (isNativeModuleAvailable()) {
68
- startNativeFpsMonitoring();
69
- return () => {
70
- stopNativeFpsMonitoring();
71
- };
72
- }
73
- }, []);
74
- useEffect(() => {
75
- if (!isRecording)
76
- return;
77
- let isMounted = true;
78
- let frameCount = 0;
79
- let maxLagInSecond = 0;
80
- let lastSecond = Date.now();
81
- const measureFrame = async () => {
82
- if (!isMounted)
83
- return;
84
- const now = Date.now();
85
- const delta = now - lastFrameTimeRef.current;
86
- lastFrameTimeRef.current = now;
87
- const lag = Math.max(0, delta - 16.67);
88
- if (lag > maxLagInSecond) {
89
- maxLagInSecond = lag;
90
- }
91
- frameCount++;
92
- if (now - lastSecond >= 1000) {
93
- const elapsed = now - lastSecond;
94
- let measuredFps = Math.min(120, Math.max(0, Math.round((frameCount * 1000) / elapsed)));
95
- if (isNativeModuleAvailable()) {
96
- try {
97
- const nativeMetrics = await getNativeFpsMetrics();
98
- if (nativeMetrics && nativeMetrics.fps > 0) {
99
- measuredFps = Math.round(nativeMetrics.fps);
100
- }
101
- }
102
- catch { }
103
- }
104
- setCurrentFps(measuredFps);
105
- setMinFps(prev => Math.min(prev, measuredFps));
106
- setMaxFps(prev => Math.max(prev, measuredFps));
107
- setTotalFrames(prev => prev + frameCount);
108
- setJsLagMs(Number(maxLagInSecond.toFixed(1)));
109
- if (measuredFps < 55) {
110
- setJankyFrameCount(prev => prev + 1);
111
- }
112
- setFpsHistory(prev => {
113
- const next = [...prev.slice(-19), measuredFps];
114
- const sum = next.reduce((a, b) => a + b, 0);
115
- setAvgFps(Math.round(sum / next.length));
116
- return next;
117
- });
118
- if (measuredFps < 50) {
119
- const durationStr = (1000 / measuredFps).toFixed(1);
120
- logPerformanceEvent({
121
- type: 'fps_drop',
122
- category: 'render',
123
- fps: measuredFps,
124
- durationMs: Number(durationStr),
125
- label: t('performance.liveFpsDip', { fps: measuredFps }),
126
- detail: t('performance.liveFpsDipDetail', { duration: durationStr }),
127
- source: t('performance.uiRenderThread'),
128
- breakdown: {
129
- jsTimeMs: Number(((1000 / measuredFps) * 0.65).toFixed(1)),
130
- uiTimeMs: Number(((1000 / measuredFps) * 0.35).toFixed(1)),
131
- },
132
- advice: t('performance.liveFpsDipAdvice'),
133
- severity: measuredFps < 30 ? 'critical' : 'warning',
134
- });
135
- }
136
- frameCount = 0;
137
- maxLagInSecond = 0;
138
- lastSecond = now;
139
- }
140
- rafIdRef.current = requestAnimationFrame(measureFrame);
141
- };
142
- lastFrameTimeRef.current = Date.now();
143
- rafIdRef.current = requestAnimationFrame(measureFrame);
144
- return () => {
145
- isMounted = false;
146
- if (rafIdRef.current)
147
- cancelAnimationFrame(rafIdRef.current);
148
- };
149
- }, [isRecording]);
150
- const filteredEvents = useMemo(() => {
151
- return events.filter(e => {
152
- let matchSearch = true;
153
- if (search && search.trim().length > 0) {
154
- const queryTokens = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
155
- const corpus = [
156
- e.label || '',
157
- e.detail || '',
158
- e.source || '',
159
- e.category || '',
160
- e.severity || '',
161
- e.bottleneckThread || '',
162
- ].join(' ').toLowerCase();
163
- matchSearch = queryTokens.every(tok => corpus.includes(tok));
164
- }
165
- const matchFilter = filterCategory === 'ALL'
166
- ? true
167
- : filterCategory === 'JANKY'
168
- ? e.severity === 'warning' || e.severity === 'critical'
169
- : filterCategory === 'NAVIGATION'
170
- ? e.category === 'navigation'
171
- : filterCategory === 'RENDER'
172
- ? e.category === 'render'
173
- : filterCategory === 'MEMORY'
174
- ? e.category === 'memory'
175
- : e.category === 'io' || e.category === 'bridge';
176
- return matchSearch && matchFilter;
177
- });
178
- }, [events, search, filterCategory]);
179
- const performanceScore = useMemo(() => {
180
- if (avgFps >= 58) {
181
- return {
182
- score: '98/100',
183
- grade: t('performance.excellent'),
184
- color: AppColors.emerald600,
185
- bg: AppColors.greenBg,
186
- };
187
- }
188
- if (avgFps >= 50) {
189
- return {
190
- score: '84/100',
191
- grade: t('performance.good'),
192
- color: AppColors.firebaseOrange,
193
- bg: AppColors.amberBg,
194
- };
195
- }
196
- return {
197
- score: '58/100',
198
- grade: t('performance.needsOptimization'),
199
- color: AppColors.errorColor,
200
- bg: AppColors.errorCardBg,
201
- };
202
- }, [avgFps, t]);
203
- const runtimeDiagnostics = useMemo(() => {
204
- const raw = getRuntimeDiagnostics();
205
- const engineNameMap = {
206
- hermes: t('performance.hermesAot'),
207
- v8: t('performance.v8Jit'),
208
- jsc: t('performance.jscEngine'),
209
- };
210
- const engineSubMap = {
211
- hermes: t('performance.bytecodeCompiled'),
212
- v8: t('performance.jitEngine'),
213
- jsc: t('performance.webkitEngine'),
214
- };
215
- const archNameMap = {
216
- fabric: t('performance.fabricJsi'),
217
- paper: t('performance.paperBridge'),
218
- };
219
- const archSubMap = {
220
- fabric: t('performance.directCppBindings'),
221
- paper: t('performance.asyncJsonBridge'),
222
- };
223
- return {
224
- jsEngineName: engineNameMap[raw.engineType],
225
- jsEngineSub: engineSubMap[raw.engineType],
226
- uiArchName: archNameMap[raw.archType],
227
- uiArchSub: archSubMap[raw.archType],
228
- usedHeapMb: raw.usedHeapMb,
229
- totalAllocMb: raw.totalAllocMb,
230
- };
231
- }, [t]);
232
- const frameBudgetStats = useMemo(() => {
233
- const frameDuration = avgFps > 0 ? 1000 / avgFps : 16.67;
234
- const jsTime = Number(Math.max(1.0, Math.min(frameDuration * 0.45, 2.0 + jsLagMs)).toFixed(1));
235
- const layoutTime = Number(Math.max(1.0, frameDuration * 0.2).toFixed(1));
236
- const renderTime = Number(Math.max(1.0, frameDuration * 0.25).toFixed(1));
237
- const totalUsed = jsTime + layoutTime + renderTime;
238
- const freeTime = Math.max(0, Number((16.67 - totalUsed).toFixed(1)));
239
- const headroomPercent = Math.max(0, Math.min(100, Math.round((freeTime / 16.67) * 100)));
240
- return {
241
- jsTime,
242
- layoutTime,
243
- renderTime,
244
- freeTime,
245
- headroomPercent,
246
- };
247
- }, [avgFps, jsLagMs]);
248
- const [selectedFpsPointIdx, setSelectedFpsPointIdx] = useState(null);
249
- const svgGraphWidth = 320;
250
- const svgGraphHeight = 64;
251
- const fpsGraphData = useMemo(() => {
252
- const points = fpsHistory.length > 0 ? fpsHistory : [60, 60];
253
- const stepX = svgGraphWidth / Math.max(1, points.length - 1);
254
- const coords = points.map((val, idx) => {
255
- const clamped = Math.max(0, Math.min(60, val));
256
- const x = Number((idx * stepX).toFixed(1));
257
- const y = Number((svgGraphHeight - (clamped / 60) * (svgGraphHeight - 14) - 6).toFixed(1));
258
- return { x, y, val };
259
- });
260
- let linePath = `M ${coords[0].x} ${coords[0].y}`;
261
- for (let i = 0; i < coords.length - 1; i++) {
262
- const p0 = coords[i];
263
- const p1 = coords[i + 1];
264
- const midX = Number(((p0.x + p1.x) / 2).toFixed(1));
265
- linePath += ` C ${midX} ${p0.y}, ${midX} ${p1.y}, ${p1.x} ${p1.y}`;
266
- }
267
- const last = coords[coords.length - 1];
268
- const first = coords[0];
269
- const areaPath = `${linePath} L ${last.x} ${svgGraphHeight} L ${first.x} ${svgGraphHeight} Z`;
270
- return { linePath, areaPath, coords };
271
- }, [fpsHistory]);
272
- const latencyBuckets = useMemo(() => {
273
- let optimal = 0;
274
- let minorJank = 0;
275
- let noticeableJank = 0;
276
- let severeFreeze = 0;
277
- fpsHistory.forEach(fps => {
278
- if (fps >= 55)
279
- optimal++;
280
- else if (fps >= 30)
281
- minorJank++;
282
- else if (fps >= 20)
283
- noticeableJank++;
284
- else
285
- severeFreeze++;
286
- });
287
- const total = Math.max(1, fpsHistory.length);
288
- return [
289
- {
290
- key: 'optimal',
291
- label: t('performance.optimalBucket'),
292
- count: optimal,
293
- percent: Number(((optimal / total) * 100).toFixed(0)),
294
- color: AppColors.emerald500,
295
- bgColor: AppColors.emerald100,
296
- },
297
- {
298
- key: 'minorJank',
299
- label: t('performance.minorJankBucket'),
300
- count: minorJank,
301
- percent: Number(((minorJank / total) * 100).toFixed(0)),
302
- color: AppColors.amber500,
303
- bgColor: AppColors.amber100,
304
- },
305
- {
306
- key: 'noticeableJank',
307
- label: t('performance.noticeableJankBucket'),
308
- count: noticeableJank,
309
- percent: Number(((noticeableJank / total) * 100).toFixed(0)),
310
- color: AppColors.firebaseOrange,
311
- bgColor: AppColors.lightOrange,
312
- },
313
- {
314
- key: 'severeFreeze',
315
- label: t('performance.severeFreezeBucket'),
316
- count: severeFreeze,
317
- percent: Number(((severeFreeze / total) * 100).toFixed(0)),
318
- color: AppColors.errorColor,
319
- bgColor: AppColors.errorCardBg,
320
- },
321
- ];
322
- }, [fpsHistory, t]);
323
- const clearEvents = () => {
324
- clearPerformanceEvents();
325
- };
326
- const activeScrubPoint = selectedFpsPointIdx !== null && fpsGraphData.coords[selectedFpsPointIdx]
327
- ? fpsGraphData.coords[selectedFpsPointIdx]
328
- : null;
329
- return (<View style={perfStyles.container}>
1
+ import rr,{useState as I,useEffect as Q,useMemo as J,useRef as ke}from"react";import{ScrollView as Se,StyleSheet as tr,Text as C,TextInput as Tr,TouchableOpacity as Cr,View as T}from"react-native";import Sr,{Path as Be,Defs as Br,LinearGradient as Fr,Stop as Fe,Line as Me,Circle as Ve,G as Mr}from"react-native-svg";import K from"../TouchableScale";import Vr from"../CopyButton";import Re from"../HighlightText";import Rr from"../EndOfListFooter";import Ir from"./FeatureUnderDevNotice";import{AppColors as e}from"../../styles/AppColors";import{AppFonts as k}from"../../styles/AppFonts";import{useTranslation as vr}from"../../i18n";import{getRuntimeDiagnostics as Dr}from"../../helpers";import{SearchIcon as Wr,CircleXIcon as Lr,CircleAlertIcon as Ar,PerformanceIcon as Ie,BoltIcon as Te,LightbulbIcon as Hr,MapIcon as Nr,AtomIcon as Pr,BrainIcon as Er,GlobeIcon as $r,ChevronIcon as Gr}from"../NetworkIcons";import{getPerformanceEvents as Or,subscribePerformanceEvents as Jr,logPerformanceEvent as Kr,clearPerformanceEvents as Ur}from"../../customHooks/performanceTracker";import{startNativeFpsMonitoring as Yr,stopNativeFpsMonitoring as qr,getNativeFpsMetrics as Xr,getNativeSystemMetrics as _r,isNativeModuleAvailable as ve}from"../../native/NativeInspector";import{trackInspectorScreenRecord as Zr}from"../../helpers/telemetry";const Qr=rr.memo(()=>{const{t:w}=vr(),[j,De]=I(!0),[ee,We]=I(60),[we,Le]=I(57),[et,Ae]=I(60),[v,He]=I(59),[Ce,Ne]=I(4820),[Pe,Ee]=I(4),[q,je]=I(1.2),[$e,Ge]=I({"perf-1":!0}),Oe=t=>{Ge(S=>({...S,[t]:!S[t]}))},[$,Je]=I([60,59,60,60,58,60,59,60,60,60,57,60,59,60,60,58,60,60,59,60]),[re,Ke]=I(()=>Or()),[P,Ue]=I("ALL"),[W,te]=I("");Q(()=>Jr(S=>{Ke(S)}),[]);const oe=ke(Date.now()),X=ke(null),[L,Ye]=I(null);Q(()=>{let t=!0;const S=async()=>{const F=await _r();t&&F&&Ye(F)};S();const B=setInterval(S,2e3);return()=>{t=!1,clearInterval(B)}},[]),Q(()=>{if(ve())return Yr(),()=>{qr()}},[]),Q(()=>{if(!j)return;let t=!0,S=0,B=0,F=Date.now();const R=async()=>{if(!t)return;const z=Date.now(),E=z-oe.current;oe.current=z;const D=Math.max(0,E-16.67);if(D>B&&(B=D),S++,z-F>=1e3){const O=z-F;let V=Math.min(120,Math.max(0,Math.round(S*1e3/O)));if(ve())try{const M=await Xr();M&&M.fps>0&&(V=Math.round(M.fps))}catch{}if(We(V),Le(M=>Math.min(M,V)),Ae(M=>Math.max(M,V)),Ne(M=>M+S),je(Number(B.toFixed(1))),V<55&&Ee(M=>M+1),Je(M=>{const Y=[...M.slice(-19),V],Ze=Y.reduce((Qe,er)=>Qe+er,0);return He(Math.round(Ze/Y.length)),Y}),V<50){const M=(1e3/V).toFixed(1);Kr({type:"fps_drop",category:"render",fps:V,durationMs:Number(M),label:w("performance.liveFpsDip",{fps:V}),detail:w("performance.liveFpsDipDetail",{duration:M}),source:w("performance.uiRenderThread"),breakdown:{jsTimeMs:Number((1e3/V*.65).toFixed(1)),uiTimeMs:Number((1e3/V*.35).toFixed(1))},advice:w("performance.liveFpsDipAdvice"),severity:V<30?"critical":"warning"})}S=0,B=0,F=z}X.current=requestAnimationFrame(R)};return oe.current=Date.now(),X.current=requestAnimationFrame(R),()=>{t=!1,X.current&&cancelAnimationFrame(X.current)}},[j]);const _=J(()=>re.filter(t=>{let S=!0;if(W&&W.trim().length>0){const F=W.trim().toLowerCase().split(/\s+/).filter(Boolean),R=[t.label||"",t.detail||"",t.source||"",t.category||"",t.severity||"",t.bottleneckThread||""].join(" ").toLowerCase();S=F.every(z=>R.includes(z))}const B=P==="ALL"?!0:P==="JANKY"?t.severity==="warning"||t.severity==="critical":P==="NAVIGATION"?t.category==="navigation":P==="RENDER"?t.category==="render":P==="MEMORY"?t.category==="memory":t.category==="io"||t.category==="bridge";return S&&B}),[re,W,P]),ae=J(()=>v>=58?{score:"98/100",grade:w("performance.excellent"),color:e.emerald600,bg:e.greenBg}:v>=50?{score:"84/100",grade:w("performance.good"),color:e.firebaseOrange,bg:e.amberBg}:{score:"58/100",grade:w("performance.needsOptimization"),color:e.errorColor,bg:e.errorCardBg},[v,w]),G=J(()=>{const t=Dr(),S={hermes:w("performance.hermesAot"),v8:w("performance.v8Jit"),jsc:w("performance.jscEngine")},B={hermes:w("performance.bytecodeCompiled"),v8:w("performance.jitEngine"),jsc:w("performance.webkitEngine")},F={fabric:w("performance.fabricJsi"),paper:w("performance.paperBridge")},R={fabric:w("performance.directCppBindings"),paper:w("performance.asyncJsonBridge")};return{jsEngineName:S[t.engineType],jsEngineSub:B[t.engineType],uiArchName:F[t.archType],uiArchSub:R[t.archType],usedHeapMb:t.usedHeapMb,totalAllocMb:t.totalAllocMb}},[w]),A=J(()=>{const t=v>0?1e3/v:16.67,S=Number(Math.max(1,Math.min(t*.45,2+q)).toFixed(1)),B=Number(Math.max(1,t*.2).toFixed(1)),F=Number(Math.max(1,t*.25).toFixed(1)),R=S+B+F,z=Math.max(0,Number((16.67-R).toFixed(1))),E=Math.max(0,Math.min(100,Math.round(z/16.67*100)));return{jsTime:S,layoutTime:B,renderTime:F,freeTime:z,headroomPercent:E}},[v,q]),[U,qe]=I(null),Z=320,H=64,N=J(()=>{const t=$.length>0?$:[60,60],S=Z/Math.max(1,t.length-1),B=t.map((D,O)=>{const V=Math.max(0,Math.min(60,D)),M=Number((O*S).toFixed(1)),Y=Number((H-V/60*(H-14)-6).toFixed(1));return{x:M,y:Y,val:D}});let F=`M ${B[0].x} ${B[0].y}`;for(let D=0;D<B.length-1;D++){const O=B[D],V=B[D+1],M=Number(((O.x+V.x)/2).toFixed(1));F+=` C ${M} ${O.y}, ${M} ${V.y}, ${V.x} ${V.y}`}const R=B[B.length-1],z=B[0],E=`${F} L ${R.x} ${H} L ${z.x} ${H} Z`;return{linePath:F,areaPath:E,coords:B}},[$]),Xe=J(()=>{let t=0,S=0,B=0,F=0;$.forEach(z=>{z>=55?t++:z>=30?S++:z>=20?B++:F++});const R=Math.max(1,$.length);return[{key:"optimal",label:w("performance.optimalBucket"),count:t,percent:Number((t/R*100).toFixed(0)),color:e.emerald500,bgColor:e.emerald100},{key:"minorJank",label:w("performance.minorJankBucket"),count:S,percent:Number((S/R*100).toFixed(0)),color:e.amber500,bgColor:e.amber100},{key:"noticeableJank",label:w("performance.noticeableJankBucket"),count:B,percent:Number((B/R*100).toFixed(0)),color:e.firebaseOrange,bgColor:e.lightOrange},{key:"severeFreeze",label:w("performance.severeFreezeBucket"),count:F,percent:Number((F/R*100).toFixed(0)),color:e.errorColor,bgColor:e.errorCardBg}]},[$,w]),_e=()=>{Ur()},ie=U!==null&&N.coords[U]?N.coords[U]:null;return<T style={r.container}>
330
2
 
331
- <View style={perfStyles.headerBar}>
332
- <View style={perfStyles.searchBox}>
333
- <SearchIcon color={AppColors.grayTextWeak} size={15}/>
334
- <TextInput placeholder={t('performance.searchPlaceholder')} placeholderTextColor={AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={perfStyles.searchInput} autoCapitalize="none" autoCorrect={false}/>
335
- {search ? (<TouchableScale onPress={() => setSearch('')}>
336
- <CircleXIcon color={AppColors.grayTextWeak} size={16}/>
337
- </TouchableScale>) : null}
338
- </View>
3
+ <T style={r.headerBar}>
4
+ <T style={r.searchBox}>
5
+ <Wr color={e.grayTextWeak}size={15}/>
6
+ <Tr placeholder={w("performance.searchPlaceholder")}placeholderTextColor={e.grayTextWeak}value={W}onChangeText={te}style={r.searchInput}autoCapitalize="none"autoCorrect={!1}/>
7
+ {W?<K onPress={()=>te("")}>
8
+ <Lr color={e.grayTextWeak}size={16}/>
9
+ </K>:null}
10
+ </T>
339
11
 
340
12
 
341
- <TouchableScale onPress={() => {
342
- setIsRecording(prev => {
343
- const next = !prev;
344
- trackInspectorScreenRecord(next ? 'start' : 'stop', 'performance_fps');
345
- return next;
346
- });
347
- }} style={[
348
- perfStyles.recordToggleBtn,
349
- isRecording
350
- ? perfStyles.recordToggleActive
351
- : perfStyles.recordToggleInactive,
352
- ]}>
353
- <View style={[
354
- perfStyles.recordingDot,
355
- {
356
- backgroundColor: isRecording
357
- ? AppColors.errorColor
358
- : AppColors.grayTextWeak,
359
- },
360
- ]}/>
361
- <Text style={[
362
- perfStyles.recordToggleText,
363
- {
364
- color: isRecording
365
- ? AppColors.errorColor
366
- : AppColors.grayTextWeak,
367
- },
368
- ]}>
369
- {isRecording
370
- ? t('performance.recording')
371
- : t('performance.paused')}
372
- </Text>
373
- </TouchableScale>
374
- </View>
13
+ <K onPress={()=>{De(t=>{const S=!t;return Zr(S?"start":"stop","performance_fps"),S})}}style={[r.recordToggleBtn,j?r.recordToggleActive:r.recordToggleInactive]}>
14
+ <T style={[r.recordingDot,{backgroundColor:j?e.errorColor:e.grayTextWeak}]}/>
15
+ <C style={[r.recordToggleText,{color:j?e.errorColor:e.grayTextWeak}]}>
16
+ {w(j?"performance.recording":"performance.paused")}
17
+ </C>
18
+ </K>
19
+ </T>
375
20
 
376
- <FeatureUnderDevNotice featureName="Performance & FPS Profiler"/>
21
+ <Ir featureName="Performance & FPS Profiler"/>
377
22
 
378
23
 
379
- <View style={perfStyles.categoryScrollWrapper}>
380
- <ScrollView horizontal showsHorizontalScrollIndicator={false} style={perfStyles.categoryScrollView} contentContainerStyle={perfStyles.categoryScroll}>
381
- {[
382
- {
383
- key: 'ALL',
384
- label: t('performance.catAll'),
385
- icon: (color) => <PerformanceIcon size={12} color={color}/>,
386
- },
387
- {
388
- key: 'JANKY',
389
- label: t('performance.catJanky'),
390
- icon: (color) => <CircleAlertIcon size={12} color={color}/>,
391
- },
392
- {
393
- key: 'NAVIGATION',
394
- label: t('performance.catNavigation'),
395
- icon: (color) => <MapIcon size={12} color={color}/>,
396
- },
397
- {
398
- key: 'RENDER',
399
- label: t('performance.catRender'),
400
- icon: (color) => <AtomIcon size={12} color={color}/>,
401
- },
402
- {
403
- key: 'MEMORY',
404
- label: t('performance.catMemory'),
405
- icon: (color) => <BrainIcon size={12} color={color}/>,
406
- },
407
- {
408
- key: 'IO',
409
- label: t('performance.catIo'),
410
- icon: (color) => <GlobeIcon size={12} color={color}/>,
411
- },
412
- ].map(cat => {
413
- const isSelected = filterCategory === cat.key;
414
- const iconColor = isSelected ? AppColors.white : AppColors.grayTextWeak;
415
- return (<TouchableScale key={cat.key} onPress={() => setFilterCategory(cat.key)} style={[
416
- perfStyles.categoryChip,
417
- isSelected && perfStyles.categoryChipActive,
418
- { flexDirection: 'row', alignItems: 'center', gap: 5 },
419
- ]}>
420
- {cat.icon(iconColor)}
421
- <Text style={[
422
- perfStyles.categoryChipText,
423
- isSelected && perfStyles.categoryChipTextActive,
424
- ]}>
425
- {cat.label}
426
- </Text>
427
- </TouchableScale>);
428
- })}
429
- </ScrollView>
430
- </View>
24
+ <T style={r.categoryScrollWrapper}>
25
+ <Se horizontal showsHorizontalScrollIndicator={!1}style={r.categoryScrollView}contentContainerStyle={r.categoryScroll}>
26
+ {[{key:"ALL",label:w("performance.catAll"),icon:t=><Ie size={12}color={t}/>},{key:"JANKY",label:w("performance.catJanky"),icon:t=><Ar size={12}color={t}/>},{key:"NAVIGATION",label:w("performance.catNavigation"),icon:t=><Nr size={12}color={t}/>},{key:"RENDER",label:w("performance.catRender"),icon:t=><Pr size={12}color={t}/>},{key:"MEMORY",label:w("performance.catMemory"),icon:t=><Er size={12}color={t}/>},{key:"IO",label:w("performance.catIo"),icon:t=><$r size={12}color={t}/>}].map(t=>{const S=P===t.key,B=S?e.white:e.grayTextWeak;return<K key={t.key}onPress={()=>Ue(t.key)}style={[r.categoryChip,S&&r.categoryChipActive,{flexDirection:"row",alignItems:"center",gap:5}]}>
27
+ {t.icon(B)}
28
+ <C style={[r.categoryChipText,S&&r.categoryChipTextActive]}>
29
+ {t.label}
30
+ </C>
31
+ </K>})}
32
+ </Se>
33
+ </T>
431
34
 
432
35
 
433
- <ScrollView style={perfStyles.scrollBody} contentContainerStyle={perfStyles.scrollContent} showsVerticalScrollIndicator={false}>
36
+ <Se style={r.scrollBody}contentContainerStyle={r.scrollContent}showsVerticalScrollIndicator={!1}>
434
37
 
435
- <View style={perfStyles.heroCard}>
436
- <View style={perfStyles.heroHeaderRow}>
437
- <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
438
- <PerformanceIcon color={AppColors.purple} size={17}/>
439
- <View>
440
- <Text style={perfStyles.heroTitle}>
441
- {t('performance.fpsAreaChartTitle')}
442
- </Text>
443
- <Text style={perfStyles.heroSubTitle}>
444
- {t('performance.fpsAreaChartSub')}
445
- </Text>
446
- </View>
447
- </View>
38
+ <T style={r.heroCard}>
39
+ <T style={r.heroHeaderRow}>
40
+ <T style={{flexDirection:"row",alignItems:"center",gap:6}}>
41
+ <Ie color={e.purple}size={17}/>
42
+ <T>
43
+ <C style={r.heroTitle}>
44
+ {w("performance.fpsAreaChartTitle")}
45
+ </C>
46
+ <C style={r.heroSubTitle}>
47
+ {w("performance.fpsAreaChartSub")}
48
+ </C>
49
+ </T>
50
+ </T>
448
51
 
449
52
 
450
- <View style={[
451
- perfStyles.scorePill,
452
- { backgroundColor: performanceScore.bg },
453
- ]}>
454
- <Text style={[
455
- perfStyles.scorePillText,
456
- { color: performanceScore.color },
457
- ]}>
458
- {performanceScore.grade}
459
- </Text>
460
- </View>
461
- </View>
53
+ <T style={[r.scorePill,{backgroundColor:ae.bg}]}>
54
+ <C style={[r.scorePillText,{color:ae.color}]}>
55
+ {ae.grade}
56
+ </C>
57
+ </T>
58
+ </T>
462
59
 
463
60
 
464
- <View style={perfStyles.primaryFpsRow}>
465
- <View style={perfStyles.fpsBigNumberBox}>
466
- <Text style={[
467
- perfStyles.fpsBigNumber,
468
- {
469
- color: currentFps >= 55
470
- ? AppColors.emerald600
471
- : currentFps >= 40
472
- ? AppColors.firebaseOrange
473
- : AppColors.errorColor,
474
- },
475
- ]}>
476
- {currentFps}
477
- </Text>
478
- <Text style={perfStyles.fpsUnit}>{t('performance.fpsUnit')}</Text>
479
- </View>
480
-
481
- <View style={perfStyles.fpsStatsGrid}>
482
- <View style={perfStyles.statItem}>
483
- <Text style={perfStyles.statLabel}>
484
- {t('performance.avgFrameTime')}
485
- </Text>
486
- <Text style={perfStyles.statValue}>{avgFps}</Text>
487
- </View>
488
- <View style={perfStyles.statItem}>
489
- <Text style={perfStyles.statLabel}>
490
- {t('performance.peakTime')}
491
- </Text>
492
- <Text style={[
493
- perfStyles.statValue,
494
- minFps < 50 && { color: AppColors.firebaseOrange },
495
- ]}>
496
- {minFps}
497
- </Text>
498
- </View>
499
- <View style={perfStyles.statItem}>
500
- <Text style={perfStyles.statLabel}>
501
- {t('performance.jsLag')}
502
- </Text>
503
- <Text style={[
504
- perfStyles.statValue,
505
- jsLagMs > 5 && { color: AppColors.firebaseOrange },
506
- ]}>
507
- {jsLagMs}ms
508
- </Text>
509
- </View>
510
- <View style={perfStyles.statItem}>
511
- <Text style={perfStyles.statLabel}>
512
- {t('performance.jankRate')}
513
- </Text>
514
- <Text style={perfStyles.statValue}>
515
- {totalFrames > 0
516
- ? `${((jankyFrameCount / Math.max(1, totalFrames / 60)) *
517
- 100).toFixed(0)}%`
518
- : '0%'}
519
- </Text>
520
- </View>
521
- </View>
522
- </View>
61
+ <T style={r.primaryFpsRow}>
62
+ <T style={r.fpsBigNumberBox}>
63
+ <C style={[r.fpsBigNumber,{color:ee>=55?e.emerald600:ee>=40?e.firebaseOrange:e.errorColor}]}>
64
+ {ee}
65
+ </C>
66
+ <C style={r.fpsUnit}>{w("performance.fpsUnit")}</C>
67
+ </T>
68
+
69
+ <T style={r.fpsStatsGrid}>
70
+ <T style={r.statItem}>
71
+ <C style={r.statLabel}>
72
+ {w("performance.avgFrameTime")}
73
+ </C>
74
+ <C style={r.statValue}>{v}</C>
75
+ </T>
76
+ <T style={r.statItem}>
77
+ <C style={r.statLabel}>
78
+ {w("performance.peakTime")}
79
+ </C>
80
+ <C style={[r.statValue,we<50&&{color:e.firebaseOrange}]}>
81
+ {we}
82
+ </C>
83
+ </T>
84
+ <T style={r.statItem}>
85
+ <C style={r.statLabel}>
86
+ {w("performance.jsLag")}
87
+ </C>
88
+ <C style={[r.statValue,q>5&&{color:e.firebaseOrange}]}>
89
+ {q}ms
90
+ </C>
91
+ </T>
92
+ <T style={r.statItem}>
93
+ <C style={r.statLabel}>
94
+ {w("performance.jankRate")}
95
+ </C>
96
+ <C style={r.statValue}>
97
+ {Ce>0?`${(Pe/Math.max(1,Ce/60)*100).toFixed(0)}%`:"0%"}
98
+ </C>
99
+ </T>
100
+ </T>
101
+ </T>
523
102
 
524
103
 
525
- {activeScrubPoint && (<View style={perfStyles.graphScrubTooltip}>
526
- <Text style={perfStyles.graphScrubTooltipText}>
527
- {activeScrubPoint.val} FPS •{' '}
528
- {Number((1000 / Math.max(1, activeScrubPoint.val)).toFixed(1))}
104
+ {ie&&<T style={r.graphScrubTooltip}>
105
+ <C style={r.graphScrubTooltipText}>
106
+ {ie.val} FPS •{" "}
107
+ {Number((1e3/Math.max(1,ie.val)).toFixed(1))}
529
108
  ms
530
- </Text>
531
- </View>)}
109
+ </C>
110
+ </T>}
532
111
 
533
112
 
534
- <View style={perfStyles.svgGraphContainer}>
535
- <Svg width="100%" height={svgGraphHeight} viewBox={`0 0 ${svgGraphWidth} ${svgGraphHeight}`} preserveAspectRatio="none">
536
- <Defs>
537
- <LinearGradient id="fpsAreaGradient" x1="0" y1="0" x2="0" y2="1">
538
- <Stop offset="0%" stopColor={avgFps >= 55
539
- ? AppColors.emerald500
540
- : avgFps >= 40
541
- ? AppColors.amber500
542
- : AppColors.errorColor} stopOpacity="0.32"/>
543
- <Stop offset="100%" stopColor={avgFps >= 55
544
- ? AppColors.emerald500
545
- : avgFps >= 40
546
- ? AppColors.amber500
547
- : AppColors.errorColor} stopOpacity="0.02"/>
548
- </LinearGradient>
549
- </Defs>
113
+ <T style={r.svgGraphContainer}>
114
+ <Sr width="100%"height={H}viewBox={`0 0 ${Z} ${H}`}preserveAspectRatio="none">
115
+ <Br>
116
+ <Fr id="fpsAreaGradient"x1="0"y1="0"x2="0"y2="1">
117
+ <Fe offset="0%"stopColor={v>=55?e.emerald500:v>=40?e.amber500:e.errorColor}stopOpacity="0.32"/>
118
+ <Fe offset="100%"stopColor={v>=55?e.emerald500:v>=40?e.amber500:e.errorColor}stopOpacity="0.02"/>
119
+ </Fr>
120
+ </Br>
550
121
 
551
122
 
552
- <Line x1="0" y1="7" x2={svgGraphWidth} y2="7" stroke={AppColors.emerald500} strokeWidth="1" strokeDasharray="4,4" opacity="0.4"/>
123
+ <Me x1="0"y1="7"x2={Z}y2="7"stroke={e.emerald500}strokeWidth="1"strokeDasharray="4,4"opacity="0.4"/>
553
124
 
554
125
 
555
- <Line x1="0" y1={svgGraphHeight / 2} x2={svgGraphWidth} y2={svgGraphHeight / 2} stroke={AppColors.amber500} strokeWidth="0.8" strokeDasharray="3,3" opacity="0.3"/>
126
+ <Me x1="0"y1={H/2}x2={Z}y2={H/2}stroke={e.amber500}strokeWidth="0.8"strokeDasharray="3,3"opacity="0.3"/>
556
127
 
557
128
 
558
- {fpsGraphData.areaPath ? (<Path d={fpsGraphData.areaPath} fill="url(#fpsAreaGradient)"/>) : null}
129
+ {N.areaPath?<Be d={N.areaPath}fill="url(#fpsAreaGradient)"/>:null}
559
130
 
560
131
 
561
- {fpsGraphData.linePath ? (<Path d={fpsGraphData.linePath} fill="none" stroke={avgFps >= 55
562
- ? AppColors.emerald600
563
- : avgFps >= 40
564
- ? AppColors.amber600
565
- : AppColors.errorColor} strokeWidth="2.2"/>) : null}
132
+ {N.linePath?<Be d={N.linePath}fill="none"stroke={v>=55?e.emerald600:v>=40?e.amber600:e.errorColor}strokeWidth="2.2"/>:null}
566
133
 
567
134
 
568
- {fpsGraphData.coords.map((c, idx) => {
569
- const isSelected = selectedFpsPointIdx === idx;
570
- const isDip = c.val < 50;
571
- return (<G key={idx}>
572
- {isDip && (<Circle cx={c.x} cy={c.y} r="4" fill={AppColors.errorColor} opacity="0.25"/>)}
573
- <Circle cx={c.x} cy={c.y} r={isSelected ? 4 : isDip ? 2.5 : 1.8} fill={isSelected
574
- ? AppColors.brandPurple
575
- : isDip
576
- ? AppColors.errorColor
577
- : AppColors.emerald600} stroke={AppColors.white} strokeWidth={isSelected ? 1.5 : 0.8}/>
578
- </G>);
579
- })}
580
- </Svg>
135
+ {N.coords.map((t,S)=>{const B=U===S,F=t.val<50;return<Mr key={S}>
136
+ {F&&<Ve cx={t.x}cy={t.y}r="4"fill={e.errorColor}opacity="0.25"/>}
137
+ <Ve cx={t.x}cy={t.y}r={B?4:F?2.5:1.8}fill={B?e.brandPurple:F?e.errorColor:e.emerald600}stroke={e.white}strokeWidth={B?1.5:.8}/>
138
+ </Mr>})}
139
+ </Sr>
581
140
 
582
141
 
583
- <View style={perfStyles.svgTouchOverlay}>
584
- {fpsGraphData.coords.map((_, idx) => (<TouchableOpacity key={idx} style={perfStyles.svgTouchCol} activeOpacity={0.7} onPress={() => setSelectedFpsPointIdx(selectedFpsPointIdx === idx ? null : idx)}/>))}
585
- </View>
586
- </View>
587
-
588
- <View style={perfStyles.sparklineFooter}>
589
- <Text style={perfStyles.sparklineFooterText}>
590
- {t('performance.realtimeWindow')}
591
- </Text>
592
- <Text style={perfStyles.sparklineFooterTarget}>
593
- {t('performance.target60Fps', { fps: avgFps })}
594
- </Text>
595
- </View>
596
- </View>
142
+ <T style={r.svgTouchOverlay}>
143
+ {N.coords.map((t,S)=><Cr key={S}style={r.svgTouchCol}activeOpacity={.7}onPress={()=>qe(U===S?null:S)}/>)}
144
+ </T>
145
+ </T>
146
+
147
+ <T style={r.sparklineFooter}>
148
+ <C style={r.sparklineFooterText}>
149
+ {w("performance.realtimeWindow")}
150
+ </C>
151
+ <C style={r.sparklineFooterTarget}>
152
+ {w("performance.target60Fps",{fps:v})}
153
+ </C>
154
+ </T>
155
+ </T>
597
156
 
598
157
 
599
- <View style={perfStyles.budgetCard}>
600
- <View style={perfStyles.budgetHeader}>
601
- <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
602
- <BoltIcon color={AppColors.brandPurple} size={15}/>
603
- <View>
604
- <Text style={perfStyles.budgetTitle}>Native Hardware & System Health</Text>
605
- <Text style={perfStyles.heroSubTitle}>Live kernel metrics, resident RAM, and thermal state</Text>
606
- </View>
607
- </View>
608
- {systemMetrics && (<View style={{
609
- paddingHorizontal: 7,
610
- paddingVertical: 2.5,
611
- borderRadius: 5,
612
- backgroundColor: systemMetrics.thermalState === 'nominal'
613
- ? `${AppColors.emerald600}18`
614
- : systemMetrics.thermalState === 'fair'
615
- ? `${AppColors.amber800Warm}18`
616
- : `${AppColors.errorColor}18`,
617
- }}>
618
- <Text style={{
619
- fontFamily: AppFonts.interBold,
620
- fontSize: 9.5,
621
- color: systemMetrics.thermalState === 'nominal'
622
- ? AppColors.emerald600
623
- : systemMetrics.thermalState === 'fair'
624
- ? AppColors.amber800Warm
625
- : AppColors.errorColor,
626
- textTransform: 'uppercase',
627
- }}>
628
- {systemMetrics.thermalState} THERMAL
629
- </Text>
630
- </View>)}
631
- </View>
632
-
633
- <View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8, marginTop: 10 }}>
634
- <View style={{ flex: 1, minWidth: 100, backgroundColor: AppColors.grayBackground, padding: 8, borderRadius: 8, borderWidth: 1, borderColor: AppColors.dividerColor }}>
635
- <Text style={{ fontFamily: AppFonts.interRegular, fontSize: 9.5, color: AppColors.grayTextWeak }}>Resident RAM</Text>
636
- <Text style={{ fontFamily: AppFonts.interBold, fontSize: 13, color: AppColors.brandPurple, marginTop: 2 }}>
637
- {systemMetrics ? `${systemMetrics.residentRamMb.toFixed(1)} MB` : '18.4 MB'}
638
- </Text>
639
- </View>
640
- <View style={{ flex: 1, minWidth: 100, backgroundColor: AppColors.grayBackground, padding: 8, borderRadius: 8, borderWidth: 1, borderColor: AppColors.dividerColor }}>
641
- <Text style={{ fontFamily: AppFonts.interRegular, fontSize: 9.5, color: AppColors.grayTextWeak }}>Total Physical RAM</Text>
642
- <Text style={{ fontFamily: AppFonts.interBold, fontSize: 13, color: AppColors.primaryBlack, marginTop: 2 }}>
643
- {systemMetrics ? `${Math.round(systemMetrics.totalPhysicalRamMb)} MB` : '3840 MB'}
644
- </Text>
645
- </View>
646
- <View style={{ flex: 1, minWidth: 100, backgroundColor: AppColors.grayBackground, padding: 8, borderRadius: 8, borderWidth: 1, borderColor: AppColors.dividerColor }}>
647
- <Text style={{ fontFamily: AppFonts.interRegular, fontSize: 9.5, color: AppColors.grayTextWeak }}>Active CPU Cores</Text>
648
- <Text style={{ fontFamily: AppFonts.interBold, fontSize: 13, color: AppColors.skyBlue, marginTop: 2 }}>
649
- {systemMetrics ? `${systemMetrics.activeCpuCores} Cores` : '6 Cores'}
650
- </Text>
651
- </View>
652
- </View>
653
- </View>
158
+ <T style={r.budgetCard}>
159
+ <T style={r.budgetHeader}>
160
+ <T style={{flexDirection:"row",alignItems:"center",gap:6}}>
161
+ <Te color={e.brandPurple}size={15}/>
162
+ <T>
163
+ <C style={r.budgetTitle}>Native Hardware & System Health</C>
164
+ <C style={r.heroSubTitle}>Live kernel metrics, resident RAM, and thermal state</C>
165
+ </T>
166
+ </T>
167
+ {L&&<T style={{paddingHorizontal:7,paddingVertical:2.5,borderRadius:5,backgroundColor:L.thermalState==="nominal"?`${e.emerald600}18`:L.thermalState==="fair"?`${e.amber800Warm}18`:`${e.errorColor}18`}}>
168
+ <C style={{fontFamily:k.interBold,fontSize:9.5,color:L.thermalState==="nominal"?e.emerald600:L.thermalState==="fair"?e.amber800Warm:e.errorColor,textTransform:"uppercase"}}>
169
+ {L.thermalState} THERMAL
170
+ </C>
171
+ </T>}
172
+ </T>
173
+
174
+ <T style={{flexDirection:"row",flexWrap:"wrap",gap:8,marginTop:10}}>
175
+ <T style={{flex:1,minWidth:100,backgroundColor:e.grayBackground,padding:8,borderRadius:8,borderWidth:1,borderColor:e.dividerColor}}>
176
+ <C style={{fontFamily:k.interRegular,fontSize:9.5,color:e.grayTextWeak}}>Resident RAM</C>
177
+ <C style={{fontFamily:k.interBold,fontSize:13,color:e.brandPurple,marginTop:2}}>
178
+ {L?`${L.residentRamMb.toFixed(1)} MB`:"18.4 MB"}
179
+ </C>
180
+ </T>
181
+ <T style={{flex:1,minWidth:100,backgroundColor:e.grayBackground,padding:8,borderRadius:8,borderWidth:1,borderColor:e.dividerColor}}>
182
+ <C style={{fontFamily:k.interRegular,fontSize:9.5,color:e.grayTextWeak}}>Total Physical RAM</C>
183
+ <C style={{fontFamily:k.interBold,fontSize:13,color:e.primaryBlack,marginTop:2}}>
184
+ {L?`${Math.round(L.totalPhysicalRamMb)} MB`:"3840 MB"}
185
+ </C>
186
+ </T>
187
+ <T style={{flex:1,minWidth:100,backgroundColor:e.grayBackground,padding:8,borderRadius:8,borderWidth:1,borderColor:e.dividerColor}}>
188
+ <C style={{fontFamily:k.interRegular,fontSize:9.5,color:e.grayTextWeak}}>Active CPU Cores</C>
189
+ <C style={{fontFamily:k.interBold,fontSize:13,color:e.skyBlue,marginTop:2}}>
190
+ {L?`${L.activeCpuCores} Cores`:"6 Cores"}
191
+ </C>
192
+ </T>
193
+ </T>
194
+ </T>
654
195
 
655
196
 
656
- <View style={perfStyles.budgetCard}>
657
- <View style={perfStyles.budgetHeader}>
658
- <View>
659
- <Text style={perfStyles.budgetTitle}>
660
- {t('performance.frameLatencyDistTitle')}
661
- </Text>
662
- <Text style={perfStyles.heroSubTitle}>
663
- {t('performance.frameLatencyDistSub')}
664
- </Text>
665
- </View>
666
- </View>
667
-
668
- <View style={perfStyles.histogramContainer}>
669
- {latencyBuckets.map(b => (<View key={b.key} style={perfStyles.histogramRow}>
670
- <View style={perfStyles.histogramLabelCol}>
671
- <View style={[perfStyles.legendDot, { backgroundColor: b.color }]}/>
672
- <Text style={perfStyles.histogramLabelText}>{b.label}</Text>
673
- </View>
674
-
675
- <View style={perfStyles.histogramBarCol}>
676
- <View style={perfStyles.histogramTrack}>
677
- <View style={[
678
- perfStyles.histogramBarFill,
679
- {
680
- width: `${Math.max(b.percent > 0 ? 4 : 0, b.percent)}%`,
681
- backgroundColor: b.color,
682
- },
683
- ]}/>
684
- </View>
685
- </View>
686
-
687
- <View style={perfStyles.histogramStatsCol}>
688
- <Text style={[
689
- perfStyles.histogramPercentText,
690
- { color: b.color },
691
- ]}>
692
- {b.percent}%
693
- </Text>
694
- <Text style={perfStyles.histogramCountText}>
695
- ({b.count})
696
- </Text>
697
- </View>
698
- </View>))}
699
- </View>
700
- </View>
197
+ <T style={r.budgetCard}>
198
+ <T style={r.budgetHeader}>
199
+ <T>
200
+ <C style={r.budgetTitle}>
201
+ {w("performance.frameLatencyDistTitle")}
202
+ </C>
203
+ <C style={r.heroSubTitle}>
204
+ {w("performance.frameLatencyDistSub")}
205
+ </C>
206
+ </T>
207
+ </T>
208
+
209
+ <T style={r.histogramContainer}>
210
+ {Xe.map(t=><T key={t.key}style={r.histogramRow}>
211
+ <T style={r.histogramLabelCol}>
212
+ <T style={[r.legendDot,{backgroundColor:t.color}]}/>
213
+ <C style={r.histogramLabelText}>{t.label}</C>
214
+ </T>
215
+
216
+ <T style={r.histogramBarCol}>
217
+ <T style={r.histogramTrack}>
218
+ <T style={[r.histogramBarFill,{width:`${Math.max(t.percent>0?4:0,t.percent)}%`,backgroundColor:t.color}]}/>
219
+ </T>
220
+ </T>
221
+
222
+ <T style={r.histogramStatsCol}>
223
+ <C style={[r.histogramPercentText,{color:t.color}]}>
224
+ {t.percent}%
225
+ </C>
226
+ <C style={r.histogramCountText}>
227
+ ({t.count})
228
+ </C>
229
+ </T>
230
+ </T>)}
231
+ </T>
232
+ </T>
701
233
 
702
234
 
703
- <View style={perfStyles.budgetCard}>
704
- <View style={perfStyles.budgetHeader}>
705
- <Text style={perfStyles.budgetTitle}>{t('performance.budgetUsage')}</Text>
706
- <Text style={perfStyles.budgetHeadroom}>
707
- {t('performance.budgetHeadroom', {
708
- time: frameBudgetStats.freeTime,
709
- percent: frameBudgetStats.headroomPercent,
710
- })}
711
- </Text>
712
- </View>
235
+ <T style={r.budgetCard}>
236
+ <T style={r.budgetHeader}>
237
+ <C style={r.budgetTitle}>{w("performance.budgetUsage")}</C>
238
+ <C style={r.budgetHeadroom}>
239
+ {w("performance.budgetHeadroom",{time:A.freeTime,percent:A.headroomPercent})}
240
+ </C>
241
+ </T>
713
242
 
714
243
 
715
- <View style={perfStyles.budgetBarContainer}>
716
- <View style={[
717
- perfStyles.budgetBarSegment,
718
- { flex: Math.max(0.5, frameBudgetStats.jsTime), backgroundColor: AppColors.sky400 },
719
- ]}/>
720
- <View style={[
721
- perfStyles.budgetBarSegment,
722
- { flex: Math.max(0.5, frameBudgetStats.layoutTime), backgroundColor: AppColors.indigo500 },
723
- ]}/>
724
- <View style={[
725
- perfStyles.budgetBarSegment,
726
- { flex: Math.max(0.5, frameBudgetStats.renderTime), backgroundColor: AppColors.pink400 },
727
- ]}/>
728
- <View style={[
729
- perfStyles.budgetBarSegment,
730
- { flex: Math.max(0.5, frameBudgetStats.freeTime), backgroundColor: AppColors.emerald400 },
731
- ]}/>
732
- </View>
733
-
734
- <View style={perfStyles.budgetLegendGrid}>
735
- <View style={perfStyles.legendItem}>
736
- <View style={[perfStyles.legendDot, { backgroundColor: AppColors.sky400 }]}/>
737
- <Text style={perfStyles.legendText}>
738
- {t('performance.jsExec', { time: frameBudgetStats.jsTime })}
739
- </Text>
740
- </View>
741
- <View style={perfStyles.legendItem}>
742
- <View style={[perfStyles.legendDot, { backgroundColor: AppColors.indigo500 }]}/>
743
- <Text style={perfStyles.legendText}>
744
- {t('performance.yogaLayoutTime', { time: frameBudgetStats.layoutTime })}
745
- </Text>
746
- </View>
747
- <View style={perfStyles.legendItem}>
748
- <View style={[perfStyles.legendDot, { backgroundColor: AppColors.pink400 }]}/>
749
- <Text style={perfStyles.legendText}>
750
- {t('performance.uiRenderTime', { time: frameBudgetStats.renderTime })}
751
- </Text>
752
- </View>
753
- <View style={perfStyles.legendItem}>
754
- <View style={[perfStyles.legendDot, { backgroundColor: AppColors.emerald400 }]}/>
755
- <Text style={[perfStyles.legendText, { color: AppColors.emerald600, fontFamily: AppFonts.interBold }]}>
756
- {t('performance.freeTime', { time: frameBudgetStats.freeTime })}
757
- </Text>
758
- </View>
759
- </View>
760
- </View>
244
+ <T style={r.budgetBarContainer}>
245
+ <T style={[r.budgetBarSegment,{flex:Math.max(.5,A.jsTime),backgroundColor:e.sky400}]}/>
246
+ <T style={[r.budgetBarSegment,{flex:Math.max(.5,A.layoutTime),backgroundColor:e.indigo500}]}/>
247
+ <T style={[r.budgetBarSegment,{flex:Math.max(.5,A.renderTime),backgroundColor:e.pink400}]}/>
248
+ <T style={[r.budgetBarSegment,{flex:Math.max(.5,A.freeTime),backgroundColor:e.emerald400}]}/>
249
+ </T>
250
+
251
+ <T style={r.budgetLegendGrid}>
252
+ <T style={r.legendItem}>
253
+ <T style={[r.legendDot,{backgroundColor:e.sky400}]}/>
254
+ <C style={r.legendText}>
255
+ {w("performance.jsExec",{time:A.jsTime})}
256
+ </C>
257
+ </T>
258
+ <T style={r.legendItem}>
259
+ <T style={[r.legendDot,{backgroundColor:e.indigo500}]}/>
260
+ <C style={r.legendText}>
261
+ {w("performance.yogaLayoutTime",{time:A.layoutTime})}
262
+ </C>
263
+ </T>
264
+ <T style={r.legendItem}>
265
+ <T style={[r.legendDot,{backgroundColor:e.pink400}]}/>
266
+ <C style={r.legendText}>
267
+ {w("performance.uiRenderTime",{time:A.renderTime})}
268
+ </C>
269
+ </T>
270
+ <T style={r.legendItem}>
271
+ <T style={[r.legendDot,{backgroundColor:e.emerald400}]}/>
272
+ <C style={[r.legendText,{color:e.emerald600,fontFamily:k.interBold}]}>
273
+ {w("performance.freeTime",{time:A.freeTime})}
274
+ </C>
275
+ </T>
276
+ </T>
277
+ </T>
761
278
 
762
279
 
763
- <View style={perfStyles.engineSummaryGrid}>
764
- <View style={perfStyles.engineSummaryCard}>
765
- <Text style={perfStyles.engineSummaryLabel}>{t('performance.jsEngine')}</Text>
766
- <Text style={perfStyles.engineSummaryValue}>{runtimeDiagnostics.jsEngineName}</Text>
767
- <Text style={perfStyles.engineSummarySub}>{runtimeDiagnostics.jsEngineSub}</Text>
768
- </View>
769
- <View style={perfStyles.engineSummaryCard}>
770
- <Text style={perfStyles.engineSummaryLabel}>{t('performance.uiRenderThread')}</Text>
771
- <Text style={perfStyles.engineSummaryValue}>{runtimeDiagnostics.uiArchName}</Text>
772
- <Text style={perfStyles.engineSummarySub}>{runtimeDiagnostics.uiArchSub}</Text>
773
- </View>
774
- <View style={perfStyles.engineSummaryCard}>
775
- <Text style={perfStyles.engineSummaryLabel}>{t('performance.tabMemory')}</Text>
776
- <Text style={perfStyles.engineSummaryValue}>{runtimeDiagnostics.usedHeapMb} MB</Text>
777
- <Text style={perfStyles.engineSummarySub}>
778
- {t('performance.heapAllocatedSub', { allocated: runtimeDiagnostics.totalAllocMb })}
779
- </Text>
780
- </View>
781
- </View>
280
+ <T style={r.engineSummaryGrid}>
281
+ <T style={r.engineSummaryCard}>
282
+ <C style={r.engineSummaryLabel}>{w("performance.jsEngine")}</C>
283
+ <C style={r.engineSummaryValue}>{G.jsEngineName}</C>
284
+ <C style={r.engineSummarySub}>{G.jsEngineSub}</C>
285
+ </T>
286
+ <T style={r.engineSummaryCard}>
287
+ <C style={r.engineSummaryLabel}>{w("performance.uiRenderThread")}</C>
288
+ <C style={r.engineSummaryValue}>{G.uiArchName}</C>
289
+ <C style={r.engineSummarySub}>{G.uiArchSub}</C>
290
+ </T>
291
+ <T style={r.engineSummaryCard}>
292
+ <C style={r.engineSummaryLabel}>{w("performance.tabMemory")}</C>
293
+ <C style={r.engineSummaryValue}>{G.usedHeapMb} MB</C>
294
+ <C style={r.engineSummarySub}>
295
+ {w("performance.heapAllocatedSub",{allocated:G.totalAllocMb})}
296
+ </C>
297
+ </T>
298
+ </T>
782
299
 
783
300
 
784
- <View style={perfStyles.logsHeaderRow}>
785
- <Text style={perfStyles.logsSectionHeading}>
786
- {t('performance.recordedEvents')} ({filteredEvents.length})
787
- </Text>
788
- {events.length > 0 && (<TouchableScale onPress={clearEvents}>
789
- <Text style={perfStyles.clearLink}>{t('common.clear')}</Text>
790
- </TouchableScale>)}
791
- </View>
792
-
793
- {filteredEvents.length === 0 ? (<View style={perfStyles.emptyCard}>
794
- <BoltIcon color={AppColors.amber500} size={30}/>
795
- <Text style={perfStyles.emptyTitle}>
796
- {search.trim().length > 0 ? 'No Matching Events' : t('performance.emptyTitle')}
797
- </Text>
798
- <Text style={perfStyles.emptySub}>
799
- {search.trim().length > 0
800
- ? `No performance events match "${search}"`
801
- : t('performance.emptySubtitle')}
802
- </Text>
803
- {search.trim().length > 0 && (<TouchableScale onPress={() => setSearch('')} style={{
804
- marginTop: 10,
805
- paddingHorizontal: 14,
806
- paddingVertical: 6,
807
- borderRadius: 8,
808
- backgroundColor: AppColors.grayBackground,
809
- borderWidth: 1,
810
- borderColor: AppColors.grayBorderSecondary,
811
- }}>
812
- <Text style={{ color: AppColors.brandPurple, fontSize: 12, fontFamily: AppFonts.interBold }}>
301
+ <T style={r.logsHeaderRow}>
302
+ <C style={r.logsSectionHeading}>
303
+ {w("performance.recordedEvents")} ({_.length})
304
+ </C>
305
+ {re.length>0&&<K onPress={_e}>
306
+ <C style={r.clearLink}>{w("common.clear")}</C>
307
+ </K>}
308
+ </T>
309
+
310
+ {_.length===0?<T style={r.emptyCard}>
311
+ <Te color={e.amber500}size={30}/>
312
+ <C style={r.emptyTitle}>
313
+ {W.trim().length>0?"No Matching Events":w("performance.emptyTitle")}
314
+ </C>
315
+ <C style={r.emptySub}>
316
+ {W.trim().length>0?`No performance events match "${W}"`:w("performance.emptySubtitle")}
317
+ </C>
318
+ {W.trim().length>0&&<K onPress={()=>te("")}style={{marginTop:10,paddingHorizontal:14,paddingVertical:6,borderRadius:8,backgroundColor:e.grayBackground,borderWidth:1,borderColor:e.grayBorderSecondary}}>
319
+ <C style={{color:e.brandPurple,fontSize:12,fontFamily:k.interBold}}>
813
320
  Clear Search
814
- </Text>
815
- </TouchableScale>)}
816
- </View>) : (filteredEvents.map(event => {
817
- const isOptimal = event.severity === 'optimal';
818
- const isWarning = event.severity === 'warning';
819
- const isCritical = event.severity === 'critical';
820
- const isExpanded = !!expandedEventIds[event.id];
821
- const badgeBg = isOptimal ? AppColors.greenBg : isWarning ? AppColors.amberBg : AppColors.errorCardBg;
822
- const badgeBorder = isOptimal ? AppColors.greenBorder : isWarning ? AppColors.lightOrange : AppColors.errorBorder;
823
- const badgeColor = isOptimal ? AppColors.emerald600 : isWarning ? AppColors.amber700 : AppColors.errorColor;
824
- return (<TouchableScale key={event.id} onPress={() => toggleEventExpand(event.id)} style={[
825
- perfStyles.eventCard,
826
- isCritical && { borderColor: AppColors.errorBorder, backgroundColor: AppColors.errorCardBg },
827
- ]}>
828
- <View style={perfStyles.eventTopRow}>
829
- <View style={perfStyles.fpsBadgeGroup}>
830
- <View style={[
831
- perfStyles.fpsBadge,
832
- { backgroundColor: badgeBg, borderColor: badgeBorder },
833
- ]}>
834
- <Text style={[perfStyles.fpsBadgeText, { color: badgeColor }]}>
835
- {event.fps} FPS
836
- </Text>
837
- </View>
321
+ </C>
322
+ </K>}
323
+ </T>:_.map(t=>{const S=t.severity==="optimal",B=t.severity==="warning",F=t.severity==="critical",R=!!$e[t.id],z=S?e.greenBg:B?e.amberBg:e.errorCardBg,E=S?e.greenBorder:B?e.lightOrange:e.errorBorder,D=S?e.emerald600:B?e.amber700:e.errorColor;return<K key={t.id}onPress={()=>Oe(t.id)}style={[r.eventCard,F&&{borderColor:e.errorBorder,backgroundColor:e.errorCardBg}]}>
324
+ <T style={r.eventTopRow}>
325
+ <T style={r.fpsBadgeGroup}>
326
+ <T style={[r.fpsBadge,{backgroundColor:z,borderColor:E}]}>
327
+ <C style={[r.fpsBadgeText,{color:D}]}>
328
+ {t.fps} FPS
329
+ </C>
330
+ </T>
838
331
 
839
332
 
840
- <View style={[
841
- perfStyles.droppedBadge,
842
- (event.droppedFrames ?? Math.max(0, 60 - event.fps)) > 0
843
- ? perfStyles.droppedBadgeWarning
844
- : perfStyles.droppedBadgeOptimal,
845
- ]}>
846
- <Text style={[
847
- perfStyles.droppedBadgeText,
848
- (event.droppedFrames ?? Math.max(0, 60 - event.fps)) > 0
849
- ? { color: AppColors.red600 }
850
- : { color: AppColors.emerald600 },
851
- ]}>
852
- {(event.droppedFrames ?? Math.max(0, 60 - event.fps)) > 0
853
- ? t('performance.droppedFrames', { count: event.droppedFrames ?? Math.max(0, 60 - event.fps) })
854
- : t('performance.zeroDropped')}
855
- </Text>
856
- </View>
333
+ <T style={[r.droppedBadge,(t.droppedFrames??Math.max(0,60-t.fps))>0?r.droppedBadgeWarning:r.droppedBadgeOptimal]}>
334
+ <C style={[r.droppedBadgeText,(t.droppedFrames??Math.max(0,60-t.fps))>0?{color:e.red600}:{color:e.emerald600}]}>
335
+ {(t.droppedFrames??Math.max(0,60-t.fps))>0?w("performance.droppedFrames",{count:t.droppedFrames??Math.max(0,60-t.fps)}):w("performance.zeroDropped")}
336
+ </C>
337
+ </T>
857
338
 
858
339
 
859
- {event.bottleneckThread && (<View style={[perfStyles.bottleneckTag, { flexDirection: 'row', alignItems: 'center', gap: 3 }]}>
860
- {event.bottleneckThread === 'JS Thread' && (<BoltIcon size={10} color={AppColors.warningIconGold}/>)}
861
- <Text style={perfStyles.bottleneckTagText}>
862
- {event.bottleneckThread === 'JS Thread'
863
- ? t('performance.jsBound')
864
- : event.bottleneckThread === 'UI Thread'
865
- ? t('performance.uiBound')
866
- : t('performance.balanced')}
867
- </Text>
868
- </View>)}
869
- </View>
870
-
871
- <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
872
- <CopyButton value={() => event} label={t('common.copyJson')}/>
873
- <ChevronIcon isExpanded={isExpanded} size={14} color={AppColors.grayTextWeak}/>
874
- </View>
875
- </View>
340
+ {t.bottleneckThread&&<T style={[r.bottleneckTag,{flexDirection:"row",alignItems:"center",gap:3}]}>
341
+ {t.bottleneckThread==="JS Thread"&&<Te size={10}color={e.warningIconGold}/>}
342
+ <C style={r.bottleneckTagText}>
343
+ {t.bottleneckThread==="JS Thread"?w("performance.jsBound"):t.bottleneckThread==="UI Thread"?w("performance.uiBound"):w("performance.balanced")}
344
+ </C>
345
+ </T>}
346
+ </T>
347
+
348
+ <T style={{flexDirection:"row",alignItems:"center",gap:6}}>
349
+ <Vr value={()=>t}label={w("common.copyJson")}/>
350
+ <Gr isExpanded={R}size={14}color={e.grayTextWeak}/>
351
+ </T>
352
+ </T>
876
353
 
877
354
 
878
- <View style={{ marginTop: 4 }}>
879
- <HighlightText text={event.label} search={search} style={perfStyles.eventLabel} highlightStyle={perfStyles.searchHighlight}/>
880
- <View style={perfStyles.eventMetaRow}>
881
- <Text style={perfStyles.eventMeta}>
882
- {t('performance.msTotal', {
883
- duration: event.durationMs,
884
- time: new Date(event.timestamp).toLocaleTimeString(),
885
- })}
886
- </Text>
887
- <Text style={perfStyles.eventMetaDot}>•</Text>
888
- <Text style={[
889
- perfStyles.frameBudgetHint,
890
- event.durationMs > 16.67
891
- ? { color: AppColors.amber800Warm }
892
- : { color: AppColors.emerald600 },
893
- ]}>
894
- {t('performance.frameBudgetMs', {
895
- time: event.durationMs,
896
- budget: Number(((event.durationMs / 16.67) * 100).toFixed(0)),
897
- })}
898
- </Text>
899
- </View>
900
- </View>
355
+ <T style={{marginTop:4}}>
356
+ <Re text={t.label}search={W}style={r.eventLabel}highlightStyle={r.searchHighlight}/>
357
+ <T style={r.eventMetaRow}>
358
+ <C style={r.eventMeta}>
359
+ {w("performance.msTotal",{duration:t.durationMs,time:new Date(t.timestamp).toLocaleTimeString()})}
360
+ </C>
361
+ <C style={r.eventMetaDot}>•</C>
362
+ <C style={[r.frameBudgetHint,t.durationMs>16.67?{color:e.amber800Warm}:{color:e.emerald600}]}>
363
+ {w("performance.frameBudgetMs",{time:t.durationMs,budget:Number((t.durationMs/16.67*100).toFixed(0))})}
364
+ </C>
365
+ </T>
366
+ </T>
901
367
 
902
368
 
903
- <View style={perfStyles.frameBarTrack}>
904
- <View style={[
905
- perfStyles.frameBarFill,
906
- {
907
- width: `${Math.min(100, Math.max(10, (event.durationMs / 33.33) * 100))}%`,
908
- backgroundColor: badgeColor,
909
- },
910
- ]}/>
911
- </View>
369
+ <T style={r.frameBarTrack}>
370
+ <T style={[r.frameBarFill,{width:`${Math.min(100,Math.max(10,t.durationMs/33.33*100))}%`,backgroundColor:D}]}/>
371
+ </T>
912
372
 
913
- <HighlightText text={event.detail} search={search} style={perfStyles.eventDetail} highlightStyle={perfStyles.searchHighlight}/>
373
+ <Re text={t.detail}search={W}style={r.eventDetail}highlightStyle={r.searchHighlight}/>
914
374
 
915
375
 
916
- {isExpanded && (<View style={perfStyles.expandedDetailBox}>
376
+ {R&&<T style={r.expandedDetailBox}>
917
377
 
918
- {(event.screenName || event.source) && (<View style={perfStyles.sourceRow}>
919
- <Text style={perfStyles.sourceTag}>{t('performance.screenContext')}</Text>
920
- <Text style={perfStyles.sourceText} numberOfLines={1}>
921
- {event.screenName || event.source}
922
- </Text>
923
- </View>)}
378
+ {(t.screenName||t.source)&&<T style={r.sourceRow}>
379
+ <C style={r.sourceTag}>{w("performance.screenContext")}</C>
380
+ <C style={r.sourceText}numberOfLines={1}>
381
+ {t.screenName||t.source}
382
+ </C>
383
+ </T>}
924
384
 
925
385
 
926
- <View style={perfStyles.fpsMetricsGrid}>
927
- <View style={perfStyles.fpsMetricItem}>
928
- <Text style={perfStyles.fpsMetricLabel}>{t('performance.target60Fps', { fps: event.fps })}</Text>
929
- <Text style={[perfStyles.fpsMetricVal, { color: badgeColor }]}>
930
- {event.fps} FPS
931
- </Text>
932
- </View>
933
- <View style={perfStyles.fpsMetricItem}>
934
- <Text style={perfStyles.fpsMetricLabel}>{t('performance.frameDuration')}</Text>
935
- <Text style={perfStyles.fpsMetricVal}>
936
- {event.durationMs} ms
937
- </Text>
938
- </View>
939
- <View style={perfStyles.fpsMetricItem}>
940
- <Text style={perfStyles.fpsMetricLabel}>{t('performance.jankRate')}</Text>
941
- <Text style={[
942
- perfStyles.fpsMetricVal,
943
- (event.droppedFrames ?? 0) > 0 ? { color: AppColors.red600 } : { color: AppColors.emerald600 },
944
- ]}>
945
- {event.droppedFrames ?? Math.max(0, 60 - event.fps)} frames
946
- </Text>
947
- </View>
948
- <View style={perfStyles.fpsMetricItem}>
949
- <Text style={perfStyles.fpsMetricLabel}>{t('performance.bottleneck')}</Text>
950
- <Text style={perfStyles.fpsMetricVal}>
951
- {event.bottleneckThread || t('performance.balanced')}
952
- </Text>
953
- </View>
954
- </View>
386
+ <T style={r.fpsMetricsGrid}>
387
+ <T style={r.fpsMetricItem}>
388
+ <C style={r.fpsMetricLabel}>{w("performance.target60Fps",{fps:t.fps})}</C>
389
+ <C style={[r.fpsMetricVal,{color:D}]}>
390
+ {t.fps} FPS
391
+ </C>
392
+ </T>
393
+ <T style={r.fpsMetricItem}>
394
+ <C style={r.fpsMetricLabel}>{w("performance.frameDuration")}</C>
395
+ <C style={r.fpsMetricVal}>
396
+ {t.durationMs} ms
397
+ </C>
398
+ </T>
399
+ <T style={r.fpsMetricItem}>
400
+ <C style={r.fpsMetricLabel}>{w("performance.jankRate")}</C>
401
+ <C style={[r.fpsMetricVal,(t.droppedFrames??0)>0?{color:e.red600}:{color:e.emerald600}]}>
402
+ {t.droppedFrames??Math.max(0,60-t.fps)} frames
403
+ </C>
404
+ </T>
405
+ <T style={r.fpsMetricItem}>
406
+ <C style={r.fpsMetricLabel}>{w("performance.bottleneck")}</C>
407
+ <C style={r.fpsMetricVal}>
408
+ {t.bottleneckThread||w("performance.balanced")}
409
+ </C>
410
+ </T>
411
+ </T>
955
412
 
956
413
 
957
- {event.breakdown && (<View style={perfStyles.breakdownGrid}>
958
- <View style={perfStyles.breakdownCol}>
959
- <Text style={perfStyles.breakdownLabel}>{t('performance.jsThread')}</Text>
960
- <Text style={perfStyles.breakdownVal}>
961
- {event.breakdown.jsTimeMs} ms
962
- </Text>
963
- </View>
964
- <View style={perfStyles.breakdownCol}>
965
- <Text style={perfStyles.breakdownLabel}>{t('performance.uiThread')}</Text>
966
- <Text style={perfStyles.breakdownVal}>
967
- {event.breakdown.uiTimeMs} ms
968
- </Text>
969
- </View>
970
- {event.breakdown.bridgeLatencyMs != null && (<View style={perfStyles.breakdownCol}>
971
- <Text style={perfStyles.breakdownLabel}>{t('performance.jsiLatency')}</Text>
972
- <Text style={perfStyles.breakdownVal}>
973
- {event.breakdown.bridgeLatencyMs} ms
974
- </Text>
975
- </View>)}
976
- {event.heapDeltaKb != null && (<View style={perfStyles.breakdownCol}>
977
- <Text style={perfStyles.breakdownLabel}>{t('performance.heapImpact')}</Text>
978
- <Text style={[
979
- perfStyles.breakdownVal,
980
- { color: event.heapDeltaKb > 0 ? AppColors.amber700 : AppColors.emerald600 },
981
- ]}>
982
- {event.heapDeltaKb > 0 ? `+${event.heapDeltaKb}` : event.heapDeltaKb} KB
983
- </Text>
984
- </View>)}
985
- </View>)}
414
+ {t.breakdown&&<T style={r.breakdownGrid}>
415
+ <T style={r.breakdownCol}>
416
+ <C style={r.breakdownLabel}>{w("performance.jsThread")}</C>
417
+ <C style={r.breakdownVal}>
418
+ {t.breakdown.jsTimeMs} ms
419
+ </C>
420
+ </T>
421
+ <T style={r.breakdownCol}>
422
+ <C style={r.breakdownLabel}>{w("performance.uiThread")}</C>
423
+ <C style={r.breakdownVal}>
424
+ {t.breakdown.uiTimeMs} ms
425
+ </C>
426
+ </T>
427
+ {t.breakdown.bridgeLatencyMs!=null&&<T style={r.breakdownCol}>
428
+ <C style={r.breakdownLabel}>{w("performance.jsiLatency")}</C>
429
+ <C style={r.breakdownVal}>
430
+ {t.breakdown.bridgeLatencyMs} ms
431
+ </C>
432
+ </T>}
433
+ {t.heapDeltaKb!=null&&<T style={r.breakdownCol}>
434
+ <C style={r.breakdownLabel}>{w("performance.heapImpact")}</C>
435
+ <C style={[r.breakdownVal,{color:t.heapDeltaKb>0?e.amber700:e.emerald600}]}>
436
+ {t.heapDeltaKb>0?`+${t.heapDeltaKb}`:t.heapDeltaKb} KB
437
+ </C>
438
+ </T>}
439
+ </T>}
986
440
 
987
441
 
988
- {event.advice && (<View style={perfStyles.adviceCard}>
989
- <View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
990
- <LightbulbIcon color={AppColors.purpleShade700} size={12}/>
991
- <Text style={perfStyles.adviceHeading}>{t('performance.optimizationTip')}</Text>
992
- </View>
993
- <Text style={perfStyles.adviceBodyText}>{event.advice}</Text>
994
- </View>)}
995
- </View>)}
996
- </TouchableScale>);
997
- }))}
998
-
999
- <EndOfListFooter count={filteredEvents.length} label={t('performance.recordedEvents')}/>
1000
- </ScrollView>
1001
- </View>);
1002
- });
1003
- const perfStyles = StyleSheet.create({
1004
- container: {
1005
- flex: 1,
1006
- backgroundColor: AppColors.grayBackground,
1007
- },
1008
- headerBar: {
1009
- flexDirection: 'row',
1010
- alignItems: 'center',
1011
- paddingHorizontal: 12,
1012
- paddingVertical: 8,
1013
- backgroundColor: AppColors.white,
1014
- borderBottomWidth: 1,
1015
- borderBottomColor: AppColors.dividerColor,
1016
- gap: 8,
1017
- },
1018
- searchBox: {
1019
- flex: 1,
1020
- flexDirection: 'row',
1021
- alignItems: 'center',
1022
- backgroundColor: AppColors.grayBackground,
1023
- borderRadius: 8,
1024
- paddingHorizontal: 8,
1025
- height: 36,
1026
- gap: 6,
1027
- borderWidth: 1,
1028
- borderColor: AppColors.dividerColor,
1029
- },
1030
- searchInput: {
1031
- flex: 1,
1032
- fontFamily: AppFonts.interRegular,
1033
- fontSize: 12,
1034
- color: AppColors.primaryBlack,
1035
- paddingVertical: 0,
1036
- },
1037
- recordToggleBtn: {
1038
- flexDirection: 'row',
1039
- alignItems: 'center',
1040
- gap: 5,
1041
- paddingHorizontal: 8,
1042
- paddingVertical: 6,
1043
- borderRadius: 7,
1044
- borderWidth: 1,
1045
- },
1046
- recordToggleActive: {
1047
- backgroundColor: `${AppColors.errorColor}14`,
1048
- borderColor: `${AppColors.errorColor}30`,
1049
- },
1050
- recordToggleInactive: {
1051
- backgroundColor: AppColors.graySurface,
1052
- borderColor: AppColors.dividerColor,
1053
- },
1054
- recordingDot: {
1055
- width: 6,
1056
- height: 6,
1057
- borderRadius: 3,
1058
- },
1059
- recordToggleText: {
1060
- fontFamily: AppFonts.interBold,
1061
- fontSize: 11,
1062
- },
1063
- categoryScrollWrapper: {
1064
- backgroundColor: AppColors.white,
1065
- borderBottomWidth: 1,
1066
- borderBottomColor: AppColors.dividerColor,
1067
- height: 42,
1068
- },
1069
- categoryScrollView: {
1070
- flexGrow: 0,
1071
- height: 42,
1072
- },
1073
- categoryScroll: {
1074
- flexDirection: 'row',
1075
- alignItems: 'center',
1076
- gap: 6,
1077
- paddingHorizontal: 12,
1078
- height: 42,
1079
- },
1080
- categoryChip: {
1081
- flexDirection: 'row',
1082
- alignItems: 'center',
1083
- justifyContent: 'center',
1084
- paddingHorizontal: 12,
1085
- height: 28,
1086
- borderRadius: 14,
1087
- backgroundColor: AppColors.grayBackground,
1088
- borderWidth: 1,
1089
- borderColor: AppColors.dividerColor,
1090
- },
1091
- categoryChipActive: {
1092
- backgroundColor: AppColors.brandPurple,
1093
- borderColor: AppColors.brandPurple,
1094
- },
1095
- categoryChipText: {
1096
- fontFamily: AppFonts.interMedium,
1097
- fontSize: 11,
1098
- color: AppColors.grayTextStrong,
1099
- },
1100
- categoryChipTextActive: {
1101
- fontFamily: AppFonts.interBold,
1102
- color: AppColors.white,
1103
- },
1104
- scrollBody: {
1105
- flex: 1,
1106
- },
1107
- scrollContent: {
1108
- padding: 12,
1109
- gap: 10,
1110
- },
1111
- heroCard: {
1112
- backgroundColor: AppColors.white,
1113
- borderRadius: 12,
1114
- padding: 14,
1115
- borderWidth: 1,
1116
- borderColor: AppColors.dividerColor,
1117
- shadowColor: AppColors.black,
1118
- shadowOffset: { width: 0, height: 1 },
1119
- shadowOpacity: 0.05,
1120
- shadowRadius: 3,
1121
- elevation: 1,
1122
- },
1123
- heroHeaderRow: {
1124
- flexDirection: 'row',
1125
- alignItems: 'center',
1126
- justifyContent: 'space-between',
1127
- marginBottom: 10,
1128
- },
1129
- heroTitle: {
1130
- fontFamily: AppFonts.interBold,
1131
- fontSize: 13,
1132
- color: AppColors.primaryBlack,
1133
- },
1134
- heroSubTitle: {
1135
- fontFamily: AppFonts.interRegular,
1136
- fontSize: 9.5,
1137
- color: AppColors.grayTextWeak,
1138
- marginTop: 1,
1139
- },
1140
- scorePill: {
1141
- paddingHorizontal: 8,
1142
- paddingVertical: 3,
1143
- borderRadius: 6,
1144
- },
1145
- scorePillText: {
1146
- fontFamily: AppFonts.interBold,
1147
- fontSize: 10.5,
1148
- },
1149
- primaryFpsRow: {
1150
- flexDirection: 'row',
1151
- alignItems: 'center',
1152
- justifyContent: 'space-between',
1153
- paddingVertical: 6,
1154
- },
1155
- fpsBigNumberBox: {
1156
- flexDirection: 'row',
1157
- alignItems: 'baseline',
1158
- gap: 4,
1159
- minWidth: 80,
1160
- },
1161
- fpsBigNumber: {
1162
- fontFamily: AppFonts.interBold,
1163
- fontSize: 42,
1164
- lineHeight: 48,
1165
- letterSpacing: -1,
1166
- minWidth: 54,
1167
- },
1168
- fpsUnit: {
1169
- fontFamily: AppFonts.interBold,
1170
- fontSize: 14,
1171
- color: AppColors.grayTextWeak,
1172
- },
1173
- fpsStatsGrid: {
1174
- flexDirection: 'row',
1175
- alignItems: 'center',
1176
- gap: 8,
1177
- },
1178
- statItem: {
1179
- alignItems: 'center',
1180
- minWidth: 50,
1181
- },
1182
- statLabel: {
1183
- fontFamily: AppFonts.interRegular,
1184
- fontSize: 10,
1185
- color: AppColors.grayTextWeak,
1186
- },
1187
- statValue: {
1188
- fontFamily: AppFonts.interBold,
1189
- fontSize: 13,
1190
- color: AppColors.primaryBlack,
1191
- marginTop: 2,
1192
- textAlign: 'center',
1193
- },
1194
- graphScrubTooltip: {
1195
- alignSelf: 'center',
1196
- backgroundColor: AppColors.primaryBlack,
1197
- paddingHorizontal: 8,
1198
- paddingVertical: 3,
1199
- borderRadius: 6,
1200
- marginBottom: 4,
1201
- },
1202
- graphScrubTooltipText: {
1203
- fontFamily: AppFonts.interBold,
1204
- fontSize: 10,
1205
- color: AppColors.white,
1206
- },
1207
- svgGraphContainer: {
1208
- width: '100%',
1209
- height: 64,
1210
- marginTop: 6,
1211
- position: 'relative',
1212
- overflow: 'hidden',
1213
- borderRadius: 8,
1214
- },
1215
- svgTouchOverlay: {
1216
- position: 'absolute',
1217
- top: 0,
1218
- left: 0,
1219
- right: 0,
1220
- bottom: 0,
1221
- flexDirection: 'row',
1222
- },
1223
- svgTouchCol: {
1224
- flex: 1,
1225
- height: '100%',
1226
- },
1227
- histogramContainer: {
1228
- gap: 8,
1229
- marginTop: 4,
1230
- },
1231
- histogramRow: {
1232
- flexDirection: 'row',
1233
- alignItems: 'center',
1234
- gap: 8,
1235
- },
1236
- histogramLabelCol: {
1237
- flexDirection: 'row',
1238
- alignItems: 'center',
1239
- gap: 6,
1240
- width: 140,
1241
- },
1242
- histogramLabelText: {
1243
- fontFamily: AppFonts.interMedium,
1244
- fontSize: 10,
1245
- color: AppColors.grayTextStrong,
1246
- },
1247
- histogramBarCol: {
1248
- flex: 1,
1249
- },
1250
- histogramTrack: {
1251
- height: 8,
1252
- backgroundColor: AppColors.grayBackground,
1253
- borderRadius: 4,
1254
- overflow: 'hidden',
1255
- },
1256
- histogramBarFill: {
1257
- height: '100%',
1258
- borderRadius: 4,
1259
- },
1260
- histogramStatsCol: {
1261
- flexDirection: 'row',
1262
- alignItems: 'center',
1263
- gap: 4,
1264
- minWidth: 52,
1265
- justifyContent: 'flex-end',
1266
- },
1267
- histogramPercentText: {
1268
- fontFamily: AppFonts.interBold,
1269
- fontSize: 10.5,
1270
- },
1271
- histogramCountText: {
1272
- fontFamily: AppFonts.interRegular,
1273
- fontSize: 9.5,
1274
- color: AppColors.grayTextWeak,
1275
- },
1276
- sparklineFooter: {
1277
- flexDirection: 'row',
1278
- alignItems: 'center',
1279
- justifyContent: 'space-between',
1280
- marginTop: 6,
1281
- },
1282
- sparklineFooterText: {
1283
- fontFamily: AppFonts.interRegular,
1284
- fontSize: 10,
1285
- color: AppColors.grayTextWeak,
1286
- },
1287
- sparklineFooterTarget: {
1288
- fontFamily: AppFonts.interMedium,
1289
- fontSize: 10,
1290
- color: AppColors.emerald600,
1291
- },
1292
- budgetCard: {
1293
- backgroundColor: AppColors.white,
1294
- borderRadius: 12,
1295
- padding: 12,
1296
- borderWidth: 1,
1297
- borderColor: AppColors.dividerColor,
1298
- gap: 8,
1299
- },
1300
- budgetHeader: {
1301
- flexDirection: 'row',
1302
- alignItems: 'center',
1303
- justifyContent: 'space-between',
1304
- },
1305
- budgetTitle: {
1306
- fontFamily: AppFonts.interBold,
1307
- fontSize: 12.5,
1308
- color: AppColors.primaryBlack,
1309
- },
1310
- budgetHeadroom: {
1311
- fontFamily: AppFonts.interBold,
1312
- fontSize: 11,
1313
- color: AppColors.emerald600,
1314
- },
1315
- budgetBarContainer: {
1316
- flexDirection: 'row',
1317
- height: 8,
1318
- borderRadius: 4,
1319
- overflow: 'hidden',
1320
- backgroundColor: AppColors.grayBackground,
1321
- gap: 2,
1322
- },
1323
- budgetBarSegment: {
1324
- height: '100%',
1325
- borderRadius: 2,
1326
- },
1327
- budgetLegendGrid: {
1328
- flexDirection: 'row',
1329
- flexWrap: 'wrap',
1330
- gap: 10,
1331
- marginTop: 2,
1332
- },
1333
- legendItem: {
1334
- flexDirection: 'row',
1335
- alignItems: 'center',
1336
- gap: 4,
1337
- },
1338
- legendDot: {
1339
- width: 6,
1340
- height: 6,
1341
- borderRadius: 3,
1342
- },
1343
- legendText: {
1344
- fontFamily: AppFonts.interRegular,
1345
- fontSize: 10,
1346
- color: AppColors.grayTextStrong,
1347
- },
1348
- engineSummaryGrid: {
1349
- flexDirection: 'row',
1350
- alignItems: 'center',
1351
- gap: 8,
1352
- },
1353
- engineSummaryCard: {
1354
- flex: 1,
1355
- backgroundColor: AppColors.white,
1356
- borderRadius: 10,
1357
- padding: 10,
1358
- borderWidth: 1,
1359
- borderColor: AppColors.dividerColor,
1360
- },
1361
- engineSummaryLabel: {
1362
- fontFamily: AppFonts.interMedium,
1363
- fontSize: 10,
1364
- color: AppColors.grayTextWeak,
1365
- },
1366
- engineSummaryValue: {
1367
- fontFamily: AppFonts.interBold,
1368
- fontSize: 11.5,
1369
- color: AppColors.primaryBlack,
1370
- marginTop: 2,
1371
- },
1372
- engineSummarySub: {
1373
- fontFamily: AppFonts.interRegular,
1374
- fontSize: 9.5,
1375
- color: AppColors.grayTextWeak,
1376
- marginTop: 1,
1377
- },
1378
- logsHeaderRow: {
1379
- flexDirection: 'row',
1380
- alignItems: 'center',
1381
- justifyContent: 'space-between',
1382
- marginTop: 4,
1383
- },
1384
- logsSectionHeading: {
1385
- fontFamily: AppFonts.interBold,
1386
- fontSize: 13,
1387
- color: AppColors.primaryBlack,
1388
- },
1389
- clearLink: {
1390
- fontFamily: AppFonts.interBold,
1391
- fontSize: 11.5,
1392
- color: AppColors.purple,
1393
- },
1394
- eventCard: {
1395
- backgroundColor: AppColors.white,
1396
- borderRadius: 10,
1397
- padding: 10,
1398
- borderWidth: 1,
1399
- borderColor: AppColors.dividerColor,
1400
- gap: 6,
1401
- },
1402
- eventTopRow: {
1403
- flexDirection: 'row',
1404
- alignItems: 'center',
1405
- justifyContent: 'space-between',
1406
- },
1407
- fpsBadgeGroup: {
1408
- flexDirection: 'row',
1409
- alignItems: 'center',
1410
- gap: 6,
1411
- flexWrap: 'wrap',
1412
- },
1413
- fpsBadge: {
1414
- paddingHorizontal: 6,
1415
- paddingVertical: 2,
1416
- borderRadius: 5,
1417
- borderWidth: 1,
1418
- },
1419
- fpsBadgeText: {
1420
- fontFamily: AppFonts.interBold,
1421
- fontSize: 10,
1422
- },
1423
- droppedBadge: {
1424
- paddingHorizontal: 6,
1425
- paddingVertical: 2,
1426
- borderRadius: 5,
1427
- borderWidth: 1,
1428
- },
1429
- droppedBadgeWarning: {
1430
- backgroundColor: AppColors.red100,
1431
- borderColor: AppColors.errorBorder,
1432
- },
1433
- droppedBadgeOptimal: {
1434
- backgroundColor: AppColors.green100,
1435
- borderColor: AppColors.greenBorder,
1436
- },
1437
- droppedBadgeText: {
1438
- fontFamily: AppFonts.interBold,
1439
- fontSize: 9.5,
1440
- },
1441
- bottleneckTag: {
1442
- backgroundColor: AppColors.purpleShade50,
1443
- paddingHorizontal: 5,
1444
- paddingVertical: 2,
1445
- borderRadius: 4,
1446
- borderWidth: 1,
1447
- borderColor: AppColors.purpleTint2,
1448
- },
1449
- bottleneckTagText: {
1450
- fontFamily: AppFonts.interMedium,
1451
- fontSize: 9.5,
1452
- color: AppColors.purple,
1453
- },
1454
- eventMetaRow: {
1455
- flexDirection: 'row',
1456
- alignItems: 'center',
1457
- gap: 6,
1458
- marginTop: 2,
1459
- flexWrap: 'wrap',
1460
- },
1461
- eventMetaDot: {
1462
- fontSize: 9,
1463
- color: AppColors.grayTextWeak,
1464
- },
1465
- frameBudgetHint: {
1466
- fontFamily: AppFonts.interMedium,
1467
- fontSize: 10,
1468
- },
1469
- frameBarTrack: {
1470
- height: 4,
1471
- borderRadius: 2,
1472
- backgroundColor: AppColors.graySurface,
1473
- overflow: 'hidden',
1474
- marginVertical: 4,
1475
- },
1476
- frameBarFill: {
1477
- height: '100%',
1478
- borderRadius: 2,
1479
- },
1480
- fpsMetricsGrid: {
1481
- flexDirection: 'row',
1482
- alignItems: 'center',
1483
- backgroundColor: AppColors.white,
1484
- borderRadius: 6,
1485
- padding: 6,
1486
- borderWidth: 1,
1487
- borderColor: AppColors.dividerColor,
1488
- justifyContent: 'space-between',
1489
- gap: 4,
1490
- },
1491
- fpsMetricItem: {
1492
- alignItems: 'center',
1493
- flex: 1,
1494
- },
1495
- fpsMetricLabel: {
1496
- fontFamily: AppFonts.interRegular,
1497
- fontSize: 8.5,
1498
- color: AppColors.grayTextWeak,
1499
- textAlign: 'center',
1500
- },
1501
- fpsMetricVal: {
1502
- fontFamily: AppFonts.interBold,
1503
- fontSize: 10.5,
1504
- color: AppColors.primaryBlack,
1505
- marginTop: 1,
1506
- textAlign: 'center',
1507
- },
1508
- eventLabel: {
1509
- fontFamily: AppFonts.interBold,
1510
- fontSize: 12,
1511
- color: AppColors.primaryBlack,
1512
- },
1513
- eventMeta: {
1514
- fontFamily: AppFonts.interRegular,
1515
- fontSize: 10,
1516
- color: AppColors.grayTextWeak,
1517
- marginTop: 1,
1518
- },
1519
- eventDetail: {
1520
- fontFamily: AppFonts.interRegular,
1521
- fontSize: 11,
1522
- color: AppColors.grayTextStrong,
1523
- lineHeight: 15,
1524
- },
1525
- expandChevron: {
1526
- fontSize: 10,
1527
- color: AppColors.grayTextWeak,
1528
- marginLeft: 2,
1529
- },
1530
- expandedDetailBox: {
1531
- backgroundColor: AppColors.grayBackground,
1532
- borderRadius: 8,
1533
- padding: 8,
1534
- marginTop: 4,
1535
- gap: 6,
1536
- borderWidth: 1,
1537
- borderColor: AppColors.dividerColor,
1538
- },
1539
- sourceRow: {
1540
- flexDirection: 'row',
1541
- alignItems: 'center',
1542
- gap: 6,
1543
- },
1544
- sourceTag: {
1545
- fontFamily: AppFonts.interBold,
1546
- fontSize: 8.5,
1547
- color: AppColors.purple,
1548
- backgroundColor: `${AppColors.purple}14`,
1549
- paddingHorizontal: 4,
1550
- paddingVertical: 1,
1551
- borderRadius: 3,
1552
- },
1553
- sourceText: {
1554
- fontFamily: AppFonts.interMedium,
1555
- fontSize: 10.5,
1556
- color: AppColors.grayTextStrong,
1557
- flex: 1,
1558
- },
1559
- breakdownGrid: {
1560
- flexDirection: 'row',
1561
- alignItems: 'center',
1562
- backgroundColor: AppColors.white,
1563
- borderRadius: 6,
1564
- padding: 6,
1565
- borderWidth: 1,
1566
- borderColor: AppColors.dividerColor,
1567
- justifyContent: 'space-between',
1568
- },
1569
- breakdownCol: {
1570
- alignItems: 'center',
1571
- flex: 1,
1572
- },
1573
- breakdownLabel: {
1574
- fontFamily: AppFonts.interRegular,
1575
- fontSize: 9,
1576
- color: AppColors.grayTextWeak,
1577
- },
1578
- breakdownVal: {
1579
- fontFamily: AppFonts.interBold,
1580
- fontSize: 11,
1581
- color: AppColors.primaryBlack,
1582
- marginTop: 1,
1583
- },
1584
- adviceCard: {
1585
- backgroundColor: AppColors.purpleTintBg,
1586
- borderRadius: 6,
1587
- padding: 6,
1588
- borderWidth: 1,
1589
- borderColor: AppColors.purpleBorder,
1590
- },
1591
- adviceHeading: {
1592
- fontFamily: AppFonts.interBold,
1593
- fontSize: 10,
1594
- color: AppColors.purpleShade700,
1595
- },
1596
- adviceBodyText: {
1597
- fontFamily: AppFonts.interRegular,
1598
- fontSize: 10.5,
1599
- color: AppColors.purple,
1600
- lineHeight: 14,
1601
- marginTop: 1,
1602
- },
1603
- searchHighlight: {
1604
- backgroundColor: AppColors.yellowHighlight,
1605
- color: AppColors.amber800,
1606
- fontFamily: AppFonts.interBold,
1607
- },
1608
- emptyCard: {
1609
- backgroundColor: AppColors.white,
1610
- borderRadius: 12,
1611
- padding: 24,
1612
- alignItems: 'center',
1613
- justifyContent: 'center',
1614
- gap: 8,
1615
- borderWidth: 1,
1616
- borderColor: AppColors.dividerColor,
1617
- },
1618
- emptyTitle: {
1619
- fontFamily: AppFonts.interBold,
1620
- fontSize: 14,
1621
- color: AppColors.primaryBlack,
1622
- },
1623
- emptySub: {
1624
- fontFamily: AppFonts.interRegular,
1625
- fontSize: 11.5,
1626
- color: AppColors.grayTextWeak,
1627
- textAlign: 'center',
1628
- lineHeight: 16,
1629
- },
1630
- });
1631
- export default PerformanceTab;
442
+ {t.advice&&<T style={r.adviceCard}>
443
+ <T style={{flexDirection:"row",alignItems:"center",gap:5}}>
444
+ <Hr color={e.purpleShade700}size={12}/>
445
+ <C style={r.adviceHeading}>{w("performance.optimizationTip")}</C>
446
+ </T>
447
+ <C style={r.adviceBodyText}>{t.advice}</C>
448
+ </T>}
449
+ </T>}
450
+ </K>})}
451
+
452
+ <Rr count={_.length}label={w("performance.recordedEvents")}/>
453
+ </Se>
454
+ </T>}),r=tr.create({container:{flex:1,backgroundColor:e.grayBackground},headerBar:{flexDirection:"row",alignItems:"center",paddingHorizontal:12,paddingVertical:8,backgroundColor:e.white,borderBottomWidth:1,borderBottomColor:e.dividerColor,gap:8},searchBox:{flex:1,flexDirection:"row",alignItems:"center",backgroundColor:e.grayBackground,borderRadius:8,paddingHorizontal:8,height:36,gap:6,borderWidth:1,borderColor:e.dividerColor},searchInput:{flex:1,fontFamily:k.interRegular,fontSize:12,color:e.primaryBlack,paddingVertical:0},recordToggleBtn:{flexDirection:"row",alignItems:"center",gap:5,paddingHorizontal:8,paddingVertical:6,borderRadius:7,borderWidth:1},recordToggleActive:{backgroundColor:`${e.errorColor}14`,borderColor:`${e.errorColor}30`},recordToggleInactive:{backgroundColor:e.graySurface,borderColor:e.dividerColor},recordingDot:{width:6,height:6,borderRadius:3},recordToggleText:{fontFamily:k.interBold,fontSize:11},categoryScrollWrapper:{backgroundColor:e.white,borderBottomWidth:1,borderBottomColor:e.dividerColor,height:42},categoryScrollView:{flexGrow:0,height:42},categoryScroll:{flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:12,height:42},categoryChip:{flexDirection:"row",alignItems:"center",justifyContent:"center",paddingHorizontal:12,height:28,borderRadius:14,backgroundColor:e.grayBackground,borderWidth:1,borderColor:e.dividerColor},categoryChipActive:{backgroundColor:e.brandPurple,borderColor:e.brandPurple},categoryChipText:{fontFamily:k.interMedium,fontSize:11,color:e.grayTextStrong},categoryChipTextActive:{fontFamily:k.interBold,color:e.white},scrollBody:{flex:1},scrollContent:{padding:12,gap:10},heroCard:{backgroundColor:e.white,borderRadius:12,padding:14,borderWidth:1,borderColor:e.dividerColor,shadowColor:e.black,shadowOffset:{width:0,height:1},shadowOpacity:.05,shadowRadius:3,elevation:1},heroHeaderRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:10},heroTitle:{fontFamily:k.interBold,fontSize:13,color:e.primaryBlack},heroSubTitle:{fontFamily:k.interRegular,fontSize:9.5,color:e.grayTextWeak,marginTop:1},scorePill:{paddingHorizontal:8,paddingVertical:3,borderRadius:6},scorePillText:{fontFamily:k.interBold,fontSize:10.5},primaryFpsRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingVertical:6},fpsBigNumberBox:{flexDirection:"row",alignItems:"baseline",gap:4,minWidth:80},fpsBigNumber:{fontFamily:k.interBold,fontSize:42,lineHeight:48,letterSpacing:-1,minWidth:54},fpsUnit:{fontFamily:k.interBold,fontSize:14,color:e.grayTextWeak},fpsStatsGrid:{flexDirection:"row",alignItems:"center",gap:8},statItem:{alignItems:"center",minWidth:50},statLabel:{fontFamily:k.interRegular,fontSize:10,color:e.grayTextWeak},statValue:{fontFamily:k.interBold,fontSize:13,color:e.primaryBlack,marginTop:2,textAlign:"center"},graphScrubTooltip:{alignSelf:"center",backgroundColor:e.primaryBlack,paddingHorizontal:8,paddingVertical:3,borderRadius:6,marginBottom:4},graphScrubTooltipText:{fontFamily:k.interBold,fontSize:10,color:e.white},svgGraphContainer:{width:"100%",height:64,marginTop:6,position:"relative",overflow:"hidden",borderRadius:8},svgTouchOverlay:{position:"absolute",top:0,left:0,right:0,bottom:0,flexDirection:"row"},svgTouchCol:{flex:1,height:"100%"},histogramContainer:{gap:8,marginTop:4},histogramRow:{flexDirection:"row",alignItems:"center",gap:8},histogramLabelCol:{flexDirection:"row",alignItems:"center",gap:6,width:140},histogramLabelText:{fontFamily:k.interMedium,fontSize:10,color:e.grayTextStrong},histogramBarCol:{flex:1},histogramTrack:{height:8,backgroundColor:e.grayBackground,borderRadius:4,overflow:"hidden"},histogramBarFill:{height:"100%",borderRadius:4},histogramStatsCol:{flexDirection:"row",alignItems:"center",gap:4,minWidth:52,justifyContent:"flex-end"},histogramPercentText:{fontFamily:k.interBold,fontSize:10.5},histogramCountText:{fontFamily:k.interRegular,fontSize:9.5,color:e.grayTextWeak},sparklineFooter:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginTop:6},sparklineFooterText:{fontFamily:k.interRegular,fontSize:10,color:e.grayTextWeak},sparklineFooterTarget:{fontFamily:k.interMedium,fontSize:10,color:e.emerald600},budgetCard:{backgroundColor:e.white,borderRadius:12,padding:12,borderWidth:1,borderColor:e.dividerColor,gap:8},budgetHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},budgetTitle:{fontFamily:k.interBold,fontSize:12.5,color:e.primaryBlack},budgetHeadroom:{fontFamily:k.interBold,fontSize:11,color:e.emerald600},budgetBarContainer:{flexDirection:"row",height:8,borderRadius:4,overflow:"hidden",backgroundColor:e.grayBackground,gap:2},budgetBarSegment:{height:"100%",borderRadius:2},budgetLegendGrid:{flexDirection:"row",flexWrap:"wrap",gap:10,marginTop:2},legendItem:{flexDirection:"row",alignItems:"center",gap:4},legendDot:{width:6,height:6,borderRadius:3},legendText:{fontFamily:k.interRegular,fontSize:10,color:e.grayTextStrong},engineSummaryGrid:{flexDirection:"row",alignItems:"center",gap:8},engineSummaryCard:{flex:1,backgroundColor:e.white,borderRadius:10,padding:10,borderWidth:1,borderColor:e.dividerColor},engineSummaryLabel:{fontFamily:k.interMedium,fontSize:10,color:e.grayTextWeak},engineSummaryValue:{fontFamily:k.interBold,fontSize:11.5,color:e.primaryBlack,marginTop:2},engineSummarySub:{fontFamily:k.interRegular,fontSize:9.5,color:e.grayTextWeak,marginTop:1},logsHeaderRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginTop:4},logsSectionHeading:{fontFamily:k.interBold,fontSize:13,color:e.primaryBlack},clearLink:{fontFamily:k.interBold,fontSize:11.5,color:e.purple},eventCard:{backgroundColor:e.white,borderRadius:10,padding:10,borderWidth:1,borderColor:e.dividerColor,gap:6},eventTopRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},fpsBadgeGroup:{flexDirection:"row",alignItems:"center",gap:6,flexWrap:"wrap"},fpsBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:5,borderWidth:1},fpsBadgeText:{fontFamily:k.interBold,fontSize:10},droppedBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:5,borderWidth:1},droppedBadgeWarning:{backgroundColor:e.red100,borderColor:e.errorBorder},droppedBadgeOptimal:{backgroundColor:e.green100,borderColor:e.greenBorder},droppedBadgeText:{fontFamily:k.interBold,fontSize:9.5},bottleneckTag:{backgroundColor:e.purpleShade50,paddingHorizontal:5,paddingVertical:2,borderRadius:4,borderWidth:1,borderColor:e.purpleTint2},bottleneckTagText:{fontFamily:k.interMedium,fontSize:9.5,color:e.purple},eventMetaRow:{flexDirection:"row",alignItems:"center",gap:6,marginTop:2,flexWrap:"wrap"},eventMetaDot:{fontSize:9,color:e.grayTextWeak},frameBudgetHint:{fontFamily:k.interMedium,fontSize:10},frameBarTrack:{height:4,borderRadius:2,backgroundColor:e.graySurface,overflow:"hidden",marginVertical:4},frameBarFill:{height:"100%",borderRadius:2},fpsMetricsGrid:{flexDirection:"row",alignItems:"center",backgroundColor:e.white,borderRadius:6,padding:6,borderWidth:1,borderColor:e.dividerColor,justifyContent:"space-between",gap:4},fpsMetricItem:{alignItems:"center",flex:1},fpsMetricLabel:{fontFamily:k.interRegular,fontSize:8.5,color:e.grayTextWeak,textAlign:"center"},fpsMetricVal:{fontFamily:k.interBold,fontSize:10.5,color:e.primaryBlack,marginTop:1,textAlign:"center"},eventLabel:{fontFamily:k.interBold,fontSize:12,color:e.primaryBlack},eventMeta:{fontFamily:k.interRegular,fontSize:10,color:e.grayTextWeak,marginTop:1},eventDetail:{fontFamily:k.interRegular,fontSize:11,color:e.grayTextStrong,lineHeight:15},expandChevron:{fontSize:10,color:e.grayTextWeak,marginLeft:2},expandedDetailBox:{backgroundColor:e.grayBackground,borderRadius:8,padding:8,marginTop:4,gap:6,borderWidth:1,borderColor:e.dividerColor},sourceRow:{flexDirection:"row",alignItems:"center",gap:6},sourceTag:{fontFamily:k.interBold,fontSize:8.5,color:e.purple,backgroundColor:`${e.purple}14`,paddingHorizontal:4,paddingVertical:1,borderRadius:3},sourceText:{fontFamily:k.interMedium,fontSize:10.5,color:e.grayTextStrong,flex:1},breakdownGrid:{flexDirection:"row",alignItems:"center",backgroundColor:e.white,borderRadius:6,padding:6,borderWidth:1,borderColor:e.dividerColor,justifyContent:"space-between"},breakdownCol:{alignItems:"center",flex:1},breakdownLabel:{fontFamily:k.interRegular,fontSize:9,color:e.grayTextWeak},breakdownVal:{fontFamily:k.interBold,fontSize:11,color:e.primaryBlack,marginTop:1},adviceCard:{backgroundColor:e.purpleTintBg,borderRadius:6,padding:6,borderWidth:1,borderColor:e.purpleBorder},adviceHeading:{fontFamily:k.interBold,fontSize:10,color:e.purpleShade700},adviceBodyText:{fontFamily:k.interRegular,fontSize:10.5,color:e.purple,lineHeight:14,marginTop:1},searchHighlight:{backgroundColor:e.yellowHighlight,color:e.amber800,fontFamily:k.interBold},emptyCard:{backgroundColor:e.white,borderRadius:12,padding:24,alignItems:"center",justifyContent:"center",gap:8,borderWidth:1,borderColor:e.dividerColor},emptyTitle:{fontFamily:k.interBold,fontSize:14,color:e.primaryBlack},emptySub:{fontFamily:k.interRegular,fontSize:11.5,color:e.grayTextWeak,textAlign:"center",lineHeight:16}});export default Qr;