sitepong 0.2.10 → 0.2.12
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/dist/entries/rn.d.ts +6 -0
- package/dist/entries/rn.js +88 -18
- package/dist/entries/rn.js.map +1 -1
- package/ios/ScreenRecorder/ScreenRecorderModule.swift +3 -1
- package/ios/WatchtowerCore/TapEvent.swift +10 -0
- package/ios/WatchtowerCore/Watchtower.swift +3 -3
- package/ios/WatchtowerCore/WatchtowerEngine.swift +81 -5
- package/package.json +1 -1
package/dist/entries/rn.d.ts
CHANGED
|
@@ -732,6 +732,12 @@ interface WatchtowerConfig {
|
|
|
732
732
|
* you give the SDK's identify() so users line up across pipelines.
|
|
733
733
|
*/
|
|
734
734
|
distinctId?: string;
|
|
735
|
+
/**
|
|
736
|
+
* Idle grace in ms: reopening the app within this window of backgrounding
|
|
737
|
+
* resumes the same session; beyond it, a new (linked) session starts.
|
|
738
|
+
* Default 30_000 (30s). Lower it in tests to exercise session rolling.
|
|
739
|
+
*/
|
|
740
|
+
sessionGraceMs?: number;
|
|
735
741
|
}
|
|
736
742
|
/**
|
|
737
743
|
* Start the shared native capture engine for React Native. Idempotent.
|
package/dist/entries/rn.js
CHANGED
|
@@ -3430,33 +3430,35 @@ function attrDiff(id, prev, next) {
|
|
|
3430
3430
|
}
|
|
3431
3431
|
function diff(prev, next, mirror) {
|
|
3432
3432
|
const { next: nextIndex, order } = indexTree(next, mirror);
|
|
3433
|
-
const
|
|
3434
|
-
const
|
|
3435
|
-
for (const id of prev.keys()) if (!nextIndex.has(id)) removed.add(id);
|
|
3436
|
-
for (const id of removed) {
|
|
3437
|
-
const rec = prev.get(id);
|
|
3438
|
-
if (!removed.has(rec.parentId)) messages.push(RemoveNode(id));
|
|
3439
|
-
}
|
|
3433
|
+
const creates = [];
|
|
3434
|
+
const updates = [];
|
|
3440
3435
|
for (const id of order) {
|
|
3441
3436
|
const rec = nextIndex.get(id);
|
|
3442
3437
|
const before = prev.get(id);
|
|
3443
3438
|
if (!before) {
|
|
3444
3439
|
if (rec.tag === "#text") {
|
|
3445
|
-
|
|
3440
|
+
creates.push(CreateTextNode(id, rec.parentId, rec.index));
|
|
3446
3441
|
} else {
|
|
3447
|
-
|
|
3442
|
+
creates.push(CreateElementNode(id, rec.parentId, rec.index, rec.tag));
|
|
3448
3443
|
}
|
|
3449
|
-
for (const k of Object.keys(rec.attrs))
|
|
3450
|
-
if (rec.text !== void 0 && rec.text !== "")
|
|
3444
|
+
for (const k of Object.keys(rec.attrs)) creates.push(SetNodeAttribute(id, k, rec.attrs[k]));
|
|
3445
|
+
if (rec.text !== void 0 && rec.text !== "") creates.push(SetNodeData(id, rec.text));
|
|
3451
3446
|
} else {
|
|
3452
3447
|
if (before.parentId !== rec.parentId || before.index !== rec.index) {
|
|
3453
|
-
|
|
3448
|
+
updates.push(MoveNode(id, rec.parentId, rec.index));
|
|
3454
3449
|
}
|
|
3455
|
-
|
|
3456
|
-
if ((before.text ?? "") !== (rec.text ?? ""))
|
|
3450
|
+
updates.push(...attrDiff(id, before.attrs, rec.attrs));
|
|
3451
|
+
if ((before.text ?? "") !== (rec.text ?? "")) updates.push(SetNodeData(id, rec.text ?? ""));
|
|
3457
3452
|
}
|
|
3458
3453
|
}
|
|
3459
|
-
|
|
3454
|
+
const removed = /* @__PURE__ */ new Set();
|
|
3455
|
+
for (const id of prev.keys()) if (!nextIndex.has(id)) removed.add(id);
|
|
3456
|
+
const removes = [];
|
|
3457
|
+
for (const id of removed) {
|
|
3458
|
+
const rec = prev.get(id);
|
|
3459
|
+
if (!removed.has(rec.parentId)) removes.push(RemoveNode(id));
|
|
3460
|
+
}
|
|
3461
|
+
return { messages: [...creates, ...updates, ...removes], index: nextIndex };
|
|
3460
3462
|
}
|
|
3461
3463
|
function stableAnchor(step) {
|
|
3462
3464
|
if (step.attrs.testID) return `@${step.attrs.testID}`;
|
|
@@ -3578,6 +3580,21 @@ var Recorder = class {
|
|
|
3578
3580
|
emit(t, m) {
|
|
3579
3581
|
this.stream.push({ t, m });
|
|
3580
3582
|
}
|
|
3583
|
+
/**
|
|
3584
|
+
* Reinitialize for a brand-new session — fresh id space, empty tree/stream,
|
|
3585
|
+
* no pending outcome windows. The capture engine calls this when it rolls to
|
|
3586
|
+
* a new session (app reopened after the idle grace) so the new stream begins
|
|
3587
|
+
* with a clean full snapshot rather than diffing against the prior session's
|
|
3588
|
+
* tree (which would leave the new session missing its initial creates).
|
|
3589
|
+
*/
|
|
3590
|
+
reset() {
|
|
3591
|
+
this.mirror = new Mirror();
|
|
3592
|
+
this.index = emptyIndex();
|
|
3593
|
+
this.analyzer = new InteractionAnalyzer();
|
|
3594
|
+
this.stream = [];
|
|
3595
|
+
this.pending = [];
|
|
3596
|
+
this.viewport = { w: 0, h: 0 };
|
|
3597
|
+
}
|
|
3581
3598
|
setViewport(w, h, t) {
|
|
3582
3599
|
this.viewport = { w, h };
|
|
3583
3600
|
this.emit(t, [5, w, h]);
|
|
@@ -3991,6 +4008,7 @@ var StructuralCapture = class {
|
|
|
3991
4008
|
this.scrollOffsets.clear();
|
|
3992
4009
|
this.overloadSkip = 0;
|
|
3993
4010
|
this.explicitRoot = null;
|
|
4011
|
+
this.recorder.reset();
|
|
3994
4012
|
const { width, height } = reactNative.Dimensions.get("window");
|
|
3995
4013
|
this.recorder.setViewport(Math.round(width), Math.round(height), 0);
|
|
3996
4014
|
this.sampleTimer = setInterval(() => this.sample(), cfg.sampleIntervalMs ?? 120);
|
|
@@ -4718,7 +4736,8 @@ function startWatchtower(config) {
|
|
|
4718
4736
|
projectId: config.projectId,
|
|
4719
4737
|
endpoint: config.endpoint,
|
|
4720
4738
|
sampleRate: config.sampleRate ?? 0.1,
|
|
4721
|
-
platform: config.platform ?? "react-native-ios"
|
|
4739
|
+
platform: config.platform ?? "react-native-ios",
|
|
4740
|
+
sessionGraceMs: config.sessionGraceMs ?? 3e4
|
|
4722
4741
|
});
|
|
4723
4742
|
started = true;
|
|
4724
4743
|
if (config.distinctId) setWatchtowerUser(config.distinctId);
|
|
@@ -4776,9 +4795,60 @@ function StructuralCaptureProvider({ children, ...cfg }) {
|
|
|
4776
4795
|
cfgRef.current = cfg;
|
|
4777
4796
|
const rootRef = React2.useRef(null);
|
|
4778
4797
|
React2.useEffect(() => {
|
|
4779
|
-
|
|
4780
|
-
|
|
4798
|
+
let cancelled = false;
|
|
4799
|
+
let poll = null;
|
|
4800
|
+
let adoptTimer = null;
|
|
4801
|
+
let currentSid;
|
|
4802
|
+
let readopting = false;
|
|
4803
|
+
const begin = (sessionId) => {
|
|
4804
|
+
if (cancelled) return;
|
|
4805
|
+
currentSid = sessionId;
|
|
4806
|
+
structuralCapture.start({ ...cfgRef.current, sessionId });
|
|
4807
|
+
structuralCapture.setRootInstance(rootRef.current);
|
|
4808
|
+
};
|
|
4809
|
+
const readopt = async (sessionId) => {
|
|
4810
|
+
if (cancelled || readopting) return;
|
|
4811
|
+
readopting = true;
|
|
4812
|
+
try {
|
|
4813
|
+
await structuralCapture.stop();
|
|
4814
|
+
begin(sessionId);
|
|
4815
|
+
} finally {
|
|
4816
|
+
readopting = false;
|
|
4817
|
+
}
|
|
4818
|
+
};
|
|
4819
|
+
const watchForRoll = () => {
|
|
4820
|
+
adoptTimer = setInterval(() => {
|
|
4821
|
+
if (cancelled || readopting) return;
|
|
4822
|
+
const wt = getWatchtowerSessionId();
|
|
4823
|
+
if (wt && wt !== currentSid) void readopt(wt);
|
|
4824
|
+
}, 1e3);
|
|
4825
|
+
};
|
|
4826
|
+
const explicit = cfgRef.current.sessionId;
|
|
4827
|
+
if (explicit) {
|
|
4828
|
+
begin(explicit);
|
|
4829
|
+
} else {
|
|
4830
|
+
let tries = 0;
|
|
4831
|
+
const resolve = () => {
|
|
4832
|
+
if (cancelled) return;
|
|
4833
|
+
const wt = getWatchtowerSessionId();
|
|
4834
|
+
if (wt) {
|
|
4835
|
+
begin(wt);
|
|
4836
|
+
watchForRoll();
|
|
4837
|
+
return;
|
|
4838
|
+
}
|
|
4839
|
+
if (++tries >= 25) {
|
|
4840
|
+
begin(void 0);
|
|
4841
|
+
watchForRoll();
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
poll = setTimeout(resolve, 200);
|
|
4845
|
+
};
|
|
4846
|
+
resolve();
|
|
4847
|
+
}
|
|
4781
4848
|
return () => {
|
|
4849
|
+
cancelled = true;
|
|
4850
|
+
if (poll) clearTimeout(poll);
|
|
4851
|
+
if (adoptTimer) clearInterval(adoptTimer);
|
|
4782
4852
|
void structuralCapture.stop();
|
|
4783
4853
|
};
|
|
4784
4854
|
}, []);
|