react-native-inapp-inspector 1.1.13 → 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 (250) 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 +120 -50
  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/analyticsLogger.d.ts +8 -0
  94. package/dist/commonjs/customHooks/analyticsLogger.js +42 -1
  95. package/dist/commonjs/customHooks/consoleLogger.js +137 -13
  96. package/dist/commonjs/customHooks/networkLogger.d.ts +0 -1
  97. package/dist/commonjs/customHooks/networkLogger.js +0 -1
  98. package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -9
  99. package/dist/commonjs/enums/index.d.ts +39 -0
  100. package/dist/commonjs/enums/index.js +50 -0
  101. package/dist/commonjs/helpers/index.d.ts +27 -1
  102. package/dist/commonjs/helpers/index.js +187 -12
  103. package/dist/commonjs/helpers/settingsStore.d.ts +2 -24
  104. package/dist/commonjs/i18n/en.json +144 -0
  105. package/dist/commonjs/i18n/index.d.ts +2 -0
  106. package/dist/commonjs/i18n/index.js +27 -0
  107. package/dist/commonjs/i18n/locales/en.json +314 -0
  108. package/dist/commonjs/index.d.ts +2 -3
  109. package/dist/commonjs/index.js +207 -4927
  110. package/dist/commonjs/styles/AppColors.d.ts +148 -0
  111. package/dist/commonjs/styles/AppColors.js +176 -0
  112. package/dist/commonjs/styles/common.d.ts +3 -0
  113. package/dist/commonjs/styles/common.js +201 -0
  114. package/dist/commonjs/styles/index.d.ts +219 -435
  115. package/dist/commonjs/styles/index.js +312 -488
  116. package/dist/commonjs/types/enums.d.ts +9 -0
  117. package/dist/commonjs/types/enums.js +4 -0
  118. package/dist/commonjs/types/index.d.ts +4 -111
  119. package/dist/commonjs/types/index.js +16 -0
  120. package/dist/commonjs/types/interfaces.d.ts +337 -0
  121. package/dist/commonjs/types/interfaces.js +2 -0
  122. package/dist/esm/assets/svgAssets.d.ts +3 -0
  123. package/dist/esm/assets/svgAssets.js +14 -0
  124. package/dist/esm/components/AnalyticsEventCard.d.ts +1 -14
  125. package/dist/esm/components/AnalyticsEventCard.js +118 -48
  126. package/dist/esm/components/AnalyticsGraph.d.ts +2 -6
  127. package/dist/esm/components/AnalyticsGraph.js +8 -8
  128. package/dist/esm/components/AnalyticsTabView.d.ts +15 -0
  129. package/dist/esm/components/AnalyticsTabView.js +151 -0
  130. package/dist/esm/components/AnimatedEntrance.d.ts +1 -1
  131. package/dist/esm/components/AnimatedEntrance.js +2 -2
  132. package/dist/esm/components/ApiDetailView.d.ts +22 -0
  133. package/dist/esm/components/ApiDetailView.js +264 -0
  134. package/dist/esm/components/ApisTabView.d.ts +33 -0
  135. package/dist/esm/components/ApisTabView.js +196 -0
  136. package/dist/esm/components/CodeSnippet.d.ts +1 -5
  137. package/dist/esm/components/CodeSnippet.js +34 -34
  138. package/dist/esm/components/ConsoleLogCard.d.ts +1 -8
  139. package/dist/esm/components/ConsoleLogCard.js +262 -409
  140. package/dist/esm/components/ConsoleLogDetailView.d.ts +9 -0
  141. package/dist/esm/components/ConsoleLogDetailView.js +271 -0
  142. package/dist/esm/components/ConsoleLogsTabView.d.ts +24 -0
  143. package/dist/esm/components/ConsoleLogsTabView.js +348 -0
  144. package/dist/esm/components/DiffViewer.js +4 -2
  145. package/dist/esm/components/DomainHeader.js +66 -41
  146. package/dist/esm/components/EmptyState.d.ts +2 -2
  147. package/dist/esm/components/EmptyState.js +2 -2
  148. package/dist/esm/components/EndOfListFooter.d.ts +8 -0
  149. package/dist/esm/components/EndOfListFooter.js +83 -0
  150. package/dist/esm/components/ErrorBoundary.d.ts +5 -14
  151. package/dist/esm/components/ErrorBoundary.js +29 -29
  152. package/dist/esm/components/FloatingBubble.d.ts +14 -0
  153. package/dist/esm/components/FloatingBubble.js +68 -0
  154. package/dist/esm/components/HeadersSection.js +5 -3
  155. package/dist/esm/components/HighlightText.d.ts +1 -1
  156. package/dist/esm/components/HighlightText.js +5 -7
  157. package/dist/esm/components/Inspector/AnalyticsTab.d.ts +3 -0
  158. package/dist/esm/components/Inspector/AnalyticsTab.js +194 -0
  159. package/dist/esm/components/Inspector/ConsoleTab.d.ts +3 -0
  160. package/dist/esm/components/Inspector/ConsoleTab.js +372 -0
  161. package/dist/esm/components/Inspector/FabLauncher.d.ts +3 -0
  162. package/dist/esm/components/Inspector/FabLauncher.js +49 -0
  163. package/dist/esm/components/Inspector/InsightsDashboard.d.ts +3 -0
  164. package/dist/esm/components/Inspector/InsightsDashboard.js +614 -0
  165. package/dist/esm/components/Inspector/InspectorContext.d.ts +5 -0
  166. package/dist/esm/components/Inspector/InspectorContext.js +13 -0
  167. package/dist/esm/components/Inspector/InspectorHeader.d.ts +3 -0
  168. package/dist/esm/components/Inspector/InspectorHeader.js +447 -0
  169. package/dist/esm/components/Inspector/LogDetail.d.ts +3 -0
  170. package/dist/esm/components/Inspector/LogDetail.js +925 -0
  171. package/dist/esm/components/Inspector/MainScreen.d.ts +3 -0
  172. package/dist/esm/components/Inspector/MainScreen.js +63 -0
  173. package/dist/esm/components/Inspector/NavigationTracker.d.ts +3 -0
  174. package/dist/esm/components/Inspector/NavigationTracker.js +10 -0
  175. package/dist/esm/components/Inspector/NetworkDetail.d.ts +3 -0
  176. package/dist/esm/components/Inspector/NetworkDetail.js +367 -0
  177. package/dist/esm/components/Inspector/NetworkTab.d.ts +3 -0
  178. package/dist/esm/components/Inspector/NetworkTab.js +243 -0
  179. package/dist/esm/components/Inspector/ReduxTab.d.ts +3 -0
  180. package/dist/esm/components/Inspector/ReduxTab.js +70 -0
  181. package/dist/esm/components/Inspector/SettingsPanel.d.ts +3 -0
  182. package/dist/esm/components/Inspector/SettingsPanel.js +1438 -0
  183. package/dist/esm/components/Inspector/TabBar.d.ts +3 -0
  184. package/dist/esm/components/Inspector/TabBar.js +90 -0
  185. package/dist/esm/components/Inspector/WebViewTab.d.ts +3 -0
  186. package/dist/esm/components/Inspector/WebViewTab.js +752 -0
  187. package/dist/esm/components/InspectorHeader.d.ts +19 -0
  188. package/dist/esm/components/InspectorHeader.js +323 -0
  189. package/dist/esm/components/InspectorTabBar.d.ts +16 -0
  190. package/dist/esm/components/InspectorTabBar.js +84 -0
  191. package/dist/esm/components/JsonViewer.d.ts +4 -1
  192. package/dist/esm/components/JsonViewer.js +111 -172
  193. package/dist/esm/components/LogCard.js +111 -88
  194. package/dist/esm/components/MetaAccordion.d.ts +1 -10
  195. package/dist/esm/components/MetaAccordion.js +23 -21
  196. package/dist/esm/components/NavigationTracker.d.ts +7 -0
  197. package/dist/esm/components/NavigationTracker.js +39 -0
  198. package/dist/esm/components/NetworkIcons.d.ts +6 -0
  199. package/dist/esm/components/NetworkIcons.js +46 -6
  200. package/dist/esm/components/ReduxTabView.d.ts +9 -0
  201. package/dist/esm/components/ReduxTabView.js +50 -0
  202. package/dist/esm/components/ReduxTreeView.js +243 -202
  203. package/dist/esm/components/SegmentedTabs.d.ts +15 -0
  204. package/dist/esm/components/SegmentedTabs.js +47 -0
  205. package/dist/esm/components/SettingsView.d.ts +13 -0
  206. package/dist/esm/components/SettingsView.js +321 -0
  207. package/dist/esm/components/TouchableScale.d.ts +2 -2
  208. package/dist/esm/components/TouchableScale.js +2 -2
  209. package/dist/esm/components/TreeNode.js +2 -2
  210. package/dist/esm/constants/index.js +1 -12
  211. package/dist/esm/constants/version.d.ts +1 -1
  212. package/dist/esm/constants/version.js +1 -1
  213. package/dist/esm/customHooks/analyticsLogger.d.ts +8 -0
  214. package/dist/esm/customHooks/analyticsLogger.js +37 -0
  215. package/dist/esm/customHooks/consoleLogger.js +137 -13
  216. package/dist/esm/customHooks/networkLogger.d.ts +0 -1
  217. package/dist/esm/customHooks/networkLogger.js +0 -1
  218. package/dist/esm/customHooks/reduxLogger.d.ts +2 -9
  219. package/dist/esm/enums/index.d.ts +39 -0
  220. package/dist/esm/enums/index.js +47 -0
  221. package/dist/esm/helpers/index.d.ts +27 -1
  222. package/dist/esm/helpers/index.js +180 -11
  223. package/dist/esm/helpers/settingsStore.d.ts +2 -24
  224. package/dist/esm/i18n/en.json +144 -0
  225. package/dist/esm/i18n/index.d.ts +2 -0
  226. package/dist/esm/i18n/index.js +22 -0
  227. package/dist/esm/i18n/locales/en.json +314 -0
  228. package/dist/esm/index.d.ts +2 -3
  229. package/dist/esm/index.js +207 -4923
  230. package/dist/esm/styles/AppColors.d.ts +148 -0
  231. package/dist/esm/styles/AppColors.js +176 -0
  232. package/dist/esm/styles/common.d.ts +3 -0
  233. package/dist/esm/styles/common.js +197 -0
  234. package/dist/esm/styles/index.d.ts +219 -435
  235. package/dist/esm/styles/index.js +312 -488
  236. package/dist/esm/types/enums.d.ts +9 -0
  237. package/dist/esm/types/enums.js +3 -0
  238. package/dist/esm/types/index.d.ts +4 -111
  239. package/dist/esm/types/index.js +2 -1
  240. package/dist/esm/types/interfaces.d.ts +337 -0
  241. package/dist/esm/types/interfaces.js +1 -0
  242. package/example/App.tsx +88 -1
  243. package/example/android/app/build.gradle +29 -1
  244. package/example/android/app/src/main/java/com/example/MainApplication.kt +25 -0
  245. package/example/android/build.gradle +31 -4
  246. package/example/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  247. package/example/android/gradle.properties +1 -0
  248. package/example/android/settings.gradle +20 -1
  249. package/example/package-lock.json +1 -1
  250. package/package.json +3 -1
@@ -0,0 +1,194 @@
1
+ import React, { useCallback } from 'react';
2
+ import { FlatList, Pressable, Text, TextInput, TouchableOpacity, View, } from 'react-native';
3
+ import { animateNextLayout, useInspector } from './InspectorContext';
4
+ import AnalyticsEventCard from '../AnalyticsEventCard';
5
+ import AnalyticsDetail from '../AnalyticsDetail';
6
+ import EndOfListFooter from '../EndOfListFooter';
7
+ import styles from '../../styles';
8
+ import { AppColors } from '../../styles/AppColors';
9
+ import { getCurrentUserId, getCurrentUserProperties, getDefaultEventParameters, getCollectionEnabled, } from '../../customHooks/analyticsLogger';
10
+ import { SearchIcon, ClearIcon, TrashIcon, EmptyRadarIcon, HeaderPauseIcon, } from '../NetworkIcons';
11
+ const AnalyticsHeader = () => {
12
+ const { filteredAnalyticsEvents, analyticsHeaderExpanded, setAnalyticsHeaderExpanded, } = useInspector();
13
+ const keyExtractor = useCallback((item, index) => item?.id?.toString() ?? index.toString(), []);
14
+ const userId = getCurrentUserId();
15
+ const userProperties = getCurrentUserProperties();
16
+ const defaultParams = getDefaultEventParameters();
17
+ const isTrackingEnabled = getCollectionEnabled();
18
+ const hasUserProps = Object.keys(userProperties).length > 0;
19
+ const hasDefaultParams = Object.keys(defaultParams).length > 0;
20
+ const totalEvents = filteredAnalyticsEvents.length;
21
+ return (<View style={styles.analyticsHeaderCard}>
22
+ <View style={[styles.analyticsHeaderTop, !analyticsHeaderExpanded && { marginBottom: 0 }]}>
23
+ <View style={{ flex: 1 }}>
24
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
25
+ <Text style={styles.analyticsHeaderTitle}>Session Info</Text>
26
+ <View style={[
27
+ styles.statusDot,
28
+ { backgroundColor: isTrackingEnabled ? AppColors.greenColor : AppColors.errorColor }
29
+ ]}/>
30
+ <Text style={styles.statusText}>
31
+ {isTrackingEnabled ? 'Active' : 'Paused'}
32
+ </Text>
33
+ </View>
34
+ <Text style={styles.analyticsHeaderSubtitle} numberOfLines={1}>
35
+ {userId ? `User ID: ${userId}` : 'Anonymous Session'}
36
+ </Text>
37
+ </View>
38
+
39
+ <TouchableOpacity style={styles.analyticsHeaderToggle} activeOpacity={0.7} onPress={() => {
40
+ animateNextLayout();
41
+ setAnalyticsHeaderExpanded(!analyticsHeaderExpanded);
42
+ }}>
43
+ <Text style={styles.analyticsHeaderToggleText}>
44
+ {analyticsHeaderExpanded ? 'Collapse' : 'Expand'}
45
+ </Text>
46
+ </TouchableOpacity>
47
+ </View>
48
+
49
+ {analyticsHeaderExpanded && (<>
50
+ {/* Stats Row */}
51
+ <View style={styles.analyticsStatsRow}>
52
+ <View style={styles.analyticsStatBox}>
53
+ <Text style={styles.analyticsStatValue}>{totalEvents}</Text>
54
+ <Text style={styles.analyticsStatLabel}>Events</Text>
55
+ </View>
56
+ <View style={styles.analyticsStatBox}>
57
+ <Text style={styles.analyticsStatValue}>
58
+ {Object.keys(userProperties).length}
59
+ </Text>
60
+ <Text style={styles.analyticsStatLabel}>User Props</Text>
61
+ </View>
62
+ <View style={styles.analyticsStatBox}>
63
+ <Text style={styles.analyticsStatValue}>
64
+ {Object.keys(defaultParams).length}
65
+ </Text>
66
+ <Text style={styles.analyticsStatLabel}>Defaults</Text>
67
+ </View>
68
+ </View>
69
+
70
+ {/* Details Section */}
71
+ {(hasUserProps || hasDefaultParams) && (<View style={styles.analyticsHeaderDetails}>
72
+ {hasUserProps && (<View style={{ marginBottom: 10 }}>
73
+ <Text style={styles.detailsGroupTitle}>Active User Properties</Text>
74
+ {Object.entries(userProperties).map(([k, v]) => (<View key={k} style={styles.detailsRow}>
75
+ <Text style={styles.detailsKey} selectable={true}>{k}</Text>
76
+ <Text style={styles.detailsValue} selectable={true}>{String(v)}</Text>
77
+ </View>))}
78
+ </View>)}
79
+
80
+ {hasDefaultParams && (<View>
81
+ <Text style={styles.detailsGroupTitle}>Default Event Parameters</Text>
82
+ {Object.entries(defaultParams).map(([k, v]) => (<View key={k} style={styles.detailsRow}>
83
+ <Text style={styles.detailsKey} selectable={true}>{k}</Text>
84
+ <Text style={styles.detailsValue} selectable={true}>{String(v)}</Text>
85
+ </View>))}
86
+ </View>)}
87
+ </View>)}
88
+ </>)}
89
+ </View>);
90
+ };
91
+ const AnalyticsTab = () => {
92
+ const { analyticsSearch, setAnalyticsSearch, handleDelete, filteredAnalyticsEvents, selectedEvent, setSelectedEvent, newEventIds, logRouteMapRef, isAnalyticsLayoutReady, setIsAnalyticsLayoutReady, isAnalyticsPaused, setIsAnalyticsPaused, } = useInspector();
93
+ const renderItem = useCallback(({ item, index }) => {
94
+ const prev = filteredAnalyticsEvents[index + 1];
95
+ const next = filteredAnalyticsEvents[index - 1];
96
+ const msSincePrev = prev
97
+ ? item.timestamp - prev.timestamp
98
+ : undefined;
99
+ const thisMin = Math.floor(item.timestamp / 60000);
100
+ const nextMin = next
101
+ ? Math.floor(next.timestamp / 60000)
102
+ : -1;
103
+ const showTimestamp = index === 0 || thisMin !== nextMin;
104
+ return (<AnalyticsEventCard event={item} onPress={() => {
105
+ animateNextLayout();
106
+ setSelectedEvent(item);
107
+ }} isNew={newEventIds.has(item.id)} searchStr={analyticsSearch} isFirst={index === 0} isLast={index === filteredAnalyticsEvents.length - 1} msSincePrev={msSincePrev} showTimestamp={showTimestamp} computedScreenName={(() => {
108
+ if (!item)
109
+ return '';
110
+ const rawScreenName = item.screenName ||
111
+ item.screenClass ||
112
+ item.pageTitle ||
113
+ item.pageLocation ||
114
+ item.params?.firebase_screen ||
115
+ item.params?.screen_name ||
116
+ item.params?.firebase_screen_class ||
117
+ item.params?.screen_class;
118
+ let screenName = typeof rawScreenName === 'string'
119
+ ? rawScreenName
120
+ : (rawScreenName ? JSON.stringify(rawScreenName) : '');
121
+ const routeInfo = logRouteMapRef.current.get(item.id + 1000000);
122
+ if (!screenName) {
123
+ if (routeInfo &&
124
+ routeInfo.path !== 'Navigators') {
125
+ const parts = routeInfo.path.split(' ➔ ');
126
+ screenName = parts[parts.length - 1];
127
+ }
128
+ }
129
+ return screenName;
130
+ })()}/>);
131
+ }, [filteredAnalyticsEvents, analyticsSearch, newEventIds, setSelectedEvent]);
132
+ const keyExtractor = useCallback((item, index) => item?.id?.toString() ?? index.toString(), []);
133
+ return (<>
134
+ {/* ─── Search + Shared Toolbar for Analytics ──────────────────────── */}
135
+ {selectedEvent == null && (<View style={[
136
+ styles.toolbarRow,
137
+ { marginTop: 12, marginBottom: 8 },
138
+ ]}>
139
+ <View style={styles.searchContainer}>
140
+ <SearchIcon color={AppColors.grayTextWeak} size={16}/>
141
+ <TextInput placeholder="Search events..." placeholderTextColor={AppColors.grayTextWeak} value={analyticsSearch} onChangeText={setAnalyticsSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
142
+ {analyticsSearch.length > 0 && (<Pressable onPress={() => setAnalyticsSearch('')} hitSlop={10} style={styles.clearBtn}>
143
+ <ClearIcon color={AppColors.grayTextWeak} size={14}/>
144
+ </Pressable>)}
145
+ </View>
146
+ <View style={styles.toolbarRight}>
147
+ <TouchableOpacity style={[
148
+ styles.toolbarBtn,
149
+ isAnalyticsPaused && {
150
+ borderColor: `${AppColors.darkOrange}50`,
151
+ backgroundColor: `${AppColors.darkOrange}18`,
152
+ },
153
+ ]} onPress={() => setIsAnalyticsPaused(p => !p)} hitSlop={6}>
154
+ <HeaderPauseIcon isPaused={isAnalyticsPaused} color={isAnalyticsPaused
155
+ ? AppColors.darkOrange
156
+ : AppColors.grayTextStrong} size={16}/>
157
+ </TouchableOpacity>
158
+ <TouchableOpacity style={[
159
+ styles.toolbarBtn,
160
+ {
161
+ borderColor: `${AppColors.errorColor}38`,
162
+ backgroundColor: `${AppColors.errorColor}0F`,
163
+ },
164
+ ]} onPress={handleDelete} hitSlop={6}>
165
+ <TrashIcon color={AppColors.errorColor} size={15}/>
166
+ </TouchableOpacity>
167
+ </View>
168
+ </View>)}
169
+
170
+ <View style={{ flex: 1 }} onLayout={() => setIsAnalyticsLayoutReady(true)}>
171
+ {selectedEvent != null ? (<AnalyticsDetail event={selectedEvent}/>) : isAnalyticsLayoutReady ? (<FlatList data={filteredAnalyticsEvents} keyExtractor={keyExtractor} ListHeaderComponent={AnalyticsHeader} renderItem={renderItem} initialNumToRender={20} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews={false} ListEmptyComponent={<View style={styles.emptyContainer}>
172
+ <View style={styles.emptyIconWrap}>
173
+ <EmptyRadarIcon color={AppColors.purple} size={32}/>
174
+ </View>
175
+ <Text style={styles.emptyTitle}>
176
+ {analyticsSearch.length > 0
177
+ ? 'No matching events'
178
+ : 'No analytics events yet'}
179
+ </Text>
180
+ <Text style={styles.emptySub}>
181
+ {analyticsSearch.length > 0
182
+ ? 'Try adjusting your search.'
183
+ : 'Call setupAnalyticsLogger(analytics()) at app start.'}
184
+ </Text>
185
+ </View>} ListFooterComponent={filteredAnalyticsEvents.length > 0 ? (<EndOfListFooter count={filteredAnalyticsEvents.length} label="events"/>) : null} contentContainerStyle={[
186
+ styles.listContent,
187
+ filteredAnalyticsEvents.length === 0 && {
188
+ flexGrow: 1,
189
+ },
190
+ ]} keyboardShouldPersistTaps="handled"/>) : null}
191
+ </View>
192
+ </>);
193
+ };
194
+ export default AnalyticsTab;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const ConsoleTab: () => React.JSX.Element;
3
+ export default ConsoleTab;
@@ -0,0 +1,372 @@
1
+ import React, { useCallback, useMemo } from 'react';
2
+ import { FlatList, Pressable, ScrollView, Text, TextInput, View, } from 'react-native';
3
+ import { useInspector } from './InspectorContext';
4
+ import { useTranslation } from 'react-i18next';
5
+ import TouchableScale from '../TouchableScale';
6
+ import AnimatedEntrance from '../AnimatedEntrance';
7
+ import { ConsoleLogCard } from '../ConsoleLogCard';
8
+ import EmptyState from '../EmptyState';
9
+ import EndOfListFooter from '../EndOfListFooter';
10
+ import styles from '../../styles';
11
+ import { AppColors } from '../../styles/AppColors';
12
+ import { AppFonts } from '../../styles/AppFonts';
13
+ import { SearchIcon, ClearIcon, SortArrowIcon, TrashIcon, LayersIcon, UserIcon, InfoCircleIcon, WarningTriangleIcon, ErrorCircleIcon, AnalyticsIcon, HeaderPauseIcon, } from '../NetworkIcons';
14
+ const ConsoleTab = () => {
15
+ const { t } = useTranslation();
16
+ const { logSearch, setLogSearch, logSortOrder, setLogSortOrder, handleDelete, logFilters, setLogFilters, logCounts, filteredConsoleLogs, visibleConsoleLogs, isConsolePaused, setIsConsolePaused, } = useInspector();
17
+ const renderItem = useCallback(({ item, index }) => (<AnimatedEntrance index={index} distance={8}>
18
+ <ConsoleLogCard item={item} searchStr={logSearch}/>
19
+ </AnimatedEntrance>), [logSearch]);
20
+ const keyExtractor = useCallback((item, index) => item?.id?.toString() ?? index.toString(), []);
21
+ const listHeader = useMemo(() => (() => {
22
+ const total = visibleConsoleLogs.length;
23
+ const filtered = filteredConsoleLogs.length;
24
+ const isAllSelected = logFilters.has('all') ||
25
+ !Array.from(logFilters).some(f => f !== 'all');
26
+ if (isAllSelected) {
27
+ return (<Text style={[
28
+ styles.resultCount,
29
+ { marginBottom: 4, marginTop: 12 },
30
+ ]}>
31
+ Showing ({filtered}/{total}) logs showing
32
+ </Text>);
33
+ }
34
+ else {
35
+ const activeFilterNames = Array.from(logFilters)
36
+ .filter(f => f !== 'all')
37
+ .map(f => {
38
+ if (f === 'user-log')
39
+ return 'User Log';
40
+ if (f === 'analytics')
41
+ return 'Analytics';
42
+ return (f.charAt(0).toUpperCase() +
43
+ f.slice(1));
44
+ });
45
+ return (<Text style={[
46
+ styles.resultCount,
47
+ { marginBottom: 4, marginTop: 12 },
48
+ ]}>
49
+ Filtering with {activeFilterNames.join(', ')} (
50
+ {filtered}/{total}) logs is showing
51
+ </Text>);
52
+ }
53
+ })(), [visibleConsoleLogs, filteredConsoleLogs, logFilters]);
54
+ return (<View style={{ flex: 1 }}>
55
+ <View style={{
56
+ backgroundColor: AppColors.white,
57
+ borderBottomWidth: 1,
58
+ borderBottomColor: AppColors.dividerColor,
59
+ paddingBottom: 6,
60
+ }}>
61
+ <View style={[
62
+ styles.toolbarRow,
63
+ { marginTop: 12, marginBottom: 8 },
64
+ ]}>
65
+ <View style={styles.searchContainer}>
66
+ <SearchIcon color={AppColors.grayTextWeak} size={16}/>
67
+ <TextInput placeholder={t('console.searchPlaceholder')} placeholderTextColor={AppColors.grayTextWeak} value={logSearch} onChangeText={setLogSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
68
+ {logSearch.length > 0 && (<Pressable onPress={() => setLogSearch('')} hitSlop={10} style={styles.clearBtn}>
69
+ <ClearIcon color={AppColors.grayTextWeak} size={14}/>
70
+ </Pressable>)}
71
+ </View>
72
+
73
+ <View style={styles.toolbarRight}>
74
+ <TouchableScale style={[
75
+ styles.toolbarBtn,
76
+ isConsolePaused && {
77
+ borderColor: `${AppColors.darkOrange}50`,
78
+ backgroundColor: `${AppColors.darkOrange}18`,
79
+ },
80
+ ]} onPress={() => setIsConsolePaused(p => !p)} hitSlop={6}>
81
+ <HeaderPauseIcon isPaused={isConsolePaused} color={isConsolePaused
82
+ ? AppColors.darkOrange
83
+ : AppColors.grayTextStrong} size={16}/>
84
+ </TouchableScale>
85
+ <TouchableScale style={styles.toolbarBtn} onPress={() => setLogSortOrder(o => o === 'newest' ? 'oldest' : 'newest')} hitSlop={10}>
86
+ <SortArrowIcon color={AppColors.grayTextStrong} size={18} direction={logSortOrder === 'newest' ? 'down' : 'up'}/>
87
+ </TouchableScale>
88
+ <TouchableScale style={[
89
+ styles.toolbarBtn,
90
+ {
91
+ borderColor: `${AppColors.errorColor}38`,
92
+ backgroundColor: `${AppColors.errorColor}0F`,
93
+ },
94
+ ]} onPress={handleDelete} hitSlop={6}>
95
+ <TrashIcon color={AppColors.errorColor} size={15}/>
96
+ </TouchableScale>
97
+ </View>
98
+ </View>
99
+
100
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginVertical: 4, maxHeight: 46 }} contentContainerStyle={{
101
+ paddingHorizontal: 16,
102
+ paddingBottom: 4,
103
+ flexDirection: 'row',
104
+ alignItems: 'center',
105
+ gap: 8,
106
+ }}>
107
+ {(() => {
108
+ const active = logFilters.has('all');
109
+ return (<TouchableScale onPress={() => {
110
+ setLogFilters(new Set(['all']));
111
+ }}>
112
+ <View style={[
113
+ styles.statusFilterChip,
114
+ active && {
115
+ borderColor: AppColors.purpleShade700,
116
+ backgroundColor: AppColors.purpleTintBg,
117
+ },
118
+ ]}>
119
+ {/* #7 */}
120
+ <View style={{
121
+ flexDirection: 'row',
122
+ alignItems: 'center',
123
+ gap: 5,
124
+ }}>
125
+ <LayersIcon size={12} color={active
126
+ ? AppColors.purpleShade700
127
+ : AppColors.grayTextStrong}/>
128
+ <Text numberOfLines={1} style={[
129
+ styles.statusFilterText,
130
+ active && {
131
+ color: AppColors.purpleShade700,
132
+ fontFamily: AppFonts.interBold,
133
+ },
134
+ ]}>
135
+ All ({logCounts.all})
136
+ </Text>
137
+ </View>
138
+ </View>
139
+ </TouchableScale>);
140
+ })()}
141
+
142
+ {(() => {
143
+ const active = logFilters.has('user-log');
144
+ return (<TouchableScale onPress={() => {
145
+ setLogFilters(prev => {
146
+ const next = new Set(prev);
147
+ next.delete('all');
148
+ next.has('user-log')
149
+ ? next.delete('user-log')
150
+ : next.add('user-log');
151
+ if (next.size === 0)
152
+ next.add('all');
153
+ return next;
154
+ });
155
+ }}>
156
+ <View style={[
157
+ styles.statusFilterChip,
158
+ active && {
159
+ borderColor: AppColors.slate500,
160
+ backgroundColor: AppColors.slate100,
161
+ },
162
+ ]}>
163
+ {/* #7 */}
164
+ <View style={{
165
+ flexDirection: 'row',
166
+ alignItems: 'center',
167
+ gap: 5,
168
+ }}>
169
+ <UserIcon size={12} color={active
170
+ ? AppColors.slate700
171
+ : AppColors.grayTextStrong}/>
172
+ <Text numberOfLines={1} style={[
173
+ styles.statusFilterText,
174
+ active && {
175
+ color: AppColors.slate700,
176
+ fontFamily: AppFonts.interBold,
177
+ },
178
+ ]}>
179
+ User Log ({logCounts['user-log']})
180
+ </Text>
181
+ </View>
182
+ </View>
183
+ </TouchableScale>);
184
+ })()}
185
+
186
+ {(() => {
187
+ const active = logFilters.has('info');
188
+ return (<TouchableScale onPress={() => {
189
+ setLogFilters(prev => {
190
+ const next = new Set(prev);
191
+ next.delete('all');
192
+ next.has('info')
193
+ ? next.delete('info')
194
+ : next.add('info');
195
+ if (next.size === 0)
196
+ next.add('all');
197
+ return next;
198
+ });
199
+ }}>
200
+ <View style={[
201
+ styles.statusFilterChip,
202
+ active && {
203
+ borderColor: AppColors.purple,
204
+ backgroundColor: AppColors.purpleShade50,
205
+ },
206
+ ]}>
207
+ {/* #7 */}
208
+ <View style={{
209
+ flexDirection: 'row',
210
+ alignItems: 'center',
211
+ gap: 5,
212
+ }}>
213
+ <InfoCircleIcon size={12} color={active
214
+ ? AppColors.purple
215
+ : AppColors.grayTextStrong}/>
216
+ <Text numberOfLines={1} style={[
217
+ styles.statusFilterText,
218
+ active && {
219
+ color: AppColors.purple,
220
+ fontFamily: AppFonts.interBold,
221
+ },
222
+ ]}>
223
+ Info ({logCounts.info})
224
+ </Text>
225
+ </View>
226
+ </View>
227
+ </TouchableScale>);
228
+ })()}
229
+
230
+ {(() => {
231
+ const active = logFilters.has('warn');
232
+ return (<TouchableScale onPress={() => {
233
+ setLogFilters(prev => {
234
+ const next = new Set(prev);
235
+ next.delete('all');
236
+ next.has('warn')
237
+ ? next.delete('warn')
238
+ : next.add('warn');
239
+ if (next.size === 0)
240
+ next.add('all');
241
+ return next;
242
+ });
243
+ }}>
244
+ <View style={[
245
+ styles.statusFilterChip,
246
+ active && {
247
+ borderColor: AppColors.lightOrange,
248
+ backgroundColor: AppColors.warnCardBg,
249
+ },
250
+ ]}>
251
+ {/* #7 */}
252
+ <View style={{
253
+ flexDirection: 'row',
254
+ alignItems: 'center',
255
+ gap: 5,
256
+ }}>
257
+ <WarningTriangleIcon size={12} color={active
258
+ ? AppColors.darkOrange ||
259
+ AppColors.lightOrange
260
+ : AppColors.grayTextStrong}/>
261
+ <Text numberOfLines={1} style={[
262
+ styles.statusFilterText,
263
+ active && {
264
+ color: AppColors.darkOrange ||
265
+ AppColors.lightOrange,
266
+ fontFamily: AppFonts.interBold,
267
+ },
268
+ ]}>
269
+ Warning ({logCounts.warn})
270
+ </Text>
271
+ </View>
272
+ </View>
273
+ </TouchableScale>);
274
+ })()}
275
+
276
+ {(() => {
277
+ const active = logFilters.has('error');
278
+ return (<TouchableScale onPress={() => {
279
+ setLogFilters(prev => {
280
+ const next = new Set(prev);
281
+ next.delete('all');
282
+ next.has('error')
283
+ ? next.delete('error')
284
+ : next.add('error');
285
+ if (next.size === 0)
286
+ next.add('all');
287
+ return next;
288
+ });
289
+ }}>
290
+ <View style={[
291
+ styles.statusFilterChip,
292
+ active && {
293
+ borderColor: AppColors.errorColor,
294
+ backgroundColor: AppColors.errorCardBg,
295
+ },
296
+ ]}>
297
+ {/* #7 */}
298
+ <View style={{
299
+ flexDirection: 'row',
300
+ alignItems: 'center',
301
+ gap: 5,
302
+ }}>
303
+ <ErrorCircleIcon size={12} color={active
304
+ ? AppColors.errorColor
305
+ : AppColors.grayTextStrong}/>
306
+ <Text numberOfLines={1} style={[
307
+ styles.statusFilterText,
308
+ active && {
309
+ color: AppColors.errorColor,
310
+ fontFamily: AppFonts.interBold,
311
+ },
312
+ ]}>
313
+ Error ({logCounts.error})
314
+ </Text>
315
+ </View>
316
+ </View>
317
+ </TouchableScale>);
318
+ })()}
319
+
320
+ {(() => {
321
+ const active = logFilters.has('analytics');
322
+ return (<TouchableScale onPress={() => {
323
+ setLogFilters(prev => {
324
+ const next = new Set(prev);
325
+ next.delete('all');
326
+ next.has('analytics')
327
+ ? next.delete('analytics')
328
+ : next.add('analytics');
329
+ if (next.size === 0)
330
+ next.add('all');
331
+ return next;
332
+ });
333
+ }}>
334
+ <View style={[
335
+ styles.statusFilterChip,
336
+ active && {
337
+ borderColor: AppColors.skyBlue,
338
+ backgroundColor: `${AppColors.skyBlue}15`,
339
+ },
340
+ ]}>
341
+ {/* #7 */}
342
+ <View style={{
343
+ flexDirection: 'row',
344
+ alignItems: 'center',
345
+ gap: 5,
346
+ }}>
347
+ <AnalyticsIcon size={12} color={active
348
+ ? AppColors.skyBlue
349
+ : AppColors.grayTextStrong}/>
350
+ <Text numberOfLines={1} style={[
351
+ styles.statusFilterText,
352
+ active && {
353
+ color: AppColors.skyBlue,
354
+ fontFamily: AppFonts.interBold,
355
+ },
356
+ ]}>
357
+ Analytics ({logCounts.analytics})
358
+ </Text>
359
+ </View>
360
+ </View>
361
+ </TouchableScale>);
362
+ })()}
363
+ </ScrollView>
364
+ </View>
365
+
366
+ <FlatList data={filteredConsoleLogs} keyExtractor={keyExtractor} ListHeaderComponent={listHeader} renderItem={renderItem} initialNumToRender={15} maxToRenderPerBatch={15} windowSize={7} removeClippedSubviews={true} ListEmptyComponent={<EmptyState isSearch={logSearch.length > 0 || logFilters.size > 0}/>} ListFooterComponent={filteredConsoleLogs.length > 0 ? (<EndOfListFooter count={filteredConsoleLogs.length} label="logs"/>) : null} contentContainerStyle={[
367
+ styles.listContent,
368
+ filteredConsoleLogs.length === 0 && { flexGrow: 1 },
369
+ ]} keyboardShouldPersistTaps="handled"/>
370
+ </View>);
371
+ };
372
+ export default ConsoleTab;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const FabLauncher: () => React.JSX.Element;
3
+ export default FabLauncher;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import { Animated, View } from 'react-native';
3
+ import LinearGradient from 'react-native-linear-gradient';
4
+ import { useInspector } from './InspectorContext';
5
+ import TouchableScale from '../TouchableScale';
6
+ import BrandCircleIcon from '../BrandCircleIcon';
7
+ import { AppColors } from '../../styles/AppColors';
8
+ import styles from '../../styles';
9
+ const FabLauncher = () => {
10
+ const { setVisible, fabPan, fabPanResponder, fabDraggedRef, pulseAnim, fabShineAnim, unreadPulseAnim, logs, analyticsEvents, } = useInspector();
11
+ return (<Animated.View style={[styles.fabWrapper, { transform: fabPan.getTranslateTransform() }]} {...fabPanResponder.panHandlers}>
12
+ <TouchableScale style={{ alignItems: 'center', justifyContent: 'center' }} onPress={() => {
13
+ if (fabDraggedRef.current)
14
+ return;
15
+ setVisible(true);
16
+ }} hitSlop={10}>
17
+ <Animated.View style={[styles.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
18
+ <BrandCircleIcon size={62}/>
19
+ {/* #4 — shining sweep, clipped inside the circular launcher */}
20
+ <View pointerEvents="none" style={styles.fabShineClip}>
21
+ <Animated.View style={[
22
+ styles.fabShineStreak,
23
+ {
24
+ transform: [
25
+ {
26
+ translateX: fabShineAnim.interpolate({
27
+ inputRange: [0, 1],
28
+ outputRange: [-48, 96],
29
+ }),
30
+ },
31
+ { rotate: '25deg' },
32
+ ],
33
+ },
34
+ ]}>
35
+ <LinearGradient colors={[
36
+ `${AppColors.white}00`,
37
+ `${AppColors.white}8C`,
38
+ `${AppColors.white}00`,
39
+ ]} start={{ x: 0, y: 0.5 }} end={{ x: 1, y: 0.5 }} style={{ flex: 1 }}/>
40
+ </Animated.View>
41
+ </View>
42
+ {(logs.length > 0 || analyticsEvents.length > 0) && (<Animated.View style={[
43
+ styles.fabGreenDot,
44
+ { transform: [{ scale: unreadPulseAnim }] },
45
+ ]}/>)}
46
+ </TouchableScale>
47
+ </Animated.View>);
48
+ };
49
+ export default FabLauncher;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const InsightsDashboard: () => React.JSX.Element;
3
+ export default InsightsDashboard;