react-native-inapp-inspector 1.1.14 → 1.1.15

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 (239) hide show
  1. package/README.md +9 -34
  2. package/dist/commonjs/assets/svgAssets.d.ts +3 -0
  3. package/dist/commonjs/assets/svgAssets.js +17 -0
  4. package/dist/commonjs/components/AnalyticsEventCard.d.ts +1 -14
  5. package/dist/commonjs/components/AnalyticsEventCard.js +34 -51
  6. package/dist/commonjs/components/AnalyticsGraph.d.ts +2 -6
  7. package/dist/commonjs/components/AnalyticsGraph.js +8 -8
  8. package/dist/commonjs/components/AnalyticsTabView.d.ts +15 -0
  9. package/dist/commonjs/components/AnalyticsTabView.js +157 -0
  10. package/dist/commonjs/components/AnimatedEntrance.d.ts +1 -1
  11. package/dist/commonjs/components/AnimatedEntrance.js +2 -2
  12. package/dist/commonjs/components/ApiDetailView.d.ts +22 -0
  13. package/dist/commonjs/components/ApiDetailView.js +304 -0
  14. package/dist/commonjs/components/ApisTabView.d.ts +33 -0
  15. package/dist/commonjs/components/ApisTabView.js +235 -0
  16. package/dist/commonjs/components/CodeSnippet.d.ts +1 -5
  17. package/dist/commonjs/components/CodeSnippet.js +34 -34
  18. package/dist/commonjs/components/ConsoleLogCard.d.ts +1 -8
  19. package/dist/commonjs/components/ConsoleLogCard.js +262 -442
  20. package/dist/commonjs/components/ConsoleLogDetailView.d.ts +9 -0
  21. package/dist/commonjs/components/ConsoleLogDetailView.js +278 -0
  22. package/dist/commonjs/components/ConsoleLogsTabView.d.ts +24 -0
  23. package/dist/commonjs/components/ConsoleLogsTabView.js +354 -0
  24. package/dist/commonjs/components/DiffViewer.js +4 -2
  25. package/dist/commonjs/components/DomainHeader.js +66 -41
  26. package/dist/commonjs/components/EmptyState.d.ts +2 -2
  27. package/dist/commonjs/components/EmptyState.js +2 -2
  28. package/dist/commonjs/components/EndOfListFooter.d.ts +8 -0
  29. package/dist/commonjs/components/EndOfListFooter.js +90 -0
  30. package/dist/commonjs/components/ErrorBoundary.d.ts +5 -14
  31. package/dist/commonjs/components/ErrorBoundary.js +28 -28
  32. package/dist/commonjs/components/FloatingBubble.d.ts +14 -0
  33. package/dist/commonjs/components/FloatingBubble.js +75 -0
  34. package/dist/commonjs/components/HeadersSection.js +5 -3
  35. package/dist/commonjs/components/HighlightText.d.ts +1 -1
  36. package/dist/commonjs/components/HighlightText.js +5 -7
  37. package/dist/commonjs/components/Inspector/AnalyticsTab.d.ts +3 -0
  38. package/dist/commonjs/components/Inspector/AnalyticsTab.js +232 -0
  39. package/dist/commonjs/components/Inspector/ConsoleTab.d.ts +3 -0
  40. package/dist/commonjs/components/Inspector/ConsoleTab.js +410 -0
  41. package/dist/commonjs/components/Inspector/FabLauncher.d.ts +3 -0
  42. package/dist/commonjs/components/Inspector/FabLauncher.js +54 -0
  43. package/dist/commonjs/components/Inspector/InsightsDashboard.d.ts +3 -0
  44. package/dist/commonjs/components/Inspector/InsightsDashboard.js +619 -0
  45. package/dist/commonjs/components/Inspector/InspectorContext.d.ts +5 -0
  46. package/dist/commonjs/components/Inspector/InspectorContext.js +18 -0
  47. package/dist/commonjs/components/Inspector/InspectorHeader.d.ts +3 -0
  48. package/dist/commonjs/components/Inspector/InspectorHeader.js +452 -0
  49. package/dist/commonjs/components/Inspector/LogDetail.d.ts +3 -0
  50. package/dist/commonjs/components/Inspector/LogDetail.js +963 -0
  51. package/dist/commonjs/components/Inspector/MainScreen.d.ts +3 -0
  52. package/dist/commonjs/components/Inspector/MainScreen.js +68 -0
  53. package/dist/commonjs/components/Inspector/NavigationTracker.d.ts +3 -0
  54. package/dist/commonjs/components/Inspector/NavigationTracker.js +12 -0
  55. package/dist/commonjs/components/Inspector/NetworkDetail.d.ts +3 -0
  56. package/dist/commonjs/components/Inspector/NetworkDetail.js +405 -0
  57. package/dist/commonjs/components/Inspector/NetworkTab.d.ts +3 -0
  58. package/dist/commonjs/components/Inspector/NetworkTab.js +281 -0
  59. package/dist/commonjs/components/Inspector/ReduxTab.d.ts +3 -0
  60. package/dist/commonjs/components/Inspector/ReduxTab.js +75 -0
  61. package/dist/commonjs/components/Inspector/SettingsPanel.d.ts +3 -0
  62. package/dist/commonjs/components/Inspector/SettingsPanel.js +1476 -0
  63. package/dist/commonjs/components/Inspector/TabBar.d.ts +3 -0
  64. package/dist/commonjs/components/Inspector/TabBar.js +95 -0
  65. package/dist/commonjs/components/Inspector/WebViewTab.d.ts +3 -0
  66. package/dist/commonjs/components/Inspector/WebViewTab.js +757 -0
  67. package/dist/commonjs/components/InspectorHeader.d.ts +19 -0
  68. package/dist/commonjs/components/InspectorHeader.js +329 -0
  69. package/dist/commonjs/components/InspectorTabBar.d.ts +16 -0
  70. package/dist/commonjs/components/InspectorTabBar.js +90 -0
  71. package/dist/commonjs/components/JsonViewer.d.ts +4 -1
  72. package/dist/commonjs/components/JsonViewer.js +110 -171
  73. package/dist/commonjs/components/LogCard.js +109 -86
  74. package/dist/commonjs/components/MetaAccordion.d.ts +1 -10
  75. package/dist/commonjs/components/MetaAccordion.js +23 -21
  76. package/dist/commonjs/components/NavigationTracker.d.ts +7 -0
  77. package/dist/commonjs/components/NavigationTracker.js +76 -0
  78. package/dist/commonjs/components/NetworkIcons.d.ts +6 -0
  79. package/dist/commonjs/components/NetworkIcons.js +54 -8
  80. package/dist/commonjs/components/ReduxTabView.d.ts +9 -0
  81. package/dist/commonjs/components/ReduxTabView.js +56 -0
  82. package/dist/commonjs/components/ReduxTreeView.js +241 -200
  83. package/dist/commonjs/components/SegmentedTabs.d.ts +15 -0
  84. package/dist/commonjs/components/SegmentedTabs.js +52 -0
  85. package/dist/commonjs/components/SettingsView.d.ts +13 -0
  86. package/dist/commonjs/components/SettingsView.js +328 -0
  87. package/dist/commonjs/components/TouchableScale.d.ts +2 -2
  88. package/dist/commonjs/components/TouchableScale.js +2 -2
  89. package/dist/commonjs/components/TreeNode.js +2 -2
  90. package/dist/commonjs/constants/index.js +1 -12
  91. package/dist/commonjs/constants/version.d.ts +1 -1
  92. package/dist/commonjs/constants/version.js +1 -1
  93. package/dist/commonjs/customHooks/consoleLogger.js +137 -13
  94. package/dist/commonjs/customHooks/networkLogger.d.ts +0 -1
  95. package/dist/commonjs/customHooks/networkLogger.js +0 -1
  96. package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -9
  97. package/dist/commonjs/enums/index.d.ts +39 -0
  98. package/dist/commonjs/enums/index.js +50 -0
  99. package/dist/commonjs/helpers/index.d.ts +27 -1
  100. package/dist/commonjs/helpers/index.js +187 -12
  101. package/dist/commonjs/helpers/settingsStore.d.ts +2 -24
  102. package/dist/commonjs/i18n/en.json +144 -0
  103. package/dist/commonjs/i18n/index.d.ts +2 -0
  104. package/dist/commonjs/i18n/index.js +27 -0
  105. package/dist/commonjs/i18n/locales/en.json +314 -0
  106. package/dist/commonjs/index.d.ts +1 -2
  107. package/dist/commonjs/index.js +196 -4800
  108. package/dist/commonjs/styles/AppColors.d.ts +148 -0
  109. package/dist/commonjs/styles/AppColors.js +176 -0
  110. package/dist/commonjs/styles/common.d.ts +3 -0
  111. package/dist/commonjs/styles/common.js +201 -0
  112. package/dist/commonjs/styles/index.d.ts +167 -442
  113. package/dist/commonjs/styles/index.js +239 -471
  114. package/dist/commonjs/types/enums.d.ts +9 -0
  115. package/dist/commonjs/types/enums.js +4 -0
  116. package/dist/commonjs/types/index.d.ts +4 -111
  117. package/dist/commonjs/types/index.js +16 -0
  118. package/dist/commonjs/types/interfaces.d.ts +337 -0
  119. package/dist/commonjs/types/interfaces.js +2 -0
  120. package/dist/esm/assets/svgAssets.d.ts +3 -0
  121. package/dist/esm/assets/svgAssets.js +14 -0
  122. package/dist/esm/components/AnalyticsEventCard.d.ts +1 -14
  123. package/dist/esm/components/AnalyticsEventCard.js +32 -49
  124. package/dist/esm/components/AnalyticsGraph.d.ts +2 -6
  125. package/dist/esm/components/AnalyticsGraph.js +8 -8
  126. package/dist/esm/components/AnalyticsTabView.d.ts +15 -0
  127. package/dist/esm/components/AnalyticsTabView.js +151 -0
  128. package/dist/esm/components/AnimatedEntrance.d.ts +1 -1
  129. package/dist/esm/components/AnimatedEntrance.js +2 -2
  130. package/dist/esm/components/ApiDetailView.d.ts +22 -0
  131. package/dist/esm/components/ApiDetailView.js +264 -0
  132. package/dist/esm/components/ApisTabView.d.ts +33 -0
  133. package/dist/esm/components/ApisTabView.js +196 -0
  134. package/dist/esm/components/CodeSnippet.d.ts +1 -5
  135. package/dist/esm/components/CodeSnippet.js +34 -34
  136. package/dist/esm/components/ConsoleLogCard.d.ts +1 -8
  137. package/dist/esm/components/ConsoleLogCard.js +262 -409
  138. package/dist/esm/components/ConsoleLogDetailView.d.ts +9 -0
  139. package/dist/esm/components/ConsoleLogDetailView.js +271 -0
  140. package/dist/esm/components/ConsoleLogsTabView.d.ts +24 -0
  141. package/dist/esm/components/ConsoleLogsTabView.js +348 -0
  142. package/dist/esm/components/DiffViewer.js +4 -2
  143. package/dist/esm/components/DomainHeader.js +66 -41
  144. package/dist/esm/components/EmptyState.d.ts +2 -2
  145. package/dist/esm/components/EmptyState.js +2 -2
  146. package/dist/esm/components/EndOfListFooter.d.ts +8 -0
  147. package/dist/esm/components/EndOfListFooter.js +83 -0
  148. package/dist/esm/components/ErrorBoundary.d.ts +5 -14
  149. package/dist/esm/components/ErrorBoundary.js +29 -29
  150. package/dist/esm/components/FloatingBubble.d.ts +14 -0
  151. package/dist/esm/components/FloatingBubble.js +68 -0
  152. package/dist/esm/components/HeadersSection.js +5 -3
  153. package/dist/esm/components/HighlightText.d.ts +1 -1
  154. package/dist/esm/components/HighlightText.js +5 -7
  155. package/dist/esm/components/Inspector/AnalyticsTab.d.ts +3 -0
  156. package/dist/esm/components/Inspector/AnalyticsTab.js +194 -0
  157. package/dist/esm/components/Inspector/ConsoleTab.d.ts +3 -0
  158. package/dist/esm/components/Inspector/ConsoleTab.js +372 -0
  159. package/dist/esm/components/Inspector/FabLauncher.d.ts +3 -0
  160. package/dist/esm/components/Inspector/FabLauncher.js +49 -0
  161. package/dist/esm/components/Inspector/InsightsDashboard.d.ts +3 -0
  162. package/dist/esm/components/Inspector/InsightsDashboard.js +614 -0
  163. package/dist/esm/components/Inspector/InspectorContext.d.ts +5 -0
  164. package/dist/esm/components/Inspector/InspectorContext.js +13 -0
  165. package/dist/esm/components/Inspector/InspectorHeader.d.ts +3 -0
  166. package/dist/esm/components/Inspector/InspectorHeader.js +447 -0
  167. package/dist/esm/components/Inspector/LogDetail.d.ts +3 -0
  168. package/dist/esm/components/Inspector/LogDetail.js +925 -0
  169. package/dist/esm/components/Inspector/MainScreen.d.ts +3 -0
  170. package/dist/esm/components/Inspector/MainScreen.js +63 -0
  171. package/dist/esm/components/Inspector/NavigationTracker.d.ts +3 -0
  172. package/dist/esm/components/Inspector/NavigationTracker.js +10 -0
  173. package/dist/esm/components/Inspector/NetworkDetail.d.ts +3 -0
  174. package/dist/esm/components/Inspector/NetworkDetail.js +367 -0
  175. package/dist/esm/components/Inspector/NetworkTab.d.ts +3 -0
  176. package/dist/esm/components/Inspector/NetworkTab.js +243 -0
  177. package/dist/esm/components/Inspector/ReduxTab.d.ts +3 -0
  178. package/dist/esm/components/Inspector/ReduxTab.js +70 -0
  179. package/dist/esm/components/Inspector/SettingsPanel.d.ts +3 -0
  180. package/dist/esm/components/Inspector/SettingsPanel.js +1438 -0
  181. package/dist/esm/components/Inspector/TabBar.d.ts +3 -0
  182. package/dist/esm/components/Inspector/TabBar.js +90 -0
  183. package/dist/esm/components/Inspector/WebViewTab.d.ts +3 -0
  184. package/dist/esm/components/Inspector/WebViewTab.js +752 -0
  185. package/dist/esm/components/InspectorHeader.d.ts +19 -0
  186. package/dist/esm/components/InspectorHeader.js +323 -0
  187. package/dist/esm/components/InspectorTabBar.d.ts +16 -0
  188. package/dist/esm/components/InspectorTabBar.js +84 -0
  189. package/dist/esm/components/JsonViewer.d.ts +4 -1
  190. package/dist/esm/components/JsonViewer.js +111 -172
  191. package/dist/esm/components/LogCard.js +111 -88
  192. package/dist/esm/components/MetaAccordion.d.ts +1 -10
  193. package/dist/esm/components/MetaAccordion.js +23 -21
  194. package/dist/esm/components/NavigationTracker.d.ts +7 -0
  195. package/dist/esm/components/NavigationTracker.js +39 -0
  196. package/dist/esm/components/NetworkIcons.d.ts +6 -0
  197. package/dist/esm/components/NetworkIcons.js +46 -6
  198. package/dist/esm/components/ReduxTabView.d.ts +9 -0
  199. package/dist/esm/components/ReduxTabView.js +50 -0
  200. package/dist/esm/components/ReduxTreeView.js +243 -202
  201. package/dist/esm/components/SegmentedTabs.d.ts +15 -0
  202. package/dist/esm/components/SegmentedTabs.js +47 -0
  203. package/dist/esm/components/SettingsView.d.ts +13 -0
  204. package/dist/esm/components/SettingsView.js +321 -0
  205. package/dist/esm/components/TouchableScale.d.ts +2 -2
  206. package/dist/esm/components/TouchableScale.js +2 -2
  207. package/dist/esm/components/TreeNode.js +2 -2
  208. package/dist/esm/constants/index.js +1 -12
  209. package/dist/esm/constants/version.d.ts +1 -1
  210. package/dist/esm/constants/version.js +1 -1
  211. package/dist/esm/customHooks/consoleLogger.js +137 -13
  212. package/dist/esm/customHooks/networkLogger.d.ts +0 -1
  213. package/dist/esm/customHooks/networkLogger.js +0 -1
  214. package/dist/esm/customHooks/reduxLogger.d.ts +2 -9
  215. package/dist/esm/enums/index.d.ts +39 -0
  216. package/dist/esm/enums/index.js +47 -0
  217. package/dist/esm/helpers/index.d.ts +27 -1
  218. package/dist/esm/helpers/index.js +180 -11
  219. package/dist/esm/helpers/settingsStore.d.ts +2 -24
  220. package/dist/esm/i18n/en.json +144 -0
  221. package/dist/esm/i18n/index.d.ts +2 -0
  222. package/dist/esm/i18n/index.js +22 -0
  223. package/dist/esm/i18n/locales/en.json +314 -0
  224. package/dist/esm/index.d.ts +1 -2
  225. package/dist/esm/index.js +200 -4796
  226. package/dist/esm/styles/AppColors.d.ts +148 -0
  227. package/dist/esm/styles/AppColors.js +176 -0
  228. package/dist/esm/styles/common.d.ts +3 -0
  229. package/dist/esm/styles/common.js +197 -0
  230. package/dist/esm/styles/index.d.ts +167 -442
  231. package/dist/esm/styles/index.js +239 -471
  232. package/dist/esm/types/enums.d.ts +9 -0
  233. package/dist/esm/types/enums.js +3 -0
  234. package/dist/esm/types/index.d.ts +4 -111
  235. package/dist/esm/types/index.js +2 -1
  236. package/dist/esm/types/interfaces.d.ts +337 -0
  237. package/dist/esm/types/interfaces.js +1 -0
  238. package/example/App.tsx +88 -1
  239. package/package.json +3 -1
@@ -0,0 +1,752 @@
1
+ import React from 'react';
2
+ import { ActivityIndicator, FlatList, Linking, Pressable, ScrollView, Text, View, } from 'react-native';
3
+ import { animateNextLayout, useInspector } from './InspectorContext';
4
+ import TouchableScale from '../TouchableScale';
5
+ import AnimatedEntrance from '../AnimatedEntrance';
6
+ import EmptyState from '../EmptyState';
7
+ import HighlightText from '../HighlightText';
8
+ import CodeSnippet from '../CodeSnippet';
9
+ import CopyButton from '../CopyButton';
10
+ import styles from '../../styles';
11
+ import { AppColors } from '../../styles/AppColors';
12
+ import { AppFonts } from '../../styles/AppFonts';
13
+ import { clearWebViewData } from '../../customHooks/webViewLogger';
14
+ import { GlobeIcon, EyeIcon, HtmlIcon, ClockIcon, TerminalIcon, CssIcon, JsIcon, TrashIcon, } from '../NetworkIcons';
15
+ let OriginalWebView = null;
16
+ try {
17
+ const RNWebView = require('react-native-webview');
18
+ OriginalWebView = RNWebView.WebView || RNWebView.default;
19
+ }
20
+ catch (e) {
21
+ // Silent fail
22
+ }
23
+ const previewInspectScript = `
24
+ (function() {
25
+ var style = document.createElement('style');
26
+ style.innerHTML = '* { cursor: pointer !important; }';
27
+ document.head.appendChild(style);
28
+
29
+ document.addEventListener('click', function(e) {
30
+ var el = e.target;
31
+ if (!el) return;
32
+
33
+ e.preventDefault();
34
+ e.stopPropagation();
35
+
36
+ var oldOutline = el.style.outline;
37
+ var oldTransition = el.style.transition;
38
+ el.style.transition = 'outline 0.15s ease';
39
+ el.style.outline = '3px solid #684B9B';
40
+ setTimeout(function() {
41
+ el.style.outline = oldOutline;
42
+ el.style.transition = oldTransition;
43
+ }, 600);
44
+
45
+ var tagName = el.tagName.toLowerCase();
46
+ var searchStr = '<' + tagName;
47
+
48
+ if (el.id) {
49
+ searchStr += ' id="' + el.id + '"';
50
+ } else if (el.className && typeof el.className === 'string') {
51
+ var firstClass = el.className.trim().split(/\\s+/)[0];
52
+ if (firstClass) {
53
+ searchStr += ' class="' + firstClass;
54
+ }
55
+ } else {
56
+ var text = (el.textContent || '').trim().substring(0, 25);
57
+ if (text) {
58
+ searchStr = text;
59
+ }
60
+ }
61
+
62
+ if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {
63
+ window.ReactNativeWebView.postMessage(JSON.stringify({
64
+ type: 'preview-inspect',
65
+ tagName: tagName,
66
+ id: el.id || '',
67
+ className: typeof el.className === 'string' ? el.className : '',
68
+ searchStr: searchStr
69
+ }));
70
+ }
71
+ }, true);
72
+ })();
73
+ true;
74
+ `;
75
+ const WebViewTab = () => {
76
+ const { webViewNavHistory, webViewSearch, webViewSubTab, setWebViewSubTab, webViewLogs, webViewHtml, webViewCss, webViewJs, webViewHtmlUrl, htmlSubTab, setHtmlSubTab, isHtmlTabReady, inspectedElement, setInspectedElement, getSearchTermForTab, filteredNavHistory, isDark, } = useInspector();
77
+ if (webViewNavHistory.length === 0) {
78
+ return (<View style={styles.emptyContainer}>
79
+ <View style={styles.emptyIconWrap}>
80
+ <GlobeIcon color={AppColors.purple} size={32}/>
81
+ </View>
82
+ <Text style={styles.emptyTitle}>
83
+ No WebView Activity
84
+ </Text>
85
+ <Text style={styles.emptySub}>
86
+ Load a webpage within a connected WebView component to
87
+ inspect pages, page source, and console logs.
88
+ </Text>
89
+ </View>);
90
+ }
91
+ return (<View style={{ flex: 1 }}>
92
+ {/* ─── Current Page Address Bar (Now on top) ─── */}
93
+ {(() => {
94
+ const currentUrl = webViewNavHistory[0]?.url;
95
+ if (!currentUrl)
96
+ return null;
97
+ return (<View style={{
98
+ paddingHorizontal: 12,
99
+ paddingTop: 6,
100
+ paddingBottom: 6,
101
+ backgroundColor: AppColors.primaryLight,
102
+ borderBottomWidth: 1,
103
+ borderBottomColor: AppColors.dividerColor,
104
+ }}>
105
+ <View style={{
106
+ flexDirection: 'row',
107
+ alignItems: 'center',
108
+ backgroundColor: AppColors.grayBackground,
109
+ borderRadius: 8,
110
+ borderWidth: 1.5,
111
+ borderColor: AppColors.grayBorderSecondary,
112
+ paddingHorizontal: 10,
113
+ paddingVertical: 5,
114
+ gap: 8,
115
+ }}>
116
+ {/* Left: Lock and HTTPS label */}
117
+ <View style={{
118
+ flexDirection: 'row',
119
+ alignItems: 'center',
120
+ gap: 4,
121
+ }}>
122
+ <Text style={{ fontSize: 11 }}>🔒</Text>
123
+ <Text style={{
124
+ fontFamily: AppFonts.interBold,
125
+ fontSize: 9.5,
126
+ color: AppColors.greenColor,
127
+ letterSpacing: 0.5,
128
+ }}>
129
+ HTTPS
130
+ </Text>
131
+ </View>
132
+ <View style={{
133
+ width: 1.5,
134
+ height: 12,
135
+ backgroundColor: AppColors.grayBorderSecondary,
136
+ }}/>
137
+
138
+ {/* Middle: URL text (Address style) */}
139
+ <View style={{ flex: 1 }}>
140
+ <HighlightText text={currentUrl} search={webViewSearch} numberOfLines={1} ellipsizeMode="tail" style={{
141
+ fontFamily: AppFonts.interMedium,
142
+ fontSize: 11.5,
143
+ color: AppColors.primaryBlack,
144
+ }} highlightStyle={styles.highlight} detectLinks={false}/>
145
+ </View>
146
+
147
+ {/* Right: Copy Button */}
148
+ <CopyButton value={currentUrl} label="URL"/>
149
+
150
+ {/* Right: Globe Icon button to open browser */}
151
+ <TouchableScale onPress={() => Linking.openURL(currentUrl)} hitSlop={8} style={{
152
+ width: 26,
153
+ height: 26,
154
+ borderRadius: 13,
155
+ backgroundColor: AppColors.grayBackground,
156
+ borderWidth: 1,
157
+ borderColor: AppColors.grayBorderSecondary,
158
+ alignItems: 'center',
159
+ justifyContent: 'center',
160
+ }}>
161
+ <GlobeIcon size={11} color={AppColors.purple}/>
162
+ </TouchableScale>
163
+ </View>
164
+ </View>);
165
+ })()}
166
+
167
+ {/* ─── WebView Sub-Tabs (Now below Address Bar) ─── */}
168
+ <View style={{
169
+ backgroundColor: AppColors.primaryLight,
170
+ borderBottomWidth: 1,
171
+ borderBottomColor: AppColors.dividerColor,
172
+ paddingVertical: 6,
173
+ }}>
174
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{
175
+ paddingHorizontal: 12,
176
+ flexDirection: 'row',
177
+ gap: 8,
178
+ }}>
179
+ {/* Sub-tab 1: Preview */}
180
+ <Pressable style={[
181
+ {
182
+ paddingVertical: 6,
183
+ paddingHorizontal: 14,
184
+ borderRadius: 8,
185
+ alignItems: 'center',
186
+ flexDirection: 'row',
187
+ gap: 6,
188
+ backgroundColor: 'rgba(0, 0, 0, 0.03)',
189
+ borderWidth: 1,
190
+ borderColor: 'transparent',
191
+ },
192
+ webViewSubTab === 'preview' && {
193
+ backgroundColor: AppColors.purple,
194
+ borderColor: AppColors.purple,
195
+ },
196
+ ]} onPress={() => {
197
+ animateNextLayout();
198
+ setWebViewSubTab('preview');
199
+ }}>
200
+ <EyeIcon color={webViewSubTab === 'preview'
201
+ ? '#FFFFFF'
202
+ : AppColors.grayTextWeak} size={13}/>
203
+ <Text style={{
204
+ fontFamily: webViewSubTab === 'preview'
205
+ ? AppFonts.interBold
206
+ : AppFonts.interMedium,
207
+ fontSize: 12,
208
+ color: webViewSubTab === 'preview'
209
+ ? '#FFFFFF'
210
+ : AppColors.grayTextStrong,
211
+ }}>
212
+ Preview
213
+ </Text>
214
+ </Pressable>
215
+
216
+ {/* Sub-tab 2: Page Source */}
217
+ <Pressable style={[
218
+ {
219
+ paddingVertical: 6,
220
+ paddingHorizontal: 14,
221
+ borderRadius: 8,
222
+ alignItems: 'center',
223
+ flexDirection: 'row',
224
+ gap: 6,
225
+ backgroundColor: 'rgba(0, 0, 0, 0.03)',
226
+ borderWidth: 1,
227
+ borderColor: 'transparent',
228
+ },
229
+ webViewSubTab === 'html' && {
230
+ backgroundColor: AppColors.purple,
231
+ borderColor: AppColors.purple,
232
+ },
233
+ ]} onPress={() => {
234
+ animateNextLayout();
235
+ setWebViewSubTab('html');
236
+ }}>
237
+ <HtmlIcon color={webViewSubTab === 'html'
238
+ ? '#FFFFFF'
239
+ : AppColors.grayTextWeak} size={13}/>
240
+ <Text style={{
241
+ fontFamily: webViewSubTab === 'html'
242
+ ? AppFonts.interBold
243
+ : AppFonts.interMedium,
244
+ fontSize: 12,
245
+ color: webViewSubTab === 'html'
246
+ ? '#FFFFFF'
247
+ : AppColors.grayTextStrong,
248
+ }}>
249
+ Page Source
250
+ </Text>
251
+ </Pressable>
252
+
253
+ {/* Sub-tab 3: History */}
254
+ <Pressable style={[
255
+ {
256
+ paddingVertical: 6,
257
+ paddingHorizontal: 14,
258
+ borderRadius: 8,
259
+ alignItems: 'center',
260
+ flexDirection: 'row',
261
+ gap: 6,
262
+ backgroundColor: 'rgba(0, 0, 0, 0.03)',
263
+ borderWidth: 1,
264
+ borderColor: 'transparent',
265
+ },
266
+ webViewSubTab === 'navigation' && {
267
+ backgroundColor: AppColors.purple,
268
+ borderColor: AppColors.purple,
269
+ },
270
+ ]} onPress={() => {
271
+ animateNextLayout();
272
+ setWebViewSubTab('navigation');
273
+ }}>
274
+ <ClockIcon color={webViewSubTab === 'navigation'
275
+ ? '#FFFFFF'
276
+ : AppColors.grayTextWeak} size={13}/>
277
+ <Text style={{
278
+ fontFamily: webViewSubTab === 'navigation'
279
+ ? AppFonts.interBold
280
+ : AppFonts.interMedium,
281
+ fontSize: 12,
282
+ color: webViewSubTab === 'navigation'
283
+ ? '#FFFFFF'
284
+ : AppColors.grayTextStrong,
285
+ }}>
286
+ History ({webViewNavHistory.length})
287
+ </Text>
288
+ </Pressable>
289
+
290
+ {/* Sub-tab 4: Console */}
291
+ <Pressable style={[
292
+ {
293
+ paddingVertical: 6,
294
+ paddingHorizontal: 14,
295
+ borderRadius: 8,
296
+ alignItems: 'center',
297
+ flexDirection: 'row',
298
+ gap: 6,
299
+ backgroundColor: 'rgba(0, 0, 0, 0.03)',
300
+ borderWidth: 1,
301
+ borderColor: 'transparent',
302
+ },
303
+ webViewSubTab === 'console' && {
304
+ backgroundColor: AppColors.purple,
305
+ borderColor: AppColors.purple,
306
+ },
307
+ ]} onPress={() => {
308
+ animateNextLayout();
309
+ setWebViewSubTab('console');
310
+ }}>
311
+ <TerminalIcon color={webViewSubTab === 'console'
312
+ ? '#FFFFFF'
313
+ : AppColors.grayTextWeak} size={13}/>
314
+ <Text style={{
315
+ fontFamily: webViewSubTab === 'console'
316
+ ? AppFonts.interBold
317
+ : AppFonts.interMedium,
318
+ fontSize: 12,
319
+ color: webViewSubTab === 'console'
320
+ ? '#FFFFFF'
321
+ : AppColors.grayTextStrong,
322
+ }}>
323
+ Console ({webViewLogs.length})
324
+ </Text>
325
+ </Pressable>
326
+ </ScrollView>
327
+ </View>
328
+
329
+ {webViewSubTab === 'html' ? (<View style={{ flex: 1 }}>
330
+ {webViewHtml || webViewCss || webViewJs ? (<View style={{ flex: 1 }}>
331
+ {/* Clear Inspect Banner */}
332
+ {inspectedElement && (<View style={{
333
+ flexDirection: 'row',
334
+ alignItems: 'center',
335
+ justifyContent: 'space-between',
336
+ backgroundColor: AppColors.purpleShade50,
337
+ paddingHorizontal: 12,
338
+ paddingVertical: 6,
339
+ borderBottomWidth: 1,
340
+ borderBottomColor: AppColors.dividerColor,
341
+ }}>
342
+ <Text style={{
343
+ fontFamily: AppFonts.interMedium,
344
+ fontSize: 11.5,
345
+ color: AppColors.purple,
346
+ flex: 1,
347
+ }}>
348
+ Inspecting element:{' '}
349
+ <Text style={{
350
+ fontFamily: AppFonts.interBold,
351
+ }}>
352
+ &lt;{inspectedElement.tagName}
353
+ {inspectedElement.id
354
+ ? ` id="${inspectedElement.id}"`
355
+ : ''}
356
+ {inspectedElement.className
357
+ ? ` class="${inspectedElement.className
358
+ .trim()
359
+ .split(/\s+/)[0]}"`
360
+ : ''}
361
+ &gt;
362
+ </Text>
363
+ </Text>
364
+ <Pressable onPress={() => setInspectedElement(null)} style={{
365
+ paddingHorizontal: 8,
366
+ paddingVertical: 4,
367
+ }}>
368
+ <Text style={{
369
+ fontFamily: AppFonts.interBold,
370
+ fontSize: 11,
371
+ color: AppColors.purple,
372
+ }}>
373
+ Clear Inspect
374
+ </Text>
375
+ </Pressable>
376
+ </View>)}
377
+
378
+ {/* Inner sub-tabs inside HTML source view */}
379
+ <View style={{
380
+ flexDirection: 'row',
381
+ borderBottomWidth: 1,
382
+ borderBottomColor: AppColors.dividerColor,
383
+ backgroundColor: AppColors.primaryLight,
384
+ paddingHorizontal: 12,
385
+ gap: 12,
386
+ }}>
387
+ {['html', 'css', 'javascript'].map(tab => {
388
+ const active = htmlSubTab === tab;
389
+ const label = tab === 'html'
390
+ ? 'HTML'
391
+ : tab === 'css'
392
+ ? 'CSS'
393
+ : 'JavaScript';
394
+ const activeColor = tab === 'html'
395
+ ? '#EA580C' // Orange
396
+ : tab === 'css'
397
+ ? '#2563EB' // Blue
398
+ : '#D97706'; // Dark Yellow/Amber
399
+ return (<Pressable key={tab} onPress={() => {
400
+ animateNextLayout();
401
+ setHtmlSubTab(tab);
402
+ }} style={{
403
+ paddingVertical: 8,
404
+ paddingHorizontal: 4,
405
+ borderBottomWidth: 2,
406
+ borderBottomColor: active
407
+ ? activeColor
408
+ : 'transparent',
409
+ flexDirection: 'row',
410
+ alignItems: 'center',
411
+ gap: 4,
412
+ }}>
413
+ {tab === 'html' && (<HtmlIcon color={active
414
+ ? activeColor
415
+ : AppColors.grayTextWeak} size={14}/>)}
416
+ {tab === 'css' && (<CssIcon color={active
417
+ ? activeColor
418
+ : AppColors.grayTextWeak} size={14}/>)}
419
+ {tab === 'javascript' && (<JsIcon color={active
420
+ ? activeColor
421
+ : AppColors.grayTextWeak} size={14}/>)}
422
+ <Text style={{
423
+ fontFamily: active
424
+ ? AppFonts.interBold
425
+ : AppFonts.interMedium,
426
+ fontSize: 13,
427
+ color: active
428
+ ? activeColor
429
+ : AppColors.grayTextWeak,
430
+ }}>
431
+ {label}
432
+ </Text>
433
+ </Pressable>);
434
+ })}
435
+ </View>
436
+ <View style={{ flex: 1, padding: 12 }}>
437
+ {!isHtmlTabReady ? (<View style={{
438
+ flex: 1,
439
+ justifyContent: 'center',
440
+ alignItems: 'center',
441
+ minHeight: 200,
442
+ }}>
443
+ <ActivityIndicator size="large" color={AppColors.purple}/>
444
+ </View>) : htmlSubTab === 'html' ? (webViewHtml ? (<CodeSnippet code={webViewHtml} language="html" search={getSearchTermForTab()}/>) : (<Text style={{
445
+ fontFamily: 'monospace',
446
+ fontSize: 11,
447
+ color: '#94A3B8',
448
+ padding: 12,
449
+ }}>
450
+ No HTML content captured.
451
+ </Text>)) : htmlSubTab === 'css' ? (webViewCss ? (<CodeSnippet code={webViewCss} language="css" search={getSearchTermForTab()}/>) : (<Text style={{
452
+ fontFamily: 'monospace',
453
+ fontSize: 11,
454
+ color: '#94A3B8',
455
+ padding: 12,
456
+ }}>
457
+ No CSS styles detected on this page.
458
+ </Text>)) : webViewJs ? (<CodeSnippet code={webViewJs} language="javascript" search={getSearchTermForTab()}/>) : (<Text style={{
459
+ fontFamily: 'monospace',
460
+ fontSize: 11,
461
+ color: '#94A3B8',
462
+ padding: 12,
463
+ }}>
464
+ No scripts detected on this page.
465
+ </Text>)}
466
+ </View>
467
+ </View>) : (<View style={styles.emptyContainer}>
468
+ <View style={styles.emptyIconWrap}>
469
+ <GlobeIcon color={AppColors.purple} size={32}/>
470
+ </View>
471
+ <Text style={styles.emptyTitle}>
472
+ No Page Source Captured
473
+ </Text>
474
+ <Text style={styles.emptySub}>
475
+ Load a page in the WebView to inspect its
476
+ HTML, CSS, or Javascript source.
477
+ </Text>
478
+ </View>)}
479
+ </View>) : webViewSubTab === 'navigation' ? (<FlatList data={filteredNavHistory} keyExtractor={(item, index) => `${index}-${item.timestamp}`} style={{
480
+ flex: 1,
481
+ backgroundColor: AppColors.grayBackground,
482
+ }} ListHeaderComponent={<View style={{
483
+ paddingHorizontal: 16,
484
+ paddingTop: 12,
485
+ paddingBottom: 8,
486
+ }}>
487
+ <Text style={styles.resultCount}>
488
+ Navigation History ({webViewNavHistory.length}
489
+ )
490
+ </Text>
491
+ </View>} renderItem={({ item, index, }) => {
492
+ const isLatest = index === 0;
493
+ const formatNavTime = (ts) => {
494
+ const d = new Date(ts);
495
+ return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
496
+ };
497
+ return (<AnimatedEntrance index={index} distance={8} style={{
498
+ marginHorizontal: 16,
499
+ marginVertical: 6,
500
+ borderRadius: 12,
501
+ borderWidth: 1,
502
+ borderColor: AppColors.grayBorderSecondary,
503
+ backgroundColor: isLatest
504
+ ? AppColors.purpleShade50
505
+ : AppColors.primaryLight,
506
+ padding: 14,
507
+ flexDirection: 'row',
508
+ alignItems: 'center',
509
+ justifyContent: 'space-between',
510
+ gap: 12,
511
+ shadowColor: '#000000',
512
+ shadowOffset: { width: 0, height: 2 },
513
+ shadowOpacity: isDark ? 0.2 : 0.04,
514
+ shadowRadius: 4,
515
+ elevation: 2,
516
+ }}>
517
+ <View style={{ flex: 1, gap: 8 }}>
518
+ {/* Top row: Title and Badge */}
519
+ <View style={{
520
+ flexDirection: 'row',
521
+ alignItems: 'center',
522
+ gap: 8,
523
+ flexWrap: 'wrap',
524
+ }}>
525
+ <Text numberOfLines={1} ellipsizeMode="tail" style={{
526
+ fontFamily: AppFonts.interBold,
527
+ fontSize: 14,
528
+ color: AppColors.primaryBlack,
529
+ flexShrink: 1,
530
+ }}>
531
+ {item.title || 'Untitled Page'}
532
+ </Text>
533
+ {isLatest && (<View style={{
534
+ flexDirection: 'row',
535
+ alignItems: 'center',
536
+ gap: 4,
537
+ backgroundColor: AppColors.greenStatus,
538
+ paddingHorizontal: 8,
539
+ paddingVertical: 3,
540
+ borderRadius: 12,
541
+ }}>
542
+ <View style={{
543
+ width: 6,
544
+ height: 6,
545
+ borderRadius: 3,
546
+ backgroundColor: AppColors.greenBaggageText,
547
+ }}/>
548
+ <Text style={{
549
+ fontFamily: AppFonts.interBold,
550
+ fontSize: 9.5,
551
+ color: AppColors.greenBaggageText,
552
+ }}>
553
+ Active
554
+ </Text>
555
+ </View>)}
556
+ </View>
557
+
558
+ {/* Middle row: URL with Globe Icon */}
559
+ <View style={{
560
+ flexDirection: 'row',
561
+ alignItems: 'center',
562
+ gap: 6,
563
+ }}>
564
+ <GlobeIcon size={12} color={AppColors.grayTextWeak}/>
565
+ <HighlightText text={item.url} search={webViewSearch} numberOfLines={2} ellipsizeMode="tail" style={{
566
+ fontFamily: AppFonts.interRegular,
567
+ fontSize: 12,
568
+ color: AppColors.grayText,
569
+ flex: 1,
570
+ }} highlightStyle={styles.highlight} detectLinks={true}/>
571
+ </View>
572
+
573
+ {/* Bottom row: Time */}
574
+ <View style={{
575
+ flexDirection: 'row',
576
+ alignItems: 'center',
577
+ gap: 6,
578
+ }}>
579
+ <ClockIcon size={11} color={AppColors.grayTextWeak}/>
580
+ <Text style={{
581
+ fontFamily: AppFonts.interRegular,
582
+ fontSize: 11,
583
+ color: AppColors.grayTextWeak,
584
+ }}>
585
+ {formatNavTime(item.timestamp)}
586
+ </Text>
587
+ </View>
588
+ </View>
589
+ <CopyButton value={item.url} label="URL"/>
590
+ </AnimatedEntrance>);
591
+ }} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState isSearch={webViewSearch.length > 0}/>} contentContainerStyle={[
592
+ styles.listContent,
593
+ filteredNavHistory.length === 0 && {
594
+ flexGrow: 1,
595
+ },
596
+ ]} keyboardShouldPersistTaps="handled"/>) : webViewSubTab === 'console' ? (<View style={{
597
+ flex: 1,
598
+ backgroundColor: AppColors.grayBackground,
599
+ }}>
600
+ {webViewLogs.length > 0 ? (<FlatList data={webViewLogs} keyExtractor={(item) => String(item.id)} style={{ flex: 1 }} ListHeaderComponent={<View style={{
601
+ paddingHorizontal: 16,
602
+ paddingTop: 12,
603
+ paddingBottom: 8,
604
+ flexDirection: 'row',
605
+ justifyContent: 'space-between',
606
+ alignItems: 'center',
607
+ }}>
608
+ <Text style={styles.resultCount}>
609
+ Console Logs ({webViewLogs.length})
610
+ </Text>
611
+ <TouchableScale onPress={() => clearWebViewData()} style={{
612
+ padding: 6,
613
+ borderRadius: 6,
614
+ backgroundColor: AppColors.primaryLight,
615
+ borderWidth: 1,
616
+ borderColor: AppColors.grayBorderSecondary,
617
+ }}>
618
+ <TrashIcon color={AppColors.errorColor} size={14}/>
619
+ </TouchableScale>
620
+ </View>} renderItem={({ item }) => {
621
+ const logColor = item.type === 'error'
622
+ ? AppColors.errorColor
623
+ : item.type === 'warn'
624
+ ? AppColors.warningIconGold
625
+ : item.type === 'info'
626
+ ? AppColors.skyBlue
627
+ : AppColors.grayTextWeak;
628
+ const bgColor = item.type === 'error'
629
+ ? 'rgba(255, 46, 87, 0.06)'
630
+ : item.type === 'warn'
631
+ ? 'rgba(191, 162, 82, 0.08)'
632
+ : AppColors.primaryLight;
633
+ const d = new Date(item.timestamp);
634
+ const timeStr = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
635
+ return (<AnimatedEntrance index={item.id} distance={8} style={{
636
+ marginHorizontal: 12,
637
+ marginVertical: 3,
638
+ borderRadius: 8,
639
+ borderWidth: 1,
640
+ borderColor: AppColors.grayBorderSecondary,
641
+ borderLeftWidth: 3,
642
+ borderLeftColor: logColor,
643
+ backgroundColor: bgColor,
644
+ padding: 10,
645
+ flexDirection: 'row',
646
+ gap: 8,
647
+ alignItems: 'flex-start',
648
+ }}>
649
+ <View style={{ paddingTop: 1 }}>
650
+ <TerminalIcon color={logColor} size={11}/>
651
+ </View>
652
+ <View style={{ flex: 1, gap: 3 }}>
653
+ <View style={{
654
+ flexDirection: 'row',
655
+ alignItems: 'center',
656
+ justifyContent: 'space-between',
657
+ }}>
658
+ <Text style={{
659
+ fontFamily: AppFonts.interBold,
660
+ fontSize: 10,
661
+ color: logColor,
662
+ textTransform: 'uppercase',
663
+ letterSpacing: 0.5,
664
+ }}>
665
+ {item.type}
666
+ </Text>
667
+ <Text style={{
668
+ fontFamily: AppFonts.interRegular,
669
+ fontSize: 10,
670
+ color: AppColors.grayTextWeak,
671
+ }}>
672
+ {timeStr}
673
+ </Text>
674
+ </View>
675
+ <Text style={{
676
+ fontFamily: AppFonts.interRegular,
677
+ fontSize: 12,
678
+ color: AppColors.primaryBlack,
679
+ lineHeight: 16,
680
+ }}>
681
+ {item.message}
682
+ </Text>
683
+ </View>
684
+ </AnimatedEntrance>);
685
+ }} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={7} contentContainerStyle={[
686
+ styles.listContent,
687
+ webViewLogs.length === 0 && { flexGrow: 1 },
688
+ ]}/>) : (<View style={styles.emptyContainer}>
689
+ <View style={styles.emptyIconWrap}>
690
+ <TerminalIcon color={AppColors.purple} size={32}/>
691
+ </View>
692
+ <Text style={styles.emptyTitle}>
693
+ No Console Logs
694
+ </Text>
695
+ <Text style={styles.emptySub}>
696
+ Console logs from the WebView will appear
697
+ here.
698
+ </Text>
699
+ </View>)}
700
+ </View>) : (<View style={{
701
+ flex: 1,
702
+ backgroundColor: AppColors.grayBackground,
703
+ }}>
704
+ {webViewHtml ? (OriginalWebView ? (<OriginalWebView source={{
705
+ html: webViewHtml,
706
+ baseUrl: webViewHtmlUrl,
707
+ }} injectedJavaScript={previewInspectScript} onMessage={(event) => {
708
+ try {
709
+ const data = JSON.parse(event.nativeEvent.data);
710
+ if (data.type === 'preview-inspect') {
711
+ setInspectedElement({
712
+ tagName: data.tagName,
713
+ id: data.id,
714
+ className: data.className,
715
+ searchStr: data.searchStr,
716
+ });
717
+ setWebViewSubTab('html');
718
+ setHtmlSubTab('html');
719
+ }
720
+ }
721
+ catch (err) { }
722
+ }} style={{ flex: 1 }}/>) : (<View style={{
723
+ flex: 1,
724
+ justifyContent: 'center',
725
+ alignItems: 'center',
726
+ padding: 20,
727
+ }}>
728
+ <Text style={{
729
+ color: AppColors.grayText,
730
+ textAlign: 'center',
731
+ fontFamily: AppFonts.interMedium,
732
+ }}>
733
+ react-native-webview is not installed in the
734
+ target project. Install it to enable Preview
735
+ mode.
736
+ </Text>
737
+ </View>)) : (<View style={styles.emptyContainer}>
738
+ <View style={styles.emptyIconWrap}>
739
+ <GlobeIcon color={AppColors.purple} size={32}/>
740
+ </View>
741
+ <Text style={styles.emptyTitle}>
742
+ No Preview Available
743
+ </Text>
744
+ <Text style={styles.emptySub}>
745
+ Load a page in the WebView to see its visual
746
+ preview.
747
+ </Text>
748
+ </View>)}
749
+ </View>)}
750
+ </View>);
751
+ };
752
+ export default WebViewTab;