react-native-inapp-inspector 2.2.2 → 2.2.4

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 (159) hide show
  1. package/dist/commonjs/components/AnalyticsDetail.js +5 -1
  2. package/dist/commonjs/components/AnalyticsEventCard.js +2 -1
  3. package/dist/commonjs/components/DiffViewer.js +1 -1
  4. package/dist/commonjs/components/Inspector/BundleTab.js +22 -0
  5. package/dist/commonjs/components/Inspector/DeviceInfoTab.d.ts +3 -0
  6. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +835 -0
  7. package/dist/commonjs/components/Inspector/InspectorHeader.js +12 -14
  8. package/dist/commonjs/components/Inspector/LogDetail.js +6 -3
  9. package/dist/commonjs/components/Inspector/MainScreen.js +7 -3
  10. package/dist/commonjs/components/Inspector/NetworkTab.js +92 -15
  11. package/dist/commonjs/components/Inspector/PerformanceTab.js +38 -12
  12. package/dist/commonjs/components/Inspector/SettingsPanel.js +440 -229
  13. package/dist/commonjs/components/Inspector/StorageTab.d.ts +3 -0
  14. package/dist/commonjs/components/Inspector/StorageTab.js +892 -0
  15. package/dist/commonjs/components/Inspector/TabBar.js +14 -0
  16. package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +11 -2
  17. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +4 -1
  18. package/dist/commonjs/components/NetworkIcons.d.ts +6 -0
  19. package/dist/commonjs/components/NetworkIcons.js +30 -1
  20. package/dist/commonjs/constants/version.d.ts +1 -1
  21. package/dist/commonjs/constants/version.js +1 -1
  22. package/dist/commonjs/customHooks/bundleAnalyzer.js +44 -22
  23. package/dist/commonjs/customHooks/storageInspector.d.ts +67 -0
  24. package/dist/commonjs/customHooks/storageInspector.js +486 -0
  25. package/dist/commonjs/i18n/locales/en.json +8 -2
  26. package/dist/commonjs/index.d.ts +1 -0
  27. package/dist/commonjs/index.js +16 -1
  28. package/dist/commonjs/storage.d.ts +5 -0
  29. package/dist/commonjs/storage.js +18 -0
  30. package/dist/commonjs/types/enums.d.ts +5 -0
  31. package/dist/commonjs/types/enums.js +5 -0
  32. package/dist/esm/components/AnalyticsDetail.js +6 -2
  33. package/dist/esm/components/AnalyticsEventCard.js +2 -1
  34. package/dist/esm/components/DiffViewer.js +1 -1
  35. package/dist/esm/components/Inspector/BundleTab.js +22 -0
  36. package/dist/esm/components/Inspector/DeviceInfoTab.d.ts +3 -0
  37. package/dist/esm/components/Inspector/DeviceInfoTab.js +796 -0
  38. package/dist/esm/components/Inspector/InspectorHeader.js +13 -15
  39. package/dist/esm/components/Inspector/LogDetail.js +7 -4
  40. package/dist/esm/components/Inspector/MainScreen.js +7 -3
  41. package/dist/esm/components/Inspector/NetworkTab.js +93 -16
  42. package/dist/esm/components/Inspector/PerformanceTab.js +39 -13
  43. package/dist/esm/components/Inspector/SettingsPanel.js +441 -230
  44. package/dist/esm/components/Inspector/StorageTab.d.ts +3 -0
  45. package/dist/esm/components/Inspector/StorageTab.js +853 -0
  46. package/dist/esm/components/Inspector/TabBar.js +15 -1
  47. package/dist/esm/components/Inspector/TelemetryConsentModal.js +11 -2
  48. package/dist/esm/components/Inspector/UpdateAvailableModal.js +4 -1
  49. package/dist/esm/components/NetworkIcons.d.ts +6 -0
  50. package/dist/esm/components/NetworkIcons.js +23 -0
  51. package/dist/esm/constants/version.d.ts +1 -1
  52. package/dist/esm/constants/version.js +1 -1
  53. package/dist/esm/customHooks/bundleAnalyzer.js +44 -22
  54. package/dist/esm/customHooks/storageInspector.d.ts +67 -0
  55. package/dist/esm/customHooks/storageInspector.js +469 -0
  56. package/dist/esm/i18n/locales/en.json +8 -2
  57. package/dist/esm/index.d.ts +1 -0
  58. package/dist/esm/index.js +5 -0
  59. package/dist/esm/storage.d.ts +5 -0
  60. package/dist/esm/storage.js +5 -0
  61. package/dist/esm/types/enums.d.ts +5 -0
  62. package/dist/esm/types/enums.js +5 -0
  63. package/package.json +9 -1
  64. package/src/analytics.ts +35 -0
  65. package/src/bundle.ts +25 -0
  66. package/src/components/AnalyticsDetail.tsx +870 -0
  67. package/src/components/AnalyticsEventCard.tsx +442 -0
  68. package/src/components/AnalyticsGraph.tsx +583 -0
  69. package/src/components/AnimatedEntrance.tsx +64 -0
  70. package/src/components/AppHeaderLogo.tsx +109 -0
  71. package/src/components/BrandCircleIcon.tsx +144 -0
  72. package/src/components/BrandSquareIcon.tsx +144 -0
  73. package/src/components/CodeSnippet.tsx +725 -0
  74. package/src/components/ConsoleLogCard.tsx +628 -0
  75. package/src/components/CopyButton.tsx +87 -0
  76. package/src/components/DiffViewer.tsx +82 -0
  77. package/src/components/DomainHeader.tsx +237 -0
  78. package/src/components/EmptyState.tsx +73 -0
  79. package/src/components/EndOfListFooter.tsx +100 -0
  80. package/src/components/ErrorBoundary.tsx +688 -0
  81. package/src/components/HeadersSection.tsx +192 -0
  82. package/src/components/HighlightText.tsx +100 -0
  83. package/src/components/Inspector/AnalyticsFilterModal.tsx +1250 -0
  84. package/src/components/Inspector/AnalyticsTab.tsx +1336 -0
  85. package/src/components/Inspector/BundleTab.tsx +4760 -0
  86. package/src/components/Inspector/ConsoleTab.tsx +702 -0
  87. package/src/components/Inspector/CrashDetail.tsx +941 -0
  88. package/src/components/Inspector/CrashFilterModal.tsx +721 -0
  89. package/src/components/Inspector/CrashTab.tsx +871 -0
  90. package/src/components/Inspector/DeviceInfoTab.tsx +1204 -0
  91. package/src/components/Inspector/FabLauncher.tsx +80 -0
  92. package/src/components/Inspector/InspectorContext.tsx +28 -0
  93. package/src/components/Inspector/InspectorHeader.tsx +972 -0
  94. package/src/components/Inspector/LogDetail.tsx +1431 -0
  95. package/src/components/Inspector/MainScreen.tsx +262 -0
  96. package/src/components/Inspector/NavigationTracker.tsx +13 -0
  97. package/src/components/Inspector/NetworkDetail.tsx +794 -0
  98. package/src/components/Inspector/NetworkTab.tsx +1183 -0
  99. package/src/components/Inspector/NpmUpdateToast.tsx +392 -0
  100. package/src/components/Inspector/PerformanceTab.tsx +1928 -0
  101. package/src/components/Inspector/ReduxDetail.tsx +1651 -0
  102. package/src/components/Inspector/ReduxTab.tsx +954 -0
  103. package/src/components/Inspector/SettingsPanel.tsx +3447 -0
  104. package/src/components/Inspector/StorageTab.tsx +1048 -0
  105. package/src/components/Inspector/TabBar.tsx +207 -0
  106. package/src/components/Inspector/TelemetryConsentModal.tsx +416 -0
  107. package/src/components/Inspector/UpdateAvailableModal.tsx +557 -0
  108. package/src/components/JsonViewer.tsx +486 -0
  109. package/src/components/LogCard.tsx +491 -0
  110. package/src/components/LogSyntaxHighlighter.tsx +178 -0
  111. package/src/components/MetaAccordion.tsx +340 -0
  112. package/src/components/MiniBarChart.tsx +42 -0
  113. package/src/components/MiniLineChart.tsx +33 -0
  114. package/src/components/NetworkIcons.tsx +2221 -0
  115. package/src/components/SectionHeader.tsx +113 -0
  116. package/src/components/SegmentedTabs.tsx +83 -0
  117. package/src/components/Slider.tsx +300 -0
  118. package/src/components/SourcePageCard.tsx +148 -0
  119. package/src/components/Toast.tsx +131 -0
  120. package/src/components/TouchableScale.tsx +91 -0
  121. package/src/components/TreeNode.tsx +186 -0
  122. package/src/console.ts +24 -0
  123. package/src/constants/index.ts +38 -0
  124. package/src/constants/version.ts +3 -0
  125. package/src/crash.ts +32 -0
  126. package/src/customHooks/analyticsLogger.ts +336 -0
  127. package/src/customHooks/bundleAnalyzer.ts +1256 -0
  128. package/src/customHooks/consoleLogger.ts +497 -0
  129. package/src/customHooks/crashHandler.ts +944 -0
  130. package/src/customHooks/logFilters.ts +32 -0
  131. package/src/customHooks/networkLogger.ts +419 -0
  132. package/src/customHooks/performanceTracker.ts +1014 -0
  133. package/src/customHooks/reduxLogger.ts +406 -0
  134. package/src/customHooks/storageInspector.ts +509 -0
  135. package/src/customHooks/useAccordion.tsx +60 -0
  136. package/src/decorators/index.ts +184 -0
  137. package/src/helpers/gaAnalyticsRegistry.ts +204 -0
  138. package/src/helpers/index.ts +860 -0
  139. package/src/helpers/memoryManager.ts +138 -0
  140. package/src/helpers/searchQueryParser.ts +283 -0
  141. package/src/helpers/settingsStore.ts +171 -0
  142. package/src/helpers/telemetry.ts +505 -0
  143. package/src/helpers/toast.ts +17 -0
  144. package/src/i18n/index.ts +69 -0
  145. package/src/i18n/locales/en.json +1058 -0
  146. package/src/index.tsx +2356 -0
  147. package/src/native/NativeInspector.ts +397 -0
  148. package/src/native/NativeNetworkInspector.ts +24 -0
  149. package/src/network.ts +22 -0
  150. package/src/performance.ts +38 -0
  151. package/src/redux.ts +23 -0
  152. package/src/storage.ts +18 -0
  153. package/src/styles/AppColors.ts +408 -0
  154. package/src/styles/AppFonts.ts +8 -0
  155. package/src/styles/common.ts +209 -0
  156. package/src/styles/index.ts +1570 -0
  157. package/src/types/enums.ts +199 -0
  158. package/src/types/index.ts +34 -0
  159. package/src/types/interfaces.ts +515 -0
@@ -0,0 +1,207 @@
1
+ import React from 'react';
2
+ import {Animated, ScrollView, Text, TouchableOpacity, View} from 'react-native';
3
+ import {useInspector} from './InspectorContext';
4
+ import styles from '../../styles';
5
+ import {AppColors} from '../../styles/AppColors';
6
+ import TouchableScale from '../TouchableScale';
7
+ import {
8
+ SignalIcon,
9
+ TerminalIcon,
10
+ AnalyticsIcon,
11
+ PackageIcon,
12
+ ReduxIcon,
13
+ PerformanceIcon,
14
+ CrashIcon,
15
+ SmartphoneIcon,
16
+ DatabaseIcon,
17
+ } from '../NetworkIcons';
18
+
19
+ import {isReduxConnected} from '../../customHooks/reduxLogger';
20
+ import {isAnalyticsConnected} from '../../customHooks/analyticsLogger';
21
+ import {triggerNativeHaptic} from '../../native/NativeInspector';
22
+
23
+ const TabBar = React.memo(() => {
24
+ const {
25
+ activeTab,
26
+ switchActiveTab,
27
+ tabVisibility,
28
+ logs,
29
+ consoleLogs,
30
+ analyticsEvents,
31
+ crashRecords,
32
+ lastReadApisCount,
33
+ lastReadLogsCount,
34
+ lastReadCrashesCount,
35
+ unreadPulseAnim,
36
+ } = useInspector();
37
+
38
+ const isReduxAvail = isReduxConnected();
39
+ const isAnalyticsAvail = isAnalyticsConnected();
40
+
41
+ return (
42
+ <View style={styles.tabBarContainer}>
43
+ <ScrollView
44
+ horizontal
45
+ showsHorizontalScrollIndicator={false}
46
+ contentContainerStyle={{paddingRight: 16}}>
47
+ {(
48
+ [
49
+ {
50
+ key: 'apis',
51
+ label: 'APIs',
52
+ count: logs.length,
53
+ icon: 'apis',
54
+ },
55
+ {
56
+ key: 'logs',
57
+ label: 'Logs',
58
+ count: consoleLogs.length,
59
+ icon: 'logs',
60
+ },
61
+ {
62
+ key: 'analytics',
63
+ label: 'Analytics',
64
+ count: analyticsEvents.length,
65
+ icon: 'analytics',
66
+ },
67
+ {
68
+ key: 'redux',
69
+ label: 'Redux',
70
+ count: 0,
71
+ icon: 'redux',
72
+ },
73
+ {
74
+ key: 'bundle',
75
+ label: 'Bundle',
76
+ count: 0,
77
+ icon: 'bundle',
78
+ },
79
+ {
80
+ key: 'performance',
81
+ label: 'Performance',
82
+ count: 0,
83
+ icon: 'performance',
84
+ },
85
+ {
86
+ key: 'crash',
87
+ label: 'Crash',
88
+ count: crashRecords?.length || 0,
89
+ icon: 'crash',
90
+ },
91
+ {
92
+ key: 'device',
93
+ label: 'Device',
94
+ count: 0,
95
+ icon: 'device',
96
+ },
97
+ {
98
+ key: 'storage',
99
+ label: 'Storage',
100
+ count: 0,
101
+ icon: 'storage',
102
+ },
103
+ ] as const
104
+ )
105
+ .filter(tab => {
106
+ if (!tabVisibility?.[tab.key]) return false;
107
+ if (tab.key === 'redux' && !isReduxAvail) return false;
108
+ if (tab.key === 'analytics' && !isAnalyticsAvail) return false;
109
+ return true;
110
+ })
111
+ .map(tab => {
112
+ const isActive = activeTab === tab.key;
113
+ const iconColor = isActive
114
+ ? AppColors.white
115
+ : tab.key === 'crash' && tab.count > 0
116
+ ? AppColors.errorColor
117
+ : AppColors.grayText;
118
+ const countLabel =
119
+ tab.count > 9 ? '9+' : String(tab.count);
120
+ const hasUnreadApis =
121
+ activeTab !== 'apis' &&
122
+ logs.length > lastReadApisCount;
123
+ const hasUnreadLogs =
124
+ activeTab !== 'logs' &&
125
+ consoleLogs.length > lastReadLogsCount;
126
+ const hasUnreadCrashes =
127
+ activeTab !== 'crash' &&
128
+ (crashRecords?.length || 0) > (lastReadCrashesCount || 0);
129
+ return (
130
+ <TouchableScale
131
+ key={tab.key}
132
+ onPress={() => {
133
+ switchActiveTab(tab.key);
134
+ }}
135
+ style={[
136
+ styles.contentTabButton,
137
+ isActive && styles.contentTabButtonActive,
138
+ ]}>
139
+ <View
140
+ style={{
141
+ flexDirection: 'row',
142
+ alignItems: 'center',
143
+ gap: 6,
144
+ }}>
145
+ {tab.icon === 'apis' && (
146
+ <SignalIcon color={iconColor} size={14} />
147
+ )}
148
+ {tab.icon === 'logs' && (
149
+ <TerminalIcon color={iconColor} size={14} />
150
+ )}
151
+ {tab.icon === 'analytics' && (
152
+ <AnalyticsIcon color={iconColor} size={14} />
153
+ )}
154
+ {tab.icon === 'redux' && (
155
+ <ReduxIcon color={iconColor} size={14} />
156
+ )}
157
+ {tab.icon === 'bundle' && (
158
+ <PackageIcon color={iconColor} size={14} />
159
+ )}
160
+ {tab.icon === 'performance' && (
161
+ <PerformanceIcon color={iconColor} size={14} />
162
+ )}
163
+ {tab.icon === 'crash' && (
164
+ <CrashIcon color={iconColor} size={14} />
165
+ )}
166
+ {tab.icon === 'device' && (
167
+ <SmartphoneIcon color={iconColor} size={14} />
168
+ )}
169
+ {tab.icon === 'storage' && (
170
+ <DatabaseIcon color={iconColor} size={14} />
171
+ )}
172
+ <Text
173
+ numberOfLines={1}
174
+ ellipsizeMode="tail"
175
+ style={[
176
+ styles.contentTabButtonText,
177
+ isActive &&
178
+ styles.contentTabButtonTextActive,
179
+ ]}>
180
+ {tab.label}{' '}
181
+ {tab.count > 0 ? `(${countLabel})` : ''}
182
+ </Text>
183
+ {((tab.key === 'apis' && hasUnreadApis) ||
184
+ (tab.key === 'logs' && hasUnreadLogs) ||
185
+ (tab.key === 'crash' && hasUnreadCrashes)) && (
186
+ <Animated.View
187
+ style={{
188
+ width: 6,
189
+ height: 6,
190
+ borderRadius: 3,
191
+ backgroundColor: AppColors.errorColor,
192
+ marginLeft: 4,
193
+ alignSelf: 'center',
194
+ transform: [{scale: unreadPulseAnim}],
195
+ }}
196
+ />
197
+ )}
198
+ </View>
199
+ </TouchableScale>
200
+ );
201
+ })}
202
+ </ScrollView>
203
+ </View>
204
+ );
205
+ });
206
+
207
+ export default TabBar;
@@ -0,0 +1,416 @@
1
+ import React, {useState, useEffect} from 'react';
2
+ import {
3
+ Modal,
4
+ View,
5
+ Text,
6
+ TouchableOpacity,
7
+ StyleSheet,
8
+ Animated,
9
+ Platform,
10
+ } from 'react-native';
11
+ import Svg, {Path} from 'react-native-svg';
12
+ import {BrandSquareIcon} from '../BrandSquareIcon';
13
+ import {
14
+ getTelemetryConsentStatus,
15
+ setTelemetryConsent,
16
+ sendSessionTelemetryPing,
17
+ } from '../../helpers/telemetry';
18
+
19
+ // ─── Inline Crisp SVG Icons ───────────────────────────────────────────────────
20
+
21
+ const ShieldCheckSvg = ({size = 15, color = '#7C3AED'}: {size?: number; color?: string}) => (
22
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
23
+ <Path
24
+ d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
25
+ stroke={color}
26
+ strokeWidth="2"
27
+ strokeLinecap="round"
28
+ strokeLinejoin="round"
29
+ />
30
+ <Path
31
+ d="M9 12l2 2 4-4"
32
+ stroke={color}
33
+ strokeWidth="2"
34
+ strokeLinecap="round"
35
+ strokeLinejoin="round"
36
+ />
37
+ </Svg>
38
+ );
39
+
40
+ const CheckSvg = ({size = 14, color = '#FFFFFF'}: {size?: number; color?: string}) => (
41
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
42
+ <Path
43
+ d="M20 6L9 17l-5-5"
44
+ stroke={color}
45
+ strokeWidth="2.4"
46
+ strokeLinecap="round"
47
+ strokeLinejoin="round"
48
+ />
49
+ </Svg>
50
+ );
51
+
52
+ const CloseSvg = ({size = 13, color = '#64748B'}: {size?: number; color?: string}) => (
53
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
54
+ <Path
55
+ d="M18 6L6 18M6 6l12 12"
56
+ stroke={color}
57
+ strokeWidth="2.2"
58
+ strokeLinecap="round"
59
+ strokeLinejoin="round"
60
+ />
61
+ </Svg>
62
+ );
63
+
64
+ const GearSvg = ({size = 13, color = '#6366F1'}: {size?: number; color?: string}) => (
65
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
66
+ <Path
67
+ d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"
68
+ stroke={color}
69
+ strokeWidth="2"
70
+ strokeLinecap="round"
71
+ strokeLinejoin="round"
72
+ />
73
+ <Path
74
+ d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1Z"
75
+ stroke={color}
76
+ strokeWidth="2"
77
+ strokeLinecap="round"
78
+ strokeLinejoin="round"
79
+ />
80
+ </Svg>
81
+ );
82
+
83
+ export const TelemetryConsentModal = () => {
84
+ const [visible, setVisible] = useState(false);
85
+ const fadeAnim = useState(new Animated.Value(0))[0];
86
+ const scaleAnim = useState(new Animated.Value(0.92))[0];
87
+
88
+ useEffect(() => {
89
+ let isMounted = true;
90
+ getTelemetryConsentStatus().then(status => {
91
+ if (isMounted && status === 'undetermined') {
92
+ setVisible(true);
93
+ Animated.parallel([
94
+ Animated.timing(fadeAnim, {
95
+ toValue: 1,
96
+ duration: 250,
97
+ useNativeDriver: true,
98
+ }),
99
+ Animated.spring(scaleAnim, {
100
+ toValue: 1,
101
+ friction: 8,
102
+ tension: 45,
103
+ useNativeDriver: true,
104
+ }),
105
+ ]).start();
106
+ }
107
+ });
108
+ return () => {
109
+ isMounted = false;
110
+ };
111
+ }, [fadeAnim, scaleAnim]);
112
+
113
+ const handleDecision = async (granted: boolean) => {
114
+ Animated.parallel([
115
+ Animated.timing(fadeAnim, {
116
+ toValue: 0,
117
+ duration: 180,
118
+ useNativeDriver: true,
119
+ }),
120
+ Animated.timing(scaleAnim, {
121
+ toValue: 0.92,
122
+ duration: 180,
123
+ useNativeDriver: true,
124
+ }),
125
+ ]).start(async () => {
126
+ setVisible(false);
127
+ await setTelemetryConsent(granted);
128
+ if (granted) {
129
+ // Immediately trigger the session initialization ping
130
+ sendSessionTelemetryPing({force: true});
131
+ }
132
+ });
133
+ };
134
+
135
+ if (!visible) return null;
136
+
137
+ return (
138
+ <Modal
139
+ transparent
140
+ visible={visible}
141
+ animationType="none"
142
+ statusBarTranslucent>
143
+ <View style={styles.overlay}>
144
+ <Animated.View
145
+ style={[
146
+ styles.card,
147
+ {
148
+ opacity: fadeAnim,
149
+ transform: [{scale: scaleAnim}],
150
+ },
151
+ ]}>
152
+ {/* Top-Right Dismiss Icon Button */}
153
+ <TouchableOpacity
154
+ style={styles.topCloseButton}
155
+ onPress={() => handleDecision(false)}
156
+ hitSlop={10}
157
+ activeOpacity={0.7}>
158
+ <CloseSvg size={13} color="#64748B" />
159
+ </TouchableOpacity>
160
+
161
+ {/* Centered Enlarged Square Brand Icon Header */}
162
+ <View style={styles.headerSection}>
163
+ <View style={styles.iconHaloRing}>
164
+ <BrandSquareIcon size={54} />
165
+ </View>
166
+
167
+ <Text style={styles.title}>Help Improve In-App Inspector</Text>
168
+ <Text style={styles.subtitle}>Anonymous Diagnostic Insights</Text>
169
+
170
+ {/* Subheading instruction hint badge */}
171
+ <View style={styles.hintBadge}>
172
+ <GearSvg size={12} color="#6366F1" />
173
+ <Text style={styles.hintBadgeText}>
174
+ You can enable or disable this anytime in Settings
175
+ </Text>
176
+ </View>
177
+ </View>
178
+
179
+ {/* Description */}
180
+ <Text style={styles.description}>
181
+ To help us continually enhance tooling performance and compatibility,
182
+ would you mind sharing anonymous diagnostics (such as React Native
183
+ version, JavaScript engine, and device architecture)?
184
+ </Text>
185
+
186
+ {/* Privacy Callout Box */}
187
+ <View style={styles.privacyBadge}>
188
+ <View style={styles.privacyShieldWrapper}>
189
+ <ShieldCheckSvg size={15} color="#7C3AED" />
190
+ </View>
191
+ <Text style={styles.privacyText}>
192
+ <Text style={styles.privacyHighlight}>Privacy Guaranteed:</Text> We
193
+ strictly collect non-identifiable technical metrics. No user data,
194
+ passwords, tokens, or network payload bodies are ever captured.
195
+ </Text>
196
+ </View>
197
+
198
+ {/* Enhanced Action Buttons with Icons */}
199
+ <View style={styles.buttonRow}>
200
+ <TouchableOpacity
201
+ style={styles.declineButton}
202
+ onPress={() => handleDecision(false)}
203
+ activeOpacity={0.7}>
204
+ <CloseSvg size={12} color="#64748B" />
205
+ <Text style={styles.declineText}>Not Now</Text>
206
+ </TouchableOpacity>
207
+
208
+ <TouchableOpacity
209
+ style={styles.allowButton}
210
+ onPress={() => handleDecision(true)}
211
+ activeOpacity={0.85}>
212
+ <CheckSvg size={13} color="#FFFFFF" />
213
+ <Text style={styles.allowText}>Allow & Share</Text>
214
+ </TouchableOpacity>
215
+ </View>
216
+ </Animated.View>
217
+ </View>
218
+ </Modal>
219
+ );
220
+ };
221
+
222
+ const fontStack = Platform.select({
223
+ ios: {
224
+ fontFamily: 'System',
225
+ },
226
+ android: {
227
+ fontFamily: 'sans-serif',
228
+ },
229
+ default: {},
230
+ });
231
+
232
+ const styles = StyleSheet.create({
233
+ overlay: {
234
+ flex: 1,
235
+ backgroundColor: 'rgba(15, 23, 42, 0.56)',
236
+ justifyContent: 'center',
237
+ alignItems: 'center',
238
+ paddingHorizontal: 20,
239
+ zIndex: 999999,
240
+ },
241
+ card: {
242
+ width: '100%',
243
+ maxWidth: 356,
244
+ backgroundColor: '#FFFFFF',
245
+ borderRadius: 24,
246
+ borderWidth: 1,
247
+ borderColor: '#E2E8F0',
248
+ paddingHorizontal: 20,
249
+ paddingTop: 22,
250
+ paddingBottom: 20,
251
+ alignItems: 'center',
252
+ shadowColor: '#0F172A',
253
+ shadowOffset: {width: 0, height: 16},
254
+ shadowOpacity: 0.22,
255
+ shadowRadius: 32,
256
+ elevation: 24,
257
+ },
258
+ topCloseButton: {
259
+ position: 'absolute',
260
+ top: 14,
261
+ right: 14,
262
+ width: 28,
263
+ height: 28,
264
+ borderRadius: 14,
265
+ backgroundColor: '#F8FAFC',
266
+ justifyContent: 'center',
267
+ alignItems: 'center',
268
+ borderWidth: 1,
269
+ borderColor: '#E2E8F0',
270
+ zIndex: 10,
271
+ },
272
+ headerSection: {
273
+ alignItems: 'center',
274
+ width: '100%',
275
+ marginBottom: 4,
276
+ },
277
+ iconHaloRing: {
278
+ width: 66,
279
+ height: 66,
280
+ borderRadius: 20,
281
+ backgroundColor: '#FAF5FF',
282
+ justifyContent: 'center',
283
+ alignItems: 'center',
284
+ borderWidth: 1.5,
285
+ borderColor: '#F3E8FF',
286
+ marginBottom: 8,
287
+ shadowColor: '#7C3AED',
288
+ shadowOffset: {width: 0, height: 4},
289
+ shadowOpacity: 0.16,
290
+ shadowRadius: 10,
291
+ elevation: 4,
292
+ },
293
+ title: {
294
+ fontSize: 17,
295
+ fontWeight: '800',
296
+ color: '#0F172A',
297
+ letterSpacing: -0.4,
298
+ textAlign: 'center',
299
+ lineHeight: 22,
300
+ marginBottom: 2,
301
+ ...fontStack,
302
+ },
303
+ subtitle: {
304
+ fontSize: 11.5,
305
+ fontWeight: '600',
306
+ color: '#7C3AED',
307
+ textAlign: 'center',
308
+ letterSpacing: 0.2,
309
+ marginBottom: 6,
310
+ ...fontStack,
311
+ },
312
+ hintBadge: {
313
+ flexDirection: 'row',
314
+ alignItems: 'center',
315
+ justifyContent: 'center',
316
+ gap: 5,
317
+ backgroundColor: '#EDE9FE80',
318
+ borderWidth: 1,
319
+ borderColor: '#DDD6FE',
320
+ borderRadius: 7,
321
+ paddingHorizontal: 8,
322
+ paddingVertical: 3,
323
+ marginBottom: 8,
324
+ },
325
+ hintBadgeText: {
326
+ fontSize: 10,
327
+ fontWeight: '600',
328
+ color: '#6D28D9',
329
+ textAlign: 'center',
330
+ ...fontStack,
331
+ },
332
+ description: {
333
+ fontSize: 12,
334
+ lineHeight: 17.5,
335
+ color: '#475569',
336
+ textAlign: 'center',
337
+ marginBottom: 12,
338
+ paddingHorizontal: 2,
339
+ ...fontStack,
340
+ },
341
+ privacyBadge: {
342
+ flexDirection: 'row',
343
+ alignItems: 'flex-start',
344
+ backgroundColor: '#F8FAFC',
345
+ borderRadius: 12,
346
+ paddingVertical: 8,
347
+ paddingHorizontal: 10,
348
+ borderWidth: 1,
349
+ borderColor: '#E2E8F0',
350
+ marginBottom: 14,
351
+ width: '100%',
352
+ },
353
+ privacyShieldWrapper: {
354
+ marginRight: 7,
355
+ marginTop: 1,
356
+ },
357
+ privacyText: {
358
+ flex: 1,
359
+ fontSize: 10.8,
360
+ lineHeight: 15,
361
+ color: '#475569',
362
+ ...fontStack,
363
+ },
364
+ privacyHighlight: {
365
+ fontWeight: '700',
366
+ color: '#1E293B',
367
+ },
368
+ buttonRow: {
369
+ flexDirection: 'row',
370
+ justifyContent: 'space-between',
371
+ alignItems: 'center',
372
+ gap: 10,
373
+ width: '100%',
374
+ },
375
+ declineButton: {
376
+ flex: 1,
377
+ flexDirection: 'row',
378
+ alignItems: 'center',
379
+ justifyContent: 'center',
380
+ gap: 5,
381
+ paddingVertical: 11,
382
+ borderRadius: 12,
383
+ backgroundColor: '#F1F5F9',
384
+ borderWidth: 1,
385
+ borderColor: '#E2E8F0',
386
+ },
387
+ declineText: {
388
+ fontSize: 13,
389
+ fontWeight: '600',
390
+ color: '#475569',
391
+ ...fontStack,
392
+ },
393
+ allowButton: {
394
+ flex: 1,
395
+ flexDirection: 'row',
396
+ alignItems: 'center',
397
+ justifyContent: 'center',
398
+ gap: 5,
399
+ paddingVertical: 11,
400
+ borderRadius: 12,
401
+ backgroundColor: '#7C3AED',
402
+ shadowColor: '#7C3AED',
403
+ shadowOffset: {width: 0, height: 3},
404
+ shadowOpacity: 0.28,
405
+ shadowRadius: 6,
406
+ elevation: 4,
407
+ },
408
+ allowText: {
409
+ fontSize: 13,
410
+ fontWeight: '700',
411
+ color: '#FFFFFF',
412
+ ...fontStack,
413
+ },
414
+ });
415
+
416
+ export default TelemetryConsentModal;