@guidelytech/react-native 0.12.0 → 0.14.0
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 +56 -10
- package/dist/index.cjs +693 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +274 -7
- package/dist/index.d.ts +274 -7
- package/dist/index.js +689 -54
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4
4
|
|
|
5
5
|
// src/index.tsx
|
|
6
6
|
import { useContext as useContext3, useEffect as useEffect9, useMemo as useMemo6, useRef as useRef7, useState as useState8 } from "react";
|
|
7
|
-
import { AppState as AppState2, Dimensions, Linking, Platform as Platform6, StyleSheet as StyleSheet10, View as View12 } from "react-native";
|
|
7
|
+
import { AppState as AppState2, Dimensions, Linking, NativeModules, Platform as Platform6, StyleSheet as StyleSheet10, View as View12 } from "react-native";
|
|
8
8
|
import { createStaticFlags as createStaticFlags2, stableStringify as stableStringify3 } from "@guidelytech/flags";
|
|
9
9
|
|
|
10
10
|
// src/flags.tsx
|
|
@@ -1378,14 +1378,14 @@ function quoteValue(value) {
|
|
|
1378
1378
|
function attrSelector(name, value) {
|
|
1379
1379
|
return `[${name}=${quoteValue(value)}]`.slice(0, 300);
|
|
1380
1380
|
}
|
|
1381
|
-
function cleanText(
|
|
1382
|
-
const t = (
|
|
1381
|
+
function cleanText(text2) {
|
|
1382
|
+
const t = (text2 ?? "").replace(/\s+/g, " ").trim();
|
|
1383
1383
|
return t ? t.slice(0, 100) : void 0;
|
|
1384
1384
|
}
|
|
1385
1385
|
function tapProperties(el, x, y, platform, maskAll) {
|
|
1386
1386
|
const props = { selector: el.selector.slice(0, 300), tag: el.tag || "View", x: Math.round(x) || 0, y: Math.round(y) || 0, platform };
|
|
1387
|
-
const
|
|
1388
|
-
if (
|
|
1387
|
+
const text2 = maskAll ? void 0 : cleanText(el.text);
|
|
1388
|
+
if (text2) props.text = text2;
|
|
1389
1389
|
return props;
|
|
1390
1390
|
}
|
|
1391
1391
|
var r2 = (n) => Math.round(Math.min(1, Math.max(0, n)) * 100) / 100;
|
|
@@ -2006,10 +2006,10 @@ function xhrStreamPost() {
|
|
|
2006
2006
|
const type = xhr.getResponseHeader("content-type") || "";
|
|
2007
2007
|
if (!type.includes("text/event-stream")) return;
|
|
2008
2008
|
streamed = true;
|
|
2009
|
-
const
|
|
2010
|
-
if (
|
|
2011
|
-
onChunk(
|
|
2012
|
-
seen =
|
|
2009
|
+
const text2 = xhr.responseText || "";
|
|
2010
|
+
if (text2.length > seen) {
|
|
2011
|
+
onChunk(text2.slice(seen));
|
|
2012
|
+
seen = text2.length;
|
|
2013
2013
|
}
|
|
2014
2014
|
};
|
|
2015
2015
|
xhr.open("POST", url);
|
|
@@ -2084,14 +2084,14 @@ function fetchStreamPost(fetchImpl) {
|
|
|
2084
2084
|
if (rest) onChunk(rest);
|
|
2085
2085
|
return { status: res.status, json: null, streamed: true };
|
|
2086
2086
|
}
|
|
2087
|
-
const
|
|
2087
|
+
const text2 = await race(res.text());
|
|
2088
2088
|
if (sse) {
|
|
2089
|
-
onChunk(
|
|
2089
|
+
onChunk(text2);
|
|
2090
2090
|
return { status: res.status, json: null, streamed: true };
|
|
2091
2091
|
}
|
|
2092
2092
|
let json = null;
|
|
2093
2093
|
try {
|
|
2094
|
-
json = JSON.parse(
|
|
2094
|
+
json = JSON.parse(text2 || "null");
|
|
2095
2095
|
} catch {
|
|
2096
2096
|
json = null;
|
|
2097
2097
|
}
|
|
@@ -2204,10 +2204,10 @@ var Messenger = class {
|
|
|
2204
2204
|
if (v.kind === "tab" && v.tab === "messages") void this.refreshConversations();
|
|
2205
2205
|
}
|
|
2206
2206
|
/** Opens a new thread (optionally pre-filling the composer). */
|
|
2207
|
-
showNewMessage(
|
|
2207
|
+
showNewMessage(text2 = "") {
|
|
2208
2208
|
this.stopThreadPolling();
|
|
2209
2209
|
if (!this.snapshot.open) this.deps.onOpen();
|
|
2210
|
-
this.set({ open: true, view: { kind: "thread", conversationId: null }, thread: { conversation: null, messages: [], streaming: {}, sending: false, error: null, draft:
|
|
2210
|
+
this.set({ open: true, view: { kind: "thread", conversationId: null }, thread: { conversation: null, messages: [], streaming: {}, sending: false, error: null, draft: text2 } });
|
|
2211
2211
|
}
|
|
2212
2212
|
async openConversation(id) {
|
|
2213
2213
|
const known = this.snapshot.conversations.find((c) => c.id === id) ?? null;
|
|
@@ -2251,8 +2251,8 @@ var Messenger = class {
|
|
|
2251
2251
|
}
|
|
2252
2252
|
}
|
|
2253
2253
|
/** Sends the composer text: starts a conversation or posts to the open one. Streams Scout's reply. */
|
|
2254
|
-
async send(
|
|
2255
|
-
const body =
|
|
2254
|
+
async send(text2) {
|
|
2255
|
+
const body = text2.trim().slice(0, 4e3);
|
|
2256
2256
|
const thread = this.snapshot.thread;
|
|
2257
2257
|
if (!body || !thread || thread.sending) return;
|
|
2258
2258
|
this.setThread({ sending: true, error: null, draft: "" });
|
|
@@ -2428,6 +2428,425 @@ var Messenger = class {
|
|
|
2428
2428
|
}
|
|
2429
2429
|
};
|
|
2430
2430
|
|
|
2431
|
+
// src/core/replay.ts
|
|
2432
|
+
var RrwebEvents = {
|
|
2433
|
+
IMG_ID: 8,
|
|
2434
|
+
TOUCH_START: 7,
|
|
2435
|
+
TOUCH_END: 9,
|
|
2436
|
+
CLICK: 2,
|
|
2437
|
+
CSS: "html,body{margin:0;padding:0;width:100%;height:100%;overflow:hidden;background:#000}img{display:block;width:100%;height:100%;object-fit:contain}",
|
|
2438
|
+
dataUrl(base64) {
|
|
2439
|
+
return `data:image/jpeg;base64,${base64}`;
|
|
2440
|
+
},
|
|
2441
|
+
meta(timestamp, href, width, height) {
|
|
2442
|
+
return JSON.stringify({ type: 4, data: { href, width, height }, timestamp });
|
|
2443
|
+
},
|
|
2444
|
+
fullSnapshot(timestamp, dataUrl, width, height) {
|
|
2445
|
+
const style = { type: 2, id: 5, tagName: "style", attributes: {}, childNodes: [{ type: 3, id: 6, textContent: RrwebEvents.CSS, isStyle: true }] };
|
|
2446
|
+
const img = { type: 2, id: 8, tagName: "img", attributes: { src: dataUrl, width, height, alt: "" }, childNodes: [] };
|
|
2447
|
+
const html = { type: 2, id: 3, tagName: "html", attributes: {}, childNodes: [{ type: 2, id: 4, tagName: "head", attributes: {}, childNodes: [style] }, { type: 2, id: 7, tagName: "body", attributes: {}, childNodes: [img] }] };
|
|
2448
|
+
const node = { type: 0, id: 1, childNodes: [{ type: 1, id: 2, name: "html", publicId: "", systemId: "" }, html] };
|
|
2449
|
+
return JSON.stringify({ type: 2, data: { node, initialOffset: { left: 0, top: 0 } }, timestamp });
|
|
2450
|
+
},
|
|
2451
|
+
frame(timestamp, dataUrl) {
|
|
2452
|
+
return JSON.stringify({ type: 3, data: { source: 0, texts: [], attributes: [{ id: 8, attributes: { src: dataUrl } }], removes: [], adds: [] }, timestamp });
|
|
2453
|
+
},
|
|
2454
|
+
/** MouseInteraction (source 2): 7 TouchStart, 9 TouchEnd, 2 Click. */
|
|
2455
|
+
interaction(timestamp, type, x, y) {
|
|
2456
|
+
return JSON.stringify({ type: 3, data: { source: 2, type, id: 8, x: round1(x), y: round1(y) }, timestamp });
|
|
2457
|
+
},
|
|
2458
|
+
touchMove(timestamp, x, y) {
|
|
2459
|
+
return JSON.stringify({ type: 3, data: { source: 6, positions: [{ x: round1(x), y: round1(y), id: 8, timeOffset: 0 }] }, timestamp });
|
|
2460
|
+
},
|
|
2461
|
+
custom(timestamp, tag, payload) {
|
|
2462
|
+
return JSON.stringify({ type: 5, data: { tag, payload }, timestamp });
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2465
|
+
var round1 = (v) => Math.round(v * 10) / 10;
|
|
2466
|
+
var UPLOAD_TIMEOUT_MS = 3e4;
|
|
2467
|
+
var ReplayUploader = class {
|
|
2468
|
+
constructor(opts) {
|
|
2469
|
+
__publicField(this, "opts", opts);
|
|
2470
|
+
__publicField(this, "windowId", randomId(16));
|
|
2471
|
+
__publicField(this, "buffer", null);
|
|
2472
|
+
__publicField(this, "queue", []);
|
|
2473
|
+
__publicField(this, "queuedBytes", 0);
|
|
2474
|
+
__publicField(this, "seqs", /* @__PURE__ */ new Map());
|
|
2475
|
+
__publicField(this, "inflight", null);
|
|
2476
|
+
__publicField(this, "flushTimer", null);
|
|
2477
|
+
__publicField(this, "retryTimer", null);
|
|
2478
|
+
__publicField(this, "attempt", 0);
|
|
2479
|
+
__publicField(this, "destroyed", false);
|
|
2480
|
+
__publicField(this, "offRecover");
|
|
2481
|
+
this.offRecover = opts.health?.onRecover?.(() => {
|
|
2482
|
+
this.clearRetry();
|
|
2483
|
+
this.attempt = 0;
|
|
2484
|
+
this.flush();
|
|
2485
|
+
}) ?? null;
|
|
2486
|
+
}
|
|
2487
|
+
get pendingChunks() {
|
|
2488
|
+
return this.queue.length;
|
|
2489
|
+
}
|
|
2490
|
+
get bufferedEvents() {
|
|
2491
|
+
return this.buffer?.events.length ?? 0;
|
|
2492
|
+
}
|
|
2493
|
+
push(sessionId, json) {
|
|
2494
|
+
if (this.destroyed) return;
|
|
2495
|
+
if (this.buffer && this.buffer.sessionId !== sessionId) this.seal();
|
|
2496
|
+
const chunk = this.buffer ?? (this.buffer = { sessionId, meta: this.opts.meta(), events: [], bytes: 0 });
|
|
2497
|
+
chunk.events.push(json);
|
|
2498
|
+
chunk.bytes += json.length;
|
|
2499
|
+
if (chunk.bytes > (this.opts.maxBufferBytes ?? 1e6)) this.flush();
|
|
2500
|
+
else if (!this.flushTimer) {
|
|
2501
|
+
this.flushTimer = setTimeout(() => {
|
|
2502
|
+
this.flushTimer = null;
|
|
2503
|
+
this.flush();
|
|
2504
|
+
}, this.opts.flushIntervalMs ?? 1e4);
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
/** Seals the buffer and uploads the backlog (one chunk at a time). */
|
|
2508
|
+
flush() {
|
|
2509
|
+
if (this.destroyed) return;
|
|
2510
|
+
this.seal();
|
|
2511
|
+
if (this.retryTimer || this.inflight || !this.queue.length) return;
|
|
2512
|
+
void this.sendNext();
|
|
2513
|
+
}
|
|
2514
|
+
/** Drops everything buffered or queued (consent withdrawn, server disabled replay). */
|
|
2515
|
+
discard() {
|
|
2516
|
+
this.buffer = null;
|
|
2517
|
+
this.queue = [];
|
|
2518
|
+
this.queuedBytes = 0;
|
|
2519
|
+
this.clearFlushTimer();
|
|
2520
|
+
this.clearRetry();
|
|
2521
|
+
this.attempt = 0;
|
|
2522
|
+
}
|
|
2523
|
+
/** Uploads what is left once; no retries afterwards. */
|
|
2524
|
+
destroy() {
|
|
2525
|
+
this.flush();
|
|
2526
|
+
this.destroyed = true;
|
|
2527
|
+
this.offRecover?.();
|
|
2528
|
+
this.clearFlushTimer();
|
|
2529
|
+
this.clearRetry();
|
|
2530
|
+
}
|
|
2531
|
+
clearFlushTimer() {
|
|
2532
|
+
if (this.flushTimer) clearTimeout(this.flushTimer);
|
|
2533
|
+
this.flushTimer = null;
|
|
2534
|
+
}
|
|
2535
|
+
clearRetry() {
|
|
2536
|
+
if (this.retryTimer) clearTimeout(this.retryTimer);
|
|
2537
|
+
this.retryTimer = null;
|
|
2538
|
+
}
|
|
2539
|
+
scheduleRetry(ms) {
|
|
2540
|
+
this.retryTimer = setTimeout(() => {
|
|
2541
|
+
this.retryTimer = null;
|
|
2542
|
+
this.flush();
|
|
2543
|
+
}, ms);
|
|
2544
|
+
}
|
|
2545
|
+
seal() {
|
|
2546
|
+
this.clearFlushTimer();
|
|
2547
|
+
const chunk = this.buffer;
|
|
2548
|
+
this.buffer = null;
|
|
2549
|
+
if (!chunk || !chunk.events.length) return;
|
|
2550
|
+
this.queue.push(chunk);
|
|
2551
|
+
this.queuedBytes += chunk.bytes;
|
|
2552
|
+
const max = this.opts.maxQueuedBytes ?? 5e6;
|
|
2553
|
+
while (this.queuedBytes > max && this.queue.length > 1) {
|
|
2554
|
+
const i = this.inflight && this.queue[0] === this.inflight ? 1 : 0;
|
|
2555
|
+
const [dropped] = this.queue.splice(i, 1);
|
|
2556
|
+
if (!dropped) break;
|
|
2557
|
+
this.queuedBytes -= dropped.bytes;
|
|
2558
|
+
this.opts.log?.(`replay backlog full: dropped a chunk of ${dropped.events.length} events`);
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
nextSeq(chunk) {
|
|
2562
|
+
if (chunk.seq === void 0) {
|
|
2563
|
+
const seq = this.seqs.get(chunk.sessionId) ?? 0;
|
|
2564
|
+
this.seqs.set(chunk.sessionId, seq + 1);
|
|
2565
|
+
chunk.seq = seq;
|
|
2566
|
+
}
|
|
2567
|
+
return chunk.seq;
|
|
2568
|
+
}
|
|
2569
|
+
body(chunk) {
|
|
2570
|
+
const head = JSON.stringify({ sessionId: chunk.sessionId, windowId: this.windowId, seq: this.nextSeq(chunk), ...chunk.meta });
|
|
2571
|
+
return `${head.slice(0, -1)},"events":[${chunk.events.join(",")}]}`;
|
|
2572
|
+
}
|
|
2573
|
+
async sendNext() {
|
|
2574
|
+
const chunk = this.queue[0];
|
|
2575
|
+
if (!chunk) return;
|
|
2576
|
+
const wait = this.destroyed ? 0 : this.opts.health?.waitMs() ?? 0;
|
|
2577
|
+
if (wait > 0) return this.scheduleRetry(wait);
|
|
2578
|
+
this.inflight = chunk;
|
|
2579
|
+
const result = await this.upload(this.body(chunk));
|
|
2580
|
+
this.onResult(chunk, result);
|
|
2581
|
+
}
|
|
2582
|
+
async upload(json) {
|
|
2583
|
+
const f = this.opts.fetch();
|
|
2584
|
+
if (!f) return "drop";
|
|
2585
|
+
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
2586
|
+
const timer = ac ? setTimeout(() => ac.abort(), UPLOAD_TIMEOUT_MS) : null;
|
|
2587
|
+
try {
|
|
2588
|
+
let res;
|
|
2589
|
+
try {
|
|
2590
|
+
res = await f(this.opts.url(), { method: "POST", body: json, headers: { "Content-Type": "application/json" }, signal: ac?.signal });
|
|
2591
|
+
} catch {
|
|
2592
|
+
this.opts.health?.failure();
|
|
2593
|
+
return "retry";
|
|
2594
|
+
}
|
|
2595
|
+
if (res.status === 429 || res.status >= 500) this.opts.health?.failure();
|
|
2596
|
+
else this.opts.health?.success();
|
|
2597
|
+
if (res.ok) {
|
|
2598
|
+
const data = await res.json().catch(() => null);
|
|
2599
|
+
return data?.disabled ? "disabled" : "ok";
|
|
2600
|
+
}
|
|
2601
|
+
return res.status >= 400 && res.status < 500 && res.status !== 429 ? "drop" : "retry";
|
|
2602
|
+
} finally {
|
|
2603
|
+
if (timer) clearTimeout(timer);
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
onResult(chunk, result) {
|
|
2607
|
+
if (this.inflight === chunk) this.inflight = null;
|
|
2608
|
+
if (result === "retry" && this.queue.includes(chunk)) {
|
|
2609
|
+
if (!this.destroyed) {
|
|
2610
|
+
const max = this.opts.maxAttempts ?? 5;
|
|
2611
|
+
this.attempt = Math.min(this.attempt + 1, max);
|
|
2612
|
+
const delay = this.attempt >= max ? this.opts.slowRetryMs ?? 6e4 : backoffMs(this.attempt - 1, 1e3, 8e3);
|
|
2613
|
+
return this.scheduleRetry(Math.max(delay, this.opts.health?.waitMs() ?? 0));
|
|
2614
|
+
}
|
|
2615
|
+
this.opts.log?.("replay upload failed after the recorder stopped; dropping the chunk");
|
|
2616
|
+
}
|
|
2617
|
+
this.attempt = 0;
|
|
2618
|
+
this.remove(chunk);
|
|
2619
|
+
if (result === "disabled") {
|
|
2620
|
+
for (const c of this.queue.slice()) if (c.sessionId === chunk.sessionId) this.remove(c);
|
|
2621
|
+
if (this.buffer?.sessionId === chunk.sessionId) this.buffer = null;
|
|
2622
|
+
this.opts.onDisabled(chunk.sessionId);
|
|
2623
|
+
}
|
|
2624
|
+
if (this.queue.length && !this.retryTimer && !this.inflight) void this.sendNext();
|
|
2625
|
+
}
|
|
2626
|
+
remove(chunk) {
|
|
2627
|
+
const i = this.queue.indexOf(chunk);
|
|
2628
|
+
if (i >= 0) {
|
|
2629
|
+
this.queue.splice(i, 1);
|
|
2630
|
+
this.queuedBytes -= chunk.bytes;
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
};
|
|
2634
|
+
var TOUCH_SETTLE_MS = 200;
|
|
2635
|
+
var IDLE_FRAMES = 3;
|
|
2636
|
+
var MAX_IDLE_INTERVAL_MS = 5e3;
|
|
2637
|
+
var SessionRecorder = class {
|
|
2638
|
+
constructor(opts) {
|
|
2639
|
+
__publicField(this, "opts", opts);
|
|
2640
|
+
__publicField(this, "intervalMs");
|
|
2641
|
+
__publicField(this, "now");
|
|
2642
|
+
__publicField(this, "sid", null);
|
|
2643
|
+
__publicField(this, "foreground", true);
|
|
2644
|
+
__publicField(this, "generation", 0);
|
|
2645
|
+
__publicField(this, "timer", null);
|
|
2646
|
+
__publicField(this, "timerDue", 0);
|
|
2647
|
+
__publicField(this, "capturing", false);
|
|
2648
|
+
__publicField(this, "needKeyframe", true);
|
|
2649
|
+
__publicField(this, "hasKeyframe", false);
|
|
2650
|
+
__publicField(this, "lastFrame", null);
|
|
2651
|
+
__publicField(this, "unchanged", 0);
|
|
2652
|
+
__publicField(this, "captureSoon", false);
|
|
2653
|
+
__publicField(this, "pendingCustom", []);
|
|
2654
|
+
__publicField(this, "touchDown", false);
|
|
2655
|
+
__publicField(this, "downX", 0);
|
|
2656
|
+
__publicField(this, "downY", 0);
|
|
2657
|
+
__publicField(this, "downAt", 0);
|
|
2658
|
+
__publicField(this, "maxDistance", 0);
|
|
2659
|
+
__publicField(this, "lastMoveAt", 0);
|
|
2660
|
+
__publicField(this, "originX", 0);
|
|
2661
|
+
__publicField(this, "originY", 0);
|
|
2662
|
+
/** Viewport of the last frame (points), for chunk metadata. */
|
|
2663
|
+
__publicField(this, "viewportWidth", 0);
|
|
2664
|
+
__publicField(this, "viewportHeight", 0);
|
|
2665
|
+
this.intervalMs = Math.max(500, opts.intervalMs);
|
|
2666
|
+
this.now = opts.now ?? Date.now;
|
|
2667
|
+
}
|
|
2668
|
+
get sessionId() {
|
|
2669
|
+
return this.sid;
|
|
2670
|
+
}
|
|
2671
|
+
get isRecording() {
|
|
2672
|
+
return this.sid !== null;
|
|
2673
|
+
}
|
|
2674
|
+
get currentIntervalMs() {
|
|
2675
|
+
return this.unchanged >= IDLE_FRAMES ? Math.max(this.intervalMs, Math.min(4 * this.intervalMs, MAX_IDLE_INTERVAL_MS)) : this.intervalMs;
|
|
2676
|
+
}
|
|
2677
|
+
/** Starts (or keeps) recording `sessionId`; another session stops the current one first (uploading it). */
|
|
2678
|
+
start(sessionId) {
|
|
2679
|
+
if (this.sid === sessionId) return;
|
|
2680
|
+
if (this.sid !== null) this.stop(false);
|
|
2681
|
+
this.sid = sessionId;
|
|
2682
|
+
this.generation++;
|
|
2683
|
+
this.needKeyframe = true;
|
|
2684
|
+
this.hasKeyframe = false;
|
|
2685
|
+
this.lastFrame = null;
|
|
2686
|
+
this.unchanged = 0;
|
|
2687
|
+
this.captureSoon = false;
|
|
2688
|
+
this.pendingCustom = [];
|
|
2689
|
+
this.touchDown = false;
|
|
2690
|
+
if (this.foreground) this.schedule(0);
|
|
2691
|
+
}
|
|
2692
|
+
/** Stops recording; buffered events are uploaded unless `discard`. */
|
|
2693
|
+
stop(discard) {
|
|
2694
|
+
if (this.sid === null) return;
|
|
2695
|
+
this.sid = null;
|
|
2696
|
+
this.generation++;
|
|
2697
|
+
this.clearTimer();
|
|
2698
|
+
this.capturing = false;
|
|
2699
|
+
this.pendingCustom = [];
|
|
2700
|
+
this.touchDown = false;
|
|
2701
|
+
if (discard) this.opts.uploader.discard();
|
|
2702
|
+
else this.opts.uploader.flush();
|
|
2703
|
+
}
|
|
2704
|
+
/** App backgrounded: no captures; uploads what is buffered. */
|
|
2705
|
+
pause() {
|
|
2706
|
+
this.foreground = false;
|
|
2707
|
+
this.clearTimer();
|
|
2708
|
+
this.generation++;
|
|
2709
|
+
this.capturing = false;
|
|
2710
|
+
this.touchDown = false;
|
|
2711
|
+
this.opts.uploader.flush();
|
|
2712
|
+
}
|
|
2713
|
+
/** App foregrounded: resume with a keyframe. */
|
|
2714
|
+
resume() {
|
|
2715
|
+
if (this.foreground) return;
|
|
2716
|
+
this.foreground = true;
|
|
2717
|
+
this.needKeyframe = true;
|
|
2718
|
+
this.unchanged = 0;
|
|
2719
|
+
if (this.sid !== null) this.schedule(0);
|
|
2720
|
+
}
|
|
2721
|
+
/** A new screen: the next frame is a keyframe with the new href. */
|
|
2722
|
+
onScreen() {
|
|
2723
|
+
if (this.sid === null) return;
|
|
2724
|
+
this.needKeyframe = true;
|
|
2725
|
+
this.activity();
|
|
2726
|
+
}
|
|
2727
|
+
activity() {
|
|
2728
|
+
const wasIdle = this.unchanged >= IDLE_FRAMES;
|
|
2729
|
+
this.unchanged = 0;
|
|
2730
|
+
if (wasIdle && this.sid !== null && this.foreground && !this.capturing && !this.touchDown) this.schedule(this.intervalMs, true);
|
|
2731
|
+
}
|
|
2732
|
+
/** Adds the `guidely` marker for an analytics event. */
|
|
2733
|
+
addGuidelyEvent(name, customName, guideId) {
|
|
2734
|
+
const id = this.sid;
|
|
2735
|
+
if (id === null) return;
|
|
2736
|
+
const payload = { name };
|
|
2737
|
+
if (customName) payload.customName = customName;
|
|
2738
|
+
if (guideId) payload.guideId = guideId;
|
|
2739
|
+
this.activity();
|
|
2740
|
+
const now = this.now();
|
|
2741
|
+
if (!this.hasKeyframe) {
|
|
2742
|
+
if (this.pendingCustom.length < 50) this.pendingCustom.push([now, payload]);
|
|
2743
|
+
return;
|
|
2744
|
+
}
|
|
2745
|
+
this.opts.uploader.push(id, RrwebEvents.custom(now, "guidely", payload));
|
|
2746
|
+
}
|
|
2747
|
+
/** A primary-pointer touch at (x, y) points from the React root view. */
|
|
2748
|
+
touch(phase, rootX, rootY) {
|
|
2749
|
+
const id = this.sid;
|
|
2750
|
+
if (id === null || !this.foreground) return;
|
|
2751
|
+
const x = rootX + this.originX;
|
|
2752
|
+
const y = rootY + this.originY;
|
|
2753
|
+
const now = this.now();
|
|
2754
|
+
const emit = this.hasKeyframe;
|
|
2755
|
+
const push = (json) => emit && this.opts.uploader.push(id, json);
|
|
2756
|
+
switch (phase) {
|
|
2757
|
+
case "down":
|
|
2758
|
+
this.touchDown = true;
|
|
2759
|
+
this.unchanged = 0;
|
|
2760
|
+
this.downX = x;
|
|
2761
|
+
this.downY = y;
|
|
2762
|
+
this.downAt = now;
|
|
2763
|
+
this.maxDistance = 0;
|
|
2764
|
+
this.lastMoveAt = now;
|
|
2765
|
+
push(RrwebEvents.interaction(now, RrwebEvents.TOUCH_START, x, y));
|
|
2766
|
+
return;
|
|
2767
|
+
case "move":
|
|
2768
|
+
if (!this.touchDown) return;
|
|
2769
|
+
this.maxDistance = Math.max(this.maxDistance, Math.hypot(x - this.downX, y - this.downY));
|
|
2770
|
+
if (now - this.lastMoveAt < 50) return;
|
|
2771
|
+
this.lastMoveAt = now;
|
|
2772
|
+
push(RrwebEvents.touchMove(now, x, y));
|
|
2773
|
+
return;
|
|
2774
|
+
default:
|
|
2775
|
+
if (!this.touchDown) return;
|
|
2776
|
+
this.touchDown = false;
|
|
2777
|
+
this.unchanged = 0;
|
|
2778
|
+
this.maxDistance = Math.max(this.maxDistance, Math.hypot(x - this.downX, y - this.downY));
|
|
2779
|
+
push(RrwebEvents.interaction(now, RrwebEvents.TOUCH_END, x, y));
|
|
2780
|
+
if (phase === "up" && this.maxDistance <= 10 && now - this.downAt < 1e3) push(RrwebEvents.interaction(now, RrwebEvents.CLICK, x, y));
|
|
2781
|
+
if (this.capturing) this.captureSoon = true;
|
|
2782
|
+
else this.schedule(TOUCH_SETTLE_MS, true);
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
clearTimer() {
|
|
2786
|
+
if (this.timer) clearTimeout(this.timer);
|
|
2787
|
+
this.timer = null;
|
|
2788
|
+
}
|
|
2789
|
+
/** Schedules the next capture `delay` ms from now, or keeps an earlier one when `ifSooner`. */
|
|
2790
|
+
schedule(delay, ifSooner = false) {
|
|
2791
|
+
const due = this.now() + delay;
|
|
2792
|
+
if (ifSooner && this.timer && this.timerDue <= due) return;
|
|
2793
|
+
this.clearTimer();
|
|
2794
|
+
this.timerDue = due;
|
|
2795
|
+
const gen = this.generation;
|
|
2796
|
+
this.timer = setTimeout(() => {
|
|
2797
|
+
this.timer = null;
|
|
2798
|
+
if (gen === this.generation) void this.tick();
|
|
2799
|
+
}, delay);
|
|
2800
|
+
}
|
|
2801
|
+
async tick() {
|
|
2802
|
+
if (this.sid === null || !this.foreground || this.capturing) return;
|
|
2803
|
+
if (this.touchDown) {
|
|
2804
|
+
this.schedule(this.intervalMs);
|
|
2805
|
+
return;
|
|
2806
|
+
}
|
|
2807
|
+
this.capturing = true;
|
|
2808
|
+
this.captureSoon = false;
|
|
2809
|
+
const gen = this.generation;
|
|
2810
|
+
let frame = null;
|
|
2811
|
+
try {
|
|
2812
|
+
frame = await this.opts.capturer(await this.opts.captureOptions());
|
|
2813
|
+
} catch (err) {
|
|
2814
|
+
this.opts.onError?.(err);
|
|
2815
|
+
}
|
|
2816
|
+
if (gen !== this.generation) return;
|
|
2817
|
+
this.capturing = false;
|
|
2818
|
+
if (frame) this.onFrame(frame, this.now());
|
|
2819
|
+
if (this.sid !== null && this.foreground) this.schedule(this.captureSoon ? TOUCH_SETTLE_MS : this.currentIntervalMs);
|
|
2820
|
+
}
|
|
2821
|
+
onFrame(frame, at) {
|
|
2822
|
+
const id = this.sid;
|
|
2823
|
+
if (id === null || !(frame.width > 0) || !(frame.height > 0) || !frame.base64) return;
|
|
2824
|
+
const sizeChanged = frame.width !== this.viewportWidth || frame.height !== this.viewportHeight;
|
|
2825
|
+
const keyframe = this.needKeyframe || !this.hasKeyframe || sizeChanged;
|
|
2826
|
+
if (!keyframe && this.lastFrame === frame.base64) {
|
|
2827
|
+
this.unchanged++;
|
|
2828
|
+
return;
|
|
2829
|
+
}
|
|
2830
|
+
this.unchanged = 0;
|
|
2831
|
+
this.lastFrame = frame.base64;
|
|
2832
|
+
this.originX = frame.originX ?? 0;
|
|
2833
|
+
this.originY = frame.originY ?? 0;
|
|
2834
|
+
this.viewportWidth = frame.width;
|
|
2835
|
+
this.viewportHeight = frame.height;
|
|
2836
|
+
const url = RrwebEvents.dataUrl(frame.base64);
|
|
2837
|
+
const up = this.opts.uploader;
|
|
2838
|
+
if (!keyframe) return up.push(id, RrwebEvents.frame(at, url));
|
|
2839
|
+
this.needKeyframe = false;
|
|
2840
|
+
up.push(id, RrwebEvents.meta(at, this.opts.href(), frame.width, frame.height));
|
|
2841
|
+
up.push(id, RrwebEvents.fullSnapshot(at, url, frame.width, frame.height));
|
|
2842
|
+
if (!this.hasKeyframe) {
|
|
2843
|
+
this.hasKeyframe = true;
|
|
2844
|
+
for (const [ts, payload] of this.pendingCustom) up.push(id, RrwebEvents.custom(Math.max(ts, at), "guidely", payload));
|
|
2845
|
+
this.pendingCustom = [];
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
};
|
|
2849
|
+
|
|
2431
2850
|
// src/core/storage.ts
|
|
2432
2851
|
var PersistentStore = class {
|
|
2433
2852
|
constructor(backing, onError = () => {
|
|
@@ -2481,7 +2900,7 @@ var PersistentStore = class {
|
|
|
2481
2900
|
|
|
2482
2901
|
// src/core/client.ts
|
|
2483
2902
|
var SDK_NAME = "@guidelytech/react-native";
|
|
2484
|
-
var SDK_VERSION = "0.
|
|
2903
|
+
var SDK_VERSION = "0.14.0";
|
|
2485
2904
|
var DEFAULT_API_URL = "https://guidelytech.com";
|
|
2486
2905
|
var PAGE_SCOPED = /* @__PURE__ */ new Set(["page_load", "url_match", "element_click", "element_visible", "delay"]);
|
|
2487
2906
|
var CACHED_START_MS = 1500;
|
|
@@ -2542,6 +2961,10 @@ var GuidelyClient = class {
|
|
|
2542
2961
|
__publicField(this, "lastAudiences", /* @__PURE__ */ new Set());
|
|
2543
2962
|
__publicField(this, "backgroundedAt", null);
|
|
2544
2963
|
__publicField(this, "messenger", null);
|
|
2964
|
+
__publicField(this, "replayUploader", null);
|
|
2965
|
+
__publicField(this, "recorder", null);
|
|
2966
|
+
/** Replay decision for the current session (sampled once; forced by start/stopSessionRecording). */
|
|
2967
|
+
__publicField(this, "replayDecision", null);
|
|
2545
2968
|
__publicField(this, "ui", { steps: [], checklists: [], survey: null, resourceCenterOpen: false, theme: {}, messenger: false });
|
|
2546
2969
|
__publicField(this, "uiListeners", /* @__PURE__ */ new Set());
|
|
2547
2970
|
/** Feature flags for this environment: `guidely.flags.isEnabled("new-checkout")`. */
|
|
@@ -2693,6 +3116,7 @@ var GuidelyClient = class {
|
|
|
2693
3116
|
if (this.destroyed) return;
|
|
2694
3117
|
this.isReady = true;
|
|
2695
3118
|
if (this.config) this.emitter.emit("ready", this.config);
|
|
3119
|
+
this.syncReplay();
|
|
2696
3120
|
this.notify();
|
|
2697
3121
|
this.evaluate("ready");
|
|
2698
3122
|
} catch (err) {
|
|
@@ -2719,6 +3143,7 @@ var GuidelyClient = class {
|
|
|
2719
3143
|
this.syncMessenger();
|
|
2720
3144
|
if (this.hydrated) this.checkLaunch();
|
|
2721
3145
|
this.emitter.emit("config", this.config);
|
|
3146
|
+
this.syncReplay();
|
|
2722
3147
|
this.log("config loaded", this.config.configVersion, `${this.config.guides.length} guides`);
|
|
2723
3148
|
return true;
|
|
2724
3149
|
}
|
|
@@ -2771,6 +3196,7 @@ var GuidelyClient = class {
|
|
|
2771
3196
|
void this.outbox?.flush();
|
|
2772
3197
|
void this.store.flush();
|
|
2773
3198
|
void this.flags.flush();
|
|
3199
|
+
this.recorder?.pause();
|
|
2774
3200
|
this.messenger?.setForeground(false);
|
|
2775
3201
|
} else if (state === "active" && this.backgroundedAt !== null) {
|
|
2776
3202
|
this.messenger?.setForeground(true);
|
|
@@ -2780,7 +3206,10 @@ var GuidelyClient = class {
|
|
|
2780
3206
|
this.session = newSession();
|
|
2781
3207
|
this.persistSession();
|
|
2782
3208
|
this.firedDelays.clear();
|
|
3209
|
+
this.recorder?.stop(false);
|
|
2783
3210
|
}
|
|
3211
|
+
this.recorder?.resume();
|
|
3212
|
+
this.syncReplay();
|
|
2784
3213
|
this.cameToForeground();
|
|
2785
3214
|
void this.flags.refresh();
|
|
2786
3215
|
if (Date.now() - this.configFetchedAt > this.options.configRefreshMs && this.api.health.canSend()) void this.refresh();
|
|
@@ -2803,6 +3232,9 @@ var GuidelyClient = class {
|
|
|
2803
3232
|
this.queued = [];
|
|
2804
3233
|
this.messenger?.destroy();
|
|
2805
3234
|
this.messenger = null;
|
|
3235
|
+
this.recorder?.stop(!this.analyticsEnabled());
|
|
3236
|
+
this.recorder = null;
|
|
3237
|
+
this.replayUploader?.destroy();
|
|
2806
3238
|
this.visibilityWatchers.forEach((stop) => stop());
|
|
2807
3239
|
this.visibilityWatchers.clear();
|
|
2808
3240
|
this.timers.forEach((t) => clearTimeout(t));
|
|
@@ -2917,6 +3349,7 @@ var GuidelyClient = class {
|
|
|
2917
3349
|
this.store.set(KEYS.anon, this.anonymousId);
|
|
2918
3350
|
this.state = emptyState();
|
|
2919
3351
|
this.persistState();
|
|
3352
|
+
this.recorder?.stop(false);
|
|
2920
3353
|
this.session = newSession();
|
|
2921
3354
|
this.persistSession();
|
|
2922
3355
|
this.lastAudiences = /* @__PURE__ */ new Set();
|
|
@@ -2924,6 +3357,7 @@ var GuidelyClient = class {
|
|
|
2924
3357
|
this.firstVisit = true;
|
|
2925
3358
|
this.exposures.clear();
|
|
2926
3359
|
this.syncFlagAttributes();
|
|
3360
|
+
this.syncReplay();
|
|
2927
3361
|
this.emitter.emit("identify", { userId: null, anonymousId: this.anonymousId });
|
|
2928
3362
|
this.notify();
|
|
2929
3363
|
if (this.isReady) this.evaluate("identify");
|
|
@@ -2938,6 +3372,7 @@ var GuidelyClient = class {
|
|
|
2938
3372
|
this.whenHydrated(() => {
|
|
2939
3373
|
if (consent === "denied") this.queue?.clear();
|
|
2940
3374
|
else if (consent === "granted") void this.queue?.flush();
|
|
3375
|
+
this.syncReplay();
|
|
2941
3376
|
});
|
|
2942
3377
|
}
|
|
2943
3378
|
analyticsEnabled() {
|
|
@@ -2966,6 +3401,7 @@ var GuidelyClient = class {
|
|
|
2966
3401
|
const locale = extra.guideId ? this.guideLocales.get(extra.guideId) : void 0;
|
|
2967
3402
|
if (locale) event.properties = { ...event.properties ?? {}, locale };
|
|
2968
3403
|
this.queue.enqueue(event);
|
|
3404
|
+
this.recorder?.addGuidelyEvent(name, event.customName, event.guideId);
|
|
2969
3405
|
this.emitter.emit("track", event);
|
|
2970
3406
|
return event;
|
|
2971
3407
|
}
|
|
@@ -3003,6 +3439,7 @@ var GuidelyClient = class {
|
|
|
3003
3439
|
}
|
|
3004
3440
|
this.screenName = name;
|
|
3005
3441
|
this.targets.setScreen(name);
|
|
3442
|
+
if (changed) this.recorder?.onScreen();
|
|
3006
3443
|
if (changed) this.syncFlagAttributes();
|
|
3007
3444
|
const url = this.currentUrl();
|
|
3008
3445
|
if (changed) {
|
|
@@ -3037,6 +3474,112 @@ var GuidelyClient = class {
|
|
|
3037
3474
|
if (this.isReady) this.evaluate("click", { targetId });
|
|
3038
3475
|
}
|
|
3039
3476
|
// ---------------------------------------------------------------------------
|
|
3477
|
+
// Session replay
|
|
3478
|
+
// ---------------------------------------------------------------------------
|
|
3479
|
+
replaySettings() {
|
|
3480
|
+
const r = this.config?.settings?.replay;
|
|
3481
|
+
if (!r?.enabled || !this.options.sessionReplay?.enabled || !this.bridge.capturer) return null;
|
|
3482
|
+
return r;
|
|
3483
|
+
}
|
|
3484
|
+
/** Reconciles recording with config, consent, readiness, the session and its sample decision. Idempotent. */
|
|
3485
|
+
syncReplay() {
|
|
3486
|
+
if (this.destroyed || !this.hydrated) return;
|
|
3487
|
+
const r = this.isReady && this.analyticsEnabled() ? this.replaySettings() : null;
|
|
3488
|
+
const id = this.session.id;
|
|
3489
|
+
if (r && this.replayDecision?.sessionId !== id) {
|
|
3490
|
+
this.replayDecision = { sessionId: id, record: rolloutBucket(id, "replay") < (r.sampleRate ?? 100) };
|
|
3491
|
+
this.log(`replay ${this.replayDecision.record ? "sampled" : "not sampled"} for session ${id}`);
|
|
3492
|
+
}
|
|
3493
|
+
if (!r || !this.replayDecision?.record) {
|
|
3494
|
+
if (this.recorder?.isRecording) this.recorder.stop(!this.analyticsEnabled());
|
|
3495
|
+
return;
|
|
3496
|
+
}
|
|
3497
|
+
const rec = this.recorder ?? this.createRecorder();
|
|
3498
|
+
if (rec && rec.sessionId !== id) {
|
|
3499
|
+
this.log(`recording session ${id}`);
|
|
3500
|
+
rec.start(id);
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
createRecorder() {
|
|
3504
|
+
const capturer = this.bridge.capturer;
|
|
3505
|
+
if (!capturer) return null;
|
|
3506
|
+
const uploader = this.replayUploader ?? (this.replayUploader = new ReplayUploader({
|
|
3507
|
+
url: () => this.api.url("/replay"),
|
|
3508
|
+
fetch: () => this.options.fetch ?? (typeof fetch === "function" ? fetch : null),
|
|
3509
|
+
health: this.api.health,
|
|
3510
|
+
meta: () => {
|
|
3511
|
+
const rec2 = this.recorder;
|
|
3512
|
+
return {
|
|
3513
|
+
anonymousId: this.anonymousId,
|
|
3514
|
+
userId: this.user?.id || null,
|
|
3515
|
+
...this.collectUrls() && this.screenName ? { url: this.currentUrl() } : {},
|
|
3516
|
+
device: { type: this.bridge.device.deviceType, os: this.bridge.device.platform },
|
|
3517
|
+
...rec2 && rec2.viewportWidth > 0 && rec2.viewportHeight > 0 ? { viewport: { width: rec2.viewportWidth, height: rec2.viewportHeight } } : {},
|
|
3518
|
+
sdk: { name: SDK_NAME, version: SDK_VERSION }
|
|
3519
|
+
};
|
|
3520
|
+
},
|
|
3521
|
+
onDisabled: (sid) => {
|
|
3522
|
+
if (sid !== this.session.id) return;
|
|
3523
|
+
this.log(`replay disabled by the server for session ${sid}`);
|
|
3524
|
+
this.replayDecision = { sessionId: sid, record: false };
|
|
3525
|
+
this.recorder?.stop(true);
|
|
3526
|
+
},
|
|
3527
|
+
log: (m) => this.log(m)
|
|
3528
|
+
}));
|
|
3529
|
+
const opts = this.options.sessionReplay ?? {};
|
|
3530
|
+
const rec = new SessionRecorder({
|
|
3531
|
+
capturer,
|
|
3532
|
+
uploader,
|
|
3533
|
+
intervalMs: opts.captureIntervalMs ?? 1e3,
|
|
3534
|
+
captureOptions: () => this.replayCaptureOptions(),
|
|
3535
|
+
href: () => this.currentUrl(),
|
|
3536
|
+
onError: (err) => this.reportError(err)
|
|
3537
|
+
});
|
|
3538
|
+
if (this.backgroundedAt !== null) rec.pause();
|
|
3539
|
+
this.recorder = rec;
|
|
3540
|
+
return rec;
|
|
3541
|
+
}
|
|
3542
|
+
async replayCaptureOptions() {
|
|
3543
|
+
const r = this.config?.settings?.replay;
|
|
3544
|
+
const opts = this.options.sessionReplay ?? {};
|
|
3545
|
+
const ids = new Set((r?.blockSelectors ?? []).map((sel) => guidelyIdFromSelector(sel)).filter((id) => !!id));
|
|
3546
|
+
const rects = await Promise.all(Array.from(ids, (id) => this.targets.measure(id)));
|
|
3547
|
+
return { maskAllText: !!opts.maskAllText || !!r?.maskAllText, maskAllImages: !!opts.maskAllImages, blockRects: rects.filter((rect) => !!rect) };
|
|
3548
|
+
}
|
|
3549
|
+
/**
|
|
3550
|
+
* Records this session even when it was not sampled (still needs `sessionReplay.enabled`, replay
|
|
3551
|
+
* enabled for the project, analytics consent and the native replay module). Sticks until the session ends.
|
|
3552
|
+
*/
|
|
3553
|
+
startSessionRecording() {
|
|
3554
|
+
this.whenHydrated(() => {
|
|
3555
|
+
this.replayDecision = { sessionId: this.session.id, record: true };
|
|
3556
|
+
this.syncReplay();
|
|
3557
|
+
});
|
|
3558
|
+
}
|
|
3559
|
+
/** Stops recording for the rest of this session; what was recorded is uploaded. */
|
|
3560
|
+
stopSessionRecording() {
|
|
3561
|
+
this.whenHydrated(() => {
|
|
3562
|
+
this.replayDecision = { sessionId: this.session.id, record: false };
|
|
3563
|
+
this.recorder?.stop(false);
|
|
3564
|
+
});
|
|
3565
|
+
}
|
|
3566
|
+
/** True while this session is being recorded. */
|
|
3567
|
+
isRecording() {
|
|
3568
|
+
return !!this.recorder?.isRecording;
|
|
3569
|
+
}
|
|
3570
|
+
/** The current analytics session id (also the replay id). */
|
|
3571
|
+
getSessionId() {
|
|
3572
|
+
return this.session.id;
|
|
3573
|
+
}
|
|
3574
|
+
/** True when touches should be passed to {@link recordTouch}. */
|
|
3575
|
+
isRecordingTouches() {
|
|
3576
|
+
return !!this.recorder?.isRecording;
|
|
3577
|
+
}
|
|
3578
|
+
/** A primary-pointer touch on the app, in window points (the provider's touch observer calls this). */
|
|
3579
|
+
recordTouch(phase, x, y) {
|
|
3580
|
+
this.recorder?.touch(phase, x, y);
|
|
3581
|
+
}
|
|
3582
|
+
// ---------------------------------------------------------------------------
|
|
3040
3583
|
// Product analytics (autocapture)
|
|
3041
3584
|
// ---------------------------------------------------------------------------
|
|
3042
3585
|
captureAllowed() {
|
|
@@ -3083,7 +3626,7 @@ var GuidelyClient = class {
|
|
|
3083
3626
|
}
|
|
3084
3627
|
if (this.destroyed) return;
|
|
3085
3628
|
const platform = this.bridge.device.platform;
|
|
3086
|
-
const maskAll = !!this.config?.settings?.replay?.maskAllText;
|
|
3629
|
+
const maskAll = !!this.config?.settings?.replay?.maskAllText || !!this.options.sessionReplay?.maskAllText;
|
|
3087
3630
|
const eventUrl = this.collectUrls() && url ? url : void 0;
|
|
3088
3631
|
if (on.clicks && el) this.enqueue("click", { url: eventUrl, properties: { ...tapProperties(el, tap.x, tap.y, platform, maskAll) } });
|
|
3089
3632
|
const count = this.rage.add(tap.x, tap.y, t);
|
|
@@ -3129,12 +3672,12 @@ var GuidelyClient = class {
|
|
|
3129
3672
|
/** `{ appVersion, build }` of this launch, without unknown keys. */
|
|
3130
3673
|
appInfo() {
|
|
3131
3674
|
const appVersion = this.options.appVersion ?? this.bridge.device.appVersion;
|
|
3132
|
-
const build = this.options.appBuild;
|
|
3675
|
+
const build = this.options.appBuild ?? (this.options.appVersion ? void 0 : this.bridge.device.appBuild);
|
|
3133
3676
|
return { ...appVersion ? { appVersion: String(appVersion) } : {}, ...build ? { build: String(build) } : {} };
|
|
3134
3677
|
}
|
|
3135
3678
|
/**
|
|
3136
3679
|
* Once per launch, as soon as a config is known: `app_install` / `app_update` from the stored
|
|
3137
|
-
* version (when the app
|
|
3680
|
+
* version (when the app version is known and the app passes `storage`), then `app_open` with `coldStart: true`.
|
|
3138
3681
|
*/
|
|
3139
3682
|
checkLaunch() {
|
|
3140
3683
|
if (this.launchChecked || !this.config || this.destroyed || !this.hydrated) return;
|
|
@@ -3951,8 +4494,8 @@ var GuidelyClient = class {
|
|
|
3951
4494
|
this.messenger?.close();
|
|
3952
4495
|
}
|
|
3953
4496
|
/** Opens a new messenger conversation, optionally pre-filling the message. */
|
|
3954
|
-
showNewMessage(
|
|
3955
|
-
this.whenHydrated(() => this.messenger?.showNewMessage(
|
|
4497
|
+
showNewMessage(text2) {
|
|
4498
|
+
this.whenHydrated(() => this.messenger?.showNewMessage(text2));
|
|
3956
4499
|
}
|
|
3957
4500
|
// ---------------------------------------------------------------------------
|
|
3958
4501
|
// Feature flags
|
|
@@ -3976,7 +4519,7 @@ var GuidelyClient = class {
|
|
|
3976
4519
|
/** Device facts on every screen view, read by the Pages devices / browsers breakdowns. */
|
|
3977
4520
|
deviceProperties() {
|
|
3978
4521
|
const d = this.bridge.device;
|
|
3979
|
-
return { platform: d.platform, deviceType: d.deviceType, os: d.platform };
|
|
4522
|
+
return { platform: d.platform, deviceType: d.deviceType, os: d.platform, ...d.osVersion ? { osVersion: d.osVersion } : {} };
|
|
3980
4523
|
}
|
|
3981
4524
|
/** Attributes flags are evaluated with: identity, traits, account, audiences, screen and device. */
|
|
3982
4525
|
flagContext() {
|
|
@@ -3987,6 +4530,7 @@ var GuidelyClient = class {
|
|
|
3987
4530
|
deviceType: d.deviceType,
|
|
3988
4531
|
locale: d.locale,
|
|
3989
4532
|
appVersion: this.options.appVersion ?? d.appVersion,
|
|
4533
|
+
osVersion: d.osVersion,
|
|
3990
4534
|
environment: this.options.environment,
|
|
3991
4535
|
...this.screenName ? { screen: this.screenName, path: this.currentUrl() } : {},
|
|
3992
4536
|
...this.user?.traits ?? {},
|
|
@@ -4077,6 +4621,51 @@ function withoutCode(guide) {
|
|
|
4077
4621
|
return { ...guide, config: { ...guide.config, steps: guide.config.steps.map(({ code: _code, ...step }) => step) } };
|
|
4078
4622
|
}
|
|
4079
4623
|
|
|
4624
|
+
// src/core/device.ts
|
|
4625
|
+
function text(value) {
|
|
4626
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
4627
|
+
if (typeof value !== "string") return void 0;
|
|
4628
|
+
const v = value.trim();
|
|
4629
|
+
return v ? v.slice(0, 64) : void 0;
|
|
4630
|
+
}
|
|
4631
|
+
function constant(mod, key) {
|
|
4632
|
+
if (!mod || typeof mod !== "object" && typeof mod !== "function") return void 0;
|
|
4633
|
+
const m = mod;
|
|
4634
|
+
try {
|
|
4635
|
+
const fromGetter = typeof m.getConstants === "function" ? m.getConstants()?.[key] : void 0;
|
|
4636
|
+
return fromGetter ?? m[key];
|
|
4637
|
+
} catch {
|
|
4638
|
+
return void 0;
|
|
4639
|
+
}
|
|
4640
|
+
}
|
|
4641
|
+
function read(mod, versionKey, buildKey) {
|
|
4642
|
+
const appVersion = text(constant(mod, versionKey));
|
|
4643
|
+
if (!appVersion) return null;
|
|
4644
|
+
const appBuild = text(constant(mod, buildKey));
|
|
4645
|
+
return { appVersion, ...appBuild ? { appBuild } : {} };
|
|
4646
|
+
}
|
|
4647
|
+
function inExpoGo(src) {
|
|
4648
|
+
const c = src.expoModules?.ExponentConstants ?? src.nativeModules.ExponentConstants;
|
|
4649
|
+
return constant(c, "executionEnvironment") === "storeClient" || constant(c, "appOwnership") === "expo";
|
|
4650
|
+
}
|
|
4651
|
+
function detectAppVersion(src) {
|
|
4652
|
+
try {
|
|
4653
|
+
const expo = inExpoGo(src) ? null : src.expoModules?.ExpoApplication ?? src.nativeModules.ExpoApplication;
|
|
4654
|
+
return read(src.nativeModules.GuidelyReplay, "appVersion", "appBuild") ?? read(expo, "nativeApplicationVersion", "nativeBuildVersion") ?? read(src.nativeModules.RNDeviceInfo, "appVersion", "buildNumber") ?? {};
|
|
4655
|
+
} catch {
|
|
4656
|
+
return {};
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
function detectOsVersion(src) {
|
|
4660
|
+
try {
|
|
4661
|
+
const c = src.platform.constants ?? {};
|
|
4662
|
+
if (src.platform.OS === "android") return text(c.Release) ?? text(src.platform.Version);
|
|
4663
|
+
return text(c.osVersion) ?? text(src.platform.Version);
|
|
4664
|
+
} catch {
|
|
4665
|
+
return void 0;
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
|
|
4080
4669
|
// src/ui/Autocapture.tsx
|
|
4081
4670
|
import { useMemo as useMemo5, useRef as useRef5 } from "react";
|
|
4082
4671
|
import { View as View10 } from "react-native";
|
|
@@ -4208,8 +4797,8 @@ function describe(f, masked, opts, withText) {
|
|
|
4208
4797
|
if (!sub.masked) {
|
|
4209
4798
|
const hostProps = host?.memoizedProps && typeof host.memoizedProps === "object" ? host.memoizedProps : {};
|
|
4210
4799
|
const label = props.accessibilityLabel ?? props["aria-label"] ?? hostProps.accessibilityLabel ?? hostProps["aria-label"];
|
|
4211
|
-
const
|
|
4212
|
-
if (
|
|
4800
|
+
const text2 = cleanText(sub.text) ?? (typeof label === "string" ? cleanText(label) : void 0);
|
|
4801
|
+
if (text2) el.text = text2;
|
|
4213
4802
|
}
|
|
4214
4803
|
}
|
|
4215
4804
|
if (host) el.measure = () => measureHost(host);
|
|
@@ -4365,17 +4954,17 @@ function parseHtml(html) {
|
|
|
4365
4954
|
flush();
|
|
4366
4955
|
current = { kind, level, marker, runs: [] };
|
|
4367
4956
|
};
|
|
4368
|
-
const push = (
|
|
4369
|
-
if (!
|
|
4957
|
+
const push = (text2) => {
|
|
4958
|
+
if (!text2) return;
|
|
4370
4959
|
if (!current) current = { kind: "paragraph", level: 1, runs: [] };
|
|
4371
|
-
const run = { text };
|
|
4960
|
+
const run = { text: text2 };
|
|
4372
4961
|
if (style.bold) run.bold = true;
|
|
4373
4962
|
if (style.italic) run.italic = true;
|
|
4374
4963
|
if (style.underline) run.underline = true;
|
|
4375
4964
|
if (style.code) run.code = true;
|
|
4376
4965
|
if (hrefs.length) run.href = hrefs[hrefs.length - 1];
|
|
4377
4966
|
const last = current.runs[current.runs.length - 1];
|
|
4378
|
-
if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text +=
|
|
4967
|
+
if (last && last.bold === run.bold && last.italic === run.italic && last.underline === run.underline && last.code === run.code && last.href === run.href) last.text += text2;
|
|
4379
4968
|
else current.runs.push(run);
|
|
4380
4969
|
};
|
|
4381
4970
|
const size = (attrs, name) => {
|
|
@@ -4391,18 +4980,18 @@ function parseHtml(html) {
|
|
|
4391
4980
|
const re = /<!--[\s\S]*?-->|<\/?([a-zA-Z][a-zA-Z0-9]*)\b([^>]*)>|([^<]+|<)/g;
|
|
4392
4981
|
let m;
|
|
4393
4982
|
while (m = re.exec(html || "")) {
|
|
4394
|
-
const [token, rawTag, attrs = "",
|
|
4395
|
-
if (
|
|
4983
|
+
const [token, rawTag, attrs = "", text2] = m;
|
|
4984
|
+
if (text2 !== void 0) {
|
|
4396
4985
|
if (skipping) continue;
|
|
4397
4986
|
if (pdf) {
|
|
4398
|
-
if (pdf.inLink) pdf.name += decodeEntities(
|
|
4987
|
+
if (pdf.inLink) pdf.name += decodeEntities(text2);
|
|
4399
4988
|
continue;
|
|
4400
4989
|
}
|
|
4401
4990
|
if (fileLink) {
|
|
4402
|
-
fileLink.name += decodeEntities(
|
|
4991
|
+
fileLink.name += decodeEntities(text2);
|
|
4403
4992
|
continue;
|
|
4404
4993
|
}
|
|
4405
|
-
push(decodeEntities(
|
|
4994
|
+
push(decodeEntities(text2.replace(/\s+/g, " ")));
|
|
4406
4995
|
continue;
|
|
4407
4996
|
}
|
|
4408
4997
|
if (!rawTag) continue;
|
|
@@ -4976,13 +5565,13 @@ function Conversations({ store, palette: p }) {
|
|
|
4976
5565
|
/* @__PURE__ */ jsx5(GButton, { label: "New conversation", palette: p, onPress: () => store.showNewMessage(), style: styles4.fullWidth })
|
|
4977
5566
|
] });
|
|
4978
5567
|
}
|
|
4979
|
-
function Bubble({ m, text, name, palette: p, onArticle, onGuide }) {
|
|
5568
|
+
function Bubble({ m, text: text2, name, palette: p, onArticle, onGuide }) {
|
|
4980
5569
|
if (m.author === "system")
|
|
4981
|
-
return /* @__PURE__ */ jsx5(Text4, { accessibilityRole: "text", style: [styles4.system, { color: p.muted }], children:
|
|
5570
|
+
return /* @__PURE__ */ jsx5(Text4, { accessibilityRole: "text", style: [styles4.system, { color: p.muted }], children: text2 });
|
|
4982
5571
|
const mine = m.author === "user";
|
|
4983
5572
|
return /* @__PURE__ */ jsxs3(View4, { style: [styles4.bubbleWrap, mine ? styles4.mine : styles4.theirs], children: [
|
|
4984
5573
|
!mine ? /* @__PURE__ */ jsx5(Text4, { style: [styles4.author, { color: p.muted }], children: m.author === "agent" ? m.authorName || "Team" : name }) : null,
|
|
4985
|
-
/* @__PURE__ */ jsx5(View4, { style: [styles4.bubble, { borderRadius: Math.max(12, p.radius) }, mine ? { backgroundColor: p.primary } : { backgroundColor: p.surface }], children: m.status === "pending" && !
|
|
5574
|
+
/* @__PURE__ */ jsx5(View4, { style: [styles4.bubble, { borderRadius: Math.max(12, p.radius) }, mine ? { backgroundColor: p.primary } : { backgroundColor: p.surface }], children: m.status === "pending" && !text2 ? /* @__PURE__ */ jsx5(TypingDots, { color: p.muted }) : /* @__PURE__ */ jsx5(Text4, { style: [styles4.bubbleText, { color: mine ? p.onPrimary : p.text }], children: text2 }) }),
|
|
4986
5575
|
m.citations.length || m.suggestedGuides.length ? /* @__PURE__ */ jsxs3(View4, { style: styles4.chips, children: [
|
|
4987
5576
|
m.citations.map((c) => /* @__PURE__ */ jsx5(Pressable4, { accessibilityRole: "link", accessibilityLabel: `Article: ${c.title}`, onPress: () => onArticle(c.articleId), style: [styles4.chip, { borderColor: p.border }], children: /* @__PURE__ */ jsxs3(Text4, { style: [styles4.chipText, { color: p.text }], children: [
|
|
4988
5577
|
"\u{1F4C4} ",
|
|
@@ -5001,7 +5590,7 @@ function TypingDots({ color }) {
|
|
|
5001
5590
|
function Thread({ store, palette: p, bottomInset }) {
|
|
5002
5591
|
const snap = useMessenger(store);
|
|
5003
5592
|
const t = snap.thread;
|
|
5004
|
-
const [
|
|
5593
|
+
const [text2, setText] = useState3(t?.draft ?? "");
|
|
5005
5594
|
const scroll = useRef2(null);
|
|
5006
5595
|
const convo = t?.conversation ?? null;
|
|
5007
5596
|
useEffect3(() => {
|
|
@@ -5010,7 +5599,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
5010
5599
|
const streamingIds = useMemo3(() => Object.keys(t?.streaming ?? {}).filter((id) => !t?.messages.some((m) => m.id === id)), [t]);
|
|
5011
5600
|
if (!t) return null;
|
|
5012
5601
|
const send = () => {
|
|
5013
|
-
const value =
|
|
5602
|
+
const value = text2;
|
|
5014
5603
|
setText("");
|
|
5015
5604
|
void store.send(value);
|
|
5016
5605
|
};
|
|
@@ -5032,7 +5621,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
5032
5621
|
/* @__PURE__ */ jsx5(
|
|
5033
5622
|
TextInput,
|
|
5034
5623
|
{
|
|
5035
|
-
value:
|
|
5624
|
+
value: text2,
|
|
5036
5625
|
onChangeText: (v) => setText(v.slice(0, 4e3)),
|
|
5037
5626
|
placeholder: convo ? "Reply\u2026" : "Write a message\u2026",
|
|
5038
5627
|
placeholderTextColor: p.muted,
|
|
@@ -5041,7 +5630,7 @@ function Thread({ store, palette: p, bottomInset }) {
|
|
|
5041
5630
|
style: [styles4.input, { color: p.text, backgroundColor: p.surface, borderRadius: Math.min(18, p.radius + 6) }]
|
|
5042
5631
|
}
|
|
5043
5632
|
),
|
|
5044
|
-
/* @__PURE__ */ jsx5(GButton, { label: "Send", palette: p, onPress: send, disabled: !
|
|
5633
|
+
/* @__PURE__ */ jsx5(GButton, { label: "Send", palette: p, onPress: send, disabled: !text2.trim() || t.sending })
|
|
5045
5634
|
] })
|
|
5046
5635
|
] });
|
|
5047
5636
|
}
|
|
@@ -5955,15 +6544,15 @@ function palette(theme, systemScheme, explicit) {
|
|
|
5955
6544
|
const wantsDark = theme.dark === "dark" || theme.dark === "auto" && systemScheme === "dark";
|
|
5956
6545
|
const dark = wantsDark && !explicit?.backgroundColor;
|
|
5957
6546
|
const background = dark ? DARK.background : theme.backgroundColor ?? "#ffffff";
|
|
5958
|
-
const
|
|
6547
|
+
const text2 = dark ? DARK.text : theme.textColor ?? "#111827";
|
|
5959
6548
|
return {
|
|
5960
6549
|
primary,
|
|
5961
6550
|
onPrimary: luminance(primary) > 0.45 ? "#111827" : "#ffffff",
|
|
5962
6551
|
background,
|
|
5963
|
-
text,
|
|
5964
|
-
muted: dark ? DARK.muted : mix(
|
|
5965
|
-
border: dark ? DARK.border : mix(
|
|
5966
|
-
surface: dark ? DARK.surface : mix(
|
|
6552
|
+
text: text2,
|
|
6553
|
+
muted: dark ? DARK.muted : mix(text2, 0.65),
|
|
6554
|
+
border: dark ? DARK.border : mix(text2, 0.12),
|
|
6555
|
+
surface: dark ? DARK.surface : mix(text2, 0.05),
|
|
5967
6556
|
radius: theme.borderRadius ?? 12,
|
|
5968
6557
|
overlay: `rgba(15, 23, 42, ${theme.overlayOpacity ?? 0.55})`,
|
|
5969
6558
|
fontFamily: nativeFont(theme.fontFamily)
|
|
@@ -6052,8 +6641,9 @@ function rcLauncherLabel(client) {
|
|
|
6052
6641
|
|
|
6053
6642
|
// src/ui/Autocapture.tsx
|
|
6054
6643
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
6644
|
+
var GUIDELY_MASK_NATIVE_ID = "guidely-mask";
|
|
6055
6645
|
function GuidelyMask({ children, ...rest }) {
|
|
6056
|
-
return /* @__PURE__ */ jsx11(View10, { ...rest, children });
|
|
6646
|
+
return /* @__PURE__ */ jsx11(View10, { collapsable: false, ...rest, nativeID: GUIDELY_MASK_NATIVE_ID, children });
|
|
6057
6647
|
}
|
|
6058
6648
|
var RESOLVE = {
|
|
6059
6649
|
isIgnored: (type) => type === GuidelyOverlay,
|
|
@@ -6064,6 +6654,18 @@ function useTapObserver(client) {
|
|
|
6064
6654
|
clientRef.current = client;
|
|
6065
6655
|
return useMemo5(() => {
|
|
6066
6656
|
const tracker = new TapTracker();
|
|
6657
|
+
let replayPointer = null;
|
|
6658
|
+
const replay = (phase, e) => {
|
|
6659
|
+
const c = clientRef.current;
|
|
6660
|
+
const n = e.nativeEvent;
|
|
6661
|
+
if (!c?.isRecordingTouches()) return void (replayPointer = null);
|
|
6662
|
+
if (phase === "down") {
|
|
6663
|
+
if (replayPointer !== null) return;
|
|
6664
|
+
replayPointer = n.identifier;
|
|
6665
|
+
} else if (n.identifier !== replayPointer) return;
|
|
6666
|
+
if (phase === "up" || phase === "cancel") replayPointer = null;
|
|
6667
|
+
c.recordTouch(phase, n.pageX, n.pageY);
|
|
6668
|
+
};
|
|
6067
6669
|
const guard = (fn) => (e) => {
|
|
6068
6670
|
try {
|
|
6069
6671
|
fn(e);
|
|
@@ -6073,12 +6675,17 @@ function useTapObserver(client) {
|
|
|
6073
6675
|
};
|
|
6074
6676
|
return {
|
|
6075
6677
|
onTouchStartCapture: guard((e) => {
|
|
6678
|
+
replay("down", e);
|
|
6076
6679
|
const n = e.nativeEvent;
|
|
6077
6680
|
if (!clientRef.current?.isTapCaptureOn()) return tracker.cancel();
|
|
6078
6681
|
tracker.begin(n.pageX, n.pageY, Date.now(), Array.isArray(n.touches) ? n.touches.length : 1, n.identifier);
|
|
6079
6682
|
}),
|
|
6080
|
-
onTouchMoveCapture: guard((e) =>
|
|
6683
|
+
onTouchMoveCapture: guard((e) => {
|
|
6684
|
+
replay("move", e);
|
|
6685
|
+
tracker.move(e.nativeEvent.pageX, e.nativeEvent.pageY, e.nativeEvent.identifier);
|
|
6686
|
+
}),
|
|
6081
6687
|
onTouchEndCapture: guard((e) => {
|
|
6688
|
+
replay("up", e);
|
|
6082
6689
|
const n = e.nativeEvent;
|
|
6083
6690
|
const tap = tracker.end(n.pageX, n.pageY, Date.now(), n.identifier);
|
|
6084
6691
|
const c = clientRef.current;
|
|
@@ -6086,7 +6693,10 @@ function useTapObserver(client) {
|
|
|
6086
6693
|
const r = resolveTapTarget(e, RESOLVE);
|
|
6087
6694
|
if (!r.ignored) c.recordTap({ x: tap.x, y: tap.y, t: Date.now(), element: r.element, hit: r.hit });
|
|
6088
6695
|
}),
|
|
6089
|
-
onTouchCancelCapture: guard(() =>
|
|
6696
|
+
onTouchCancelCapture: guard((e) => {
|
|
6697
|
+
replay("cancel", e);
|
|
6698
|
+
tracker.cancel();
|
|
6699
|
+
})
|
|
6090
6700
|
};
|
|
6091
6701
|
}, []);
|
|
6092
6702
|
}
|
|
@@ -6169,20 +6779,37 @@ function deviceLocale() {
|
|
|
6169
6779
|
return void 0;
|
|
6170
6780
|
}
|
|
6171
6781
|
}
|
|
6172
|
-
function
|
|
6782
|
+
function nativeSources() {
|
|
6783
|
+
return {
|
|
6784
|
+
platform: Platform6,
|
|
6785
|
+
nativeModules: NativeModules,
|
|
6786
|
+
expoModules: globalThis.expo?.modules
|
|
6787
|
+
};
|
|
6788
|
+
}
|
|
6789
|
+
function defaultBridge(appVersion, appBuild) {
|
|
6173
6790
|
const { width, height } = Dimensions.get("window");
|
|
6791
|
+
const sources = nativeSources();
|
|
6792
|
+
const detected = appVersion ? {} : detectAppVersion(sources);
|
|
6174
6793
|
return {
|
|
6175
6794
|
device: {
|
|
6176
6795
|
platform: Platform6.OS === "android" ? "android" : "ios",
|
|
6177
6796
|
deviceType: Platform6.OS === "ios" && Platform6.isPad || Math.min(width, height) >= 600 ? "tablet" : "mobile",
|
|
6178
6797
|
locale: deviceLocale(),
|
|
6179
|
-
appVersion
|
|
6798
|
+
appVersion: appVersion ?? detected.appVersion,
|
|
6799
|
+
appBuild: appBuild ?? detected.appBuild,
|
|
6800
|
+
osVersion: detectOsVersion(sources)
|
|
6180
6801
|
},
|
|
6181
6802
|
openExternal: (url) => void Linking.openURL(url).catch(() => {
|
|
6182
6803
|
}),
|
|
6183
|
-
windowSize: () => Dimensions.get("window")
|
|
6804
|
+
windowSize: () => Dimensions.get("window"),
|
|
6805
|
+
capturer: nativeCapturer()
|
|
6184
6806
|
};
|
|
6185
6807
|
}
|
|
6808
|
+
function nativeCapturer() {
|
|
6809
|
+
const mod = NativeModules.GuidelyReplay;
|
|
6810
|
+
if (!mod || typeof mod.capture !== "function") return void 0;
|
|
6811
|
+
return (options) => mod.capture(options);
|
|
6812
|
+
}
|
|
6186
6813
|
function GuidelyProvider({ children, user, insets, launcherOffset = 72, flagsPayload, flagAttributes, ...options }) {
|
|
6187
6814
|
const [client, setClient] = useState8(null);
|
|
6188
6815
|
const optionsRef = useRef7(options);
|
|
@@ -6215,7 +6842,7 @@ function GuidelyProvider({ children, user, insets, launcherOffset = 72, flagsPay
|
|
|
6215
6842
|
onNavigate: (url) => optionsRef.current.onNavigate?.(url),
|
|
6216
6843
|
onError: (err) => optionsRef.current.onError?.(err)
|
|
6217
6844
|
},
|
|
6218
|
-
defaultBridge(latest.appVersion)
|
|
6845
|
+
defaultBridge(latest.appVersion, latest.appBuild)
|
|
6219
6846
|
);
|
|
6220
6847
|
} catch (err) {
|
|
6221
6848
|
optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -6252,7 +6879,7 @@ function GuidelyProvider({ children, user, insets, launcherOffset = 72, flagsPay
|
|
|
6252
6879
|
const flags = useMemo6(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);
|
|
6253
6880
|
const tapObserver = useTapObserver(client);
|
|
6254
6881
|
return /* @__PURE__ */ jsx13(GuidelyContext.Provider, { value: client, children: /* @__PURE__ */ jsxs9(FlagsContext.Provider, { value: flags, children: [
|
|
6255
|
-
options.autocapture === false ? children : /* @__PURE__ */ jsx13(View12, { style: styles10.root, ...tapObserver, children }),
|
|
6882
|
+
options.autocapture === false && !options.sessionReplay?.enabled ? children : /* @__PURE__ */ jsx13(View12, { style: styles10.root, ...tapObserver, children }),
|
|
6256
6883
|
client ? /* @__PURE__ */ jsx13(GuidelyOverlay, { client, insets, launcherOffset }) : null
|
|
6257
6884
|
] }) });
|
|
6258
6885
|
}
|
|
@@ -6272,6 +6899,9 @@ var NOOP_RESULTS = {
|
|
|
6272
6899
|
getMessenger: null,
|
|
6273
6900
|
isGuideCompleted: false,
|
|
6274
6901
|
isClientReady: false,
|
|
6902
|
+
isRecording: false,
|
|
6903
|
+
isRecordingTouches: false,
|
|
6904
|
+
getSessionId: "",
|
|
6275
6905
|
getScreen: "",
|
|
6276
6906
|
on: () => {
|
|
6277
6907
|
},
|
|
@@ -6405,12 +7035,17 @@ export {
|
|
|
6405
7035
|
InMemoryStickyBucketStore,
|
|
6406
7036
|
Messenger,
|
|
6407
7037
|
RageClickDetector,
|
|
7038
|
+
ReplayUploader,
|
|
7039
|
+
RrwebEvents,
|
|
6408
7040
|
SDK_NAME,
|
|
6409
7041
|
SDK_VERSION,
|
|
7042
|
+
SessionRecorder,
|
|
6410
7043
|
TapTracker,
|
|
6411
7044
|
TargetRegistry,
|
|
6412
7045
|
createFlagsClient3 as createFlagsClient,
|
|
6413
7046
|
createSseParser,
|
|
7047
|
+
detectAppVersion,
|
|
7048
|
+
detectOsVersion,
|
|
6414
7049
|
guidelyScreenLayout,
|
|
6415
7050
|
htmlToText,
|
|
6416
7051
|
noopClient,
|