react-native-inapp-inspector 1.1.14 → 1.1.16

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 (246) hide show
  1. package/README.md +133 -151
  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/CopyButton.d.ts +1 -1
  25. package/dist/commonjs/components/CopyButton.js +4 -4
  26. package/dist/commonjs/components/DiffViewer.js +4 -2
  27. package/dist/commonjs/components/DomainHeader.js +66 -41
  28. package/dist/commonjs/components/EmptyState.d.ts +2 -2
  29. package/dist/commonjs/components/EmptyState.js +2 -2
  30. package/dist/commonjs/components/EndOfListFooter.d.ts +8 -0
  31. package/dist/commonjs/components/EndOfListFooter.js +89 -0
  32. package/dist/commonjs/components/ErrorBoundary.d.ts +5 -14
  33. package/dist/commonjs/components/ErrorBoundary.js +28 -28
  34. package/dist/commonjs/components/FloatingBubble.d.ts +14 -0
  35. package/dist/commonjs/components/FloatingBubble.js +75 -0
  36. package/dist/commonjs/components/HeadersSection.js +5 -3
  37. package/dist/commonjs/components/HighlightText.d.ts +1 -1
  38. package/dist/commonjs/components/HighlightText.js +5 -7
  39. package/dist/commonjs/components/Inspector/AnalyticsTab.d.ts +3 -0
  40. package/dist/commonjs/components/Inspector/AnalyticsTab.js +231 -0
  41. package/dist/commonjs/components/Inspector/ConsoleTab.d.ts +3 -0
  42. package/dist/commonjs/components/Inspector/ConsoleTab.js +410 -0
  43. package/dist/commonjs/components/Inspector/FabLauncher.d.ts +3 -0
  44. package/dist/commonjs/components/Inspector/FabLauncher.js +54 -0
  45. package/dist/commonjs/components/Inspector/InsightsDashboard.d.ts +3 -0
  46. package/dist/commonjs/components/Inspector/InsightsDashboard.js +619 -0
  47. package/dist/commonjs/components/Inspector/InspectorContext.d.ts +5 -0
  48. package/dist/commonjs/components/Inspector/InspectorContext.js +18 -0
  49. package/dist/commonjs/components/Inspector/InspectorHeader.d.ts +3 -0
  50. package/dist/commonjs/components/Inspector/InspectorHeader.js +452 -0
  51. package/dist/commonjs/components/Inspector/LogDetail.d.ts +3 -0
  52. package/dist/commonjs/components/Inspector/LogDetail.js +963 -0
  53. package/dist/commonjs/components/Inspector/MainScreen.d.ts +3 -0
  54. package/dist/commonjs/components/Inspector/MainScreen.js +68 -0
  55. package/dist/commonjs/components/Inspector/NavigationTracker.d.ts +3 -0
  56. package/dist/commonjs/components/Inspector/NavigationTracker.js +12 -0
  57. package/dist/commonjs/components/Inspector/NetworkDetail.d.ts +3 -0
  58. package/dist/commonjs/components/Inspector/NetworkDetail.js +405 -0
  59. package/dist/commonjs/components/Inspector/NetworkTab.d.ts +3 -0
  60. package/dist/commonjs/components/Inspector/NetworkTab.js +282 -0
  61. package/dist/commonjs/components/Inspector/ReduxTab.d.ts +3 -0
  62. package/dist/commonjs/components/Inspector/ReduxTab.js +75 -0
  63. package/dist/commonjs/components/Inspector/SettingsPanel.d.ts +3 -0
  64. package/dist/commonjs/components/Inspector/SettingsPanel.js +1476 -0
  65. package/dist/commonjs/components/Inspector/TabBar.d.ts +3 -0
  66. package/dist/commonjs/components/Inspector/TabBar.js +95 -0
  67. package/dist/commonjs/components/Inspector/WebViewTab.d.ts +3 -0
  68. package/dist/commonjs/components/Inspector/WebViewTab.js +757 -0
  69. package/dist/commonjs/components/InspectorHeader.d.ts +19 -0
  70. package/dist/commonjs/components/InspectorHeader.js +329 -0
  71. package/dist/commonjs/components/InspectorTabBar.d.ts +16 -0
  72. package/dist/commonjs/components/InspectorTabBar.js +90 -0
  73. package/dist/commonjs/components/JsonViewer.d.ts +5 -2
  74. package/dist/commonjs/components/JsonViewer.js +111 -172
  75. package/dist/commonjs/components/LogCard.js +109 -86
  76. package/dist/commonjs/components/MetaAccordion.d.ts +1 -10
  77. package/dist/commonjs/components/MetaAccordion.js +23 -21
  78. package/dist/commonjs/components/NavigationTracker.d.ts +7 -0
  79. package/dist/commonjs/components/NavigationTracker.js +76 -0
  80. package/dist/commonjs/components/NetworkIcons.d.ts +6 -0
  81. package/dist/commonjs/components/NetworkIcons.js +54 -8
  82. package/dist/commonjs/components/ReduxTabView.d.ts +9 -0
  83. package/dist/commonjs/components/ReduxTabView.js +56 -0
  84. package/dist/commonjs/components/ReduxTreeView.d.ts +2 -2
  85. package/dist/commonjs/components/ReduxTreeView.js +243 -203
  86. package/dist/commonjs/components/SegmentedTabs.d.ts +15 -0
  87. package/dist/commonjs/components/SegmentedTabs.js +52 -0
  88. package/dist/commonjs/components/SettingsView.d.ts +13 -0
  89. package/dist/commonjs/components/SettingsView.js +328 -0
  90. package/dist/commonjs/components/TouchableScale.d.ts +2 -2
  91. package/dist/commonjs/components/TouchableScale.js +2 -2
  92. package/dist/commonjs/components/TreeNode.js +2 -2
  93. package/dist/commonjs/constants/index.js +1 -12
  94. package/dist/commonjs/constants/version.d.ts +1 -1
  95. package/dist/commonjs/constants/version.js +1 -1
  96. package/dist/commonjs/customHooks/consoleLogger.js +137 -13
  97. package/dist/commonjs/customHooks/networkLogger.d.ts +0 -1
  98. package/dist/commonjs/customHooks/networkLogger.js +0 -1
  99. package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -9
  100. package/dist/commonjs/enums/index.d.ts +39 -0
  101. package/dist/commonjs/enums/index.js +50 -0
  102. package/dist/commonjs/helpers/index.d.ts +27 -1
  103. package/dist/commonjs/helpers/index.js +187 -12
  104. package/dist/commonjs/helpers/settingsStore.d.ts +2 -24
  105. package/dist/commonjs/i18n/en.json +144 -0
  106. package/dist/commonjs/i18n/index.d.ts +2 -0
  107. package/dist/commonjs/i18n/index.js +27 -0
  108. package/dist/commonjs/i18n/locales/en.json +314 -0
  109. package/dist/commonjs/index.d.ts +1 -2
  110. package/dist/commonjs/index.js +196 -4800
  111. package/dist/commonjs/styles/AppColors.d.ts +148 -0
  112. package/dist/commonjs/styles/AppColors.js +176 -0
  113. package/dist/commonjs/styles/common.d.ts +3 -0
  114. package/dist/commonjs/styles/common.js +201 -0
  115. package/dist/commonjs/styles/index.d.ts +167 -442
  116. package/dist/commonjs/styles/index.js +239 -471
  117. package/dist/commonjs/types/enums.d.ts +9 -0
  118. package/dist/commonjs/types/enums.js +4 -0
  119. package/dist/commonjs/types/index.d.ts +4 -111
  120. package/dist/commonjs/types/index.js +16 -0
  121. package/dist/commonjs/types/interfaces.d.ts +337 -0
  122. package/dist/commonjs/types/interfaces.js +2 -0
  123. package/dist/esm/assets/svgAssets.d.ts +3 -0
  124. package/dist/esm/assets/svgAssets.js +14 -0
  125. package/dist/esm/components/AnalyticsEventCard.d.ts +1 -14
  126. package/dist/esm/components/AnalyticsEventCard.js +32 -49
  127. package/dist/esm/components/AnalyticsGraph.d.ts +2 -6
  128. package/dist/esm/components/AnalyticsGraph.js +8 -8
  129. package/dist/esm/components/AnalyticsTabView.d.ts +15 -0
  130. package/dist/esm/components/AnalyticsTabView.js +151 -0
  131. package/dist/esm/components/AnimatedEntrance.d.ts +1 -1
  132. package/dist/esm/components/AnimatedEntrance.js +2 -2
  133. package/dist/esm/components/ApiDetailView.d.ts +22 -0
  134. package/dist/esm/components/ApiDetailView.js +264 -0
  135. package/dist/esm/components/ApisTabView.d.ts +33 -0
  136. package/dist/esm/components/ApisTabView.js +196 -0
  137. package/dist/esm/components/CodeSnippet.d.ts +1 -5
  138. package/dist/esm/components/CodeSnippet.js +34 -34
  139. package/dist/esm/components/ConsoleLogCard.d.ts +1 -8
  140. package/dist/esm/components/ConsoleLogCard.js +262 -409
  141. package/dist/esm/components/ConsoleLogDetailView.d.ts +9 -0
  142. package/dist/esm/components/ConsoleLogDetailView.js +271 -0
  143. package/dist/esm/components/ConsoleLogsTabView.d.ts +24 -0
  144. package/dist/esm/components/ConsoleLogsTabView.js +348 -0
  145. package/dist/esm/components/CopyButton.d.ts +1 -1
  146. package/dist/esm/components/CopyButton.js +5 -5
  147. package/dist/esm/components/DiffViewer.js +4 -2
  148. package/dist/esm/components/DomainHeader.js +66 -41
  149. package/dist/esm/components/EmptyState.d.ts +2 -2
  150. package/dist/esm/components/EmptyState.js +2 -2
  151. package/dist/esm/components/EndOfListFooter.d.ts +8 -0
  152. package/dist/esm/components/EndOfListFooter.js +83 -0
  153. package/dist/esm/components/ErrorBoundary.d.ts +5 -14
  154. package/dist/esm/components/ErrorBoundary.js +29 -29
  155. package/dist/esm/components/FloatingBubble.d.ts +14 -0
  156. package/dist/esm/components/FloatingBubble.js +68 -0
  157. package/dist/esm/components/HeadersSection.js +5 -3
  158. package/dist/esm/components/HighlightText.d.ts +1 -1
  159. package/dist/esm/components/HighlightText.js +5 -7
  160. package/dist/esm/components/Inspector/AnalyticsTab.d.ts +3 -0
  161. package/dist/esm/components/Inspector/AnalyticsTab.js +193 -0
  162. package/dist/esm/components/Inspector/ConsoleTab.d.ts +3 -0
  163. package/dist/esm/components/Inspector/ConsoleTab.js +372 -0
  164. package/dist/esm/components/Inspector/FabLauncher.d.ts +3 -0
  165. package/dist/esm/components/Inspector/FabLauncher.js +49 -0
  166. package/dist/esm/components/Inspector/InsightsDashboard.d.ts +3 -0
  167. package/dist/esm/components/Inspector/InsightsDashboard.js +614 -0
  168. package/dist/esm/components/Inspector/InspectorContext.d.ts +5 -0
  169. package/dist/esm/components/Inspector/InspectorContext.js +13 -0
  170. package/dist/esm/components/Inspector/InspectorHeader.d.ts +3 -0
  171. package/dist/esm/components/Inspector/InspectorHeader.js +447 -0
  172. package/dist/esm/components/Inspector/LogDetail.d.ts +3 -0
  173. package/dist/esm/components/Inspector/LogDetail.js +925 -0
  174. package/dist/esm/components/Inspector/MainScreen.d.ts +3 -0
  175. package/dist/esm/components/Inspector/MainScreen.js +63 -0
  176. package/dist/esm/components/Inspector/NavigationTracker.d.ts +3 -0
  177. package/dist/esm/components/Inspector/NavigationTracker.js +10 -0
  178. package/dist/esm/components/Inspector/NetworkDetail.d.ts +3 -0
  179. package/dist/esm/components/Inspector/NetworkDetail.js +367 -0
  180. package/dist/esm/components/Inspector/NetworkTab.d.ts +3 -0
  181. package/dist/esm/components/Inspector/NetworkTab.js +244 -0
  182. package/dist/esm/components/Inspector/ReduxTab.d.ts +3 -0
  183. package/dist/esm/components/Inspector/ReduxTab.js +70 -0
  184. package/dist/esm/components/Inspector/SettingsPanel.d.ts +3 -0
  185. package/dist/esm/components/Inspector/SettingsPanel.js +1438 -0
  186. package/dist/esm/components/Inspector/TabBar.d.ts +3 -0
  187. package/dist/esm/components/Inspector/TabBar.js +90 -0
  188. package/dist/esm/components/Inspector/WebViewTab.d.ts +3 -0
  189. package/dist/esm/components/Inspector/WebViewTab.js +752 -0
  190. package/dist/esm/components/InspectorHeader.d.ts +19 -0
  191. package/dist/esm/components/InspectorHeader.js +323 -0
  192. package/dist/esm/components/InspectorTabBar.d.ts +16 -0
  193. package/dist/esm/components/InspectorTabBar.js +84 -0
  194. package/dist/esm/components/JsonViewer.d.ts +5 -2
  195. package/dist/esm/components/JsonViewer.js +112 -173
  196. package/dist/esm/components/LogCard.js +111 -88
  197. package/dist/esm/components/MetaAccordion.d.ts +1 -10
  198. package/dist/esm/components/MetaAccordion.js +23 -21
  199. package/dist/esm/components/NavigationTracker.d.ts +7 -0
  200. package/dist/esm/components/NavigationTracker.js +39 -0
  201. package/dist/esm/components/NetworkIcons.d.ts +6 -0
  202. package/dist/esm/components/NetworkIcons.js +46 -6
  203. package/dist/esm/components/ReduxTabView.d.ts +9 -0
  204. package/dist/esm/components/ReduxTabView.js +50 -0
  205. package/dist/esm/components/ReduxTreeView.d.ts +2 -2
  206. package/dist/esm/components/ReduxTreeView.js +245 -204
  207. package/dist/esm/components/SegmentedTabs.d.ts +15 -0
  208. package/dist/esm/components/SegmentedTabs.js +47 -0
  209. package/dist/esm/components/SettingsView.d.ts +13 -0
  210. package/dist/esm/components/SettingsView.js +321 -0
  211. package/dist/esm/components/TouchableScale.d.ts +2 -2
  212. package/dist/esm/components/TouchableScale.js +2 -2
  213. package/dist/esm/components/TreeNode.js +2 -2
  214. package/dist/esm/constants/index.js +1 -12
  215. package/dist/esm/constants/version.d.ts +1 -1
  216. package/dist/esm/constants/version.js +1 -1
  217. package/dist/esm/customHooks/consoleLogger.js +137 -13
  218. package/dist/esm/customHooks/networkLogger.d.ts +0 -1
  219. package/dist/esm/customHooks/networkLogger.js +0 -1
  220. package/dist/esm/customHooks/reduxLogger.d.ts +2 -9
  221. package/dist/esm/enums/index.d.ts +39 -0
  222. package/dist/esm/enums/index.js +47 -0
  223. package/dist/esm/helpers/index.d.ts +27 -1
  224. package/dist/esm/helpers/index.js +180 -11
  225. package/dist/esm/helpers/settingsStore.d.ts +2 -24
  226. package/dist/esm/i18n/en.json +144 -0
  227. package/dist/esm/i18n/index.d.ts +2 -0
  228. package/dist/esm/i18n/index.js +22 -0
  229. package/dist/esm/i18n/locales/en.json +314 -0
  230. package/dist/esm/index.d.ts +1 -2
  231. package/dist/esm/index.js +200 -4796
  232. package/dist/esm/styles/AppColors.d.ts +148 -0
  233. package/dist/esm/styles/AppColors.js +176 -0
  234. package/dist/esm/styles/common.d.ts +3 -0
  235. package/dist/esm/styles/common.js +197 -0
  236. package/dist/esm/styles/index.d.ts +167 -442
  237. package/dist/esm/styles/index.js +239 -471
  238. package/dist/esm/types/enums.d.ts +9 -0
  239. package/dist/esm/types/enums.js +3 -0
  240. package/dist/esm/types/index.d.ts +4 -111
  241. package/dist/esm/types/index.js +2 -1
  242. package/dist/esm/types/interfaces.d.ts +337 -0
  243. package/dist/esm/types/interfaces.js +1 -0
  244. package/example/App.tsx +145 -2
  245. package/example/README.md +33 -77
  246. package/package.json +3 -1
@@ -2,9 +2,7 @@ import React from 'react';
2
2
  import { Text } from 'react-native';
3
3
  // Helpers
4
4
  import { escapeRegex, handleOpenExternalLink } from '../helpers';
5
- const HighlightText = ({ text, search, style, highlightStyle, detectLinks, ...rest }) => {
6
- const hasNumberOfLines = 'numberOfLines' in rest;
7
- const numLines = hasNumberOfLines ? rest.numberOfLines : 1;
5
+ const HighlightText = React.memo(function HighlightText({ text, search, style, highlightStyle, detectLinks, numberOfLines, ...rest }) {
8
6
  // Regex to detect absolute URLs
9
7
  const URL_REGEX = /(https?:\/\/[^\s]+)/g;
10
8
  const renderNormalOrHighlighted = (subText, keyPrefix) => {
@@ -21,7 +19,7 @@ const HighlightText = ({ text, search, style, highlightStyle, detectLinks, ...re
21
19
  };
22
20
  if (detectLinks && text) {
23
21
  const parts = text.split(URL_REGEX);
24
- return (<Text style={style} numberOfLines={numLines} {...rest}>
22
+ return (<Text style={style} numberOfLines={numberOfLines} {...rest}>
25
23
  {parts.map((part, i) => {
26
24
  if (part.match(URL_REGEX)) {
27
25
  return (<Text key={`link-${i}`} style={{
@@ -38,15 +36,15 @@ const HighlightText = ({ text, search, style, highlightStyle, detectLinks, ...re
38
36
  </Text>);
39
37
  }
40
38
  if (!search)
41
- return (<Text style={style} numberOfLines={numLines} {...rest}>
39
+ return (<Text style={style} numberOfLines={numberOfLines} {...rest}>
42
40
  {text}
43
41
  </Text>);
44
42
  const regex = new RegExp(`(${escapeRegex(search)})`, 'gi');
45
43
  const parts = text.split(regex);
46
- return (<Text style={style} numberOfLines={numLines} {...rest}>
44
+ return (<Text style={style} numberOfLines={numberOfLines} {...rest}>
47
45
  {parts.map((part, i) => part.toLowerCase() === search.toLowerCase() ? (<Text key={i} style={highlightStyle}>
48
46
  {part}
49
47
  </Text>) : (<Text key={i}>{part}</Text>))}
50
48
  </Text>);
51
- };
49
+ });
52
50
  export default HighlightText;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const AnalyticsTab: React.MemoExoticComponent<() => React.JSX.Element>;
3
+ export default AnalyticsTab;
@@ -0,0 +1,193 @@
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 = React.memo(() => {
12
+ const { filteredAnalyticsEvents, analyticsHeaderExpanded, setAnalyticsHeaderExpanded, } = useInspector();
13
+ const userId = getCurrentUserId();
14
+ const userProperties = getCurrentUserProperties();
15
+ const defaultParams = getDefaultEventParameters();
16
+ const isTrackingEnabled = getCollectionEnabled();
17
+ const hasUserProps = Object.keys(userProperties).length > 0;
18
+ const hasDefaultParams = Object.keys(defaultParams).length > 0;
19
+ const totalEvents = filteredAnalyticsEvents.length;
20
+ return (<View style={styles.analyticsHeaderCard}>
21
+ <View style={[styles.analyticsHeaderTop, !analyticsHeaderExpanded && { marginBottom: 0 }]}>
22
+ <View style={{ flex: 1 }}>
23
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
24
+ <Text style={styles.analyticsHeaderTitle}>Session Info</Text>
25
+ <View style={[
26
+ styles.statusDot,
27
+ { backgroundColor: isTrackingEnabled ? AppColors.greenColor : AppColors.errorColor }
28
+ ]}/>
29
+ <Text style={styles.statusText}>
30
+ {isTrackingEnabled ? 'Active' : 'Paused'}
31
+ </Text>
32
+ </View>
33
+ <Text style={styles.analyticsHeaderSubtitle} numberOfLines={1}>
34
+ {userId ? `User ID: ${userId}` : 'Anonymous Session'}
35
+ </Text>
36
+ </View>
37
+
38
+ <TouchableOpacity style={styles.analyticsHeaderToggle} activeOpacity={0.7} onPress={() => {
39
+ animateNextLayout();
40
+ setAnalyticsHeaderExpanded(!analyticsHeaderExpanded);
41
+ }}>
42
+ <Text style={styles.analyticsHeaderToggleText}>
43
+ {analyticsHeaderExpanded ? 'Collapse' : 'Expand'}
44
+ </Text>
45
+ </TouchableOpacity>
46
+ </View>
47
+
48
+ {analyticsHeaderExpanded && (<>
49
+ {/* Stats Row */}
50
+ <View style={styles.analyticsStatsRow}>
51
+ <View style={styles.analyticsStatBox}>
52
+ <Text style={styles.analyticsStatValue}>{totalEvents}</Text>
53
+ <Text style={styles.analyticsStatLabel}>Events</Text>
54
+ </View>
55
+ <View style={styles.analyticsStatBox}>
56
+ <Text style={styles.analyticsStatValue}>
57
+ {Object.keys(userProperties).length}
58
+ </Text>
59
+ <Text style={styles.analyticsStatLabel}>User Props</Text>
60
+ </View>
61
+ <View style={styles.analyticsStatBox}>
62
+ <Text style={styles.analyticsStatValue}>
63
+ {Object.keys(defaultParams).length}
64
+ </Text>
65
+ <Text style={styles.analyticsStatLabel}>Defaults</Text>
66
+ </View>
67
+ </View>
68
+
69
+ {/* Details Section */}
70
+ {(hasUserProps || hasDefaultParams) && (<View style={styles.analyticsHeaderDetails}>
71
+ {hasUserProps && (<View style={{ marginBottom: 10 }}>
72
+ <Text style={styles.detailsGroupTitle}>Active User Properties</Text>
73
+ {Object.entries(userProperties).map(([k, v]) => (<View key={k} style={styles.detailsRow}>
74
+ <Text style={styles.detailsKey} selectable={true}>{k}</Text>
75
+ <Text style={styles.detailsValue} selectable={true}>{String(v)}</Text>
76
+ </View>))}
77
+ </View>)}
78
+
79
+ {hasDefaultParams && (<View>
80
+ <Text style={styles.detailsGroupTitle}>Default Event Parameters</Text>
81
+ {Object.entries(defaultParams).map(([k, v]) => (<View key={k} style={styles.detailsRow}>
82
+ <Text style={styles.detailsKey} selectable={true}>{k}</Text>
83
+ <Text style={styles.detailsValue} selectable={true}>{String(v)}</Text>
84
+ </View>))}
85
+ </View>)}
86
+ </View>)}
87
+ </>)}
88
+ </View>);
89
+ });
90
+ const AnalyticsTab = React.memo(() => {
91
+ const { filteredAnalyticsEvents, analyticsSearch, setAnalyticsSearch, handleDelete, selectedEvent, setSelectedEvent, newEventIds, logRouteMapRef, isAnalyticsLayoutReady, setIsAnalyticsLayoutReady, isAnalyticsPaused, setIsAnalyticsPaused, } = useInspector();
92
+ const keyExtractor = useCallback((item, index) => item?.id?.toString() ?? index.toString(), []);
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, logRouteMapRef]);
132
+ return (<>
133
+ {/* ─── Search + Shared Toolbar for Analytics ──────────────────────── */}
134
+ {selectedEvent == null && (<View style={[
135
+ styles.toolbarRow,
136
+ { marginTop: 12, marginBottom: 8 },
137
+ ]}>
138
+ <View style={styles.searchContainer}>
139
+ <SearchIcon color={AppColors.grayTextWeak} size={16}/>
140
+ <TextInput placeholder="Search events..." placeholderTextColor={AppColors.grayTextWeak} value={analyticsSearch} onChangeText={setAnalyticsSearch} style={styles.searchInput} autoCorrect={false} autoCapitalize="none"/>
141
+ {analyticsSearch.length > 0 && (<Pressable onPress={() => setAnalyticsSearch('')} hitSlop={10} style={styles.clearBtn}>
142
+ <ClearIcon color={AppColors.grayTextWeak} size={14}/>
143
+ </Pressable>)}
144
+ </View>
145
+ <View style={styles.toolbarRight}>
146
+ <TouchableOpacity style={[
147
+ styles.toolbarBtn,
148
+ isAnalyticsPaused && {
149
+ borderColor: `${AppColors.darkOrange}50`,
150
+ backgroundColor: `${AppColors.darkOrange}18`,
151
+ },
152
+ ]} onPress={() => setIsAnalyticsPaused(p => !p)} hitSlop={6}>
153
+ <HeaderPauseIcon isPaused={isAnalyticsPaused} color={isAnalyticsPaused
154
+ ? AppColors.darkOrange
155
+ : AppColors.grayTextStrong} size={16}/>
156
+ </TouchableOpacity>
157
+ <TouchableOpacity style={[
158
+ styles.toolbarBtn,
159
+ {
160
+ borderColor: `${AppColors.errorColor}38`,
161
+ backgroundColor: `${AppColors.errorColor}0F`,
162
+ },
163
+ ]} onPress={handleDelete} hitSlop={6}>
164
+ <TrashIcon color={AppColors.errorColor} size={15}/>
165
+ </TouchableOpacity>
166
+ </View>
167
+ </View>)}
168
+
169
+ <View style={{ flex: 1 }} onLayout={() => setIsAnalyticsLayoutReady(true)}>
170
+ {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}>
171
+ <View style={styles.emptyIconWrap}>
172
+ <EmptyRadarIcon color={AppColors.purple} size={32}/>
173
+ </View>
174
+ <Text style={styles.emptyTitle}>
175
+ {analyticsSearch.length > 0
176
+ ? 'No matching events'
177
+ : 'No analytics events yet'}
178
+ </Text>
179
+ <Text style={styles.emptySub}>
180
+ {analyticsSearch.length > 0
181
+ ? 'Try adjusting your search.'
182
+ : 'Call setupAnalyticsLogger(analytics()) at app start.'}
183
+ </Text>
184
+ </View>} ListFooterComponent={filteredAnalyticsEvents.length > 0 ? (<EndOfListFooter count={filteredAnalyticsEvents.length} label="events"/>) : null} contentContainerStyle={[
185
+ styles.listContent,
186
+ filteredAnalyticsEvents.length === 0 && {
187
+ flexGrow: 1,
188
+ },
189
+ ]} keyboardShouldPersistTaps="handled"/>) : null}
190
+ </View>
191
+ </>);
192
+ });
193
+ export default AnalyticsTab;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const ConsoleTab: React.MemoExoticComponent<() => 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 = React.memo(() => {
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.length, filteredConsoleLogs.length, 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;