react-native-inapp-inspector 1.0.0

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 (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/commonjs/components/AnalyticsDetail.d.ts +6 -0
  4. package/dist/commonjs/components/AnalyticsDetail.js +558 -0
  5. package/dist/commonjs/components/AnalyticsEventCard.d.ts +18 -0
  6. package/dist/commonjs/components/AnalyticsEventCard.js +327 -0
  7. package/dist/commonjs/components/AnalyticsGraph.d.ts +8 -0
  8. package/dist/commonjs/components/AnalyticsGraph.js +416 -0
  9. package/dist/commonjs/components/CodeSnippet.d.ts +8 -0
  10. package/dist/commonjs/components/CodeSnippet.js +427 -0
  11. package/dist/commonjs/components/ConsoleLogCard.d.ts +10 -0
  12. package/dist/commonjs/components/ConsoleLogCard.js +401 -0
  13. package/dist/commonjs/components/CopyButton.d.ts +4 -0
  14. package/dist/commonjs/components/CopyButton.js +69 -0
  15. package/dist/commonjs/components/DiffViewer.d.ts +7 -0
  16. package/dist/commonjs/components/DiffViewer.js +86 -0
  17. package/dist/commonjs/components/DomainHeader.d.ts +18 -0
  18. package/dist/commonjs/components/DomainHeader.js +136 -0
  19. package/dist/commonjs/components/EmptyState.d.ts +5 -0
  20. package/dist/commonjs/components/EmptyState.js +40 -0
  21. package/dist/commonjs/components/HeadersSection.d.ts +4 -0
  22. package/dist/commonjs/components/HeadersSection.js +155 -0
  23. package/dist/commonjs/components/HighlightText.d.ts +3 -0
  24. package/dist/commonjs/components/HighlightText.js +57 -0
  25. package/dist/commonjs/components/JsonViewer.d.ts +7 -0
  26. package/dist/commonjs/components/JsonViewer.js +19 -0
  27. package/dist/commonjs/components/LogCard.d.ts +4 -0
  28. package/dist/commonjs/components/LogCard.js +179 -0
  29. package/dist/commonjs/components/MetaAccordion.d.ts +4 -0
  30. package/dist/commonjs/components/MetaAccordion.js +113 -0
  31. package/dist/commonjs/components/MiniBarChart.d.ts +7 -0
  32. package/dist/commonjs/components/MiniBarChart.js +56 -0
  33. package/dist/commonjs/components/MiniLineChart.d.ts +6 -0
  34. package/dist/commonjs/components/MiniLineChart.js +58 -0
  35. package/dist/commonjs/components/NetworkIcons.d.ts +31 -0
  36. package/dist/commonjs/components/NetworkIcons.js +245 -0
  37. package/dist/commonjs/components/SectionHeader.d.ts +4 -0
  38. package/dist/commonjs/components/SectionHeader.js +87 -0
  39. package/dist/commonjs/components/SourcePageCard.d.ts +4 -0
  40. package/dist/commonjs/components/SourcePageCard.js +132 -0
  41. package/dist/commonjs/components/TouchableScale.d.ts +9 -0
  42. package/dist/commonjs/components/TouchableScale.js +44 -0
  43. package/dist/commonjs/components/TreeNode.d.ts +4 -0
  44. package/dist/commonjs/components/TreeNode.js +140 -0
  45. package/dist/commonjs/constants/index.d.ts +7 -0
  46. package/dist/commonjs/constants/index.js +35 -0
  47. package/dist/commonjs/customHooks/analyticsLogger.d.ts +21 -0
  48. package/dist/commonjs/customHooks/analyticsLogger.js +160 -0
  49. package/dist/commonjs/customHooks/consoleLogger.d.ts +5 -0
  50. package/dist/commonjs/customHooks/consoleLogger.js +141 -0
  51. package/dist/commonjs/customHooks/logFilters.d.ts +5 -0
  52. package/dist/commonjs/customHooks/logFilters.js +34 -0
  53. package/dist/commonjs/customHooks/networkLogger.d.ts +20 -0
  54. package/dist/commonjs/customHooks/networkLogger.js +272 -0
  55. package/dist/commonjs/customHooks/useAccordion.d.ts +17 -0
  56. package/dist/commonjs/customHooks/useAccordion.js +48 -0
  57. package/dist/commonjs/customHooks/webViewLogger.d.ts +22 -0
  58. package/dist/commonjs/customHooks/webViewLogger.js +412 -0
  59. package/dist/commonjs/helpers/index.d.ts +20 -0
  60. package/dist/commonjs/helpers/index.js +229 -0
  61. package/dist/commonjs/index.d.ts +7 -0
  62. package/dist/commonjs/index.js +2668 -0
  63. package/dist/commonjs/styles/AppColors.d.ts +27 -0
  64. package/dist/commonjs/styles/AppColors.js +30 -0
  65. package/dist/commonjs/styles/AppFonts.d.ts +7 -0
  66. package/dist/commonjs/styles/AppFonts.js +10 -0
  67. package/dist/commonjs/styles/index.d.ts +1488 -0
  68. package/dist/commonjs/styles/index.js +1357 -0
  69. package/dist/commonjs/types/index.d.ts +127 -0
  70. package/dist/commonjs/types/index.js +2 -0
  71. package/dist/esm/components/AnalyticsDetail.d.ts +6 -0
  72. package/dist/esm/components/AnalyticsDetail.js +520 -0
  73. package/dist/esm/components/AnalyticsEventCard.d.ts +18 -0
  74. package/dist/esm/components/AnalyticsEventCard.js +288 -0
  75. package/dist/esm/components/AnalyticsGraph.d.ts +8 -0
  76. package/dist/esm/components/AnalyticsGraph.js +378 -0
  77. package/dist/esm/components/CodeSnippet.d.ts +8 -0
  78. package/dist/esm/components/CodeSnippet.js +392 -0
  79. package/dist/esm/components/ConsoleLogCard.d.ts +10 -0
  80. package/dist/esm/components/ConsoleLogCard.js +362 -0
  81. package/dist/esm/components/CopyButton.d.ts +4 -0
  82. package/dist/esm/components/CopyButton.js +31 -0
  83. package/dist/esm/components/DiffViewer.d.ts +7 -0
  84. package/dist/esm/components/DiffViewer.js +48 -0
  85. package/dist/esm/components/DomainHeader.d.ts +18 -0
  86. package/dist/esm/components/DomainHeader.js +98 -0
  87. package/dist/esm/components/EmptyState.d.ts +5 -0
  88. package/dist/esm/components/EmptyState.js +35 -0
  89. package/dist/esm/components/HeadersSection.d.ts +4 -0
  90. package/dist/esm/components/HeadersSection.js +117 -0
  91. package/dist/esm/components/HighlightText.d.ts +3 -0
  92. package/dist/esm/components/HighlightText.js +52 -0
  93. package/dist/esm/components/JsonViewer.d.ts +7 -0
  94. package/dist/esm/components/JsonViewer.js +14 -0
  95. package/dist/esm/components/LogCard.d.ts +4 -0
  96. package/dist/esm/components/LogCard.js +141 -0
  97. package/dist/esm/components/MetaAccordion.d.ts +4 -0
  98. package/dist/esm/components/MetaAccordion.js +108 -0
  99. package/dist/esm/components/MiniBarChart.d.ts +7 -0
  100. package/dist/esm/components/MiniBarChart.js +18 -0
  101. package/dist/esm/components/MiniLineChart.d.ts +6 -0
  102. package/dist/esm/components/MiniLineChart.js +20 -0
  103. package/dist/esm/components/NetworkIcons.d.ts +31 -0
  104. package/dist/esm/components/NetworkIcons.js +176 -0
  105. package/dist/esm/components/SectionHeader.d.ts +4 -0
  106. package/dist/esm/components/SectionHeader.js +49 -0
  107. package/dist/esm/components/SourcePageCard.d.ts +4 -0
  108. package/dist/esm/components/SourcePageCard.js +94 -0
  109. package/dist/esm/components/TouchableScale.d.ts +9 -0
  110. package/dist/esm/components/TouchableScale.js +9 -0
  111. package/dist/esm/components/TreeNode.d.ts +4 -0
  112. package/dist/esm/components/TreeNode.js +102 -0
  113. package/dist/esm/constants/index.d.ts +7 -0
  114. package/dist/esm/constants/index.js +32 -0
  115. package/dist/esm/customHooks/analyticsLogger.d.ts +21 -0
  116. package/dist/esm/customHooks/analyticsLogger.js +152 -0
  117. package/dist/esm/customHooks/consoleLogger.d.ts +5 -0
  118. package/dist/esm/customHooks/consoleLogger.js +134 -0
  119. package/dist/esm/customHooks/logFilters.d.ts +5 -0
  120. package/dist/esm/customHooks/logFilters.js +31 -0
  121. package/dist/esm/customHooks/networkLogger.d.ts +20 -0
  122. package/dist/esm/customHooks/networkLogger.js +264 -0
  123. package/dist/esm/customHooks/useAccordion.d.ts +17 -0
  124. package/dist/esm/customHooks/useAccordion.js +46 -0
  125. package/dist/esm/customHooks/webViewLogger.d.ts +22 -0
  126. package/dist/esm/customHooks/webViewLogger.js +365 -0
  127. package/dist/esm/helpers/index.d.ts +20 -0
  128. package/dist/esm/helpers/index.js +207 -0
  129. package/dist/esm/index.d.ts +7 -0
  130. package/dist/esm/index.js +2611 -0
  131. package/dist/esm/styles/AppColors.d.ts +27 -0
  132. package/dist/esm/styles/AppColors.js +27 -0
  133. package/dist/esm/styles/AppFonts.d.ts +7 -0
  134. package/dist/esm/styles/AppFonts.js +7 -0
  135. package/dist/esm/styles/index.d.ts +1488 -0
  136. package/dist/esm/styles/index.js +1355 -0
  137. package/dist/esm/types/index.d.ts +127 -0
  138. package/dist/esm/types/index.js +1 -0
  139. package/fonts/Inter/Inter.ttc +0 -0
  140. package/fonts/Inter/InterVariable-Italic.ttf +0 -0
  141. package/fonts/Inter/InterVariable.ttf +0 -0
  142. package/fonts/Inter/LICENSE.txt +92 -0
  143. package/fonts/Inter/extras/otf/Inter-Black.otf +0 -0
  144. package/fonts/Inter/extras/otf/Inter-BlackItalic.otf +0 -0
  145. package/fonts/Inter/extras/otf/Inter-Bold.otf +0 -0
  146. package/fonts/Inter/extras/otf/Inter-BoldItalic.otf +0 -0
  147. package/fonts/Inter/extras/otf/Inter-ExtraBold.otf +0 -0
  148. package/fonts/Inter/extras/otf/Inter-ExtraBoldItalic.otf +0 -0
  149. package/fonts/Inter/extras/otf/Inter-ExtraLight.otf +0 -0
  150. package/fonts/Inter/extras/otf/Inter-ExtraLightItalic.otf +0 -0
  151. package/fonts/Inter/extras/otf/Inter-Italic.otf +0 -0
  152. package/fonts/Inter/extras/otf/Inter-Light.otf +0 -0
  153. package/fonts/Inter/extras/otf/Inter-LightItalic.otf +0 -0
  154. package/fonts/Inter/extras/otf/Inter-Medium.otf +0 -0
  155. package/fonts/Inter/extras/otf/Inter-MediumItalic.otf +0 -0
  156. package/fonts/Inter/extras/otf/Inter-Regular.otf +0 -0
  157. package/fonts/Inter/extras/otf/Inter-SemiBold.otf +0 -0
  158. package/fonts/Inter/extras/otf/Inter-SemiBoldItalic.otf +0 -0
  159. package/fonts/Inter/extras/otf/Inter-Thin.otf +0 -0
  160. package/fonts/Inter/extras/otf/Inter-ThinItalic.otf +0 -0
  161. package/fonts/Inter/extras/otf/InterDisplay-Black.otf +0 -0
  162. package/fonts/Inter/extras/otf/InterDisplay-BlackItalic.otf +0 -0
  163. package/fonts/Inter/extras/otf/InterDisplay-Bold.otf +0 -0
  164. package/fonts/Inter/extras/otf/InterDisplay-BoldItalic.otf +0 -0
  165. package/fonts/Inter/extras/otf/InterDisplay-ExtraBold.otf +0 -0
  166. package/fonts/Inter/extras/otf/InterDisplay-ExtraBoldItalic.otf +0 -0
  167. package/fonts/Inter/extras/otf/InterDisplay-ExtraLight.otf +0 -0
  168. package/fonts/Inter/extras/otf/InterDisplay-ExtraLightItalic.otf +0 -0
  169. package/fonts/Inter/extras/otf/InterDisplay-Italic.otf +0 -0
  170. package/fonts/Inter/extras/otf/InterDisplay-Light.otf +0 -0
  171. package/fonts/Inter/extras/otf/InterDisplay-LightItalic.otf +0 -0
  172. package/fonts/Inter/extras/otf/InterDisplay-Medium.otf +0 -0
  173. package/fonts/Inter/extras/otf/InterDisplay-MediumItalic.otf +0 -0
  174. package/fonts/Inter/extras/otf/InterDisplay-Regular.otf +0 -0
  175. package/fonts/Inter/extras/otf/InterDisplay-SemiBold.otf +0 -0
  176. package/fonts/Inter/extras/otf/InterDisplay-SemiBoldItalic.otf +0 -0
  177. package/fonts/Inter/extras/otf/InterDisplay-Thin.otf +0 -0
  178. package/fonts/Inter/extras/otf/InterDisplay-ThinItalic.otf +0 -0
  179. package/fonts/Inter/extras/ttf/Inter-Black.ttf +0 -0
  180. package/fonts/Inter/extras/ttf/Inter-BlackItalic.ttf +0 -0
  181. package/fonts/Inter/extras/ttf/Inter-Bold.ttf +0 -0
  182. package/fonts/Inter/extras/ttf/Inter-BoldItalic.ttf +0 -0
  183. package/fonts/Inter/extras/ttf/Inter-ExtraBold.ttf +0 -0
  184. package/fonts/Inter/extras/ttf/Inter-ExtraBoldItalic.ttf +0 -0
  185. package/fonts/Inter/extras/ttf/Inter-ExtraLight.ttf +0 -0
  186. package/fonts/Inter/extras/ttf/Inter-ExtraLightItalic.ttf +0 -0
  187. package/fonts/Inter/extras/ttf/Inter-Italic.ttf +0 -0
  188. package/fonts/Inter/extras/ttf/Inter-Light.ttf +0 -0
  189. package/fonts/Inter/extras/ttf/Inter-LightItalic.ttf +0 -0
  190. package/fonts/Inter/extras/ttf/Inter-Medium.ttf +0 -0
  191. package/fonts/Inter/extras/ttf/Inter-MediumItalic.ttf +0 -0
  192. package/fonts/Inter/extras/ttf/Inter-Regular.ttf +0 -0
  193. package/fonts/Inter/extras/ttf/Inter-SemiBold.ttf +0 -0
  194. package/fonts/Inter/extras/ttf/Inter-SemiBoldItalic.ttf +0 -0
  195. package/fonts/Inter/extras/ttf/Inter-Thin.ttf +0 -0
  196. package/fonts/Inter/extras/ttf/Inter-ThinItalic.ttf +0 -0
  197. package/fonts/Inter/extras/ttf/InterDisplay-Black.ttf +0 -0
  198. package/fonts/Inter/extras/ttf/InterDisplay-BlackItalic.ttf +0 -0
  199. package/fonts/Inter/extras/ttf/InterDisplay-Bold.ttf +0 -0
  200. package/fonts/Inter/extras/ttf/InterDisplay-BoldItalic.ttf +0 -0
  201. package/fonts/Inter/extras/ttf/InterDisplay-ExtraBold.ttf +0 -0
  202. package/fonts/Inter/extras/ttf/InterDisplay-ExtraBoldItalic.ttf +0 -0
  203. package/fonts/Inter/extras/ttf/InterDisplay-ExtraLight.ttf +0 -0
  204. package/fonts/Inter/extras/ttf/InterDisplay-ExtraLightItalic.ttf +0 -0
  205. package/fonts/Inter/extras/ttf/InterDisplay-Italic.ttf +0 -0
  206. package/fonts/Inter/extras/ttf/InterDisplay-Light.ttf +0 -0
  207. package/fonts/Inter/extras/ttf/InterDisplay-LightItalic.ttf +0 -0
  208. package/fonts/Inter/extras/ttf/InterDisplay-Medium.ttf +0 -0
  209. package/fonts/Inter/extras/ttf/InterDisplay-MediumItalic.ttf +0 -0
  210. package/fonts/Inter/extras/ttf/InterDisplay-Regular.ttf +0 -0
  211. package/fonts/Inter/extras/ttf/InterDisplay-SemiBold.ttf +0 -0
  212. package/fonts/Inter/extras/ttf/InterDisplay-SemiBoldItalic.ttf +0 -0
  213. package/fonts/Inter/extras/ttf/InterDisplay-Thin.ttf +0 -0
  214. package/fonts/Inter/extras/ttf/InterDisplay-ThinItalic.ttf +0 -0
  215. package/fonts/Inter/extras/woff-hinted/Inter-Black.woff2 +0 -0
  216. package/fonts/Inter/extras/woff-hinted/Inter-BlackItalic.woff2 +0 -0
  217. package/fonts/Inter/extras/woff-hinted/Inter-Bold.woff2 +0 -0
  218. package/fonts/Inter/extras/woff-hinted/Inter-BoldItalic.woff2 +0 -0
  219. package/fonts/Inter/extras/woff-hinted/Inter-ExtraBold.woff2 +0 -0
  220. package/fonts/Inter/extras/woff-hinted/Inter-ExtraBoldItalic.woff2 +0 -0
  221. package/fonts/Inter/extras/woff-hinted/Inter-ExtraLight.woff2 +0 -0
  222. package/fonts/Inter/extras/woff-hinted/Inter-ExtraLightItalic.woff2 +0 -0
  223. package/fonts/Inter/extras/woff-hinted/Inter-Italic.woff2 +0 -0
  224. package/fonts/Inter/extras/woff-hinted/Inter-Light.woff2 +0 -0
  225. package/fonts/Inter/extras/woff-hinted/Inter-LightItalic.woff2 +0 -0
  226. package/fonts/Inter/extras/woff-hinted/Inter-Medium.woff2 +0 -0
  227. package/fonts/Inter/extras/woff-hinted/Inter-MediumItalic.woff2 +0 -0
  228. package/fonts/Inter/extras/woff-hinted/Inter-Regular.woff2 +0 -0
  229. package/fonts/Inter/extras/woff-hinted/Inter-SemiBold.woff2 +0 -0
  230. package/fonts/Inter/extras/woff-hinted/Inter-SemiBoldItalic.woff2 +0 -0
  231. package/fonts/Inter/extras/woff-hinted/Inter-Thin.woff2 +0 -0
  232. package/fonts/Inter/extras/woff-hinted/Inter-ThinItalic.woff2 +0 -0
  233. package/fonts/Inter/extras/woff-hinted/InterDisplay-Black.woff2 +0 -0
  234. package/fonts/Inter/extras/woff-hinted/InterDisplay-BlackItalic.woff2 +0 -0
  235. package/fonts/Inter/extras/woff-hinted/InterDisplay-Bold.woff2 +0 -0
  236. package/fonts/Inter/extras/woff-hinted/InterDisplay-BoldItalic.woff2 +0 -0
  237. package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraBold.woff2 +0 -0
  238. package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraBoldItalic.woff2 +0 -0
  239. package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraLight.woff2 +0 -0
  240. package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraLightItalic.woff2 +0 -0
  241. package/fonts/Inter/extras/woff-hinted/InterDisplay-Italic.woff2 +0 -0
  242. package/fonts/Inter/extras/woff-hinted/InterDisplay-Light.woff2 +0 -0
  243. package/fonts/Inter/extras/woff-hinted/InterDisplay-LightItalic.woff2 +0 -0
  244. package/fonts/Inter/extras/woff-hinted/InterDisplay-Medium.woff2 +0 -0
  245. package/fonts/Inter/extras/woff-hinted/InterDisplay-MediumItalic.woff2 +0 -0
  246. package/fonts/Inter/extras/woff-hinted/InterDisplay-Regular.woff2 +0 -0
  247. package/fonts/Inter/extras/woff-hinted/InterDisplay-SemiBold.woff2 +0 -0
  248. package/fonts/Inter/extras/woff-hinted/InterDisplay-SemiBoldItalic.woff2 +0 -0
  249. package/fonts/Inter/extras/woff-hinted/InterDisplay-Thin.woff2 +0 -0
  250. package/fonts/Inter/extras/woff-hinted/InterDisplay-ThinItalic.woff2 +0 -0
  251. package/fonts/Inter/help.txt +165 -0
  252. package/fonts/Inter/web/Inter-Black.woff2 +0 -0
  253. package/fonts/Inter/web/Inter-BlackItalic.woff2 +0 -0
  254. package/fonts/Inter/web/Inter-Bold.woff2 +0 -0
  255. package/fonts/Inter/web/Inter-BoldItalic.woff2 +0 -0
  256. package/fonts/Inter/web/Inter-ExtraBold.woff2 +0 -0
  257. package/fonts/Inter/web/Inter-ExtraBoldItalic.woff2 +0 -0
  258. package/fonts/Inter/web/Inter-ExtraLight.woff2 +0 -0
  259. package/fonts/Inter/web/Inter-ExtraLightItalic.woff2 +0 -0
  260. package/fonts/Inter/web/Inter-Italic.woff2 +0 -0
  261. package/fonts/Inter/web/Inter-Light.woff2 +0 -0
  262. package/fonts/Inter/web/Inter-LightItalic.woff2 +0 -0
  263. package/fonts/Inter/web/Inter-Medium.woff2 +0 -0
  264. package/fonts/Inter/web/Inter-MediumItalic.woff2 +0 -0
  265. package/fonts/Inter/web/Inter-Regular.woff2 +0 -0
  266. package/fonts/Inter/web/Inter-SemiBold.woff2 +0 -0
  267. package/fonts/Inter/web/Inter-SemiBoldItalic.woff2 +0 -0
  268. package/fonts/Inter/web/Inter-Thin.woff2 +0 -0
  269. package/fonts/Inter/web/Inter-ThinItalic.woff2 +0 -0
  270. package/fonts/Inter/web/InterDisplay-Black.woff2 +0 -0
  271. package/fonts/Inter/web/InterDisplay-BlackItalic.woff2 +0 -0
  272. package/fonts/Inter/web/InterDisplay-Bold.woff2 +0 -0
  273. package/fonts/Inter/web/InterDisplay-BoldItalic.woff2 +0 -0
  274. package/fonts/Inter/web/InterDisplay-ExtraBold.woff2 +0 -0
  275. package/fonts/Inter/web/InterDisplay-ExtraBoldItalic.woff2 +0 -0
  276. package/fonts/Inter/web/InterDisplay-ExtraLight.woff2 +0 -0
  277. package/fonts/Inter/web/InterDisplay-ExtraLightItalic.woff2 +0 -0
  278. package/fonts/Inter/web/InterDisplay-Italic.woff2 +0 -0
  279. package/fonts/Inter/web/InterDisplay-Light.woff2 +0 -0
  280. package/fonts/Inter/web/InterDisplay-LightItalic.woff2 +0 -0
  281. package/fonts/Inter/web/InterDisplay-Medium.woff2 +0 -0
  282. package/fonts/Inter/web/InterDisplay-MediumItalic.woff2 +0 -0
  283. package/fonts/Inter/web/InterDisplay-Regular.woff2 +0 -0
  284. package/fonts/Inter/web/InterDisplay-SemiBold.woff2 +0 -0
  285. package/fonts/Inter/web/InterDisplay-SemiBoldItalic.woff2 +0 -0
  286. package/fonts/Inter/web/InterDisplay-Thin.woff2 +0 -0
  287. package/fonts/Inter/web/InterDisplay-ThinItalic.woff2 +0 -0
  288. package/fonts/Inter/web/InterVariable-Italic.woff2 +0 -0
  289. package/fonts/Inter/web/InterVariable.woff2 +0 -0
  290. package/fonts/Inter/web/inter.css +148 -0
  291. package/package.json +52 -0
@@ -0,0 +1,2668 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.subscribeWebView = exports.clearWebViewData = exports.getWebViewHtmlUrl = exports.getWebViewJs = exports.getWebViewCss = exports.getWebViewHtml = exports.getWebViewNavHistory = exports.getWebViewLogs = exports.clearAnalyticsEvents = exports.subscribeAnalyticsEvents = exports.logAnalyticsEvent = exports.setupAnalyticsLogger = exports.subscribeConsoleLogs = exports.clearConsoleLogs = exports.setupConsoleLogger = exports.subscribeNetworkLogs = exports.clearNetworkLogs = exports.setupNetworkLogger = void 0;
40
+ const react_1 = __importStar(require("react"));
41
+ const react_native_1 = require("react-native");
42
+ const react_native_svg_1 = __importStar(require("react-native-svg"));
43
+ const react_native_linear_gradient_1 = __importDefault(require("react-native-linear-gradient"));
44
+ const native_1 = require("@react-navigation/native");
45
+ // Components
46
+ const TouchableScale_1 = __importDefault(require("./components/TouchableScale"));
47
+ const useAccordion_1 = __importDefault(require("./customHooks/useAccordion"));
48
+ const MetaAccordion_1 = __importDefault(require("./components/MetaAccordion"));
49
+ const CopyButton_1 = __importDefault(require("./components/CopyButton"));
50
+ const MiniBarChart_1 = __importDefault(require("./components/MiniBarChart"));
51
+ const MiniLineChart_1 = __importDefault(require("./components/MiniLineChart"));
52
+ const SectionHeader_1 = __importDefault(require("./components/SectionHeader"));
53
+ const EmptyState_1 = __importDefault(require("./components/EmptyState"));
54
+ const JsonViewer_1 = __importDefault(require("./components/JsonViewer"));
55
+ const DomainHeader_1 = __importDefault(require("./components/DomainHeader"));
56
+ const DiffViewer_1 = __importDefault(require("./components/DiffViewer"));
57
+ const LogCard_1 = __importDefault(require("./components/LogCard"));
58
+ const HeadersSection_1 = __importDefault(require("./components/HeadersSection"));
59
+ const SourcePageCard_1 = __importDefault(require("./components/SourcePageCard"));
60
+ const ConsoleLogCard_1 = require("./components/ConsoleLogCard");
61
+ const HighlightText_1 = __importDefault(require("./components/HighlightText"));
62
+ const CodeSnippet_1 = __importDefault(require("./components/CodeSnippet"));
63
+ // Helpers
64
+ const helpers_1 = require("./helpers");
65
+ // Assets
66
+ const NetworkIcons_1 = require("./components/NetworkIcons");
67
+ // Stylesheet
68
+ const AppColors_1 = require("./styles/AppColors");
69
+ const AppFonts_1 = require("./styles/AppFonts");
70
+ const styles_1 = __importDefault(require("./styles"));
71
+ // Network
72
+ const networkLogger_1 = require("./customHooks/networkLogger");
73
+ // Console
74
+ const consoleLogger_1 = require("./customHooks/consoleLogger");
75
+ const logFilters_1 = require("./customHooks/logFilters");
76
+ const analyticsLogger_1 = require("./customHooks/analyticsLogger");
77
+ const AnalyticsEventCard_1 = __importStar(require("./components/AnalyticsEventCard"));
78
+ const AnalyticsDetail_1 = __importDefault(require("./components/AnalyticsDetail"));
79
+ // WebView
80
+ const webViewLogger_1 = require("./customHooks/webViewLogger");
81
+ const constants_1 = require("./constants");
82
+ const NetworkInspector = () => {
83
+ const [logs, setLogs] = (0, react_1.useState)([]);
84
+ const [visible, setVisible] = (0, react_1.useState)(false);
85
+ const [isReady, setIsReady] = (0, react_1.useState)(false);
86
+ const [selected, setSelected] = (0, react_1.useState)(null);
87
+ const [selectedLogs, setSelectedLogs] = (0, react_1.useState)(new Set());
88
+ const [search, setSearch] = (0, react_1.useState)('');
89
+ const [detailSearch, setDetailSearch] = (0, react_1.useState)('');
90
+ const [statusFilters, setStatusFilters] = (0, react_1.useState)(new Set());
91
+ const [methodFilters, setMethodFilters] = (0, react_1.useState)(new Set());
92
+ const [sectionFilters, setSectionFilters] = (0, react_1.useState)({});
93
+ const [collapsedSections, setCollapsedSections] = (0, react_1.useState)(new Set());
94
+ const [showNetworkMenu, setShowNetworkMenu] = (0, react_1.useState)(false);
95
+ const [showUiMenu, setShowUiMenu] = (0, react_1.useState)(false);
96
+ const [sortOrder, setSortOrder] = (0, react_1.useState)('newest');
97
+ const [reqExpanded, setReqExpanded] = (0, react_1.useState)(undefined);
98
+ const [resExpanded, setResExpanded] = (0, react_1.useState)(undefined);
99
+ const [showReqDiff, setShowReqDiff] = (0, react_1.useState)(false);
100
+ const [showResDiff, setShowResDiff] = (0, react_1.useState)(false);
101
+ const filtersAccordion = (0, useAccordion_1.default)(false, 300, 260);
102
+ // ─── Analytics state ───────────────────────────────────────────────────────
103
+ const [activeTab, setActiveTab] = (0, react_1.useState)('apis');
104
+ const [analyticsEvents, setAnalyticsEvents] = (0, react_1.useState)([]);
105
+ // ─── Logs state ────────────────────────────────────────────────────────────
106
+ const [consoleLogs, setConsoleLogs] = (0, react_1.useState)([]);
107
+ const visibleConsoleLogs = (0, react_1.useMemo)(() => {
108
+ return consoleLogs.filter(log => {
109
+ const type = log.type;
110
+ const message = log.message || '';
111
+ const allPrefixes = [
112
+ ...((logFilters_1.IGNORED_LOG_PREFIXES && logFilters_1.IGNORED_LOG_PREFIXES.info) || []),
113
+ ...((logFilters_1.IGNORED_LOG_PREFIXES && logFilters_1.IGNORED_LOG_PREFIXES.warn) || []),
114
+ ...((logFilters_1.IGNORED_LOG_PREFIXES && logFilters_1.IGNORED_LOG_PREFIXES.error) || []),
115
+ ].filter(p => typeof p === 'string' && p.trim().length > 0);
116
+ const isIgnored = allPrefixes.some(prefix => message
117
+ .toLowerCase()
118
+ .trim()
119
+ .startsWith(prefix.toLowerCase().trim()) ||
120
+ message.toLowerCase().trim().includes(prefix.toLowerCase().trim()));
121
+ return !isIgnored;
122
+ });
123
+ }, [consoleLogs]);
124
+ const [logSearch, setLogSearch] = (0, react_1.useState)('');
125
+ const [logFilters, setLogFilters] = (0, react_1.useState)(new Set(['user-log']));
126
+ // ─── WebView state ─────────────────────────────────────────────────────────
127
+ const [webViewLogs, setWebViewLogs] = (0, react_1.useState)([]);
128
+ const [webViewNavHistory, setWebViewNavHistory] = (0, react_1.useState)([]);
129
+ const [webViewSubTab, setWebViewSubTab] = (0, react_1.useState)('html');
130
+ const [webViewSearch, setWebViewSearch] = (0, react_1.useState)('');
131
+ const [htmlSearch, setHtmlSearch] = (0, react_1.useState)('');
132
+ const [cssSearch, setCssSearch] = (0, react_1.useState)('');
133
+ const [jsSearch, setJsSearch] = (0, react_1.useState)('');
134
+ const [webViewHtml, setWebViewHtml] = (0, react_1.useState)('');
135
+ const [webViewCss, setWebViewCss] = (0, react_1.useState)('');
136
+ const [webViewJs, setWebViewJs] = (0, react_1.useState)('');
137
+ const [webViewHtmlUrl, setWebViewHtmlUrl] = (0, react_1.useState)('');
138
+ const [htmlSubTab, setHtmlSubTab] = (0, react_1.useState)('html');
139
+ const [selectedEvent, setSelectedEvent] = (0, react_1.useState)(null);
140
+ const [analyticsSearch, setAnalyticsSearch] = (0, react_1.useState)('');
141
+ const [hideScreenView, setHideScreenView] = (0, react_1.useState)(true);
142
+ const [analyticsSubTab, setAnalyticsSubTab] = (0, react_1.useState)('ga_events');
143
+ const [groupByScreen, setGroupByScreen] = (0, react_1.useState)(false);
144
+ const [expandedScreens, setExpandedScreens] = (0, react_1.useState)(new Set());
145
+ const [topEventsExpanded, setTopEventsExpanded] = (0, react_1.useState)(true);
146
+ const [newEventIds, setNewEventIds] = (0, react_1.useState)(new Set());
147
+ const prevEventIdsRef = (0, react_1.useRef)(new Set());
148
+ const navState = (0, native_1.useNavigationState)(state => state);
149
+ const currentRouteRef = (0, react_1.useRef)({
150
+ path: 'Navigators',
151
+ params: null,
152
+ });
153
+ (0, react_1.useEffect)(() => {
154
+ currentRouteRef.current = (0, helpers_1.getNavigationInfo)(navState);
155
+ }, [navState]);
156
+ const logRouteMapRef = (0, react_1.useRef)(new Map());
157
+ const prevLogIdsRef = (0, react_1.useRef)(new Set());
158
+ const [newLogIds, setNewLogIds] = (0, react_1.useState)(new Set());
159
+ const pulseAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
160
+ const badgeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
161
+ (0, react_1.useEffect)(() => {
162
+ const loop = react_native_1.Animated.loop(react_native_1.Animated.sequence([
163
+ react_native_1.Animated.timing(pulseAnim, {
164
+ toValue: 1.2,
165
+ duration: 800,
166
+ useNativeDriver: true,
167
+ }),
168
+ react_native_1.Animated.timing(pulseAnim, {
169
+ toValue: 1,
170
+ duration: 800,
171
+ useNativeDriver: true,
172
+ }),
173
+ ]));
174
+ loop.start();
175
+ return () => loop.stop();
176
+ }, [pulseAnim]);
177
+ (0, react_1.useEffect)(() => {
178
+ if ((logs.length > 0 || analyticsEvents.length > 0) && newLogIds.size > 0) {
179
+ badgeAnim.setValue(0.8);
180
+ react_native_1.Animated.spring(badgeAnim, {
181
+ toValue: 1,
182
+ tension: 300,
183
+ friction: 10,
184
+ useNativeDriver: true,
185
+ }).start();
186
+ }
187
+ }, [newLogIds]);
188
+ (0, react_1.useEffect)(() => {
189
+ if (visible) {
190
+ const task = react_native_1.InteractionManager.runAfterInteractions(() => {
191
+ setIsReady(true);
192
+ });
193
+ return () => task.cancel();
194
+ }
195
+ else {
196
+ setIsReady(false);
197
+ setSelectedLogs(new Set());
198
+ }
199
+ }, [visible]);
200
+ (0, react_1.useEffect)(() => {
201
+ (0, networkLogger_1.setupNetworkLogger)();
202
+ (0, networkLogger_1.clearNetworkLogs)();
203
+ (0, consoleLogger_1.setupConsoleLogger)();
204
+ // Note: setupAnalyticsLogger(analytics()) is called by the consumer at app startup
205
+ let timeoutId;
206
+ const unsubscribe = (0, networkLogger_1.subscribeNetworkLogs)((raw) => {
207
+ clearTimeout(timeoutId);
208
+ timeoutId = setTimeout(() => {
209
+ const deduped = (0, helpers_1.deduplicateLogs)(raw);
210
+ const incoming = new Set(deduped.map(l => l.id));
211
+ const freshIds = new Set();
212
+ incoming.forEach(id => {
213
+ if (!prevLogIdsRef.current.has(id))
214
+ freshIds.add(id);
215
+ });
216
+ prevLogIdsRef.current = incoming;
217
+ if (freshIds.size > 0) {
218
+ freshIds.forEach(id => {
219
+ if (!logRouteMapRef.current.has(id)) {
220
+ logRouteMapRef.current.set(id, currentRouteRef.current);
221
+ }
222
+ });
223
+ setNewLogIds(freshIds);
224
+ setTimeout(() => setNewLogIds(new Set()), 1200);
225
+ }
226
+ setLogs(deduped);
227
+ }, 250);
228
+ });
229
+ // ─── Analytics subscription ──────────────────────────────────────────────
230
+ let analyticsTimeoutId;
231
+ const unsubscribeAnalytics = (0, analyticsLogger_1.subscribeAnalyticsEvents)((raw) => {
232
+ clearTimeout(analyticsTimeoutId);
233
+ analyticsTimeoutId = setTimeout(() => {
234
+ const incoming = new Set(raw.map(e => e.id));
235
+ const freshIds = new Set();
236
+ incoming.forEach(id => {
237
+ if (!prevEventIdsRef.current.has(id))
238
+ freshIds.add(id);
239
+ });
240
+ prevEventIdsRef.current = incoming;
241
+ if (freshIds.size > 0) {
242
+ freshIds.forEach(id => {
243
+ if (!logRouteMapRef.current.has(id + 1000000)) {
244
+ logRouteMapRef.current.set(id + 1000000, currentRouteRef.current);
245
+ }
246
+ });
247
+ setNewEventIds(freshIds);
248
+ setTimeout(() => setNewEventIds(new Set()), 1200);
249
+ }
250
+ setAnalyticsEvents(raw);
251
+ }, 200);
252
+ });
253
+ // ─── Console subscription ────────────────────────────────────────────────
254
+ let consoleTimeoutId;
255
+ const unsubscribeConsole = (0, consoleLogger_1.subscribeConsoleLogs)((raw) => {
256
+ clearTimeout(consoleTimeoutId);
257
+ consoleTimeoutId = setTimeout(() => {
258
+ setConsoleLogs(raw);
259
+ }, 200);
260
+ });
261
+ setWebViewLogs((0, webViewLogger_1.getWebViewLogs)());
262
+ setWebViewNavHistory((0, webViewLogger_1.getWebViewNavHistory)());
263
+ setWebViewHtml((0, webViewLogger_1.getWebViewHtml)());
264
+ setWebViewCss((0, webViewLogger_1.getWebViewCss)());
265
+ setWebViewJs((0, webViewLogger_1.getWebViewJs)());
266
+ setWebViewHtmlUrl((0, webViewLogger_1.getWebViewHtmlUrl)());
267
+ // ─── WebView subscription ────────────────────────────────────────────────
268
+ let webViewTimeoutId;
269
+ const unsubscribeWebView = (0, webViewLogger_1.subscribeWebView)(() => {
270
+ clearTimeout(webViewTimeoutId);
271
+ webViewTimeoutId = setTimeout(() => {
272
+ setWebViewLogs((0, webViewLogger_1.getWebViewLogs)());
273
+ setWebViewNavHistory((0, webViewLogger_1.getWebViewNavHistory)());
274
+ setWebViewHtml((0, webViewLogger_1.getWebViewHtml)());
275
+ setWebViewCss((0, webViewLogger_1.getWebViewCss)());
276
+ setWebViewJs((0, webViewLogger_1.getWebViewJs)());
277
+ setWebViewHtmlUrl((0, webViewLogger_1.getWebViewHtmlUrl)());
278
+ }, 200);
279
+ });
280
+ return () => {
281
+ unsubscribe();
282
+ clearTimeout(timeoutId);
283
+ unsubscribeAnalytics();
284
+ clearTimeout(analyticsTimeoutId);
285
+ unsubscribeConsole();
286
+ clearTimeout(consoleTimeoutId);
287
+ unsubscribeWebView();
288
+ clearTimeout(webViewTimeoutId);
289
+ };
290
+ }, []);
291
+ (0, react_1.useEffect)(() => {
292
+ setReqExpanded(undefined);
293
+ setResExpanded(undefined);
294
+ setShowReqDiff(false);
295
+ setShowResDiff(false);
296
+ setDetailSearch('');
297
+ }, [selected]);
298
+ const filteredLogs = (0, react_1.useMemo)(() => {
299
+ let result = logs.filter(log => {
300
+ // Status Filter Check
301
+ if (statusFilters.size > 0) {
302
+ const matched = [...statusFilters].some(f => {
303
+ if (f === 'ALL')
304
+ return true;
305
+ if (f === 'Failed')
306
+ return log.status === 0 || log.status == null;
307
+ return String(log.status)[0] === f[0];
308
+ });
309
+ if (!matched)
310
+ return false;
311
+ }
312
+ // Method Filter Check
313
+ if (methodFilters.size > 0) {
314
+ const matchedMethod = [...methodFilters].some(m => {
315
+ if (m === 'ALL')
316
+ return true;
317
+ return log.method?.toUpperCase() === m;
318
+ });
319
+ if (!matchedMethod)
320
+ return false;
321
+ }
322
+ // Search Bar Check
323
+ if (search && !log.url?.toLowerCase().includes(search.toLowerCase()))
324
+ return false;
325
+ return true;
326
+ });
327
+ if (sortOrder === 'oldest') {
328
+ result = [...result].reverse();
329
+ }
330
+ return result;
331
+ }, [logs, search, statusFilters, methodFilters, sortOrder]);
332
+ const availableMethods = (0, react_1.useMemo)(() => {
333
+ const methods = new Set();
334
+ logs.forEach(log => {
335
+ if (log.method)
336
+ methods.add(log.method.toUpperCase());
337
+ });
338
+ return ['ALL', ...Array.from(methods)];
339
+ }, [logs]);
340
+ const toggleSectionFilter = (0, react_1.useCallback)((pageName, filter) => {
341
+ setSectionFilters(prev => {
342
+ const current = prev[pageName] || new Set(['success', 'failed', 'loading']);
343
+ const next = new Set(current);
344
+ if (next.has(filter)) {
345
+ next.delete(filter);
346
+ }
347
+ else {
348
+ next.add(filter);
349
+ }
350
+ return { ...prev, [pageName]: next };
351
+ });
352
+ }, []);
353
+ const toggleSectionCollapse = (0, react_1.useCallback)((pageName) => {
354
+ setCollapsedSections(prev => {
355
+ const next = new Set(prev);
356
+ if (next.has(pageName))
357
+ next.delete(pageName);
358
+ else
359
+ next.add(pageName);
360
+ return next;
361
+ });
362
+ }, []);
363
+ const groupedData = (0, react_1.useMemo)(() => {
364
+ const result = [];
365
+ const groups = [];
366
+ for (let i = 0; i < filteredLogs.length; i++) {
367
+ const log = filteredLogs[i];
368
+ const routeInfo = logRouteMapRef.current.get(log.id);
369
+ const pageName = routeInfo?.path || 'Navigators';
370
+ if (groups.length === 0 ||
371
+ groups[groups.length - 1].pageName !== pageName) {
372
+ groups.push({ pageName, color: (0, helpers_1.getDomainColor)(pageName), logs: [] });
373
+ }
374
+ groups[groups.length - 1].logs.push(log);
375
+ }
376
+ groups.forEach((g, idx) => {
377
+ let success = 0;
378
+ let failed = 0;
379
+ let loading = 0;
380
+ g.logs.forEach(l => {
381
+ if (l.status == null)
382
+ loading++;
383
+ else if (l.status === 0 || l.status >= 400)
384
+ failed++;
385
+ else
386
+ success++;
387
+ });
388
+ const activeFilters = sectionFilters[g.pageName] || new Set(['success', 'failed', 'loading']);
389
+ const isCollapsed = collapsedSections.has(g.pageName);
390
+ const timestamp = g.logs[0]?.startTime || 0;
391
+ result.push({
392
+ type: 'header',
393
+ id: `hdr-${g.logs[0]?.id || 'empty'}-${g.pageName}`,
394
+ pageName: g.pageName,
395
+ color: g.color,
396
+ stats: { success, failed, loading },
397
+ timestamp,
398
+ activeFilters,
399
+ isCollapsed,
400
+ isFirst: idx === 0,
401
+ });
402
+ if (!isCollapsed) {
403
+ const displayLogs = g.logs.filter(l => {
404
+ if (l.status == null)
405
+ return activeFilters.has('loading');
406
+ if (l.status === 0 || l.status >= 400)
407
+ return activeFilters.has('failed');
408
+ return activeFilters.has('success');
409
+ });
410
+ displayLogs.forEach((log, index) => {
411
+ result.push({
412
+ type: 'log',
413
+ id: log.id,
414
+ log,
415
+ isLast: index === displayLogs.length - 1,
416
+ color: g.color,
417
+ });
418
+ });
419
+ }
420
+ });
421
+ return result;
422
+ }, [filteredLogs, logs, sectionFilters, collapsedSections]);
423
+ const stats = (0, react_1.useMemo)(() => {
424
+ const total = logs.length;
425
+ const errors = filteredLogs.filter(l => (l.status != null && l.status >= 400) || l.status === 0).length;
426
+ const durations = filteredLogs
427
+ .filter(l => l.duration != null)
428
+ .map(l => l.duration);
429
+ const avgDuration = durations.length > 0
430
+ ? Math.round(durations.reduce((a, b) => a + b, 0) / durations.length)
431
+ : null;
432
+ const totalBytes = filteredLogs.reduce((acc, log) => {
433
+ const resSize = log.response
434
+ ? JSON.stringify(log.response)?.length || 0
435
+ : 0;
436
+ return acc + resSize;
437
+ }, 0);
438
+ const size = totalBytes < 1024
439
+ ? `${totalBytes} B`
440
+ : totalBytes < 1048576
441
+ ? `${(totalBytes / 1024).toFixed(1)} KB`
442
+ : `${(totalBytes / 1048576).toFixed(1)} MB`;
443
+ const recentLogs = [...filteredLogs].slice(0, 10).reverse();
444
+ const durationTrend = recentLogs.map(l => l.duration || 0);
445
+ const sizeTrend = recentLogs.map(l => JSON.stringify(l.response)?.length || 0);
446
+ const errorTrend = recentLogs.map(l => l.status === 0 || (l.status && l.status >= 400) ? 1 : 0);
447
+ const reqTrend = recentLogs.map(() => Math.random() * 5 + 5);
448
+ return {
449
+ total,
450
+ errors,
451
+ avgDuration,
452
+ filtered: filteredLogs.length,
453
+ size,
454
+ durationTrend,
455
+ sizeTrend,
456
+ errorTrend,
457
+ reqTrend,
458
+ };
459
+ }, [logs, filteredLogs]);
460
+ const hasErrors = (0, react_1.useMemo)(() => logs.some(l => (l.status != null && l.status >= 400) || l.status === 0), [logs]);
461
+ const { minStart, totalRange } = (0, react_1.useMemo)(() => {
462
+ if (filteredLogs.length === 0)
463
+ return { minStart: 0, totalRange: 0 };
464
+ const min = Math.min(...filteredLogs.map(l => l.startTime));
465
+ const max = Math.max(...filteredLogs.map(l => l.startTime + (l.duration || 10)));
466
+ return { minStart: min, totalRange: max - min };
467
+ }, [filteredLogs]);
468
+ const prevSameRequest = (0, react_1.useMemo)(() => {
469
+ if (!selected)
470
+ return null;
471
+ const index = logs.findIndex(l => l.id === selected.id);
472
+ if (index === -1)
473
+ return null;
474
+ for (let i = index + 1; i < logs.length; i++) {
475
+ const l = logs[i];
476
+ if (l.url === selected.url && l.method === selected.method) {
477
+ return l;
478
+ }
479
+ }
480
+ return null;
481
+ }, [selected, logs]);
482
+ const prevRequestData = prevSameRequest ? prevSameRequest.request : null;
483
+ const prevResponseData = prevSameRequest ? prevSameRequest.response : null;
484
+ const filteredAnalyticsEvents = (0, react_1.useMemo)(() => {
485
+ let events = analyticsEvents;
486
+ if (hideScreenView) {
487
+ events = events.filter(e => e.name !== 'screen_view');
488
+ }
489
+ if (analyticsSearch) {
490
+ const s = analyticsSearch.toLowerCase();
491
+ events = events.filter(e => e.name.toLowerCase().includes(s) ||
492
+ JSON.stringify(e.params).toLowerCase().includes(s) ||
493
+ (e.pageTitle ?? '').toLowerCase().includes(s));
494
+ }
495
+ const deduplicatedEvents = [];
496
+ for (const e of events) {
497
+ if (deduplicatedEvents.length === 0) {
498
+ deduplicatedEvents.push({ ...e, count: 1 });
499
+ continue;
500
+ }
501
+ const last = deduplicatedEvents[deduplicatedEvents.length - 1];
502
+ if (last.name === e.name &&
503
+ JSON.stringify(last.params) === JSON.stringify(e.params) &&
504
+ JSON.stringify(last.userProperties) === JSON.stringify(e.userProperties)) {
505
+ last.count = (last.count || 1) + 1;
506
+ // Point to the newest timestamp and id
507
+ last.timestamp = e.timestamp;
508
+ last.id = e.id;
509
+ }
510
+ else {
511
+ deduplicatedEvents.push({ ...e, count: 1 });
512
+ }
513
+ }
514
+ return deduplicatedEvents;
515
+ }, [analyticsEvents, analyticsSearch, hideScreenView]);
516
+ const filteredConsoleLogs = (0, react_1.useMemo)(() => {
517
+ let result = visibleConsoleLogs;
518
+ // Filters check
519
+ if (logFilters.size > 0 && !logFilters.has('all')) {
520
+ result = result.filter(log => {
521
+ if (logFilters.has(log.type))
522
+ return true;
523
+ if (logFilters.has('user-log') && log.sourceMethod === 'log')
524
+ return true;
525
+ if (logFilters.has('analytics') &&
526
+ log.message.toLowerCase().includes('[analytics error]'))
527
+ return true;
528
+ return false;
529
+ });
530
+ }
531
+ // Search bar check
532
+ if (logSearch) {
533
+ const s = logSearch.toLowerCase();
534
+ result = result.filter(log => log.message.toLowerCase().includes(s) ||
535
+ (log.caller ?? '').toLowerCase().includes(s));
536
+ }
537
+ return result;
538
+ }, [visibleConsoleLogs, logFilters, logSearch]);
539
+ const filteredWebViewLogs = (0, react_1.useMemo)(() => {
540
+ let result = webViewLogs;
541
+ if (webViewSearch) {
542
+ const s = webViewSearch.toLowerCase();
543
+ result = result.filter(log => log.message.toLowerCase().includes(s));
544
+ }
545
+ return result;
546
+ }, [webViewLogs, webViewSearch]);
547
+ const filteredNavHistory = (0, react_1.useMemo)(() => {
548
+ let result = webViewNavHistory;
549
+ if (webViewSearch) {
550
+ const s = webViewSearch.toLowerCase();
551
+ result = result.filter(nav => nav.url.toLowerCase().includes(s) ||
552
+ (nav.title ?? '').toLowerCase().includes(s));
553
+ }
554
+ return result;
555
+ }, [webViewNavHistory, webViewSearch]);
556
+ const logCounts = (0, react_1.useMemo)(() => {
557
+ let searchedLogs = visibleConsoleLogs;
558
+ if (logSearch) {
559
+ const s = logSearch.toLowerCase();
560
+ searchedLogs = visibleConsoleLogs.filter(log => log.message.toLowerCase().includes(s) ||
561
+ (log.caller ?? '').toLowerCase().includes(s));
562
+ }
563
+ const total = visibleConsoleLogs.length;
564
+ return {
565
+ all: `${searchedLogs.length}/${total}`,
566
+ info: `${searchedLogs.filter(l => l.type === 'info').length}/${total}`,
567
+ warn: `${searchedLogs.filter(l => l.type === 'warn').length}/${total}`,
568
+ error: `${searchedLogs.filter(l => l.type === 'error').length}/${total}`,
569
+ 'user-log': `${searchedLogs.filter(l => l.sourceMethod === 'log').length}/${total}`,
570
+ analytics: `${searchedLogs.filter(l => l.message.toLowerCase().includes('[analytics error]')).length}/${total}`,
571
+ };
572
+ }, [visibleConsoleLogs, logSearch]);
573
+ const groupedAnalyticsEvents = (0, react_1.useMemo)(() => {
574
+ if (!groupByScreen)
575
+ return [];
576
+ const map = new Map();
577
+ for (const e of filteredAnalyticsEvents) {
578
+ const routeInfo = logRouteMapRef.current.get(e.id + 1000000);
579
+ let screenName = e.screenName ||
580
+ e.screenClass ||
581
+ e.pageTitle ||
582
+ e.pageLocation ||
583
+ e.params?.firebase_screen ||
584
+ e.params?.screen_name ||
585
+ e.params?.firebase_screen_class ||
586
+ e.params?.screen_class;
587
+ if (!screenName) {
588
+ if (routeInfo && routeInfo.path !== 'Navigators') {
589
+ const parts = routeInfo.path.split(' ➔ ');
590
+ screenName = parts[parts.length - 1];
591
+ }
592
+ else {
593
+ screenName = 'Unknown Component';
594
+ }
595
+ }
596
+ if (!map.has(screenName))
597
+ map.set(screenName, []);
598
+ map.get(screenName).push(e);
599
+ }
600
+ const sections = [];
601
+ for (const [title, data] of map.entries()) {
602
+ sections.push({ title, data });
603
+ }
604
+ return sections;
605
+ }, [groupByScreen, filteredAnalyticsEvents]);
606
+ const topEventsArray = (0, react_1.useMemo)(() => {
607
+ const freq = {};
608
+ filteredAnalyticsEvents.forEach(e => {
609
+ if (e.name === 'screen_view')
610
+ return;
611
+ freq[e.name] = (freq[e.name] || 0) + 1;
612
+ });
613
+ return Object.entries(freq).sort((a, b) => b[1] - a[1]);
614
+ }, [filteredAnalyticsEvents]);
615
+ const groupedNetworkLogs = (0, react_1.useMemo)(() => {
616
+ if (!groupByScreen)
617
+ return [];
618
+ const map = new Map();
619
+ for (const l of filteredLogs) {
620
+ const routeInfo = logRouteMapRef.current.get(l.id);
621
+ let screenName = 'Unknown Origin';
622
+ if (routeInfo && routeInfo.path !== 'Navigators') {
623
+ const parts = routeInfo.path.split(' ➔ ');
624
+ screenName = parts[parts.length - 1];
625
+ }
626
+ if (!map.has(screenName))
627
+ map.set(screenName, []);
628
+ map.get(screenName).push(l);
629
+ }
630
+ const sections = [];
631
+ for (const [title, data] of map.entries()) {
632
+ sections.push({ title, data });
633
+ }
634
+ return sections;
635
+ }, [groupByScreen, filteredLogs]);
636
+ const toggleScreenAccordion = (0, react_1.useCallback)((title) => {
637
+ setExpandedScreens(prev => {
638
+ const next = new Set(prev);
639
+ if (next.has(title))
640
+ next.delete(title);
641
+ else
642
+ next.add(title);
643
+ return next;
644
+ });
645
+ }, []);
646
+ const renderScreenSectionHeader = (0, react_1.useCallback)(({ section: { title, data } }) => {
647
+ const isExpanded = expandedScreens.has(title);
648
+ return (<react_native_1.Pressable onPress={() => toggleScreenAccordion(title)} style={styles_1.default.screenSectionHeader}>
649
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
650
+ <react_native_1.View style={{
651
+ transform: [{ rotate: isExpanded ? '180deg' : '0deg' }],
652
+ }}>
653
+ <NetworkIcons_1.ExpandCollapseIcon color={AppColors_1.AppColors.primaryBlack} size={14} isExpanded={false}/>
654
+ </react_native_1.View>
655
+ <react_native_1.Text style={styles_1.default.screenSectionTitle}>{title}</react_native_1.Text>
656
+ </react_native_1.View>
657
+ <react_native_1.Text style={styles_1.default.screenSectionCount}>{data.length} logs</react_native_1.Text>
658
+ </react_native_1.Pressable>);
659
+ }, [expandedScreens, toggleScreenAccordion]);
660
+ function closeModal() {
661
+ setVisible(false);
662
+ setSelected(null);
663
+ setSelectedEvent(null);
664
+ }
665
+ function handleClearAll() {
666
+ (0, networkLogger_1.clearNetworkLogs)();
667
+ setLogs([]);
668
+ setSelectedLogs(new Set());
669
+ setSectionFilters({});
670
+ setCollapsedSections(new Set());
671
+ setStatusFilters(new Set());
672
+ setMethodFilters(new Set());
673
+ prevLogIdsRef.current = new Set();
674
+ logRouteMapRef.current = new Map();
675
+ // Also clear analytics
676
+ (0, analyticsLogger_1.clearAnalyticsEvents)();
677
+ setAnalyticsEvents([]);
678
+ prevEventIdsRef.current = new Set();
679
+ // Also clear console logs
680
+ (0, consoleLogger_1.clearConsoleLogs)();
681
+ setConsoleLogs([]);
682
+ // Also clear webview logs/nav history
683
+ (0, webViewLogger_1.clearWebViewData)();
684
+ setWebViewLogs([]);
685
+ setWebViewNavHistory([]);
686
+ setWebViewHtml('');
687
+ setWebViewCss('');
688
+ setWebViewJs('');
689
+ setWebViewHtmlUrl('');
690
+ }
691
+ function handleDelete() {
692
+ if (activeTab === 'webview') {
693
+ react_native_1.Alert.alert('Clear WebView Data', 'Are you sure you want to clear all WebView logs and navigation history?', [
694
+ { text: 'Cancel', style: 'cancel' },
695
+ {
696
+ text: 'Clear All',
697
+ onPress: () => {
698
+ (0, webViewLogger_1.clearWebViewData)();
699
+ setWebViewLogs([]);
700
+ setWebViewNavHistory([]);
701
+ setWebViewHtml('');
702
+ setWebViewCss('');
703
+ setWebViewJs('');
704
+ setWebViewHtmlUrl('');
705
+ },
706
+ style: 'destructive',
707
+ },
708
+ ]);
709
+ return;
710
+ }
711
+ if (activeTab === 'logs') {
712
+ react_native_1.Alert.alert('Clear Logs', 'Are you sure you want to clear all console logs?', [
713
+ { text: 'Cancel', style: 'cancel' },
714
+ {
715
+ text: 'Clear All',
716
+ onPress: () => {
717
+ (0, consoleLogger_1.clearConsoleLogs)();
718
+ setConsoleLogs([]);
719
+ },
720
+ style: 'destructive',
721
+ },
722
+ ]);
723
+ return;
724
+ }
725
+ if (activeTab === 'analytics') {
726
+ react_native_1.Alert.alert('Clear Analytics', 'Are you sure you want to clear all analytics events?', [
727
+ { text: 'Cancel', style: 'cancel' },
728
+ {
729
+ text: 'Clear All',
730
+ onPress: () => {
731
+ (0, analyticsLogger_1.clearAnalyticsEvents)();
732
+ setAnalyticsEvents([]);
733
+ setSelectedEvent(null);
734
+ prevEventIdsRef.current = new Set();
735
+ },
736
+ style: 'destructive',
737
+ },
738
+ ]);
739
+ return;
740
+ }
741
+ if (selectedLogs.size > 0) {
742
+ setLogs(prev => prev.filter(l => !selectedLogs.has(l.id)));
743
+ setSelectedLogs(new Set());
744
+ }
745
+ else {
746
+ react_native_1.Alert.alert('Clear Logs', 'Are you sure you want to clear all network logs?', [
747
+ { text: 'Cancel', style: 'cancel' },
748
+ { text: 'Clear All', onPress: handleClearAll, style: 'destructive' },
749
+ ]);
750
+ }
751
+ }
752
+ const detailTitle = (0, react_1.useMemo)(() => {
753
+ if (!selected)
754
+ return '';
755
+ try {
756
+ const path = new URL(selected.url).pathname;
757
+ const parts = path.split('/').filter(Boolean);
758
+ return parts.length > 0 ? `/${parts.slice(-2).join('/')}` : '/';
759
+ }
760
+ catch {
761
+ const parts = selected.url.split('/').filter(Boolean);
762
+ return parts.length > 0 ? `/${parts.slice(-2).join('/')}` : selected.url;
763
+ }
764
+ }, [selected]);
765
+ const detailDisplayUrl = (0, react_1.useMemo)(() => {
766
+ return selected ? (0, helpers_1.formatDisplayUrl)(selected.url) : '';
767
+ }, [selected]);
768
+ const toggleSelect = (0, react_1.useCallback)((id) => {
769
+ setSelectedLogs(prev => {
770
+ const next = new Set(prev);
771
+ if (next.has(id))
772
+ next.delete(id);
773
+ else
774
+ next.add(id);
775
+ return next;
776
+ });
777
+ }, []);
778
+ const renderItem = (0, react_1.useCallback)(({ item }) => {
779
+ if (item.type === 'header') {
780
+ return (<DomainHeader_1.default pageName={item.pageName} color={item.color} stats={item.stats} activeFilters={item.activeFilters} onToggleFilter={toggleSectionFilter} isCollapsed={item.isCollapsed} onToggleCollapse={toggleSectionCollapse} isFirst={item.isFirst} timestamp={item.timestamp}/>);
781
+ }
782
+ const { log, isLast, color } = item;
783
+ return (<react_native_1.View style={styles_1.default.treeNodeRow}>
784
+ <react_native_1.View style={styles_1.default.treeLines}>
785
+ <react_native_1.View style={[
786
+ styles_1.default.modernTreeLine,
787
+ { borderColor: color },
788
+ isLast && styles_1.default.modernTreeLineLast,
789
+ ]}/>
790
+ {!isLast && (<react_native_1.View style={[styles_1.default.modernTreeBranch, { borderColor: color }]}/>)}
791
+ </react_native_1.View>
792
+ <react_native_1.View style={styles_1.default.treeCardWrapper}>
793
+ <LogCard_1.default item={log} isSelected={selectedLogs.has(log.id)} onToggleSelect={toggleSelect} onPress={() => setSelected(log)} timelineMinStart={minStart} timelineTotalRange={totalRange} isNew={newLogIds.has(log.id)} searchStr={search}/>
794
+ </react_native_1.View>
795
+ </react_native_1.View>);
796
+ }, [
797
+ minStart,
798
+ totalRange,
799
+ newLogIds,
800
+ selectedLogs,
801
+ toggleSelect,
802
+ search,
803
+ toggleSectionFilter,
804
+ toggleSectionCollapse,
805
+ ]);
806
+ return (<>
807
+ <TouchableScale_1.default style={styles_1.default.fabWrapper} onPress={() => setVisible(true)} hitSlop={10}>
808
+ <react_native_1.Animated.View style={[styles_1.default.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
809
+ <react_native_linear_gradient_1.default colors={[AppColors_1.AppColors.purple, '#8F6EFF']} style={styles_1.default.fab}>
810
+ <react_native_1.Text style={styles_1.default.fabText}>API</react_native_1.Text>
811
+ </react_native_linear_gradient_1.default>
812
+ {(logs.length > 0 || analyticsEvents.length > 0) && (<react_native_1.Animated.View style={[
813
+ styles_1.default.fabBadge,
814
+ hasErrors ? styles_1.default.fabBadgeError : styles_1.default.fabBadgeNormal,
815
+ { transform: [{ scale: badgeAnim }] },
816
+ ]}>
817
+ <react_native_1.Text style={styles_1.default.fabBadgeText}>
818
+ {logs.length + analyticsEvents.length > 99
819
+ ? '99+'
820
+ : logs.length + analyticsEvents.length}
821
+ </react_native_1.Text>
822
+ </react_native_1.Animated.View>)}
823
+ </TouchableScale_1.default>
824
+
825
+ <react_native_1.Modal visible={visible} animationType="slide" transparent>
826
+ {visible && (<react_native_1.View style={{ flex: 1, backgroundColor: AppColors_1.AppColors.grayBackground }}>
827
+ <react_native_1.StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
828
+
829
+ <react_native_linear_gradient_1.default colors={[AppColors_1.AppColors.purple, '#6B4EFF']} style={styles_1.default.headerGradient}>
830
+ <react_native_1.View style={[
831
+ styles_1.default.header,
832
+ {
833
+ paddingTop: react_native_1.Platform.OS === 'android'
834
+ ? (react_native_1.StatusBar.currentHeight ?? 24) + 16
835
+ : 54,
836
+ },
837
+ ]}>
838
+ <react_native_1.View style={[
839
+ styles_1.default.headerLeft,
840
+ { flexDirection: 'row', alignItems: 'center', gap: 16 },
841
+ ]}>
842
+ <TouchableScale_1.default onPress={() => {
843
+ requestAnimationFrame(() => {
844
+ setSelected(null);
845
+ setSelectedEvent(null);
846
+ });
847
+ }} hitSlop={15} style={[
848
+ styles_1.default.iconBtnMinimal,
849
+ selected == null &&
850
+ selectedEvent == null && { display: 'none' },
851
+ ]}>
852
+ <NetworkIcons_1.WhiteBackNavigation />
853
+ </TouchableScale_1.default>
854
+
855
+ {selected == null && selectedEvent == null ? (<react_native_1.View style={styles_1.default.headerButtonGroup}>
856
+ {/* Network Dropdown */}
857
+ <react_native_1.Pressable onPress={() => {
858
+ setShowNetworkMenu(prev => !prev);
859
+ setShowUiMenu(false);
860
+ }} style={[
861
+ styles_1.default.headerGroupButton,
862
+ ['apis', 'analytics', 'logs'].includes(activeTab) &&
863
+ styles_1.default.headerGroupButtonActive,
864
+ ]}>
865
+ <react_native_1.Text style={[
866
+ styles_1.default.headerGroupButtonText,
867
+ ['apis', 'analytics', 'logs'].includes(activeTab) && { color: '#FFFFFF' },
868
+ ]}>
869
+ APIs
870
+ </react_native_1.Text>
871
+ <react_native_1.View style={{
872
+ transform: [
873
+ { rotate: showNetworkMenu ? '180deg' : '0deg' },
874
+ ],
875
+ }}>
876
+ <NetworkIcons_1.ChevronIcon color={['apis', 'analytics', 'logs'].includes(activeTab)
877
+ ? '#FFFFFF'
878
+ : 'rgba(255, 255, 255, 0.6)'} size={10}/>
879
+ </react_native_1.View>
880
+ </react_native_1.Pressable>
881
+
882
+ {/* UI Dropdown */}
883
+ <react_native_1.Pressable onPress={() => {
884
+ setShowUiMenu(prev => !prev);
885
+ setShowNetworkMenu(false);
886
+ }} style={[
887
+ styles_1.default.headerGroupButton,
888
+ activeTab === 'webview' &&
889
+ styles_1.default.headerGroupButtonActive,
890
+ ]}>
891
+ <react_native_1.Text style={[
892
+ styles_1.default.headerGroupButtonText,
893
+ activeTab === 'webview' && { color: '#FFFFFF' },
894
+ ]}>
895
+ UI
896
+ </react_native_1.Text>
897
+ <react_native_1.View style={{
898
+ transform: [
899
+ { rotate: showUiMenu ? '180deg' : '0deg' },
900
+ ],
901
+ }}>
902
+ <NetworkIcons_1.ChevronIcon color={activeTab === 'webview'
903
+ ? '#FFFFFF'
904
+ : 'rgba(255, 255, 255, 0.6)'} size={10}/>
905
+ </react_native_1.View>
906
+ </react_native_1.Pressable>
907
+ </react_native_1.View>) : null}
908
+ </react_native_1.View>
909
+
910
+ <react_native_1.View style={styles_1.default.headerCenter}>
911
+ {selected != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
912
+ <react_native_1.View style={styles_1.default.headerDetailRow}>
913
+ <react_native_1.View style={[
914
+ styles_1.default.headerMethodBadge,
915
+ {
916
+ backgroundColor: constants_1.METHOD_COLORS[selected.method] ??
917
+ AppColors_1.AppColors.grayText,
918
+ },
919
+ ]}>
920
+ <react_native_1.Text style={styles_1.default.headerMethodText}>
921
+ {selected.method}
922
+ </react_native_1.Text>
923
+ </react_native_1.View>
924
+ <react_native_1.Text style={styles_1.default.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
925
+ {detailTitle}
926
+ </react_native_1.Text>
927
+ </react_native_1.View>
928
+ <react_native_1.View style={styles_1.default.headerDetailSubRow}>
929
+ <react_native_1.View style={[
930
+ styles_1.default.headerStatusDot,
931
+ { backgroundColor: (0, helpers_1.getStatusColor)(selected.status) },
932
+ ]}/>
933
+ <react_native_1.Text style={styles_1.default.headerSubTitle}>
934
+ {selected.status === 0
935
+ ? 'Failed'
936
+ : selected.status ?? 'Pending'}{' '}
937
+ •{' '}
938
+ {selected.duration != null
939
+ ? `${selected.duration}ms`
940
+ : '-'}
941
+ </react_native_1.Text>
942
+ </react_native_1.View>
943
+ </react_native_1.View>) : selectedEvent != null ? (<react_native_1.View style={styles_1.default.headerDetailCenter}>
944
+ <react_native_1.View style={styles_1.default.headerDetailRow}>
945
+ <react_native_1.View style={[
946
+ styles_1.default.headerMethodBadge,
947
+ {
948
+ backgroundColor: selectedEvent.source === 'firebase'
949
+ ? 'rgba(224,123,26,0.3)'
950
+ : 'rgba(124,92,191,0.3)',
951
+ },
952
+ ]}>
953
+ <react_native_1.Text style={styles_1.default.headerMethodText}>
954
+ {selectedEvent.source === 'firebase' ? 'FB' : 'MAN'}
955
+ </react_native_1.Text>
956
+ </react_native_1.View>
957
+ <react_native_1.Text style={styles_1.default.headerDetailTitle} numberOfLines={1} ellipsizeMode="middle">
958
+ {selectedEvent.name}
959
+ </react_native_1.Text>
960
+ </react_native_1.View>
961
+ <react_native_1.View style={styles_1.default.headerDetailSubRow}>
962
+ <react_native_1.View style={[
963
+ styles_1.default.headerStatusDot,
964
+ {
965
+ backgroundColor: selectedEvent.source === 'firebase'
966
+ ? '#E07B1A'
967
+ : AppColors_1.AppColors.purple,
968
+ },
969
+ ]}/>
970
+ <react_native_1.Text style={styles_1.default.headerSubTitle}>
971
+ {Object.keys(selectedEvent.params).length} param
972
+ {Object.keys(selectedEvent.params).length !== 1
973
+ ? 's'
974
+ : ''}
975
+ {' · '}
976
+ {selectedEvent.source}
977
+ </react_native_1.Text>
978
+ </react_native_1.View>
979
+ </react_native_1.View>) : (<react_native_1.View style={styles_1.default.headerCountBadge}>
980
+ <react_native_1.Text style={styles_1.default.headerCountText}>
981
+ {activeTab === 'apis'
982
+ ? `${logs.length} API${logs.length !== 1 ? 's' : ''}`
983
+ : activeTab === 'logs'
984
+ ? `${visibleConsoleLogs.length} log${visibleConsoleLogs.length !== 1 ? 's' : ''}`
985
+ : activeTab === 'analytics'
986
+ ? `${analyticsEvents.length} event${analyticsEvents.length !== 1 ? 's' : ''}`
987
+ : `${webViewLogs.length} log${webViewLogs.length !== 1 ? 's' : ''}`}
988
+ </react_native_1.Text>
989
+ </react_native_1.View>)}
990
+ </react_native_1.View>
991
+
992
+ <react_native_1.View style={styles_1.default.headerRight}>
993
+ <TouchableScale_1.default onPress={closeModal} hitSlop={15} style={styles_1.default.iconBtnMinimal}>
994
+ <NetworkIcons_1.CloseWhite />
995
+ </TouchableScale_1.default>
996
+ </react_native_1.View>
997
+ </react_native_1.View>
998
+ </react_native_linear_gradient_1.default>
999
+
1000
+ {(showNetworkMenu || showUiMenu) && selected == null && (<react_native_1.Pressable style={{
1001
+ position: 'absolute',
1002
+ top: 0,
1003
+ left: 0,
1004
+ right: 0,
1005
+ bottom: 0,
1006
+ zIndex: 99,
1007
+ }} onPress={() => {
1008
+ setShowNetworkMenu(false);
1009
+ setShowUiMenu(false);
1010
+ }}/>)}
1011
+
1012
+ {selected == null && selectedEvent == null && (<react_native_1.View style={{
1013
+ paddingHorizontal: 16,
1014
+ paddingTop: 10,
1015
+ paddingBottom: 2,
1016
+ }}>
1017
+ <react_native_1.Text style={{
1018
+ fontFamily: AppFonts_1.AppFonts.interMedium,
1019
+ fontSize: 11.5,
1020
+ color: AppColors_1.AppColors.grayTextWeak,
1021
+ }}>
1022
+ {['apis', 'analytics', 'logs'].includes(activeTab)
1023
+ ? 'APIs'
1024
+ : 'UI'}
1025
+ {' ➔ '}
1026
+ <react_native_1.Text style={{
1027
+ color: AppColors_1.AppColors.purple,
1028
+ fontFamily: AppFonts_1.AppFonts.interBold,
1029
+ }}>
1030
+ {activeTab === 'apis'
1031
+ ? 'APIs'
1032
+ : activeTab === 'analytics'
1033
+ ? 'Analytics'
1034
+ : activeTab === 'logs'
1035
+ ? 'Logs'
1036
+ : 'WebView'}
1037
+ </react_native_1.Text>
1038
+ </react_native_1.Text>
1039
+ </react_native_1.View>)}
1040
+
1041
+ {showNetworkMenu && selected == null && selectedEvent == null && (<react_native_1.View style={[styles_1.default.menuDropdown, { left: 16 }]}>
1042
+ {['apis', 'analytics', 'logs'].map(tab => {
1043
+ const label = tab === 'apis'
1044
+ ? 'APIs'
1045
+ : tab === 'analytics'
1046
+ ? 'Analytics'
1047
+ : 'Logs';
1048
+ const count = tab === 'apis'
1049
+ ? logs.length
1050
+ : tab === 'analytics'
1051
+ ? analyticsEvents.length
1052
+ : visibleConsoleLogs.length;
1053
+ const isActive = activeTab === tab;
1054
+ return (<react_native_1.Pressable key={tab} style={[
1055
+ styles_1.default.dropdownItem,
1056
+ isActive && { backgroundColor: `${AppColors_1.AppColors.purple}12` },
1057
+ ]} onPress={() => {
1058
+ setActiveTab(tab);
1059
+ setShowNetworkMenu(false);
1060
+ }} hitSlop={10}>
1061
+ <react_native_1.Text style={{
1062
+ fontFamily: AppFonts_1.AppFonts.interMedium,
1063
+ color: isActive
1064
+ ? AppColors_1.AppColors.purple
1065
+ : AppColors_1.AppColors.primaryBlack,
1066
+ }}>
1067
+ {label} {count > 0 ? `(${count})` : ''}
1068
+ </react_native_1.Text>
1069
+ </react_native_1.Pressable>);
1070
+ })}
1071
+ </react_native_1.View>)}
1072
+
1073
+ {showUiMenu && selected == null && selectedEvent == null && (<react_native_1.View style={[styles_1.default.menuDropdown, { left: 120 }]}>
1074
+ {['webview'].map(tab => {
1075
+ const isActive = activeTab === tab;
1076
+ return (<react_native_1.Pressable key={tab} style={[
1077
+ styles_1.default.dropdownItem,
1078
+ isActive && { backgroundColor: `${AppColors_1.AppColors.purple}12` },
1079
+ ]} onPress={() => {
1080
+ setActiveTab(tab);
1081
+ setShowUiMenu(false);
1082
+ }} hitSlop={10}>
1083
+ <react_native_1.Text style={{
1084
+ fontFamily: AppFonts_1.AppFonts.interMedium,
1085
+ color: isActive
1086
+ ? AppColors_1.AppColors.purple
1087
+ : AppColors_1.AppColors.primaryBlack,
1088
+ }}>
1089
+ WebView{' '}
1090
+ {webViewLogs.length > 0
1091
+ ? `(${webViewLogs.length})`
1092
+ : ''}
1093
+ </react_native_1.Text>
1094
+ </react_native_1.Pressable>);
1095
+ })}
1096
+ </react_native_1.View>)}
1097
+
1098
+ {/* ─── Secondary Tab Bar for Analytics ──────────────────────── */}
1099
+ {isReady && activeTab === 'analytics' && selectedEvent == null && (<react_native_1.View>
1100
+ {/* ─── Search + Shared Toolbar for Analytics ──────────────────────── */}
1101
+ <react_native_1.View style={[styles_1.default.toolbarRow, { marginTop: 12, marginBottom: 4 }]}>
1102
+ <react_native_1.View style={styles_1.default.searchContainer}>
1103
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
1104
+ <react_native_1.TextInput placeholder="Search events..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={analyticsSearch} onChangeText={setAnalyticsSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
1105
+ {analyticsSearch.length > 0 && (<react_native_1.Pressable onPress={() => setAnalyticsSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
1106
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1107
+ </react_native_1.Pressable>)}
1108
+ </react_native_1.View>
1109
+ {analyticsSubTab === 'ga_events' && (<react_native_1.View style={styles_1.default.toolbarRight}>
1110
+ <TouchableScale_1.default style={[
1111
+ styles_1.default.toolbarBtn,
1112
+ groupByScreen && styles_1.default.toolbarBtnActive,
1113
+ ]} onPress={() => setGroupByScreen(prev => !prev)} hitSlop={10}>
1114
+ <NetworkIcons_1.MapPinIcon color={groupByScreen
1115
+ ? AppColors_1.AppColors.purple
1116
+ : AppColors_1.AppColors.grayTextStrong} size={18}/>
1117
+ </TouchableScale_1.default>
1118
+ <TouchableScale_1.default style={[
1119
+ styles_1.default.toolbarBtn,
1120
+ !hideScreenView && styles_1.default.toolbarBtnActive,
1121
+ ]} onPress={() => setHideScreenView(prev => !prev)} hitSlop={10}>
1122
+ <NetworkIcons_1.ScreenIcon color={!hideScreenView
1123
+ ? AppColors_1.AppColors.purple
1124
+ : AppColors_1.AppColors.grayTextStrong} size={18}/>
1125
+ </TouchableScale_1.default>
1126
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
1127
+ <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1128
+ </TouchableScale_1.default>
1129
+ </react_native_1.View>)}
1130
+ </react_native_1.View>
1131
+
1132
+ {/* ─── Secondary Tab Bar for Analytics ──────────────────────── */}
1133
+ <react_native_1.View style={{
1134
+ marginHorizontal: 16,
1135
+ marginTop: 4,
1136
+ marginBottom: 8,
1137
+ backgroundColor: AppColors_1.AppColors.grayBackground,
1138
+ borderRadius: 8,
1139
+ padding: 4,
1140
+ flexDirection: 'row',
1141
+ borderWidth: 1,
1142
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
1143
+ }}>
1144
+ <react_native_1.Pressable style={[
1145
+ {
1146
+ flex: 1,
1147
+ paddingVertical: 8,
1148
+ borderRadius: 6,
1149
+ alignItems: 'center',
1150
+ },
1151
+ analyticsSubTab === 'ga_events' && {
1152
+ backgroundColor: AppColors_1.AppColors.primaryLight,
1153
+ shadowColor: '#000',
1154
+ shadowOpacity: 0.1,
1155
+ shadowRadius: 3,
1156
+ shadowOffset: { width: 0, height: 1 },
1157
+ elevation: 2,
1158
+ },
1159
+ ]} onPress={() => setAnalyticsSubTab('ga_events')}>
1160
+ <react_native_1.Text style={[
1161
+ {
1162
+ fontFamily: AppFonts_1.AppFonts.interMedium,
1163
+ fontSize: 13,
1164
+ color: AppColors_1.AppColors.grayTextStrong,
1165
+ },
1166
+ analyticsSubTab === 'ga_events' && {
1167
+ fontFamily: AppFonts_1.AppFonts.interBold,
1168
+ color: AppColors_1.AppColors.purple,
1169
+ },
1170
+ ]}>
1171
+ GA Events (
1172
+ {analyticsSearch
1173
+ ? filteredAnalyticsEvents.length
1174
+ : analyticsEvents.length}
1175
+ )
1176
+ </react_native_1.Text>
1177
+ </react_native_1.Pressable>
1178
+ <react_native_1.Pressable style={[
1179
+ {
1180
+ flex: 1,
1181
+ paddingVertical: 8,
1182
+ borderRadius: 6,
1183
+ alignItems: 'center',
1184
+ },
1185
+ analyticsSubTab === 'top_events' && {
1186
+ backgroundColor: AppColors_1.AppColors.primaryLight,
1187
+ shadowColor: '#000',
1188
+ shadowOpacity: 0.1,
1189
+ shadowRadius: 3,
1190
+ shadowOffset: { width: 0, height: 1 },
1191
+ elevation: 2,
1192
+ },
1193
+ ]} onPress={() => setAnalyticsSubTab('top_events')}>
1194
+ <react_native_1.Text style={[
1195
+ {
1196
+ fontFamily: AppFonts_1.AppFonts.interMedium,
1197
+ fontSize: 13,
1198
+ color: AppColors_1.AppColors.grayTextStrong,
1199
+ },
1200
+ analyticsSubTab === 'top_events' && {
1201
+ fontFamily: AppFonts_1.AppFonts.interBold,
1202
+ color: AppColors_1.AppColors.purple,
1203
+ },
1204
+ ]}>
1205
+ Top Events ({topEventsArray.length})
1206
+ </react_native_1.Text>
1207
+ </react_native_1.Pressable>
1208
+ </react_native_1.View>
1209
+ </react_native_1.View>)}
1210
+
1211
+ {isReady ? (activeTab === 'analytics' ? (selectedEvent != null ? (<AnalyticsDetail_1.default event={selectedEvent}/>) : analyticsSubTab === 'top_events' ? (<react_native_1.FlatList data={topEventsArray} keyExtractor={item => item[0]} contentContainerStyle={[
1212
+ styles_1.default.listContent,
1213
+ { paddingHorizontal: 16, paddingTop: 16 },
1214
+ ]} renderItem={({ item: [name, count] }) => {
1215
+ const maxCount = topEventsArray[0]?.[1] || 1;
1216
+ const color = (0, AnalyticsEventCard_1.getEventColor)(name);
1217
+ return (<react_native_1.View style={[
1218
+ analyticsListStyles.topEventsCard,
1219
+ { marginBottom: 12, paddingVertical: 16 },
1220
+ ]}>
1221
+ <react_native_1.View style={analyticsListStyles.topEventRow}>
1222
+ <react_native_1.View style={{
1223
+ flexDirection: 'row',
1224
+ alignItems: 'center',
1225
+ gap: 8,
1226
+ flex: 1,
1227
+ }}>
1228
+ <react_native_1.View style={[
1229
+ analyticsListStyles.iconCircle,
1230
+ { backgroundColor: `${color}1A` },
1231
+ ]}>
1232
+ <react_native_svg_1.default width={14} height={14} viewBox="0 0 24 24" fill={color}>
1233
+ <react_native_svg_1.Circle cx="12" cy="12" r="10" opacity="0.3"/>
1234
+ <react_native_svg_1.Path d="M7 14l3-3 4 4 6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
1235
+ </react_native_svg_1.default>
1236
+ </react_native_1.View>
1237
+ <react_native_1.Text style={analyticsListStyles.topEventName} numberOfLines={2}>
1238
+ {name}
1239
+ </react_native_1.Text>
1240
+ </react_native_1.View>
1241
+ <react_native_1.View style={analyticsListStyles.topEventBarWrap}>
1242
+ <react_native_linear_gradient_1.default colors={[color, `${color}99`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={[
1243
+ analyticsListStyles.topEventBar,
1244
+ {
1245
+ width: `${Math.max(6, (count / maxCount) * 100)}%`,
1246
+ },
1247
+ ]}/>
1248
+ </react_native_1.View>
1249
+ <react_native_1.Text style={analyticsListStyles.topEventCount}>
1250
+ {count}
1251
+ </react_native_1.Text>
1252
+ </react_native_1.View>
1253
+ </react_native_1.View>);
1254
+ }} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1255
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
1256
+ <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
1257
+ </react_native_1.View>
1258
+ <react_native_1.Text style={styles_1.default.emptyTitle}>No Top Events</react_native_1.Text>
1259
+ </react_native_1.View>}/>) : groupByScreen ? (<react_native_1.SectionList sections={groupedAnalyticsEvents} keyExtractor={item => item.id.toString()} renderSectionHeader={renderScreenSectionHeader} renderItem={({ item, index, section }) => {
1260
+ if (expandedScreens.has(section.title))
1261
+ return null;
1262
+ const events = section.data;
1263
+ const prev = events[index + 1];
1264
+ const next = events[index - 1];
1265
+ const msSincePrev = prev
1266
+ ? item.timestamp - prev.timestamp
1267
+ : undefined;
1268
+ const thisMin = Math.floor(item.timestamp / 60000);
1269
+ const nextMin = next
1270
+ ? Math.floor(next.timestamp / 60000)
1271
+ : -1;
1272
+ const showTimestamp = index === 0 || thisMin !== nextMin;
1273
+ return (<AnalyticsEventCard_1.default event={item} onPress={() => setSelectedEvent(item)} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === events.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={section.title}/>);
1274
+ }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListHeaderComponent={null} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1275
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
1276
+ <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
1277
+ </react_native_1.View>
1278
+ <react_native_1.Text style={styles_1.default.emptyTitle}>
1279
+ {analyticsSearch.length > 0
1280
+ ? 'No matching events'
1281
+ : 'No analytics events yet'}
1282
+ </react_native_1.Text>
1283
+ <react_native_1.Text style={styles_1.default.emptySub}>
1284
+ {analyticsSearch.length > 0
1285
+ ? 'Try adjusting your search.'
1286
+ : 'Call setupAnalyticsLogger(analytics()) at app start.'}
1287
+ </react_native_1.Text>
1288
+ </react_native_1.View>} contentContainerStyle={[
1289
+ styles_1.default.listContent,
1290
+ filteredAnalyticsEvents.length === 0 && { flexGrow: 1 },
1291
+ ]} keyboardShouldPersistTaps="handled"/>) : (<react_native_1.FlatList data={filteredAnalyticsEvents} keyExtractor={item => item.id.toString()} renderItem={({ item, index }) => {
1292
+ const prev = filteredAnalyticsEvents[index + 1];
1293
+ const next = filteredAnalyticsEvents[index - 1];
1294
+ const msSincePrev = prev
1295
+ ? item.timestamp - prev.timestamp
1296
+ : undefined;
1297
+ const thisMin = Math.floor(item.timestamp / 60000);
1298
+ const nextMin = next
1299
+ ? Math.floor(next.timestamp / 60000)
1300
+ : -1;
1301
+ const showTimestamp = index === 0 || thisMin !== nextMin;
1302
+ return (<AnalyticsEventCard_1.default event={item} onPress={() => setSelectedEvent(item)} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === filteredAnalyticsEvents.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={(() => {
1303
+ let screenName = item.screenName ||
1304
+ item.screenClass ||
1305
+ item.pageTitle ||
1306
+ item.pageLocation ||
1307
+ item.params?.firebase_screen ||
1308
+ item.params?.screen_name ||
1309
+ item.params?.firebase_screen_class ||
1310
+ item.params?.screen_class;
1311
+ const routeInfo = logRouteMapRef.current.get(item.id + 1000000);
1312
+ if (!screenName) {
1313
+ if (routeInfo &&
1314
+ routeInfo.path !== 'Navigators') {
1315
+ const parts = routeInfo.path.split(' ➔ ');
1316
+ screenName = parts[parts.length - 1];
1317
+ }
1318
+ }
1319
+ return screenName;
1320
+ })()}/>);
1321
+ }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews ListHeaderComponent={null} ListEmptyComponent={<react_native_1.View style={styles_1.default.emptyContainer}>
1322
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
1323
+ <NetworkIcons_1.EmptyRadarIcon color={AppColors_1.AppColors.purple} size={32}/>
1324
+ </react_native_1.View>
1325
+ <react_native_1.Text style={styles_1.default.emptyTitle}>
1326
+ {analyticsSearch.length > 0
1327
+ ? 'No matching events'
1328
+ : 'No analytics events yet'}
1329
+ </react_native_1.Text>
1330
+ <react_native_1.Text style={styles_1.default.emptySub}>
1331
+ {analyticsSearch.length > 0
1332
+ ? 'Try adjusting your search.'
1333
+ : 'Call setupAnalyticsLogger(analytics()) at app start.'}
1334
+ </react_native_1.Text>
1335
+ </react_native_1.View>} contentContainerStyle={[
1336
+ styles_1.default.listContent,
1337
+ filteredAnalyticsEvents.length === 0 && { flexGrow: 1 },
1338
+ ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'apis' && selected == null ? (groupByScreen ? (<react_native_1.SectionList sections={groupedNetworkLogs} keyExtractor={item => item?.id?.toString()} renderSectionHeader={renderScreenSectionHeader} renderItem={({ item, section }) => {
1339
+ if (expandedScreens.has(section.title))
1340
+ return null;
1341
+ return renderItem({
1342
+ item: {
1343
+ type: 'log',
1344
+ log: item,
1345
+ color: AppColors_1.AppColors.purple,
1346
+ },
1347
+ });
1348
+ }} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<react_native_1.View style={{ marginTop: 8 }}>
1349
+ {logs.length > 0 && (<react_native_1.View style={styles_1.default.dashboardCard}>
1350
+ <react_native_1.View style={styles_1.default.dashboardStatsRow}>
1351
+ <react_native_1.View style={styles_1.default.statBox}>
1352
+ <react_native_1.Text style={styles_1.default.statValue}>
1353
+ {stats.filtered < stats.total
1354
+ ? stats.filtered
1355
+ : stats.total}
1356
+ </react_native_1.Text>
1357
+ <react_native_1.Text style={styles_1.default.statLabel}>
1358
+ {stats.filtered < stats.total
1359
+ ? `of ${stats.total} Req`
1360
+ : 'Requests'}
1361
+ </react_native_1.Text>
1362
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1363
+ <MiniBarChart_1.default data={stats.reqTrend} color={AppColors_1.AppColors.purple}/>
1364
+ </react_native_1.View>
1365
+ </react_native_1.View>
1366
+ <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1367
+ <react_native_1.View style={styles_1.default.statBox}>
1368
+ <react_native_1.Text style={[
1369
+ styles_1.default.statValue,
1370
+ stats.errors > 0 && {
1371
+ color: AppColors_1.AppColors.errorColor,
1372
+ },
1373
+ ]}>
1374
+ {stats.errors}
1375
+ </react_native_1.Text>
1376
+ <react_native_1.Text style={styles_1.default.statLabel}>Errors</react_native_1.Text>
1377
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1378
+ <MiniBarChart_1.default data={stats.errorTrend} color={AppColors_1.AppColors.errorColor} maxVal={1}/>
1379
+ </react_native_1.View>
1380
+ </react_native_1.View>
1381
+ <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1382
+ <react_native_1.View style={styles_1.default.statBox}>
1383
+ <react_native_1.Text style={[
1384
+ styles_1.default.statValue,
1385
+ stats.avgDuration != null
1386
+ ? {
1387
+ color: (0, helpers_1.getDurationColor)(stats.avgDuration),
1388
+ }
1389
+ : null,
1390
+ ]}>
1391
+ {stats.avgDuration != null
1392
+ ? `${stats.avgDuration}ms`
1393
+ : '—'}
1394
+ </react_native_1.Text>
1395
+ <react_native_1.Text style={styles_1.default.statLabel}>Avg Time</react_native_1.Text>
1396
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1397
+ <MiniLineChart_1.default data={stats.durationTrend} color={AppColors_1.AppColors.darkOrange}/>
1398
+ </react_native_1.View>
1399
+ </react_native_1.View>
1400
+ <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1401
+ <react_native_1.View style={styles_1.default.statBox}>
1402
+ <react_native_1.Text style={[
1403
+ styles_1.default.statValue,
1404
+ { color: AppColors_1.AppColors.skyBlue },
1405
+ ]}>
1406
+ {stats.size}
1407
+ </react_native_1.Text>
1408
+ <react_native_1.Text style={styles_1.default.statLabel}>Payload</react_native_1.Text>
1409
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1410
+ <MiniBarChart_1.default data={stats.sizeTrend} color={AppColors_1.AppColors.skyBlue}/>
1411
+ </react_native_1.View>
1412
+ </react_native_1.View>
1413
+ </react_native_1.View>
1414
+ </react_native_1.View>)}
1415
+
1416
+ <react_native_1.View style={styles_1.default.toolbarRow}>
1417
+ <react_native_1.View style={styles_1.default.searchContainer}>
1418
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
1419
+ <react_native_1.TextInput placeholder="Search endpoints..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
1420
+ {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
1421
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1422
+ </react_native_1.Pressable>)}
1423
+ </react_native_1.View>
1424
+
1425
+ <react_native_1.View style={styles_1.default.toolbarRight}>
1426
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
1427
+ <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1428
+ {selectedLogs.size > 0 && (<react_native_1.View style={styles_1.default.trashBadge}>
1429
+ <react_native_1.Text style={styles_1.default.trashBadgeText}>
1430
+ {selectedLogs.size}
1431
+ </react_native_1.Text>
1432
+ </react_native_1.View>)}
1433
+ </TouchableScale_1.default>
1434
+
1435
+ <TouchableScale_1.default style={[
1436
+ styles_1.default.toolbarBtn,
1437
+ groupByScreen && styles_1.default.toolbarBtnActive,
1438
+ ]} onPress={() => setGroupByScreen(prev => !prev)} hitSlop={10}>
1439
+ <NetworkIcons_1.MapPinIcon color={groupByScreen
1440
+ ? AppColors_1.AppColors.purple
1441
+ : AppColors_1.AppColors.grayTextStrong} size={18}/>
1442
+ </TouchableScale_1.default>
1443
+
1444
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
1445
+ <NetworkIcons_1.SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1446
+ </TouchableScale_1.default>
1447
+
1448
+ <TouchableScale_1.default style={[
1449
+ styles_1.default.toolbarBtn,
1450
+ filtersAccordion.isOpen &&
1451
+ styles_1.default.toolbarBtnActive,
1452
+ ]} onPress={filtersAccordion.toggleOpen} hitSlop={10}>
1453
+ <NetworkIcons_1.FilterIcon color={filtersAccordion.isOpen
1454
+ ? AppColors_1.AppColors.purple
1455
+ : AppColors_1.AppColors.grayTextStrong} size={18}/>
1456
+ </TouchableScale_1.default>
1457
+ </react_native_1.View>
1458
+ </react_native_1.View>
1459
+
1460
+ <react_native_1.Animated.View style={[
1461
+ filtersAccordion.bodyStyle,
1462
+ { overflow: 'hidden' },
1463
+ ]}>
1464
+ <react_native_1.View style={styles_1.default.filtersContainer}>
1465
+ <react_native_1.Text style={styles_1.default.filtersHeading}>STATUS</react_native_1.Text>
1466
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
1467
+ {constants_1.STATUS_FILTERS.map(filter => {
1468
+ const isAll = filter === 'ALL';
1469
+ const active = isAll
1470
+ ? statusFilters.size === 0
1471
+ : statusFilters.has(filter);
1472
+ return (<TouchableScale_1.default key={filter} style={styles_1.default.statusFilterWrap} onPress={() => {
1473
+ if (isAll) {
1474
+ setStatusFilters(new Set());
1475
+ }
1476
+ else {
1477
+ setStatusFilters(prev => {
1478
+ const next = new Set(prev);
1479
+ next.has(filter)
1480
+ ? next.delete(filter)
1481
+ : next.add(filter);
1482
+ return next;
1483
+ });
1484
+ }
1485
+ }} hitSlop={10}>
1486
+ {active ? (<react_native_linear_gradient_1.default colors={[
1487
+ AppColors_1.AppColors.purpleShade50,
1488
+ '#EAE5FF',
1489
+ ]} style={[
1490
+ styles_1.default.statusFilterChip,
1491
+ styles_1.default.statusFilterActive,
1492
+ ]}>
1493
+ <react_native_1.Text style={[
1494
+ styles_1.default.statusFilterText,
1495
+ { color: AppColors_1.AppColors.purple },
1496
+ ]}>
1497
+ {filter}
1498
+ </react_native_1.Text>
1499
+ </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1500
+ <react_native_1.Text style={styles_1.default.statusFilterText}>
1501
+ {filter}
1502
+ </react_native_1.Text>
1503
+ </react_native_1.View>)}
1504
+ </TouchableScale_1.default>);
1505
+ })}
1506
+ </react_native_1.ScrollView>
1507
+
1508
+ <react_native_1.Text style={[styles_1.default.filtersHeading, { marginTop: 16 }]}>
1509
+ METHOD
1510
+ </react_native_1.Text>
1511
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
1512
+ {availableMethods.map(filter => {
1513
+ const isAll = filter === 'ALL';
1514
+ const active = isAll
1515
+ ? methodFilters.size === 0
1516
+ : methodFilters.has(filter);
1517
+ return (<TouchableScale_1.default key={filter} style={styles_1.default.statusFilterWrap} onPress={() => {
1518
+ if (isAll) {
1519
+ setMethodFilters(new Set());
1520
+ }
1521
+ else {
1522
+ setMethodFilters(prev => {
1523
+ const next = new Set(prev);
1524
+ next.has(filter)
1525
+ ? next.delete(filter)
1526
+ : next.add(filter);
1527
+ return next;
1528
+ });
1529
+ }
1530
+ }} hitSlop={10}>
1531
+ {active ? (<react_native_linear_gradient_1.default colors={[
1532
+ AppColors_1.AppColors.purpleShade50,
1533
+ '#EAE5FF',
1534
+ ]} style={[
1535
+ styles_1.default.statusFilterChip,
1536
+ styles_1.default.statusFilterActive,
1537
+ ]}>
1538
+ <react_native_1.Text style={[
1539
+ styles_1.default.statusFilterText,
1540
+ { color: AppColors_1.AppColors.purple },
1541
+ ]}>
1542
+ {filter}
1543
+ </react_native_1.Text>
1544
+ </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1545
+ <react_native_1.Text style={styles_1.default.statusFilterText}>
1546
+ {filter}
1547
+ </react_native_1.Text>
1548
+ </react_native_1.View>)}
1549
+ </TouchableScale_1.default>);
1550
+ })}
1551
+ </react_native_1.ScrollView>
1552
+ </react_native_1.View>
1553
+ </react_native_1.Animated.View>
1554
+
1555
+ {(search ||
1556
+ statusFilters.size > 0 ||
1557
+ methodFilters.size > 0) && (<react_native_1.Text style={styles_1.default.resultCount}>
1558
+ {filteredLogs.length === logs.length
1559
+ ? `${logs.length} requests`
1560
+ : `${filteredLogs.length} of ${logs.length} filtered requests`}
1561
+ </react_native_1.Text>)}
1562
+ </react_native_1.View>} ListEmptyComponent={<EmptyState_1.default isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
1563
+ styles_1.default.listContent,
1564
+ filteredLogs.length === 0 && { flexGrow: 1 },
1565
+ ]} keyboardShouldPersistTaps="handled"/>) : (<react_native_1.FlatList data={groupedData} keyExtractor={item => item?.id?.toString()} renderItem={renderItem} initialNumToRender={10} maxToRenderPerBatch={10} windowSize={5} removeClippedSubviews={true} ListHeaderComponent={<react_native_1.View style={{ marginTop: 8 }}>
1566
+ {logs.length > 0 && (<react_native_1.View style={styles_1.default.dashboardCard}>
1567
+ <react_native_1.View style={styles_1.default.dashboardStatsRow}>
1568
+ <react_native_1.View style={styles_1.default.statBox}>
1569
+ <react_native_1.Text style={styles_1.default.statValue}>
1570
+ {stats.filtered < stats.total
1571
+ ? stats.filtered
1572
+ : stats.total}
1573
+ </react_native_1.Text>
1574
+ <react_native_1.Text style={styles_1.default.statLabel}>
1575
+ {stats.filtered < stats.total
1576
+ ? `of ${stats.total} Req`
1577
+ : 'Requests'}
1578
+ </react_native_1.Text>
1579
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1580
+ <MiniBarChart_1.default data={stats.reqTrend} color={AppColors_1.AppColors.purple}/>
1581
+ </react_native_1.View>
1582
+ </react_native_1.View>
1583
+ <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1584
+ <react_native_1.View style={styles_1.default.statBox}>
1585
+ <react_native_1.Text style={[
1586
+ styles_1.default.statValue,
1587
+ stats.errors > 0 && {
1588
+ color: AppColors_1.AppColors.errorColor,
1589
+ },
1590
+ ]}>
1591
+ {stats.errors}
1592
+ </react_native_1.Text>
1593
+ <react_native_1.Text style={styles_1.default.statLabel}>Errors</react_native_1.Text>
1594
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1595
+ <MiniBarChart_1.default data={stats.errorTrend} color={AppColors_1.AppColors.errorColor} maxVal={1}/>
1596
+ </react_native_1.View>
1597
+ </react_native_1.View>
1598
+ <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1599
+ <react_native_1.View style={styles_1.default.statBox}>
1600
+ <react_native_1.Text style={[
1601
+ styles_1.default.statValue,
1602
+ stats.avgDuration != null
1603
+ ? {
1604
+ color: (0, helpers_1.getDurationColor)(stats.avgDuration),
1605
+ }
1606
+ : null,
1607
+ ]}>
1608
+ {stats.avgDuration != null
1609
+ ? `${stats.avgDuration}ms`
1610
+ : '—'}
1611
+ </react_native_1.Text>
1612
+ <react_native_1.Text style={styles_1.default.statLabel}>Avg Time</react_native_1.Text>
1613
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1614
+ <MiniLineChart_1.default data={stats.durationTrend} color={AppColors_1.AppColors.darkOrange}/>
1615
+ </react_native_1.View>
1616
+ </react_native_1.View>
1617
+ <react_native_1.View style={styles_1.default.dashboardStatDivider}/>
1618
+ <react_native_1.View style={styles_1.default.statBox}>
1619
+ <react_native_1.Text style={[
1620
+ styles_1.default.statValue,
1621
+ { color: AppColors_1.AppColors.skyBlue },
1622
+ ]}>
1623
+ {stats.size}
1624
+ </react_native_1.Text>
1625
+ <react_native_1.Text style={styles_1.default.statLabel}>Payload</react_native_1.Text>
1626
+ <react_native_1.View style={styles_1.default.miniGraphWrap}>
1627
+ <MiniBarChart_1.default data={stats.sizeTrend} color={AppColors_1.AppColors.skyBlue}/>
1628
+ </react_native_1.View>
1629
+ </react_native_1.View>
1630
+ </react_native_1.View>
1631
+ </react_native_1.View>)}
1632
+
1633
+ <react_native_1.View style={styles_1.default.toolbarRow}>
1634
+ <react_native_1.View style={styles_1.default.searchContainer}>
1635
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
1636
+ <react_native_1.TextInput placeholder="Search endpoints..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
1637
+ {search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
1638
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1639
+ </react_native_1.Pressable>)}
1640
+ </react_native_1.View>
1641
+
1642
+ <react_native_1.View style={styles_1.default.toolbarRight}>
1643
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
1644
+ <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1645
+ {selectedLogs.size > 0 && (<react_native_1.View style={styles_1.default.trashBadge}>
1646
+ <react_native_1.Text style={styles_1.default.trashBadgeText}>
1647
+ {selectedLogs.size}
1648
+ </react_native_1.Text>
1649
+ </react_native_1.View>)}
1650
+ </TouchableScale_1.default>
1651
+
1652
+ <TouchableScale_1.default style={[
1653
+ styles_1.default.toolbarBtn,
1654
+ groupByScreen && styles_1.default.toolbarBtnActive,
1655
+ ]} onPress={() => setGroupByScreen(prev => !prev)} hitSlop={10}>
1656
+ <NetworkIcons_1.MapPinIcon color={groupByScreen
1657
+ ? AppColors_1.AppColors.purple
1658
+ : AppColors_1.AppColors.grayTextStrong} size={18}/>
1659
+ </TouchableScale_1.default>
1660
+
1661
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={() => setSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
1662
+ <NetworkIcons_1.SortArrowIcon direction={sortOrder === 'newest' ? 'down' : 'up'} color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1663
+ </TouchableScale_1.default>
1664
+
1665
+ <TouchableScale_1.default style={[
1666
+ styles_1.default.toolbarBtn,
1667
+ filtersAccordion.isOpen &&
1668
+ styles_1.default.toolbarBtnActive,
1669
+ ]} onPress={filtersAccordion.toggleOpen} hitSlop={10}>
1670
+ <NetworkIcons_1.FilterIcon color={filtersAccordion.isOpen
1671
+ ? AppColors_1.AppColors.purple
1672
+ : AppColors_1.AppColors.grayTextStrong} size={18}/>
1673
+ </TouchableScale_1.default>
1674
+ </react_native_1.View>
1675
+ </react_native_1.View>
1676
+
1677
+ <react_native_1.Animated.View style={[
1678
+ filtersAccordion.bodyStyle,
1679
+ { overflow: 'hidden' },
1680
+ ]}>
1681
+ <react_native_1.View style={styles_1.default.filtersContainer}>
1682
+ <react_native_1.Text style={styles_1.default.filtersHeading}>STATUS</react_native_1.Text>
1683
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
1684
+ {constants_1.STATUS_FILTERS.map(filter => {
1685
+ const isAll = filter === 'ALL';
1686
+ const active = isAll
1687
+ ? statusFilters.size === 0
1688
+ : statusFilters.has(filter);
1689
+ return (<TouchableScale_1.default key={filter} style={styles_1.default.statusFilterWrap} onPress={() => {
1690
+ if (isAll) {
1691
+ setStatusFilters(new Set());
1692
+ }
1693
+ else {
1694
+ setStatusFilters(prev => {
1695
+ const next = new Set(prev);
1696
+ next.has(filter)
1697
+ ? next.delete(filter)
1698
+ : next.add(filter);
1699
+ return next;
1700
+ });
1701
+ }
1702
+ }} hitSlop={10}>
1703
+ {active ? (<react_native_linear_gradient_1.default colors={[
1704
+ AppColors_1.AppColors.purpleShade50,
1705
+ '#EAE5FF',
1706
+ ]} style={[
1707
+ styles_1.default.statusFilterChip,
1708
+ styles_1.default.statusFilterActive,
1709
+ ]}>
1710
+ <react_native_1.Text style={[
1711
+ styles_1.default.statusFilterText,
1712
+ { color: AppColors_1.AppColors.purple },
1713
+ ]}>
1714
+ {filter}
1715
+ </react_native_1.Text>
1716
+ </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1717
+ <react_native_1.Text style={styles_1.default.statusFilterText}>
1718
+ {filter}
1719
+ </react_native_1.Text>
1720
+ </react_native_1.View>)}
1721
+ </TouchableScale_1.default>);
1722
+ })}
1723
+ </react_native_1.ScrollView>
1724
+
1725
+ <react_native_1.Text style={[styles_1.default.filtersHeading, { marginTop: 16 }]}>
1726
+ METHOD
1727
+ </react_native_1.Text>
1728
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles_1.default.statusRowContent}>
1729
+ {availableMethods.map(filter => {
1730
+ const isAll = filter === 'ALL';
1731
+ const active = isAll
1732
+ ? methodFilters.size === 0
1733
+ : methodFilters.has(filter);
1734
+ return (<TouchableScale_1.default key={filter} style={styles_1.default.statusFilterWrap} onPress={() => {
1735
+ if (isAll) {
1736
+ setMethodFilters(new Set());
1737
+ }
1738
+ else {
1739
+ setMethodFilters(prev => {
1740
+ const next = new Set(prev);
1741
+ next.has(filter)
1742
+ ? next.delete(filter)
1743
+ : next.add(filter);
1744
+ return next;
1745
+ });
1746
+ }
1747
+ }} hitSlop={10}>
1748
+ {active ? (<react_native_linear_gradient_1.default colors={[
1749
+ AppColors_1.AppColors.purpleShade50,
1750
+ '#EAE5FF',
1751
+ ]} style={[
1752
+ styles_1.default.statusFilterChip,
1753
+ styles_1.default.statusFilterActive,
1754
+ ]}>
1755
+ <react_native_1.Text style={[
1756
+ styles_1.default.statusFilterText,
1757
+ { color: AppColors_1.AppColors.purple },
1758
+ ]}>
1759
+ {filter}
1760
+ </react_native_1.Text>
1761
+ </react_native_linear_gradient_1.default>) : (<react_native_1.View style={styles_1.default.statusFilterChip}>
1762
+ <react_native_1.Text style={styles_1.default.statusFilterText}>
1763
+ {filter}
1764
+ </react_native_1.Text>
1765
+ </react_native_1.View>)}
1766
+ </TouchableScale_1.default>);
1767
+ })}
1768
+ </react_native_1.ScrollView>
1769
+ </react_native_1.View>
1770
+ </react_native_1.Animated.View>
1771
+
1772
+ {(search ||
1773
+ statusFilters.size > 0 ||
1774
+ methodFilters.size > 0) && (<react_native_1.Text style={styles_1.default.resultCount}>
1775
+ {filteredLogs.length === logs.length
1776
+ ? `${logs.length} requests`
1777
+ : `${filteredLogs.length} of ${logs.length} filtered requests`}
1778
+ </react_native_1.Text>)}
1779
+ </react_native_1.View>} ListEmptyComponent={<EmptyState_1.default isSearch={search.length > 0 || statusFilters.size > 0}/>} contentContainerStyle={[
1780
+ styles_1.default.listContent,
1781
+ filteredLogs.length === 0 && { flexGrow: 1 },
1782
+ ]} keyboardShouldPersistTaps="handled"/>)) : activeTab === 'logs' ? (<react_native_1.View style={{ flex: 1 }}>
1783
+ <react_native_1.View style={{
1784
+ backgroundColor: '#FFFFFF',
1785
+ borderBottomWidth: 1,
1786
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
1787
+ paddingBottom: 6,
1788
+ }}>
1789
+ <react_native_1.View style={[
1790
+ styles_1.default.toolbarRow,
1791
+ { marginTop: 12, marginBottom: 8 },
1792
+ ]}>
1793
+ <react_native_1.View style={styles_1.default.searchContainer}>
1794
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
1795
+ <react_native_1.TextInput placeholder="Search logs..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={logSearch} onChangeText={setLogSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
1796
+ {logSearch.length > 0 && (<react_native_1.Pressable onPress={() => setLogSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
1797
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
1798
+ </react_native_1.Pressable>)}
1799
+ </react_native_1.View>
1800
+
1801
+ <react_native_1.View style={styles_1.default.toolbarRight}>
1802
+ <TouchableScale_1.default style={styles_1.default.toolbarBtn} onPress={handleDelete} hitSlop={10}>
1803
+ <NetworkIcons_1.TrashIcon color={AppColors_1.AppColors.grayTextStrong} size={18}/>
1804
+ </TouchableScale_1.default>
1805
+ </react_native_1.View>
1806
+ </react_native_1.View>
1807
+
1808
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginVertical: 4, maxHeight: 46 }} contentContainerStyle={{
1809
+ paddingHorizontal: 16,
1810
+ paddingBottom: 4,
1811
+ flexDirection: 'row',
1812
+ alignItems: 'center',
1813
+ gap: 8,
1814
+ }}>
1815
+ {(() => {
1816
+ const active = logFilters.has('all');
1817
+ return (<TouchableScale_1.default onPress={() => {
1818
+ setLogFilters(new Set(['all']));
1819
+ }}>
1820
+ <react_native_1.View style={[
1821
+ styles_1.default.statusFilterChip,
1822
+ active && {
1823
+ borderColor: AppColors_1.AppColors.purpleShade700,
1824
+ backgroundColor: '#F4EBFF',
1825
+ },
1826
+ ]}>
1827
+ <react_native_1.Text numberOfLines={1} style={[
1828
+ styles_1.default.statusFilterText,
1829
+ active && {
1830
+ color: AppColors_1.AppColors.purpleShade700,
1831
+ fontFamily: AppFonts_1.AppFonts.interBold,
1832
+ },
1833
+ ]}>
1834
+ All ({logCounts.all})
1835
+ </react_native_1.Text>
1836
+ </react_native_1.View>
1837
+ </TouchableScale_1.default>);
1838
+ })()}
1839
+
1840
+ {(() => {
1841
+ const active = logFilters.has('user-log');
1842
+ return (<TouchableScale_1.default onPress={() => {
1843
+ setLogFilters(prev => {
1844
+ const next = new Set(prev);
1845
+ next.delete('all');
1846
+ next.has('user-log')
1847
+ ? next.delete('user-log')
1848
+ : next.add('user-log');
1849
+ if (next.size === 0)
1850
+ next.add('all');
1851
+ return next;
1852
+ });
1853
+ }}>
1854
+ <react_native_1.View style={[
1855
+ styles_1.default.statusFilterChip,
1856
+ active && {
1857
+ borderColor: '#64748B',
1858
+ backgroundColor: '#F1F5F9',
1859
+ },
1860
+ ]}>
1861
+ <react_native_1.Text numberOfLines={1} style={[
1862
+ styles_1.default.statusFilterText,
1863
+ active && {
1864
+ color: '#334155',
1865
+ fontFamily: AppFonts_1.AppFonts.interBold,
1866
+ },
1867
+ ]}>
1868
+ User Log ({logCounts['user-log']})
1869
+ </react_native_1.Text>
1870
+ </react_native_1.View>
1871
+ </TouchableScale_1.default>);
1872
+ })()}
1873
+
1874
+ {(() => {
1875
+ const active = logFilters.has('info');
1876
+ return (<TouchableScale_1.default onPress={() => {
1877
+ setLogFilters(prev => {
1878
+ const next = new Set(prev);
1879
+ next.delete('all');
1880
+ next.has('info')
1881
+ ? next.delete('info')
1882
+ : next.add('info');
1883
+ if (next.size === 0)
1884
+ next.add('all');
1885
+ return next;
1886
+ });
1887
+ }}>
1888
+ <react_native_1.View style={[
1889
+ styles_1.default.statusFilterChip,
1890
+ active && {
1891
+ borderColor: AppColors_1.AppColors.purple,
1892
+ backgroundColor: AppColors_1.AppColors.purpleShade50,
1893
+ },
1894
+ ]}>
1895
+ <react_native_1.Text numberOfLines={1} style={[
1896
+ styles_1.default.statusFilterText,
1897
+ active && {
1898
+ color: AppColors_1.AppColors.purple,
1899
+ fontFamily: AppFonts_1.AppFonts.interBold,
1900
+ },
1901
+ ]}>
1902
+ Info ({logCounts.info})
1903
+ </react_native_1.Text>
1904
+ </react_native_1.View>
1905
+ </TouchableScale_1.default>);
1906
+ })()}
1907
+
1908
+ {(() => {
1909
+ const active = logFilters.has('warn');
1910
+ return (<TouchableScale_1.default onPress={() => {
1911
+ setLogFilters(prev => {
1912
+ const next = new Set(prev);
1913
+ next.delete('all');
1914
+ next.has('warn')
1915
+ ? next.delete('warn')
1916
+ : next.add('warn');
1917
+ if (next.size === 0)
1918
+ next.add('all');
1919
+ return next;
1920
+ });
1921
+ }}>
1922
+ <react_native_1.View style={[
1923
+ styles_1.default.statusFilterChip,
1924
+ active && {
1925
+ borderColor: AppColors_1.AppColors.lightOrange,
1926
+ backgroundColor: '#FFFDF6',
1927
+ },
1928
+ ]}>
1929
+ <react_native_1.Text numberOfLines={1} style={[
1930
+ styles_1.default.statusFilterText,
1931
+ active && {
1932
+ color: AppColors_1.AppColors.darkOrange ||
1933
+ AppColors_1.AppColors.lightOrange,
1934
+ fontFamily: AppFonts_1.AppFonts.interBold,
1935
+ },
1936
+ ]}>
1937
+ Warning ({logCounts.warn})
1938
+ </react_native_1.Text>
1939
+ </react_native_1.View>
1940
+ </TouchableScale_1.default>);
1941
+ })()}
1942
+
1943
+ {(() => {
1944
+ const active = logFilters.has('error');
1945
+ return (<TouchableScale_1.default onPress={() => {
1946
+ setLogFilters(prev => {
1947
+ const next = new Set(prev);
1948
+ next.delete('all');
1949
+ next.has('error')
1950
+ ? next.delete('error')
1951
+ : next.add('error');
1952
+ if (next.size === 0)
1953
+ next.add('all');
1954
+ return next;
1955
+ });
1956
+ }}>
1957
+ <react_native_1.View style={[
1958
+ styles_1.default.statusFilterChip,
1959
+ active && {
1960
+ borderColor: AppColors_1.AppColors.errorColor,
1961
+ backgroundColor: '#FFF5F6',
1962
+ },
1963
+ ]}>
1964
+ <react_native_1.Text numberOfLines={1} style={[
1965
+ styles_1.default.statusFilterText,
1966
+ active && {
1967
+ color: AppColors_1.AppColors.errorColor,
1968
+ fontFamily: AppFonts_1.AppFonts.interBold,
1969
+ },
1970
+ ]}>
1971
+ Error ({logCounts.error})
1972
+ </react_native_1.Text>
1973
+ </react_native_1.View>
1974
+ </TouchableScale_1.default>);
1975
+ })()}
1976
+
1977
+ {(() => {
1978
+ const active = logFilters.has('analytics');
1979
+ return (<TouchableScale_1.default onPress={() => {
1980
+ setLogFilters(prev => {
1981
+ const next = new Set(prev);
1982
+ next.delete('all');
1983
+ next.has('analytics')
1984
+ ? next.delete('analytics')
1985
+ : next.add('analytics');
1986
+ if (next.size === 0)
1987
+ next.add('all');
1988
+ return next;
1989
+ });
1990
+ }}>
1991
+ <react_native_1.View style={[
1992
+ styles_1.default.statusFilterChip,
1993
+ active && {
1994
+ borderColor: AppColors_1.AppColors.skyBlue,
1995
+ backgroundColor: `${AppColors_1.AppColors.skyBlue}15`,
1996
+ },
1997
+ ]}>
1998
+ <react_native_1.Text numberOfLines={1} style={[
1999
+ styles_1.default.statusFilterText,
2000
+ active && {
2001
+ color: AppColors_1.AppColors.skyBlue,
2002
+ fontFamily: AppFonts_1.AppFonts.interBold,
2003
+ },
2004
+ ]}>
2005
+ Analytics ({logCounts.analytics})
2006
+ </react_native_1.Text>
2007
+ </react_native_1.View>
2008
+ </TouchableScale_1.default>);
2009
+ })()}
2010
+ </react_native_1.ScrollView>
2011
+ </react_native_1.View>
2012
+
2013
+ <react_native_1.FlatList data={filteredConsoleLogs} keyExtractor={item => item.id.toString()} ListHeaderComponent={(() => {
2014
+ const total = visibleConsoleLogs.length;
2015
+ const filtered = filteredConsoleLogs.length;
2016
+ const isAllSelected = logFilters.has('all') ||
2017
+ !Array.from(logFilters).some(f => f !== 'all');
2018
+ if (isAllSelected) {
2019
+ return (<react_native_1.Text style={[
2020
+ styles_1.default.resultCount,
2021
+ { marginBottom: 4, marginTop: 12 },
2022
+ ]}>
2023
+ Showing ({filtered}/{total}) logs showing
2024
+ </react_native_1.Text>);
2025
+ }
2026
+ else {
2027
+ const activeFilterNames = Array.from(logFilters)
2028
+ .filter(f => f !== 'all')
2029
+ .map(f => {
2030
+ if (f === 'user-log')
2031
+ return 'User Log';
2032
+ if (f === 'analytics')
2033
+ return 'Analytics';
2034
+ return f.charAt(0).toUpperCase() + f.slice(1);
2035
+ });
2036
+ return (<react_native_1.Text style={[
2037
+ styles_1.default.resultCount,
2038
+ { marginBottom: 4, marginTop: 12 },
2039
+ ]}>
2040
+ Filtering with {activeFilterNames.join(', ')} (
2041
+ {filtered}/{total}) logs is showing
2042
+ </react_native_1.Text>);
2043
+ }
2044
+ })()} renderItem={({ item }) => (<ConsoleLogCard_1.ConsoleLogCard item={item} searchStr={logSearch}/>)} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState_1.default isSearch={logSearch.length > 0 || logFilters.size > 0}/>} contentContainerStyle={[
2045
+ styles_1.default.listContent,
2046
+ filteredConsoleLogs.length === 0 && { flexGrow: 1 },
2047
+ ]} keyboardShouldPersistTaps="handled"/>
2048
+ </react_native_1.View>) : activeTab === 'webview' ? (<react_native_1.View style={{ flex: 1 }}>
2049
+ <react_native_1.View style={{
2050
+ backgroundColor: '#FFFFFF',
2051
+ borderBottomWidth: 1,
2052
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
2053
+ paddingBottom: 6,
2054
+ }}>
2055
+ {/* ─── WebView Sub-Tabs ─────────────────────────────────────── */}
2056
+ <react_native_1.View style={{
2057
+ marginHorizontal: 16,
2058
+ marginTop: webViewSubTab === 'navigation' ? 12 : 4,
2059
+ marginBottom: 8,
2060
+ backgroundColor: AppColors_1.AppColors.grayBackground,
2061
+ borderRadius: 8,
2062
+ padding: 4,
2063
+ flexDirection: 'row',
2064
+ borderWidth: 1,
2065
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
2066
+ }}>
2067
+ <react_native_1.Pressable style={[
2068
+ {
2069
+ flex: 1,
2070
+ paddingVertical: 8,
2071
+ borderRadius: 6,
2072
+ alignItems: 'center',
2073
+ },
2074
+ webViewSubTab === 'html' && {
2075
+ backgroundColor: AppColors_1.AppColors.primaryLight,
2076
+ shadowColor: '#000',
2077
+ shadowOpacity: 0.1,
2078
+ shadowRadius: 3,
2079
+ shadowOffset: { width: 0, height: 1 },
2080
+ elevation: 2,
2081
+ },
2082
+ ]} onPress={() => setWebViewSubTab('html')}>
2083
+ <react_native_1.Text style={[
2084
+ {
2085
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2086
+ fontSize: 12,
2087
+ color: AppColors_1.AppColors.grayTextStrong,
2088
+ },
2089
+ webViewSubTab === 'html' && {
2090
+ fontFamily: AppFonts_1.AppFonts.interBold,
2091
+ color: '#475569',
2092
+ },
2093
+ ]}>
2094
+ HTML Source
2095
+ </react_native_1.Text>
2096
+ </react_native_1.Pressable>
2097
+ <react_native_1.Pressable style={[
2098
+ {
2099
+ flex: 1,
2100
+ paddingVertical: 8,
2101
+ borderRadius: 6,
2102
+ alignItems: 'center',
2103
+ },
2104
+ webViewSubTab === 'navigation' && {
2105
+ backgroundColor: AppColors_1.AppColors.primaryLight,
2106
+ shadowColor: '#000',
2107
+ shadowOpacity: 0.1,
2108
+ shadowRadius: 3,
2109
+ shadowOffset: { width: 0, height: 1 },
2110
+ elevation: 2,
2111
+ },
2112
+ ]} onPress={() => setWebViewSubTab('navigation')}>
2113
+ <react_native_1.Text style={[
2114
+ {
2115
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2116
+ fontSize: 12,
2117
+ color: AppColors_1.AppColors.grayTextStrong,
2118
+ },
2119
+ webViewSubTab === 'navigation' && {
2120
+ fontFamily: AppFonts_1.AppFonts.interBold,
2121
+ color: '#475569',
2122
+ },
2123
+ ]}>
2124
+ Nav History ({webViewNavHistory.length})
2125
+ </react_native_1.Text>
2126
+ </react_native_1.Pressable>
2127
+ </react_native_1.View>
2128
+ </react_native_1.View>
2129
+
2130
+ {/* ─── Current Page Address Bar (Always visible at the top) ─── */}
2131
+ {(() => {
2132
+ const currentUrl = webViewNavHistory[0]?.url;
2133
+ if (!currentUrl)
2134
+ return null;
2135
+ return (<react_native_1.View style={{
2136
+ paddingHorizontal: 16,
2137
+ paddingTop: 10,
2138
+ paddingBottom: 10,
2139
+ backgroundColor: '#FFFFFF',
2140
+ borderBottomWidth: 1,
2141
+ borderBottomColor: AppColors_1.AppColors.dividerColor,
2142
+ }}>
2143
+ <react_native_1.Text style={{
2144
+ fontFamily: AppFonts_1.AppFonts.interBold,
2145
+ fontSize: 10,
2146
+ color: '#64748B',
2147
+ textTransform: 'uppercase',
2148
+ letterSpacing: 0.5,
2149
+ marginBottom: 6,
2150
+ }}>
2151
+ Currently debugging for URL
2152
+ </react_native_1.Text>
2153
+ <react_native_1.View style={{
2154
+ flexDirection: 'row',
2155
+ alignItems: 'center',
2156
+ backgroundColor: '#F1F5F9',
2157
+ borderRadius: 20,
2158
+ borderWidth: 1,
2159
+ borderColor: '#E2E8F0',
2160
+ paddingHorizontal: 12,
2161
+ paddingVertical: 6,
2162
+ gap: 8,
2163
+ }}>
2164
+ {/* Left: Clickable Globe Icon to open browser */}
2165
+ <TouchableScale_1.default onPress={() => react_native_1.Linking.openURL(currentUrl)} hitSlop={8} style={{
2166
+ width: 24,
2167
+ height: 24,
2168
+ borderRadius: 12,
2169
+ backgroundColor: '#E2E8F0',
2170
+ alignItems: 'center',
2171
+ justifyContent: 'center',
2172
+ }} children={<NetworkIcons_1.GlobeIcon size={12} color="#475569"/>}/>
2173
+
2174
+ {/* Middle: URL text (Address style) */}
2175
+ <react_native_1.View style={{ flex: 1 }}>
2176
+ <HighlightText_1.default text={currentUrl} search={webViewSearch} numberOfLines={1} ellipsizeMode="tail" style={{
2177
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2178
+ fontSize: 11,
2179
+ color: '#475569',
2180
+ }} highlightStyle={styles_1.default.highlight} detectLinks={false}/>
2181
+ </react_native_1.View>
2182
+
2183
+ {/* Right: Copy Button */}
2184
+ <CopyButton_1.default value={currentUrl} label="URL"/>
2185
+ </react_native_1.View>
2186
+ </react_native_1.View>);
2187
+ })()}
2188
+
2189
+ {webViewSubTab === 'html' ? (<react_native_1.View style={{ flex: 1 }}>
2190
+ {webViewHtml || webViewCss || webViewJs ? (<react_native_1.View style={{ flex: 1 }}>
2191
+ {/* Inner sub-tabs inside HTML source view */}
2192
+ <react_native_1.View style={{
2193
+ flexDirection: 'row',
2194
+ borderBottomWidth: 1,
2195
+ borderBottomColor: '#E2E8F0',
2196
+ backgroundColor: '#FFFFFF',
2197
+ paddingHorizontal: 16,
2198
+ }}>
2199
+ {['html', 'css', 'javascript'].map(tab => {
2200
+ const active = htmlSubTab === tab;
2201
+ const label = tab === 'html'
2202
+ ? 'HTML'
2203
+ : tab === 'css'
2204
+ ? 'CSS'
2205
+ : 'Javascript';
2206
+ return (<react_native_1.Pressable key={tab} onPress={() => setHtmlSubTab(tab)} style={{
2207
+ paddingVertical: 10,
2208
+ marginRight: 16,
2209
+ borderBottomWidth: 2,
2210
+ borderBottomColor: active
2211
+ ? AppColors_1.AppColors.purple
2212
+ : 'transparent',
2213
+ }}>
2214
+ <react_native_1.Text style={{
2215
+ fontFamily: active
2216
+ ? AppFonts_1.AppFonts.interBold
2217
+ : AppFonts_1.AppFonts.interMedium,
2218
+ fontSize: 12,
2219
+ color: active
2220
+ ? AppColors_1.AppColors.purple
2221
+ : '#64748B',
2222
+ }}>
2223
+ {label}
2224
+ </react_native_1.Text>
2225
+ </react_native_1.Pressable>);
2226
+ })}
2227
+ </react_native_1.View>
2228
+ <react_native_1.View style={{ flex: 1, padding: 12 }}>
2229
+ {htmlSubTab === 'html' ? (webViewHtml ? (<react_native_1.View style={{ flex: 1 }}>
2230
+ <react_native_1.View style={{
2231
+ flexDirection: 'row',
2232
+ alignItems: 'center',
2233
+ marginBottom: 8,
2234
+ gap: 8,
2235
+ }}>
2236
+ <react_native_1.View style={[
2237
+ styles_1.default.searchContainer,
2238
+ { flex: 1 },
2239
+ ]}>
2240
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
2241
+ <react_native_1.TextInput placeholder="Search HTML..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={htmlSearch} onChangeText={setHtmlSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
2242
+ {htmlSearch.length > 0 && (<react_native_1.Pressable onPress={() => setHtmlSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
2243
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2244
+ </react_native_1.Pressable>)}
2245
+ </react_native_1.View>
2246
+ <CopyButton_1.default value={webViewHtml} label="HTML Source"/>
2247
+ </react_native_1.View>
2248
+ <CodeSnippet_1.default code={webViewHtml} language="html" search={htmlSearch}/>
2249
+ </react_native_1.View>) : (<react_native_1.Text style={{
2250
+ fontFamily: 'monospace',
2251
+ fontSize: 11,
2252
+ color: '#94A3B8',
2253
+ padding: 12,
2254
+ }}>
2255
+ No HTML content captured.
2256
+ </react_native_1.Text>)) : htmlSubTab === 'css' ? (webViewCss ? (<react_native_1.View style={{ flex: 1 }}>
2257
+ <react_native_1.View style={{
2258
+ flexDirection: 'row',
2259
+ alignItems: 'center',
2260
+ marginBottom: 8,
2261
+ gap: 8,
2262
+ }}>
2263
+ <react_native_1.View style={[
2264
+ styles_1.default.searchContainer,
2265
+ { flex: 1 },
2266
+ ]}>
2267
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
2268
+ <react_native_1.TextInput placeholder="Search CSS..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={cssSearch} onChangeText={setCssSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
2269
+ {cssSearch.length > 0 && (<react_native_1.Pressable onPress={() => setCssSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
2270
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2271
+ </react_native_1.Pressable>)}
2272
+ </react_native_1.View>
2273
+ <CopyButton_1.default value={webViewCss} label="CSS Source"/>
2274
+ </react_native_1.View>
2275
+ <CodeSnippet_1.default code={webViewCss} language="css" search={cssSearch}/>
2276
+ </react_native_1.View>) : (<react_native_1.Text style={{
2277
+ fontFamily: 'monospace',
2278
+ fontSize: 11,
2279
+ color: '#94A3B8',
2280
+ padding: 12,
2281
+ }}>
2282
+ No CSS styles detected on this page.
2283
+ </react_native_1.Text>)) : webViewJs ? (<react_native_1.View style={{ flex: 1 }}>
2284
+ <react_native_1.View style={{
2285
+ flexDirection: 'row',
2286
+ alignItems: 'center',
2287
+ marginBottom: 8,
2288
+ gap: 8,
2289
+ }}>
2290
+ <react_native_1.View style={[styles_1.default.searchContainer, { flex: 1 }]}>
2291
+ <NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={16}/>
2292
+ <react_native_1.TextInput placeholder="Search Javascript..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={jsSearch} onChangeText={setJsSearch} style={styles_1.default.searchInput} autoCorrect={false} autoCapitalize="none"/>
2293
+ {jsSearch.length > 0 && (<react_native_1.Pressable onPress={() => setJsSearch('')} hitSlop={10} style={styles_1.default.clearBtn}>
2294
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2295
+ </react_native_1.Pressable>)}
2296
+ </react_native_1.View>
2297
+ <CopyButton_1.default value={webViewJs} label="JS Source"/>
2298
+ </react_native_1.View>
2299
+ <CodeSnippet_1.default code={webViewJs} language="javascript" search={jsSearch}/>
2300
+ </react_native_1.View>) : (<react_native_1.Text style={{
2301
+ fontFamily: 'monospace',
2302
+ fontSize: 11,
2303
+ color: '#94A3B8',
2304
+ padding: 12,
2305
+ }}>
2306
+ No scripts detected on this page.
2307
+ </react_native_1.Text>)}
2308
+ </react_native_1.View>
2309
+ </react_native_1.View>) : (<react_native_1.View style={styles_1.default.emptyContainer}>
2310
+ <react_native_1.View style={styles_1.default.emptyIconWrap}>
2311
+ <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.purple} size={32}/>
2312
+ </react_native_1.View>
2313
+ <react_native_1.Text style={styles_1.default.emptyTitle}>
2314
+ No Page Source Captured
2315
+ </react_native_1.Text>
2316
+ <react_native_1.Text style={styles_1.default.emptySub}>
2317
+ Load a page in the WebView to inspect its HTML, CSS,
2318
+ or Javascript source.
2319
+ </react_native_1.Text>
2320
+ </react_native_1.View>)}
2321
+ </react_native_1.View>) : (<react_native_1.FlatList data={filteredNavHistory} keyExtractor={(item, index) => `${index}-${item.timestamp}`} ListHeaderComponent={<react_native_1.View style={{
2322
+ paddingHorizontal: 16,
2323
+ paddingTop: 12,
2324
+ paddingBottom: 8,
2325
+ }}>
2326
+ <react_native_1.Text style={styles_1.default.resultCount}>
2327
+ Navigation History ({webViewNavHistory.length})
2328
+ </react_native_1.Text>
2329
+ </react_native_1.View>} renderItem={({ item, index, }) => {
2330
+ const isLatest = index === 0;
2331
+ const formatNavTime = (ts) => {
2332
+ const d = new Date(ts);
2333
+ return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
2334
+ };
2335
+ return (<react_native_1.View style={{
2336
+ paddingHorizontal: 16,
2337
+ paddingVertical: 8,
2338
+ backgroundColor: isLatest ? '#F1F5F9' : '#FFFFFF',
2339
+ borderBottomWidth: 1,
2340
+ borderBottomColor: '#E2E8F0',
2341
+ flexDirection: 'row',
2342
+ alignItems: 'center',
2343
+ justifyContent: 'space-between',
2344
+ gap: 12,
2345
+ }}>
2346
+ <react_native_1.View style={{ flex: 1, gap: 2 }}>
2347
+ <react_native_1.View style={{
2348
+ flexDirection: 'row',
2349
+ alignItems: 'center',
2350
+ gap: 6,
2351
+ flexWrap: 'wrap',
2352
+ }}>
2353
+ <react_native_1.Text numberOfLines={1} ellipsizeMode="tail" style={{
2354
+ fontFamily: AppFonts_1.AppFonts.interBold,
2355
+ fontSize: 13,
2356
+ color: '#334155',
2357
+ flexShrink: 1,
2358
+ }}>
2359
+ {item.title || 'Untitled Page'}
2360
+ </react_native_1.Text>
2361
+ {isLatest && (<react_native_1.View style={{
2362
+ backgroundColor: '#E2E8F0',
2363
+ paddingHorizontal: 6,
2364
+ paddingVertical: 2,
2365
+ borderRadius: 4,
2366
+ }}>
2367
+ <react_native_1.Text style={{
2368
+ fontFamily: AppFonts_1.AppFonts.interBold,
2369
+ fontSize: 9,
2370
+ color: '#475569',
2371
+ }}>
2372
+ Active
2373
+ </react_native_1.Text>
2374
+ </react_native_1.View>)}
2375
+ </react_native_1.View>
2376
+ <HighlightText_1.default text={item.url} search={webViewSearch} numberOfLines={3} ellipsizeMode="tail" style={{
2377
+ fontFamily: AppFonts_1.AppFonts.interRegular,
2378
+ fontSize: 11,
2379
+ color: '#64748B',
2380
+ flexShrink: 1,
2381
+ }} highlightStyle={styles_1.default.highlight} detectLinks={true}/>
2382
+ <react_native_1.Text style={{
2383
+ fontFamily: AppFonts_1.AppFonts.interRegular,
2384
+ fontSize: 10,
2385
+ color: '#94A3B8',
2386
+ }}>
2387
+ {formatNavTime(item.timestamp)}
2388
+ </react_native_1.Text>
2389
+ </react_native_1.View>
2390
+ <CopyButton_1.default value={item.url} label="Copy URL"/>
2391
+ </react_native_1.View>);
2392
+ }} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState_1.default isSearch={false}/>} contentContainerStyle={[
2393
+ styles_1.default.listContent,
2394
+ filteredNavHistory.length === 0 && { flexGrow: 1 },
2395
+ ]} keyboardShouldPersistTaps="handled"/>)}
2396
+ </react_native_1.View>) : (<react_native_1.ScrollView style={styles_1.default.detailScroll} contentContainerStyle={styles_1.default.detailContent} showsVerticalScrollIndicator={true}>
2397
+ {(() => {
2398
+ const routeInfo = logRouteMapRef.current.get(selected.id);
2399
+ const screenPath = routeInfo && routeInfo.path !== 'Navigators'
2400
+ ? routeInfo.path.split(' ➔ ')
2401
+ : [];
2402
+ const parts = ['APIs', 'APIs', ...screenPath];
2403
+ return (<react_native_1.View style={{ marginBottom: 12, marginTop: 4 }}>
2404
+ <react_native_1.Text style={{
2405
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2406
+ fontSize: 11.5,
2407
+ color: AppColors_1.AppColors.grayTextWeak,
2408
+ }}>
2409
+ {parts.map((part, index) => (<react_1.default.Fragment key={index}>
2410
+ {index > 0 && ' ➔ '}
2411
+ <react_native_1.Text style={index === parts.length - 1
2412
+ ? {
2413
+ color: AppColors_1.AppColors.purple,
2414
+ fontFamily: AppFonts_1.AppFonts.interBold,
2415
+ }
2416
+ : undefined}>
2417
+ {part}
2418
+ </react_native_1.Text>
2419
+ </react_1.default.Fragment>))}
2420
+ </react_native_1.Text>
2421
+ </react_native_1.View>);
2422
+ })()}
2423
+
2424
+ <react_native_1.View style={styles_1.default.detailInfoBar}>
2425
+ <react_native_1.View style={styles_1.default.detailInfoTop}>
2426
+ <react_native_1.View style={{
2427
+ flexDirection: 'row',
2428
+ alignItems: 'center',
2429
+ gap: 10,
2430
+ }}>
2431
+ <react_native_1.View style={[
2432
+ styles_1.default.methodBadge,
2433
+ {
2434
+ backgroundColor: `${constants_1.METHOD_COLORS[selected.method] ??
2435
+ constants_1.METHOD_COLORS.ALL}15`,
2436
+ },
2437
+ ]}>
2438
+ <react_native_1.Text style={[
2439
+ styles_1.default.methodBadgeText,
2440
+ {
2441
+ color: constants_1.METHOD_COLORS[selected.method] ??
2442
+ constants_1.METHOD_COLORS.ALL,
2443
+ },
2444
+ ]}>
2445
+ {selected.method}
2446
+ </react_native_1.Text>
2447
+ </react_native_1.View>
2448
+
2449
+ {selected.status != null && (<react_native_1.View style={[
2450
+ styles_1.default.chip,
2451
+ {
2452
+ backgroundColor: selected.status === 0
2453
+ ? `${AppColors_1.AppColors.errorColor}15`
2454
+ : `${(0, helpers_1.getStatusColor)(selected.status)}15`,
2455
+ borderColor: selected.status === 0
2456
+ ? `${AppColors_1.AppColors.errorColor}40`
2457
+ : `${(0, helpers_1.getStatusColor)(selected.status)}40`,
2458
+ },
2459
+ ]}>
2460
+ {selected.status === 0 ? (<NetworkIcons_1.FailIcon size={8} color={AppColors_1.AppColors.errorColor}/>) : (<react_native_svg_1.default width={6} height={6} viewBox="0 0 10 10" fill="none">
2461
+ <react_native_svg_1.Circle cx="5" cy="5" r="5" fill={(0, helpers_1.getStatusColor)(selected.status)}/>
2462
+ </react_native_svg_1.default>)}
2463
+ <react_native_1.Text style={[
2464
+ styles_1.default.chipText,
2465
+ {
2466
+ color: selected.status === 0
2467
+ ? AppColors_1.AppColors.errorColor
2468
+ : (0, helpers_1.getStatusColor)(selected.status),
2469
+ },
2470
+ ]}>
2471
+ {selected.status === 0
2472
+ ? 'Failed'
2473
+ : String(selected.status)}
2474
+ </react_native_1.Text>
2475
+ </react_native_1.View>)}
2476
+ </react_native_1.View>
2477
+ <react_native_1.View style={styles_1.default.detailInfoRight}>
2478
+ <TouchableScale_1.default style={styles_1.default.iconSquareBtn} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)} hitSlop={12}>
2479
+ <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2480
+ </TouchableScale_1.default>
2481
+ <CopyButton_1.default value={(0, helpers_1.getFetchCommand)(selected)} label="fetch()" iconType="fetch"/>
2482
+ <CopyButton_1.default value={(0, helpers_1.getCurlCommand)(selected)} label="cURL" iconType="terminal"/>
2483
+ <CopyButton_1.default value={detailDisplayUrl} label="URL"/>
2484
+ </react_native_1.View>
2485
+ </react_native_1.View>
2486
+
2487
+ <react_native_1.Pressable style={styles_1.default.detailUrlContainer} onPress={() => react_native_1.Linking.openURL(detailDisplayUrl)}>
2488
+ <react_native_1.Text selectable={true} style={styles_1.default.detailUrl}>
2489
+ {detailDisplayUrl}
2490
+ </react_native_1.Text>
2491
+ </react_native_1.Pressable>
2492
+ </react_native_1.View>
2493
+
2494
+ <MetaAccordion_1.default status={selected.status} statusColor={(0, helpers_1.getStatusColor)(selected.status)} duration={selected.duration} size={(0, helpers_1.getSize)(selected.response)} triggeredAt={(0, helpers_1.formatDateTime)(selected.startTime)}/>
2495
+
2496
+ {(() => {
2497
+ const routeInfo = logRouteMapRef.current.get(selected.id);
2498
+ if (!routeInfo || routeInfo.path === 'Navigators')
2499
+ return null;
2500
+ return <SourcePageCard_1.default routeInfo={routeInfo}/>;
2501
+ })()}
2502
+
2503
+ <react_native_1.View style={styles_1.default.seperator}/>
2504
+
2505
+ {(() => {
2506
+ const cType = selected.responseHeaders?.['content-type'] ||
2507
+ selected.responseHeaders?.['Content-Type'];
2508
+ if (cType?.includes('image/')) {
2509
+ return (<react_native_1.View style={styles_1.default.imagePreviewWrapper}>
2510
+ <react_native_1.Image source={{ uri: selected.url }} style={styles_1.default.imagePreview} resizeMode="contain"/>
2511
+ <TouchableScale_1.default style={styles_1.default.imageDownloadBtn} onPress={() => react_native_1.Linking.openURL(selected.url)} hitSlop={10}>
2512
+ <NetworkIcons_1.DownloadIcon color={AppColors_1.AppColors.purple} size={18}/>
2513
+ </TouchableScale_1.default>
2514
+ </react_native_1.View>);
2515
+ }
2516
+ return null;
2517
+ })()}
2518
+
2519
+ <react_native_1.View style={styles_1.default.detailSearchRow}>
2520
+ <react_native_1.View style={styles_1.default.detailSearchBox}>
2521
+ <react_native_1.TextInput placeholder="Search in request / response..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={detailSearch} onChangeText={setDetailSearch} style={styles_1.default.detailSearchInput} autoCorrect={false} autoCapitalize="none"/>
2522
+ {detailSearch.length > 0 && (<react_native_1.Pressable onPress={() => setDetailSearch('')} hitSlop={10} style={{ padding: 8 }}>
2523
+ <NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
2524
+ </react_native_1.Pressable>)}
2525
+ </react_native_1.View>
2526
+ <TouchableScale_1.default style={[styles_1.default.iconSquareBtn, { marginLeft: 8 }]} onPress={() => {
2527
+ const next = reqExpanded === true || resExpanded === true
2528
+ ? false
2529
+ : true;
2530
+ setReqExpanded(next);
2531
+ setResExpanded(next);
2532
+ }} hitSlop={10}>
2533
+ <NetworkIcons_1.ExpandCollapseIcon isExpanded={reqExpanded === true || resExpanded === true} color={reqExpanded === true || resExpanded === true
2534
+ ? AppColors_1.AppColors.purple
2535
+ : AppColors_1.AppColors.grayTextWeak} size={14}/>
2536
+ </TouchableScale_1.default>
2537
+ </react_native_1.View>
2538
+
2539
+ <HeadersSection_1.default title="Request Headers" headers={selected.requestHeaders} search={detailSearch} resetKey={selected.id}/>
2540
+ <HeadersSection_1.default title="Response Headers" headers={selected.responseHeaders} search={detailSearch} resetKey={selected.id}/>
2541
+
2542
+ {selected.request != null && selected.method !== 'GET' && (<react_native_1.View style={styles_1.default.sectionContainer}>
2543
+ <SectionHeader_1.default title="Request" value={selected.request} expanded={reqExpanded} onToggleExpand={() => setReqExpanded(v => !v)} showDiff={prevRequestData != null} isDiffing={showReqDiff} onToggleDiff={() => {
2544
+ setShowReqDiff(v => !v);
2545
+ if (!reqExpanded && !showReqDiff)
2546
+ setReqExpanded(true);
2547
+ }}/>
2548
+ {showReqDiff ? (<DiffViewer_1.default oldData={prevRequestData} newData={selected.request} forceOpen={reqExpanded}/>) : (<JsonViewer_1.default data={selected.request} search={detailSearch} forceOpen={reqExpanded}/>)}
2549
+ </react_native_1.View>)}
2550
+
2551
+ <react_native_1.View style={styles_1.default.sectionContainer}>
2552
+ <SectionHeader_1.default title="Response" value={selected.response} expanded={resExpanded} onToggleExpand={() => setResExpanded(v => !v)} showDiff={prevResponseData != null} isDiffing={showResDiff} onToggleDiff={() => {
2553
+ setShowResDiff(v => !v);
2554
+ if (!resExpanded && !showResDiff)
2555
+ setResExpanded(true);
2556
+ }}/>
2557
+ {showResDiff ? (<DiffViewer_1.default oldData={prevResponseData} newData={selected.response} forceOpen={resExpanded}/>) : (<JsonViewer_1.default data={selected.response} search={detailSearch} forceOpen={resExpanded}/>)}
2558
+ </react_native_1.View>
2559
+ </react_native_1.ScrollView>)) : (<react_native_1.View style={styles_1.default.empty}>
2560
+ <react_native_1.ActivityIndicator size="large" color={AppColors_1.AppColors.purple}/>
2561
+ <react_native_1.Text style={[styles_1.default.emptySub, { marginTop: 12 }]}>
2562
+ Loading logs...
2563
+ </react_native_1.Text>
2564
+ </react_native_1.View>)}
2565
+ </react_native_1.View>)}
2566
+ </react_native_1.Modal>
2567
+ </>);
2568
+ };
2569
+ exports.default = NetworkInspector;
2570
+ // ─── Analytics list styles (Firebase DebugView look) ─────────────────────────
2571
+ const analyticsListStyles = react_native_1.StyleSheet.create({
2572
+ cardRow: {},
2573
+ // ── Top Events summary card (mirrors Firebase DebugView right panel) ────────
2574
+ topEventsCard: {
2575
+ marginHorizontal: 16,
2576
+ marginBottom: 12,
2577
+ backgroundColor: AppColors_1.AppColors.primaryLight,
2578
+ borderRadius: 12,
2579
+ borderWidth: 1,
2580
+ borderColor: AppColors_1.AppColors.grayBorderSecondary,
2581
+ paddingHorizontal: 16,
2582
+ paddingVertical: 12,
2583
+ shadowColor: '#000',
2584
+ shadowOpacity: 0.04,
2585
+ shadowRadius: 4,
2586
+ shadowOffset: { width: 0, height: 1 },
2587
+ elevation: 1,
2588
+ },
2589
+ topEventsHeaderRow: {
2590
+ flexDirection: 'row',
2591
+ alignItems: 'center',
2592
+ justifyContent: 'space-between',
2593
+ marginBottom: 12,
2594
+ },
2595
+ topEventsTitle: {
2596
+ fontFamily: AppFonts_1.AppFonts.interBold,
2597
+ fontSize: 10,
2598
+ color: AppColors_1.AppColors.grayTextWeak,
2599
+ letterSpacing: 0.8,
2600
+ textTransform: 'uppercase',
2601
+ },
2602
+ topEventsSubtitle: {
2603
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2604
+ fontSize: 9,
2605
+ color: AppColors_1.AppColors.grayTextWeak,
2606
+ letterSpacing: 0.4,
2607
+ },
2608
+ topEventRow: {
2609
+ flexDirection: 'row',
2610
+ alignItems: 'center',
2611
+ marginBottom: 8,
2612
+ gap: 8,
2613
+ },
2614
+ topEventName: {
2615
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2616
+ fontSize: 12,
2617
+ color: AppColors_1.AppColors.primaryBlack,
2618
+ flex: 1,
2619
+ },
2620
+ topEventBarWrap: {
2621
+ flex: 0.8,
2622
+ height: 3,
2623
+ backgroundColor: AppColors_1.AppColors.grayBackground,
2624
+ borderRadius: 2,
2625
+ overflow: 'hidden',
2626
+ },
2627
+ topEventBar: {
2628
+ height: '100%',
2629
+ borderRadius: 2,
2630
+ },
2631
+ topEventCount: {
2632
+ fontFamily: AppFonts_1.AppFonts.interBold,
2633
+ fontSize: 11,
2634
+ color: AppColors_1.AppColors.grayText,
2635
+ width: 24,
2636
+ textAlign: 'right',
2637
+ },
2638
+ iconCircle: {
2639
+ width: 24,
2640
+ height: 24,
2641
+ borderRadius: 12,
2642
+ alignItems: 'center',
2643
+ justifyContent: 'center',
2644
+ },
2645
+ });
2646
+ // Re-export public APIs
2647
+ var networkLogger_2 = require("./customHooks/networkLogger");
2648
+ Object.defineProperty(exports, "setupNetworkLogger", { enumerable: true, get: function () { return networkLogger_2.setupNetworkLogger; } });
2649
+ Object.defineProperty(exports, "clearNetworkLogs", { enumerable: true, get: function () { return networkLogger_2.clearNetworkLogs; } });
2650
+ Object.defineProperty(exports, "subscribeNetworkLogs", { enumerable: true, get: function () { return networkLogger_2.subscribeNetworkLogs; } });
2651
+ var consoleLogger_2 = require("./customHooks/consoleLogger");
2652
+ Object.defineProperty(exports, "setupConsoleLogger", { enumerable: true, get: function () { return consoleLogger_2.setupConsoleLogger; } });
2653
+ Object.defineProperty(exports, "clearConsoleLogs", { enumerable: true, get: function () { return consoleLogger_2.clearConsoleLogs; } });
2654
+ Object.defineProperty(exports, "subscribeConsoleLogs", { enumerable: true, get: function () { return consoleLogger_2.subscribeConsoleLogs; } });
2655
+ var analyticsLogger_2 = require("./customHooks/analyticsLogger");
2656
+ Object.defineProperty(exports, "setupAnalyticsLogger", { enumerable: true, get: function () { return analyticsLogger_2.setupAnalyticsLogger; } });
2657
+ Object.defineProperty(exports, "logAnalyticsEvent", { enumerable: true, get: function () { return analyticsLogger_2.logAnalyticsEvent; } });
2658
+ Object.defineProperty(exports, "subscribeAnalyticsEvents", { enumerable: true, get: function () { return analyticsLogger_2.subscribeAnalyticsEvents; } });
2659
+ Object.defineProperty(exports, "clearAnalyticsEvents", { enumerable: true, get: function () { return analyticsLogger_2.clearAnalyticsEvents; } });
2660
+ var webViewLogger_2 = require("./customHooks/webViewLogger");
2661
+ Object.defineProperty(exports, "getWebViewLogs", { enumerable: true, get: function () { return webViewLogger_2.getWebViewLogs; } });
2662
+ Object.defineProperty(exports, "getWebViewNavHistory", { enumerable: true, get: function () { return webViewLogger_2.getWebViewNavHistory; } });
2663
+ Object.defineProperty(exports, "getWebViewHtml", { enumerable: true, get: function () { return webViewLogger_2.getWebViewHtml; } });
2664
+ Object.defineProperty(exports, "getWebViewCss", { enumerable: true, get: function () { return webViewLogger_2.getWebViewCss; } });
2665
+ Object.defineProperty(exports, "getWebViewJs", { enumerable: true, get: function () { return webViewLogger_2.getWebViewJs; } });
2666
+ Object.defineProperty(exports, "getWebViewHtmlUrl", { enumerable: true, get: function () { return webViewLogger_2.getWebViewHtmlUrl; } });
2667
+ Object.defineProperty(exports, "clearWebViewData", { enumerable: true, get: function () { return webViewLogger_2.clearWebViewData; } });
2668
+ Object.defineProperty(exports, "subscribeWebView", { enumerable: true, get: function () { return webViewLogger_2.subscribeWebView; } });