@mobileai/react-native 0.9.0 → 0.9.1
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.
- package/README.md +121 -0
- package/lib/module/components/AIAgent.js +248 -53
- package/lib/module/components/AIAgent.js.map +1 -1
- package/lib/module/components/AIZone.js +140 -0
- package/lib/module/components/AIZone.js.map +1 -0
- package/lib/module/components/AgentErrorBoundary.js +9 -0
- package/lib/module/components/AgentErrorBoundary.js.map +1 -1
- package/lib/module/components/HighlightOverlay.js +138 -0
- package/lib/module/components/HighlightOverlay.js.map +1 -0
- package/lib/module/components/ProactiveHint.js +138 -0
- package/lib/module/components/ProactiveHint.js.map +1 -0
- package/lib/module/components/cards/InfoCard.js +65 -0
- package/lib/module/components/cards/InfoCard.js.map +1 -0
- package/lib/module/components/cards/ReviewSummary.js +74 -0
- package/lib/module/components/cards/ReviewSummary.js.map +1 -0
- package/lib/module/core/AgentRuntime.js +16 -3
- package/lib/module/core/AgentRuntime.js.map +1 -1
- package/lib/module/core/FiberTreeWalker.js +62 -85
- package/lib/module/core/FiberTreeWalker.js.map +1 -1
- package/lib/module/core/IdleDetector.js +51 -0
- package/lib/module/core/IdleDetector.js.map +1 -0
- package/lib/module/core/ZoneRegistry.js +47 -0
- package/lib/module/core/ZoneRegistry.js.map +1 -0
- package/lib/module/core/systemPrompt.js +2 -0
- package/lib/module/core/systemPrompt.js.map +1 -1
- package/lib/module/index.js +21 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/AudioOutputService.js +10 -0
- package/lib/module/services/AudioOutputService.js.map +1 -1
- package/lib/module/services/flags/FlagService.js +117 -0
- package/lib/module/services/flags/FlagService.js.map +1 -0
- package/lib/module/services/telemetry/MobileAI.js +66 -0
- package/lib/module/services/telemetry/MobileAI.js.map +1 -0
- package/lib/module/services/telemetry/PiiScrubber.js +17 -0
- package/lib/module/services/telemetry/PiiScrubber.js.map +1 -0
- package/lib/module/services/telemetry/TelemetryService.js +260 -0
- package/lib/module/services/telemetry/TelemetryService.js.map +1 -0
- package/lib/module/services/telemetry/TouchAutoCapture.js +159 -0
- package/lib/module/services/telemetry/TouchAutoCapture.js.map +1 -0
- package/lib/module/services/telemetry/device.js +19 -0
- package/lib/module/services/telemetry/device.js.map +1 -0
- package/lib/module/services/telemetry/index.js +9 -0
- package/lib/module/services/telemetry/index.js.map +1 -0
- package/lib/module/services/telemetry/types.js +2 -0
- package/lib/module/services/telemetry/types.js.map +1 -0
- package/lib/module/support/CSATSurvey.js +273 -0
- package/lib/module/support/CSATSurvey.js.map +1 -0
- package/lib/module/support/EscalationSocket.js +92 -0
- package/lib/module/support/EscalationSocket.js.map +1 -0
- package/lib/module/support/SupportGreeting.js +142 -0
- package/lib/module/support/SupportGreeting.js.map +1 -0
- package/lib/module/support/escalateTool.js +120 -0
- package/lib/module/support/escalateTool.js.map +1 -0
- package/lib/module/support/index.js +18 -0
- package/lib/module/support/index.js.map +1 -0
- package/lib/module/support/supportPrompt.js +47 -0
- package/lib/module/support/supportPrompt.js.map +1 -0
- package/lib/module/support/types.js +2 -0
- package/lib/module/support/types.js.map +1 -0
- package/lib/module/tools/guideTool.js +61 -0
- package/lib/module/tools/guideTool.js.map +1 -0
- package/lib/module/tools/index.js +3 -0
- package/lib/module/tools/index.js.map +1 -1
- package/lib/module/tools/restoreTool.js +31 -0
- package/lib/module/tools/restoreTool.js.map +1 -0
- package/lib/module/tools/simplifyTool.js +31 -0
- package/lib/module/tools/simplifyTool.js.map +1 -0
- package/lib/module/types/jsx.d.js +4 -0
- package/lib/module/types/jsx.d.js.map +1 -0
- package/lib/typescript/src/components/AIAgent.d.ts +21 -2
- package/lib/typescript/src/components/AIAgent.d.ts.map +1 -1
- package/lib/typescript/src/components/AIZone.d.ts +16 -0
- package/lib/typescript/src/components/AIZone.d.ts.map +1 -0
- package/lib/typescript/src/components/AgentErrorBoundary.d.ts +1 -0
- package/lib/typescript/src/components/AgentErrorBoundary.d.ts.map +1 -1
- package/lib/typescript/src/components/HighlightOverlay.d.ts +10 -0
- package/lib/typescript/src/components/HighlightOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/ProactiveHint.d.ts +10 -0
- package/lib/typescript/src/components/ProactiveHint.d.ts.map +1 -0
- package/lib/typescript/src/components/cards/InfoCard.d.ts +19 -0
- package/lib/typescript/src/components/cards/InfoCard.d.ts.map +1 -0
- package/lib/typescript/src/components/cards/ReviewSummary.d.ts +19 -0
- package/lib/typescript/src/components/cards/ReviewSummary.d.ts.map +1 -0
- package/lib/typescript/src/core/AgentRuntime.d.ts +1 -0
- package/lib/typescript/src/core/AgentRuntime.d.ts.map +1 -1
- package/lib/typescript/src/core/FiberTreeWalker.d.ts.map +1 -1
- package/lib/typescript/src/core/IdleDetector.d.ts +27 -0
- package/lib/typescript/src/core/IdleDetector.d.ts.map +1 -0
- package/lib/typescript/src/core/ZoneRegistry.d.ts +13 -0
- package/lib/typescript/src/core/ZoneRegistry.d.ts.map +1 -0
- package/lib/typescript/src/core/systemPrompt.d.ts.map +1 -1
- package/lib/typescript/src/core/types.d.ts +54 -0
- package/lib/typescript/src/core/types.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/services/AudioOutputService.d.ts.map +1 -1
- package/lib/typescript/src/services/flags/FlagService.d.ts +25 -0
- package/lib/typescript/src/services/flags/FlagService.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/MobileAI.d.ts +38 -0
- package/lib/typescript/src/services/telemetry/MobileAI.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/PiiScrubber.d.ts +6 -0
- package/lib/typescript/src/services/telemetry/PiiScrubber.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/TelemetryService.d.ts +49 -0
- package/lib/typescript/src/services/telemetry/TelemetryService.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts +28 -0
- package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/device.d.ts +7 -0
- package/lib/typescript/src/services/telemetry/device.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/index.d.ts +7 -0
- package/lib/typescript/src/services/telemetry/index.d.ts.map +1 -0
- package/lib/typescript/src/services/telemetry/types.d.ts +50 -0
- package/lib/typescript/src/services/telemetry/types.d.ts.map +1 -0
- package/lib/typescript/src/support/CSATSurvey.d.ts +20 -0
- package/lib/typescript/src/support/CSATSurvey.d.ts.map +1 -0
- package/lib/typescript/src/support/EscalationSocket.d.ts +38 -0
- package/lib/typescript/src/support/EscalationSocket.d.ts.map +1 -0
- package/lib/typescript/src/support/SupportGreeting.d.ts +19 -0
- package/lib/typescript/src/support/SupportGreeting.d.ts.map +1 -0
- package/lib/typescript/src/support/escalateTool.d.ts +25 -0
- package/lib/typescript/src/support/escalateTool.d.ts.map +1 -0
- package/lib/typescript/src/support/index.d.ts +11 -0
- package/lib/typescript/src/support/index.d.ts.map +1 -0
- package/lib/typescript/src/support/supportPrompt.d.ts +12 -0
- package/lib/typescript/src/support/supportPrompt.d.ts.map +1 -0
- package/lib/typescript/src/support/types.d.ts +114 -0
- package/lib/typescript/src/support/types.d.ts.map +1 -0
- package/lib/typescript/src/tools/guideTool.d.ts +4 -0
- package/lib/typescript/src/tools/guideTool.d.ts.map +1 -0
- package/lib/typescript/src/tools/index.d.ts +3 -0
- package/lib/typescript/src/tools/index.d.ts.map +1 -1
- package/lib/typescript/src/tools/restoreTool.d.ts +3 -0
- package/lib/typescript/src/tools/restoreTool.d.ts.map +1 -0
- package/lib/typescript/src/tools/simplifyTool.d.ts +3 -0
- package/lib/typescript/src/tools/simplifyTool.d.ts.map +1 -0
- package/lib/typescript/src/tools/types.d.ts +2 -0
- package/lib/typescript/src/tools/types.d.ts.map +1 -1
- package/package.json +5 -1
- package/src/components/AIAgent.tsx +253 -15
- package/src/components/AIZone.tsx +147 -0
- package/src/components/AgentErrorBoundary.tsx +10 -0
- package/src/components/HighlightOverlay.tsx +136 -0
- package/src/components/ProactiveHint.tsx +145 -0
- package/src/components/cards/InfoCard.tsx +58 -0
- package/src/components/cards/ReviewSummary.tsx +76 -0
- package/src/core/AgentRuntime.ts +18 -0
- package/src/core/FiberTreeWalker.ts +71 -93
- package/src/core/IdleDetector.ts +72 -0
- package/src/core/ZoneRegistry.ts +44 -0
- package/src/core/systemPrompt.ts +2 -0
- package/src/core/types.ts +60 -0
- package/src/index.ts +31 -0
- package/src/services/AudioOutputService.ts +13 -0
- package/src/services/flags/FlagService.ts +137 -0
- package/src/services/telemetry/MobileAI.ts +66 -0
- package/src/services/telemetry/PiiScrubber.ts +17 -0
- package/src/services/telemetry/TelemetryService.ts +291 -0
- package/src/services/telemetry/TouchAutoCapture.ts +165 -0
- package/src/services/telemetry/device.ts +16 -0
- package/src/services/telemetry/index.ts +13 -0
- package/src/services/telemetry/types.ts +75 -0
- package/src/support/CSATSurvey.tsx +304 -0
- package/src/support/EscalationSocket.ts +113 -0
- package/src/support/SupportGreeting.tsx +161 -0
- package/src/support/escalateTool.ts +134 -0
- package/src/support/index.ts +27 -0
- package/src/support/supportPrompt.ts +55 -0
- package/src/support/types.ts +141 -0
- package/src/tools/guideTool.ts +67 -0
- package/src/tools/index.ts +3 -0
- package/src/tools/restoreTool.ts +33 -0
- package/src/tools/simplifyTool.ts +33 -0
- package/src/tools/types.ts +2 -0
- package/src/types/jsx.d.ts +20 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TelemetryService — Batches and sends analytics events to MobileAI Cloud.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Event batching (flush every N seconds or N events)
|
|
8
|
+
* - Offline queue with retry on reconnect
|
|
9
|
+
* - Lightweight — no native dependencies
|
|
10
|
+
* - Opt-in only (requires analyticsKey or analyticsProxyUrl)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { AppState, Platform } from 'react-native';
|
|
14
|
+
import { logger } from "../../utils/logger.js";
|
|
15
|
+
import { scrubPII } from "./PiiScrubber.js";
|
|
16
|
+
import { FlagService } from "../flags/FlagService.js";
|
|
17
|
+
|
|
18
|
+
// Optional: AsyncStorage for offline event persistence
|
|
19
|
+
// SDK works without it — just loses crash recovery for queued events
|
|
20
|
+
let AsyncStorageModule = null;
|
|
21
|
+
try {
|
|
22
|
+
AsyncStorageModule = require('@react-native-async-storage/async-storage').default;
|
|
23
|
+
} catch {
|
|
24
|
+
// Not installed — offline queue persistence disabled
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ─── Constants ─────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
const CLOUD_API_URL = 'https://api.maiagent.dev/v1/events';
|
|
30
|
+
const STORAGE_KEY = '@mobileai/telemetry_queue';
|
|
31
|
+
const DEFAULT_FLUSH_INTERVAL_MS = 30_000;
|
|
32
|
+
const DEFAULT_MAX_BATCH_SIZE = 50;
|
|
33
|
+
const SDK_VERSION = '0.10.0';
|
|
34
|
+
const LOG_TAG = 'Telemetry';
|
|
35
|
+
|
|
36
|
+
// ─── Utility ───────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
function generateSessionId() {
|
|
39
|
+
return `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
40
|
+
}
|
|
41
|
+
import { getDeviceId } from "./device.js";
|
|
42
|
+
|
|
43
|
+
// ─── Service ───────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
export class TelemetryService {
|
|
46
|
+
queue = [];
|
|
47
|
+
currentScreen = 'Unknown';
|
|
48
|
+
flushTimer = null;
|
|
49
|
+
isFlushing = false;
|
|
50
|
+
appStateSubscription = null;
|
|
51
|
+
|
|
52
|
+
/** Public getter for the current screen, used by auto-capture utilities */
|
|
53
|
+
get screen() {
|
|
54
|
+
return this.currentScreen;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* True while the AI agent is executing a tool (tap, type, navigate, etc.).
|
|
59
|
+
* The touch interceptor checks this flag to avoid double-counting AI actions
|
|
60
|
+
* as human interactions. Agent steps are already tracked as agent_step events.
|
|
61
|
+
*/
|
|
62
|
+
isAgentActing = false;
|
|
63
|
+
/** Set by AgentRuntime before/after each tool execution. */
|
|
64
|
+
setAgentActing(active) {
|
|
65
|
+
this.isAgentActing = active;
|
|
66
|
+
}
|
|
67
|
+
constructor(config) {
|
|
68
|
+
this.config = config;
|
|
69
|
+
this.sessionId = generateSessionId();
|
|
70
|
+
|
|
71
|
+
// Extract base URL for flags API (e.g. drop /v1/events)
|
|
72
|
+
let baseUrl = 'https://api.maiagent.dev';
|
|
73
|
+
try {
|
|
74
|
+
if (config.analyticsProxyUrl) {
|
|
75
|
+
baseUrl = new URL(config.analyticsProxyUrl).origin;
|
|
76
|
+
}
|
|
77
|
+
} catch {}
|
|
78
|
+
this.flags = new FlagService(baseUrl);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ─── Lifecycle ──────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
/** Start the telemetry service (call on mount) */
|
|
84
|
+
async start() {
|
|
85
|
+
if (!this.isEnabled()) {
|
|
86
|
+
logger.debug(LOG_TAG, 'Disabled — no analyticsKey or proxyUrl');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Restore queued events from previous session
|
|
91
|
+
await this.restoreQueue();
|
|
92
|
+
|
|
93
|
+
// Fetch feature flags asynchronously (do not block startup)
|
|
94
|
+
if (this.config.analyticsKey) {
|
|
95
|
+
this.flags.fetch(this.config.analyticsKey).catch(e => logger.warn(LOG_TAG, `Could not sync flags: ${e.message}`));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Start periodic flush
|
|
99
|
+
const interval = this.config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
|
|
100
|
+
this.flushTimer = setInterval(() => this.flush(), interval);
|
|
101
|
+
|
|
102
|
+
// Flush on app background
|
|
103
|
+
this.appStateSubscription = AppState.addEventListener('change', state => {
|
|
104
|
+
if (state === 'background' || state === 'inactive') {
|
|
105
|
+
this.flush();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Track session start
|
|
110
|
+
this.track('session_start', {
|
|
111
|
+
device: Platform.OS,
|
|
112
|
+
os: String(Platform.Version),
|
|
113
|
+
sdk_version: SDK_VERSION
|
|
114
|
+
});
|
|
115
|
+
logger.info(LOG_TAG, `Started (session: ${this.sessionId})`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Stop the telemetry service (call on unmount) */
|
|
119
|
+
async stop() {
|
|
120
|
+
if (!this.isEnabled()) return;
|
|
121
|
+
|
|
122
|
+
// Track session end
|
|
123
|
+
this.track('session_end', {
|
|
124
|
+
events_count: this.queue.length
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Final flush
|
|
128
|
+
await this.flush();
|
|
129
|
+
|
|
130
|
+
// Cleanup
|
|
131
|
+
if (this.flushTimer) {
|
|
132
|
+
clearInterval(this.flushTimer);
|
|
133
|
+
this.flushTimer = null;
|
|
134
|
+
}
|
|
135
|
+
if (this.appStateSubscription) {
|
|
136
|
+
this.appStateSubscription.remove();
|
|
137
|
+
this.appStateSubscription = null;
|
|
138
|
+
}
|
|
139
|
+
logger.info(LOG_TAG, 'Stopped');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ─── Public API ─────────────────────────────────────────────
|
|
143
|
+
|
|
144
|
+
/** Track an event (auto or custom) */
|
|
145
|
+
track(type, data = {}) {
|
|
146
|
+
if (!this.isEnabled()) return;
|
|
147
|
+
|
|
148
|
+
// Sanitize any string values in the data payload to remove PII
|
|
149
|
+
const sanitizedData = Object.fromEntries(Object.entries(data).map(([k, v]) => [k, typeof v === 'string' ? scrubPII(v) : v]));
|
|
150
|
+
|
|
151
|
+
// Auto-append active feature flags
|
|
152
|
+
sanitizedData.$flags = this.flags.getAllFlags();
|
|
153
|
+
const event = {
|
|
154
|
+
type,
|
|
155
|
+
data: sanitizedData,
|
|
156
|
+
timestamp: new Date().toISOString(),
|
|
157
|
+
screen: this.currentScreen,
|
|
158
|
+
sessionId: this.sessionId
|
|
159
|
+
};
|
|
160
|
+
this.queue.push(event);
|
|
161
|
+
if (this.config.debug) {
|
|
162
|
+
logger.debug(LOG_TAG, `→ ${type}`, data);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Auto-flush if batch is full
|
|
166
|
+
const maxSize = this.config.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
|
|
167
|
+
if (this.queue.length >= maxSize) {
|
|
168
|
+
this.flush();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Update current screen (called by AIAgent on navigation) */
|
|
173
|
+
setScreen(screenName) {
|
|
174
|
+
if (this.currentScreen !== screenName) {
|
|
175
|
+
const prevScreen = this.currentScreen;
|
|
176
|
+
this.currentScreen = screenName;
|
|
177
|
+
this.track('screen_view', {
|
|
178
|
+
screen: screenName,
|
|
179
|
+
prev_screen: prevScreen
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ─── Flush ──────────────────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
/** Send queued events to the cloud API */
|
|
187
|
+
async flush() {
|
|
188
|
+
if (!this.isEnabled() || this.queue.length === 0 || this.isFlushing) return;
|
|
189
|
+
this.isFlushing = true;
|
|
190
|
+
const eventsToSend = [...this.queue];
|
|
191
|
+
this.queue = [];
|
|
192
|
+
try {
|
|
193
|
+
const url = this.config.analyticsProxyUrl ?? CLOUD_API_URL;
|
|
194
|
+
const headers = {
|
|
195
|
+
'Content-Type': 'application/json',
|
|
196
|
+
...(this.config.analyticsProxyHeaders ?? {})
|
|
197
|
+
};
|
|
198
|
+
const batch = {
|
|
199
|
+
analyticsKey: this.config.analyticsKey ?? '',
|
|
200
|
+
appId: Platform.OS,
|
|
201
|
+
// Consumer can override via config later
|
|
202
|
+
deviceId: getDeviceId(),
|
|
203
|
+
sdkVersion: SDK_VERSION,
|
|
204
|
+
events: eventsToSend
|
|
205
|
+
};
|
|
206
|
+
const response = await fetch(url, {
|
|
207
|
+
method: 'POST',
|
|
208
|
+
headers,
|
|
209
|
+
body: JSON.stringify(batch)
|
|
210
|
+
});
|
|
211
|
+
if (!response.ok) {
|
|
212
|
+
throw new Error(`HTTP ${response.status}`);
|
|
213
|
+
}
|
|
214
|
+
logger.info(LOG_TAG, `Flushed ${eventsToSend.length} events`);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
// Re-queue failed events for retry
|
|
217
|
+
this.queue = [...eventsToSend, ...this.queue];
|
|
218
|
+
await this.persistQueue();
|
|
219
|
+
logger.warn(LOG_TAG, `Flush failed (${eventsToSend.length} events re-queued): ${error.message}`);
|
|
220
|
+
} finally {
|
|
221
|
+
this.isFlushing = false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ─── Persistence (offline support) ──────────────────────────
|
|
226
|
+
|
|
227
|
+
/** Save queued events to AsyncStorage for crash/restart recovery */
|
|
228
|
+
async persistQueue() {
|
|
229
|
+
if (!AsyncStorageModule) return;
|
|
230
|
+
try {
|
|
231
|
+
await AsyncStorageModule.setItem(STORAGE_KEY, JSON.stringify(this.queue));
|
|
232
|
+
} catch {
|
|
233
|
+
// AsyncStorage may not be available in all environments
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Restore queued events from previous session */
|
|
238
|
+
async restoreQueue() {
|
|
239
|
+
if (!AsyncStorageModule) return;
|
|
240
|
+
try {
|
|
241
|
+
const stored = await AsyncStorageModule.getItem(STORAGE_KEY);
|
|
242
|
+
if (stored) {
|
|
243
|
+
const events = JSON.parse(stored);
|
|
244
|
+
this.queue = [...events, ...this.queue];
|
|
245
|
+
await AsyncStorageModule.removeItem(STORAGE_KEY);
|
|
246
|
+
logger.info(LOG_TAG, `Restored ${events.length} events from previous session`);
|
|
247
|
+
}
|
|
248
|
+
} catch {
|
|
249
|
+
// Silently fail — telemetry is non-critical
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ─── Helpers ────────────────────────────────────────────────
|
|
254
|
+
|
|
255
|
+
/** Check if telemetry is configured */
|
|
256
|
+
isEnabled() {
|
|
257
|
+
return !!(this.config.analyticsKey || this.config.analyticsProxyUrl);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=TelemetryService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["AppState","Platform","logger","scrubPII","FlagService","AsyncStorageModule","require","default","CLOUD_API_URL","STORAGE_KEY","DEFAULT_FLUSH_INTERVAL_MS","DEFAULT_MAX_BATCH_SIZE","SDK_VERSION","LOG_TAG","generateSessionId","Date","now","Math","random","toString","slice","getDeviceId","TelemetryService","queue","currentScreen","flushTimer","isFlushing","appStateSubscription","screen","isAgentActing","setAgentActing","active","constructor","config","sessionId","baseUrl","analyticsProxyUrl","URL","origin","flags","start","isEnabled","debug","restoreQueue","analyticsKey","fetch","catch","e","warn","message","interval","flushIntervalMs","setInterval","flush","addEventListener","state","track","device","OS","os","String","Version","sdk_version","info","stop","events_count","length","clearInterval","remove","type","data","sanitizedData","Object","fromEntries","entries","map","k","v","$flags","getAllFlags","event","timestamp","toISOString","push","maxSize","maxBatchSize","setScreen","screenName","prevScreen","prev_screen","eventsToSend","url","headers","analyticsProxyHeaders","batch","appId","deviceId","sdkVersion","events","response","method","body","JSON","stringify","ok","Error","status","error","persistQueue","setItem","stored","getItem","parse","removeItem"],"sourceRoot":"../../../../src","sources":["services/telemetry/TelemetryService.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,QAAQ,EAAEC,QAAQ,QAAQ,cAAc;AACjD,SAASC,MAAM,QAAQ,uBAAoB;AAM3C,SAASC,QAAQ,QAAQ,kBAAe;AACxC,SAASC,WAAW,QAAQ,yBAAsB;;AAElD;AACA;AACA,IAAIC,kBAAuB,GAAG,IAAI;AAClC,IAAI;EACFA,kBAAkB,GAAGC,OAAO,CAAC,2CAA2C,CAAC,CAACC,OAAO;AACnF,CAAC,CAAC,MAAM;EACN;AAAA;;AAGF;;AAEA,MAAMC,aAAa,GAAG,oCAAoC;AAC1D,MAAMC,WAAW,GAAG,2BAA2B;AAC/C,MAAMC,yBAAyB,GAAG,MAAM;AACxC,MAAMC,sBAAsB,GAAG,EAAE;AACjC,MAAMC,WAAW,GAAG,QAAQ;AAC5B,MAAMC,OAAO,GAAG,WAAW;;AAE3B;;AAEA,SAASC,iBAAiBA,CAAA,EAAW;EACnC,OAAO,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,IAAIC,IAAI,CAACC,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC,CAACC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;AACnE;AAEA,SAASC,WAAW,QAAQ,aAAU;;AAEtC;;AAEA,OAAO,MAAMC,gBAAgB,CAAC;EACpBC,KAAK,GAAqB,EAAE;EAG5BC,aAAa,GAAG,SAAS;EACzBC,UAAU,GAA0C,IAAI;EACxDC,UAAU,GAAG,KAAK;EAClBC,oBAAoB,GAAwD,IAAI;;EAExF;EACA,IAAIC,MAAMA,CAAA,EAAW;IACnB,OAAO,IAAI,CAACJ,aAAa;EAC3B;;EAEA;AACF;AACA;AACA;AACA;EACEK,aAAa,GAAG,KAAK;EAIrB;EACAC,cAAcA,CAACC,MAAe,EAAQ;IACpC,IAAI,CAACF,aAAa,GAAGE,MAAM;EAC7B;EAEAC,WAAWA,CAACC,MAAuB,EAAE;IACnC,IAAI,CAACA,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACC,SAAS,GAAGpB,iBAAiB,CAAC,CAAC;;IAEpC;IACA,IAAIqB,OAAO,GAAG,0BAA0B;IACxC,IAAI;MACF,IAAIF,MAAM,CAACG,iBAAiB,EAAE;QAC5BD,OAAO,GAAG,IAAIE,GAAG,CAACJ,MAAM,CAACG,iBAAiB,CAAC,CAACE,MAAM;MACpD;IACF,CAAC,CAAC,MAAM,CAAC;IACT,IAAI,CAACC,KAAK,GAAG,IAAInC,WAAW,CAAC+B,OAAO,CAAC;EACvC;;EAEA;;EAEA;EACA,MAAMK,KAAKA,CAAA,EAAkB;IAC3B,IAAI,CAAC,IAAI,CAACC,SAAS,CAAC,CAAC,EAAE;MACrBvC,MAAM,CAACwC,KAAK,CAAC7B,OAAO,EAAE,wCAAwC,CAAC;MAC/D;IACF;;IAEA;IACA,MAAM,IAAI,CAAC8B,YAAY,CAAC,CAAC;;IAEzB;IACA,IAAI,IAAI,CAACV,MAAM,CAACW,YAAY,EAAE;MAC5B,IAAI,CAACL,KAAK,CAACM,KAAK,CAAC,IAAI,CAACZ,MAAM,CAACW,YAAY,CAAC,CAACE,KAAK,CAAEC,CAAC,IACjD7C,MAAM,CAAC8C,IAAI,CAACnC,OAAO,EAAE,yBAAyBkC,CAAC,CAACE,OAAO,EAAE,CAC3D,CAAC;IACH;;IAEA;IACA,MAAMC,QAAQ,GAAG,IAAI,CAACjB,MAAM,CAACkB,eAAe,IAAIzC,yBAAyB;IACzE,IAAI,CAACe,UAAU,GAAG2B,WAAW,CAAC,MAAM,IAAI,CAACC,KAAK,CAAC,CAAC,EAAEH,QAAQ,CAAC;;IAE3D;IACA,IAAI,CAACvB,oBAAoB,GAAG3B,QAAQ,CAACsD,gBAAgB,CACnD,QAAQ,EACPC,KAAK,IAAK;MACT,IAAIA,KAAK,KAAK,YAAY,IAAIA,KAAK,KAAK,UAAU,EAAE;QAClD,IAAI,CAACF,KAAK,CAAC,CAAC;MACd;IACF,CACF,CAAC;;IAED;IACA,IAAI,CAACG,KAAK,CAAC,eAAe,EAAE;MAC1BC,MAAM,EAAExD,QAAQ,CAACyD,EAAE;MACnBC,EAAE,EAAEC,MAAM,CAAC3D,QAAQ,CAAC4D,OAAO,CAAC;MAC5BC,WAAW,EAAElD;IACf,CAAC,CAAC;IAEFV,MAAM,CAAC6D,IAAI,CAAClD,OAAO,EAAE,qBAAqB,IAAI,CAACqB,SAAS,GAAG,CAAC;EAC9D;;EAEA;EACA,MAAM8B,IAAIA,CAAA,EAAkB;IAC1B,IAAI,CAAC,IAAI,CAACvB,SAAS,CAAC,CAAC,EAAE;;IAEvB;IACA,IAAI,CAACe,KAAK,CAAC,aAAa,EAAE;MACxBS,YAAY,EAAE,IAAI,CAAC1C,KAAK,CAAC2C;IAC3B,CAAC,CAAC;;IAEF;IACA,MAAM,IAAI,CAACb,KAAK,CAAC,CAAC;;IAElB;IACA,IAAI,IAAI,CAAC5B,UAAU,EAAE;MACnB0C,aAAa,CAAC,IAAI,CAAC1C,UAAU,CAAC;MAC9B,IAAI,CAACA,UAAU,GAAG,IAAI;IACxB;IACA,IAAI,IAAI,CAACE,oBAAoB,EAAE;MAC7B,IAAI,CAACA,oBAAoB,CAACyC,MAAM,CAAC,CAAC;MAClC,IAAI,CAACzC,oBAAoB,GAAG,IAAI;IAClC;IAEAzB,MAAM,CAAC6D,IAAI,CAAClD,OAAO,EAAE,SAAS,CAAC;EACjC;;EAEA;;EAEA;EACA2C,KAAKA,CAACa,IAAY,EAAEC,IAA6B,GAAG,CAAC,CAAC,EAAQ;IAC5D,IAAI,CAAC,IAAI,CAAC7B,SAAS,CAAC,CAAC,EAAE;;IAEvB;IACA,MAAM8B,aAAa,GAAGC,MAAM,CAACC,WAAW,CACtCD,MAAM,CAACE,OAAO,CAACJ,IAAI,CAAC,CAACK,GAAG,CAAC,CAAC,CAACC,CAAC,EAAEC,CAAC,CAAC,KAAK,CACnCD,CAAC,EACD,OAAOC,CAAC,KAAK,QAAQ,GAAG1E,QAAQ,CAAC0E,CAAC,CAAC,GAAGA,CAAC,CACxC,CACH,CAAC;;IAED;IACAN,aAAa,CAACO,MAAM,GAAG,IAAI,CAACvC,KAAK,CAACwC,WAAW,CAAC,CAAC;IAE/C,MAAMC,KAAqB,GAAG;MAC5BX,IAAI;MACJC,IAAI,EAAEC,aAAa;MACnBU,SAAS,EAAE,IAAIlE,IAAI,CAAC,CAAC,CAACmE,WAAW,CAAC,CAAC;MACnCtD,MAAM,EAAE,IAAI,CAACJ,aAAa;MAC1BU,SAAS,EAAE,IAAI,CAACA;IAClB,CAAC;IAED,IAAI,CAACX,KAAK,CAAC4D,IAAI,CAACH,KAAK,CAAC;IAEtB,IAAI,IAAI,CAAC/C,MAAM,CAACS,KAAK,EAAE;MACrBxC,MAAM,CAACwC,KAAK,CAAC7B,OAAO,EAAE,KAAKwD,IAAI,EAAE,EAAEC,IAAI,CAAC;IAC1C;;IAEA;IACA,MAAMc,OAAO,GAAG,IAAI,CAACnD,MAAM,CAACoD,YAAY,IAAI1E,sBAAsB;IAClE,IAAI,IAAI,CAACY,KAAK,CAAC2C,MAAM,IAAIkB,OAAO,EAAE;MAChC,IAAI,CAAC/B,KAAK,CAAC,CAAC;IACd;EACF;;EAEA;EACAiC,SAASA,CAACC,UAAkB,EAAQ;IAClC,IAAI,IAAI,CAAC/D,aAAa,KAAK+D,UAAU,EAAE;MACrC,MAAMC,UAAU,GAAG,IAAI,CAAChE,aAAa;MACrC,IAAI,CAACA,aAAa,GAAG+D,UAAU;MAE/B,IAAI,CAAC/B,KAAK,CAAC,aAAa,EAAE;QACxB5B,MAAM,EAAE2D,UAAU;QAClBE,WAAW,EAAED;MACf,CAAC,CAAC;IACJ;EACF;;EAEA;;EAEA;EACA,MAAMnC,KAAKA,CAAA,EAAkB;IAC3B,IAAI,CAAC,IAAI,CAACZ,SAAS,CAAC,CAAC,IAAI,IAAI,CAAClB,KAAK,CAAC2C,MAAM,KAAK,CAAC,IAAI,IAAI,CAACxC,UAAU,EAAE;IAErE,IAAI,CAACA,UAAU,GAAG,IAAI;IACtB,MAAMgE,YAAY,GAAG,CAAC,GAAG,IAAI,CAACnE,KAAK,CAAC;IACpC,IAAI,CAACA,KAAK,GAAG,EAAE;IAEf,IAAI;MACF,MAAMoE,GAAG,GAAG,IAAI,CAAC1D,MAAM,CAACG,iBAAiB,IAAI5B,aAAa;MAC1D,MAAMoF,OAA+B,GAAG;QACtC,cAAc,EAAE,kBAAkB;QAClC,IAAI,IAAI,CAAC3D,MAAM,CAAC4D,qBAAqB,IAAI,CAAC,CAAC;MAC7C,CAAC;MAED,MAAMC,KAAqB,GAAG;QAC5BlD,YAAY,EAAE,IAAI,CAACX,MAAM,CAACW,YAAY,IAAI,EAAE;QAC5CmD,KAAK,EAAE9F,QAAQ,CAACyD,EAAE;QAAE;QACpBsC,QAAQ,EAAE3E,WAAW,CAAC,CAAC;QACvB4E,UAAU,EAAErF,WAAW;QACvBsF,MAAM,EAAER;MACV,CAAC;MAED,MAAMS,QAAQ,GAAG,MAAMtD,KAAK,CAAC8C,GAAG,EAAE;QAChCS,MAAM,EAAE,MAAM;QACdR,OAAO;QACPS,IAAI,EAAEC,IAAI,CAACC,SAAS,CAACT,KAAK;MAC5B,CAAC,CAAC;MAEF,IAAI,CAACK,QAAQ,CAACK,EAAE,EAAE;QAChB,MAAM,IAAIC,KAAK,CAAC,QAAQN,QAAQ,CAACO,MAAM,EAAE,CAAC;MAC5C;MAEAxG,MAAM,CAAC6D,IAAI,CAAClD,OAAO,EAAE,WAAW6E,YAAY,CAACxB,MAAM,SAAS,CAAC;IAC/D,CAAC,CAAC,OAAOyC,KAAU,EAAE;MACnB;MACA,IAAI,CAACpF,KAAK,GAAG,CAAC,GAAGmE,YAAY,EAAE,GAAG,IAAI,CAACnE,KAAK,CAAC;MAC7C,MAAM,IAAI,CAACqF,YAAY,CAAC,CAAC;MAEzB1G,MAAM,CAAC8C,IAAI,CAACnC,OAAO,EAAE,iBAAiB6E,YAAY,CAACxB,MAAM,uBAAuByC,KAAK,CAAC1D,OAAO,EAAE,CAAC;IAClG,CAAC,SAAS;MACR,IAAI,CAACvB,UAAU,GAAG,KAAK;IACzB;EACF;;EAEA;;EAEA;EACA,MAAckF,YAAYA,CAAA,EAAkB;IAC1C,IAAI,CAACvG,kBAAkB,EAAE;IACzB,IAAI;MACF,MAAMA,kBAAkB,CAACwG,OAAO,CAACpG,WAAW,EAAE6F,IAAI,CAACC,SAAS,CAAC,IAAI,CAAChF,KAAK,CAAC,CAAC;IAC3E,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ;;EAEA;EACA,MAAcoB,YAAYA,CAAA,EAAkB;IAC1C,IAAI,CAACtC,kBAAkB,EAAE;IACzB,IAAI;MACF,MAAMyG,MAAM,GAAG,MAAMzG,kBAAkB,CAAC0G,OAAO,CAACtG,WAAW,CAAC;MAC5D,IAAIqG,MAAM,EAAE;QACV,MAAMZ,MAAwB,GAAGI,IAAI,CAACU,KAAK,CAACF,MAAM,CAAC;QACnD,IAAI,CAACvF,KAAK,GAAG,CAAC,GAAG2E,MAAM,EAAE,GAAG,IAAI,CAAC3E,KAAK,CAAC;QACvC,MAAMlB,kBAAkB,CAAC4G,UAAU,CAACxG,WAAW,CAAC;QAChDP,MAAM,CAAC6D,IAAI,CAAClD,OAAO,EAAE,YAAYqF,MAAM,CAAChC,MAAM,+BAA+B,CAAC;MAChF;IACF,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ;;EAEA;;EAEA;EACQzB,SAASA,CAAA,EAAY;IAC3B,OAAO,CAAC,EAAE,IAAI,CAACR,MAAM,CAACW,YAAY,IAAI,IAAI,CAACX,MAAM,CAACG,iBAAiB,CAAC;EACtE;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TouchAutoCapture — Extracts a human-readable label from a React Native
|
|
5
|
+
* touch event target by walking up the native view hierarchy.
|
|
6
|
+
*
|
|
7
|
+
* Used by AIAgent to auto-track every tap in the app without
|
|
8
|
+
* any developer code changes (zero-config analytics).
|
|
9
|
+
*
|
|
10
|
+
* Strategy:
|
|
11
|
+
* 1. Read the touched element's accessibilityLabel (best signal).
|
|
12
|
+
* 2. If none, use React Native's internal _children to find nested text.
|
|
13
|
+
* 3. Fallback to the component's testID.
|
|
14
|
+
* 4. Last resort: "Unknown Element".
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// React Native imports not needed — we use Fiber internals directly
|
|
18
|
+
|
|
19
|
+
const recentTaps = [];
|
|
20
|
+
const RAGE_WINDOW_MS = 2000;
|
|
21
|
+
const RAGE_THRESHOLD = 3;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Checks if the user is repeatedly tapping the same element in frustration.
|
|
25
|
+
* If rage click detected, emits 'rage_click' event to telemetry.
|
|
26
|
+
*/
|
|
27
|
+
export function checkRageClick(label, telemetry) {
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
recentTaps.push({
|
|
30
|
+
label,
|
|
31
|
+
ts: now
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Keep buffer unbounded size of 5
|
|
35
|
+
if (recentTaps.length > 5) recentTaps.shift();
|
|
36
|
+
const recent = recentTaps.filter(t => t.label === label && now - t.ts < RAGE_WINDOW_MS);
|
|
37
|
+
if (recent.length >= RAGE_THRESHOLD) {
|
|
38
|
+
telemetry.track('rage_click', {
|
|
39
|
+
label,
|
|
40
|
+
count: recent.length,
|
|
41
|
+
screen: telemetry.screen
|
|
42
|
+
});
|
|
43
|
+
recentTaps.length = 0; // reset buffer after emitting to avoid spam
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Extract a label from a GestureResponderEvent's native target.
|
|
49
|
+
*
|
|
50
|
+
* @param nativeEvent - The nativeEvent from onStartShouldSetResponderCapture
|
|
51
|
+
* @param rootRef - The root View ref (to resolve relative positions)
|
|
52
|
+
* @returns A descriptive label string for the tapped element
|
|
53
|
+
*/
|
|
54
|
+
export function extractTouchLabel(nativeEvent) {
|
|
55
|
+
// Try accessible properties first (most reliable)
|
|
56
|
+
const target = nativeEvent?.target;
|
|
57
|
+
if (!target) return 'Unknown Element';
|
|
58
|
+
|
|
59
|
+
// React Native internal: _internalFiberInstanceHandleDEV or _nativeTag
|
|
60
|
+
// We can walk the Fiber tree from the target to find text
|
|
61
|
+
try {
|
|
62
|
+
// Strategy 1: Walk up the Fiber tree from the touched element
|
|
63
|
+
let fiber = getFiberFromNativeTag(target);
|
|
64
|
+
if (fiber) {
|
|
65
|
+
// Walk up looking for text content or accessibility labels
|
|
66
|
+
let current = fiber;
|
|
67
|
+
let depth = 0;
|
|
68
|
+
const MAX_DEPTH = 10;
|
|
69
|
+
while (current && depth < MAX_DEPTH) {
|
|
70
|
+
// Check for accessibilityLabel
|
|
71
|
+
if (current.memoizedProps?.accessibilityLabel) {
|
|
72
|
+
return current.memoizedProps.accessibilityLabel;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check for testID
|
|
76
|
+
if (current.memoizedProps?.testID) {
|
|
77
|
+
return current.memoizedProps.testID;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check for title (Button component)
|
|
81
|
+
if (current.memoizedProps?.title) {
|
|
82
|
+
return current.memoizedProps.title;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Check for placeholder (TextInput)
|
|
86
|
+
if (current.memoizedProps?.placeholder) {
|
|
87
|
+
return `Input: ${current.memoizedProps.placeholder}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check if this is a Text node with children string
|
|
91
|
+
if (typeof current.memoizedProps?.children === 'string' && current.memoizedProps.children.trim()) {
|
|
92
|
+
return current.memoizedProps.children.trim();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Check for nested text in children array
|
|
96
|
+
if (Array.isArray(current.memoizedProps?.children)) {
|
|
97
|
+
const textChild = findTextInChildren(current.memoizedProps.children);
|
|
98
|
+
if (textChild) return textChild;
|
|
99
|
+
}
|
|
100
|
+
current = current.return;
|
|
101
|
+
depth++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// Fiber access failed — fall back gracefully
|
|
106
|
+
}
|
|
107
|
+
return 'Unknown Element';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Find the first string text in a React children tree (recursive, max 3 levels).
|
|
112
|
+
*/
|
|
113
|
+
function findTextInChildren(children, depth = 0) {
|
|
114
|
+
if (depth > 3) return null;
|
|
115
|
+
for (const child of children) {
|
|
116
|
+
if (typeof child === 'string' && child.trim()) {
|
|
117
|
+
return child.trim();
|
|
118
|
+
}
|
|
119
|
+
if (typeof child === 'number') {
|
|
120
|
+
return String(child);
|
|
121
|
+
}
|
|
122
|
+
// React element with props.children
|
|
123
|
+
if (child?.props?.children) {
|
|
124
|
+
if (typeof child.props.children === 'string' && child.props.children.trim()) {
|
|
125
|
+
return child.props.children.trim();
|
|
126
|
+
}
|
|
127
|
+
if (Array.isArray(child.props.children)) {
|
|
128
|
+
const found = findTextInChildren(child.props.children, depth + 1);
|
|
129
|
+
if (found) return found;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Attempt to get the Fiber node from a native tag (React Native internal).
|
|
138
|
+
* This uses the same technique as React DevTools and testing libraries.
|
|
139
|
+
*/
|
|
140
|
+
function getFiberFromNativeTag(nativeTag) {
|
|
141
|
+
try {
|
|
142
|
+
// React Native stores a reference from native tag → Fiber
|
|
143
|
+
// via the __internalInstanceHandle on the native node
|
|
144
|
+
const instance = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
145
|
+
if (instance?.renderers) {
|
|
146
|
+
for (const [, renderer] of instance.renderers) {
|
|
147
|
+
if (renderer?.findFiberByHostInstance) {
|
|
148
|
+
// Try to find via the devtools hook
|
|
149
|
+
const fiber = renderer.findFiberByHostInstance(nativeTag);
|
|
150
|
+
if (fiber) return fiber;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
// DevTools hook not available — expected in production
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=TouchAutoCapture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["recentTaps","RAGE_WINDOW_MS","RAGE_THRESHOLD","checkRageClick","label","telemetry","now","Date","push","ts","length","shift","recent","filter","t","track","count","screen","extractTouchLabel","nativeEvent","target","fiber","getFiberFromNativeTag","current","depth","MAX_DEPTH","memoizedProps","accessibilityLabel","testID","title","placeholder","children","trim","Array","isArray","textChild","findTextInChildren","return","child","String","props","found","nativeTag","instance","globalThis","__REACT_DEVTOOLS_GLOBAL_HOOK__","renderers","renderer","findFiberByHostInstance"],"sourceRoot":"../../../../src","sources":["services/telemetry/TouchAutoCapture.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deterministic device ID based on platform info.
|
|
7
|
+
* This ensures analytics and flags remain consistent across sessions
|
|
8
|
+
* without collecting PII hardware identifiers.
|
|
9
|
+
*/
|
|
10
|
+
export function getDeviceId() {
|
|
11
|
+
const raw = `${Platform.OS}_${Platform.Version}`;
|
|
12
|
+
let hash = 0;
|
|
13
|
+
for (let i = 0; i < raw.length; i++) {
|
|
14
|
+
hash = (hash << 5) - hash + raw.charCodeAt(i);
|
|
15
|
+
hash |= 0;
|
|
16
|
+
}
|
|
17
|
+
return `dev_${Math.abs(hash).toString(36)}`;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Platform","getDeviceId","raw","OS","Version","hash","i","length","charCodeAt","Math","abs","toString"],"sourceRoot":"../../../../src","sources":["services/telemetry/device.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;;AAEvC;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAAA,EAAW;EACpC,MAAMC,GAAG,GAAG,GAAGF,QAAQ,CAACG,EAAE,IAAIH,QAAQ,CAACI,OAAO,EAAE;EAChD,IAAIC,IAAI,GAAG,CAAC;EACZ,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,GAAG,CAACK,MAAM,EAAED,CAAC,EAAE,EAAE;IACnCD,IAAI,GAAG,CAACA,IAAI,IAAI,CAAC,IAAIA,IAAI,GAAGH,GAAG,CAACM,UAAU,CAACF,CAAC,CAAC;IAC7CD,IAAI,IAAI,CAAC;EACX;EACA,OAAO,OAAOI,IAAI,CAACC,GAAG,CAACL,IAAI,CAAC,CAACM,QAAQ,CAAC,EAAE,CAAC,EAAE;AAC7C","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TelemetryService","MobileAI","bindTelemetryService"],"sourceRoot":"../../../../src","sources":["services/telemetry/index.ts"],"mappings":";;AAAA;AACA;AACA;;AAEA,SAASA,gBAAgB,QAAQ,uBAAoB;AACrD,SAASC,QAAQ,EAAEC,oBAAoB,QAAQ,eAAY","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["services/telemetry/types.ts"],"mappings":"","ignoreList":[]}
|