sitepong 0.2.11 → 0.2.13

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.
@@ -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.
@@ -3580,6 +3580,21 @@ var Recorder = class {
3580
3580
  emit(t, m) {
3581
3581
  this.stream.push({ t, m });
3582
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
+ }
3583
3598
  setViewport(w, h, t) {
3584
3599
  this.viewport = { w, h };
3585
3600
  this.emit(t, [5, w, h]);
@@ -3850,6 +3865,12 @@ function extractAttrs(tag, props, componentName2) {
3850
3865
  if (uri) attrs.src = String(uri);
3851
3866
  }
3852
3867
  if (componentName2) attrs.rnComponent = componentName2;
3868
+ if (props.activityState !== void 0 && props.activityState !== null) {
3869
+ attrs.activityState = String(props.activityState);
3870
+ }
3871
+ if (props.isFocused !== void 0 && props.isFocused !== null) {
3872
+ attrs.isFocused = String(props.isFocused);
3873
+ }
3853
3874
  if (props.wtOverlay || props.accessibilityViewIsModal) attrs.wtOverlay = "true";
3854
3875
  if (props.wtSensitive || props.secureTextEntry) attrs.wtSensitive = "true";
3855
3876
  return attrs;
@@ -3993,6 +4014,7 @@ var StructuralCapture = class {
3993
4014
  this.scrollOffsets.clear();
3994
4015
  this.overloadSkip = 0;
3995
4016
  this.explicitRoot = null;
4017
+ this.recorder.reset();
3996
4018
  const { width, height } = reactNative.Dimensions.get("window");
3997
4019
  this.recorder.setViewport(Math.round(width), Math.round(height), 0);
3998
4020
  this.sampleTimer = setInterval(() => this.sample(), cfg.sampleIntervalMs ?? 120);
@@ -4720,7 +4742,8 @@ function startWatchtower(config) {
4720
4742
  projectId: config.projectId,
4721
4743
  endpoint: config.endpoint,
4722
4744
  sampleRate: config.sampleRate ?? 0.1,
4723
- platform: config.platform ?? "react-native-ios"
4745
+ platform: config.platform ?? "react-native-ios",
4746
+ sessionGraceMs: config.sessionGraceMs ?? 3e4
4724
4747
  });
4725
4748
  started = true;
4726
4749
  if (config.distinctId) setWatchtowerUser(config.distinctId);
@@ -4780,11 +4803,32 @@ function StructuralCaptureProvider({ children, ...cfg }) {
4780
4803
  React2.useEffect(() => {
4781
4804
  let cancelled = false;
4782
4805
  let poll = null;
4806
+ let adoptTimer = null;
4807
+ let currentSid;
4808
+ let readopting = false;
4783
4809
  const begin = (sessionId) => {
4784
4810
  if (cancelled) return;
4811
+ currentSid = sessionId;
4785
4812
  structuralCapture.start({ ...cfgRef.current, sessionId });
4786
4813
  structuralCapture.setRootInstance(rootRef.current);
4787
4814
  };
4815
+ const readopt = async (sessionId) => {
4816
+ if (cancelled || readopting) return;
4817
+ readopting = true;
4818
+ try {
4819
+ await structuralCapture.stop();
4820
+ begin(sessionId);
4821
+ } finally {
4822
+ readopting = false;
4823
+ }
4824
+ };
4825
+ const watchForRoll = () => {
4826
+ adoptTimer = setInterval(() => {
4827
+ if (cancelled || readopting) return;
4828
+ const wt = getWatchtowerSessionId();
4829
+ if (wt && wt !== currentSid) void readopt(wt);
4830
+ }, 1e3);
4831
+ };
4788
4832
  const explicit = cfgRef.current.sessionId;
4789
4833
  if (explicit) {
4790
4834
  begin(explicit);
@@ -4793,8 +4837,16 @@ function StructuralCaptureProvider({ children, ...cfg }) {
4793
4837
  const resolve = () => {
4794
4838
  if (cancelled) return;
4795
4839
  const wt = getWatchtowerSessionId();
4796
- if (wt) return begin(wt);
4797
- if (++tries >= 25) return begin(void 0);
4840
+ if (wt) {
4841
+ begin(wt);
4842
+ watchForRoll();
4843
+ return;
4844
+ }
4845
+ if (++tries >= 25) {
4846
+ begin(void 0);
4847
+ watchForRoll();
4848
+ return;
4849
+ }
4798
4850
  poll = setTimeout(resolve, 200);
4799
4851
  };
4800
4852
  resolve();
@@ -4802,6 +4854,7 @@ function StructuralCaptureProvider({ children, ...cfg }) {
4802
4854
  return () => {
4803
4855
  cancelled = true;
4804
4856
  if (poll) clearTimeout(poll);
4857
+ if (adoptTimer) clearInterval(adoptTimer);
4805
4858
  void structuralCapture.stop();
4806
4859
  };
4807
4860
  }, []);