rampkit-expo-dev 0.0.33 → 0.0.35

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.
@@ -432,8 +432,11 @@ function Overlay(props) {
432
432
  const varsRef = (0, react_1.useRef)({});
433
433
  // hold refs for injection
434
434
  const webviewsRef = (0, react_1.useRef)([]);
435
- // track when we last initialized a given page with host vars (to filter stale defaults)
436
- const lastInitSendRef = (0, react_1.useRef)([]);
435
+ // Track when we last SENT vars to each page (for stale value filtering)
436
+ // This helps filter out default/cached values that pages send back after receiving updates
437
+ const lastVarsSendTimeRef = (0, react_1.useRef)([]);
438
+ // Stale value window in milliseconds - matches iOS SDK (600ms)
439
+ const STALE_VALUE_WINDOW_MS = 600;
437
440
  // Fade-in when overlay becomes visible
438
441
  react_1.default.useEffect(() => {
439
442
  if (visible && !isClosing) {
@@ -567,13 +570,9 @@ function Overlay(props) {
567
570
  return;
568
571
  if (__DEV__)
569
572
  console.log("[Rampkit] sendVarsToWebView", i, varsRef.current, { isInitialLoad });
570
- // Only update the stale filter timestamp during initial page load,
571
- // not when syncing vars on page selection. This prevents the filter
572
- // from incorrectly rejecting legitimate user interactions that happen
573
- // immediately after navigating to a screen.
574
- if (isInitialLoad) {
575
- lastInitSendRef.current[i] = Date.now();
576
- }
573
+ // Track when we send vars to this page for stale value filtering
574
+ // This helps us ignore default/cached values that pages echo back
575
+ lastVarsSendTimeRef.current[i] = Date.now();
577
576
  // Use direct variable setting instead of MessageEvent dispatch
578
577
  // This is more reliable as it doesn't depend on event listeners being set up
579
578
  // @ts-ignore: injectJavaScript exists on WebView instance
@@ -592,6 +591,7 @@ function Overlay(props) {
592
591
  vars: varsRef.current,
593
592
  });
594
593
  const script = buildDirectVarsScript(varsRef.current);
594
+ const now = Date.now();
595
595
  for (let i = 0; i < webviewsRef.current.length; i++) {
596
596
  // Skip the source WebView to prevent echo loops
597
597
  if (excludeIndex !== undefined && i === excludeIndex) {
@@ -599,6 +599,8 @@ function Overlay(props) {
599
599
  }
600
600
  const wv = webviewsRef.current[i];
601
601
  if (wv) {
602
+ // Track send time for stale value filtering
603
+ lastVarsSendTimeRef.current[i] = now;
602
604
  // @ts-ignore: injectJavaScript exists on WebView instance
603
605
  wv.injectJavaScript(script);
604
606
  }
@@ -768,22 +770,46 @@ function Overlay(props) {
768
770
  // JSON path
769
771
  const data = JSON.parse(raw);
770
772
  // 1) Variables from a page → update shared + broadcast to OTHER pages
771
- // This mirrors the iOS SDK pattern where the source WebView is excluded
772
- // to prevent echo loops and ensure the active screen remains responsive.
773
+ // This mirrors the iOS SDK pattern with stale value filtering.
773
774
  if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:variables" &&
774
775
  (data === null || data === void 0 ? void 0 : data.vars) &&
775
776
  typeof data.vars === "object") {
776
777
  if (__DEV__)
777
778
  console.log("[Rampkit] received variables from page", i, data.vars);
778
- // Accept all variable updates from pages without filtering.
779
- // The previous filter was too aggressive and blocked legitimate
780
- // user interactions that happened within 600ms of page load.
781
- // We now trust that pages send correct variable updates.
779
+ // Check if this page is within the stale value window
780
+ // (we recently sent vars to it and it may be echoing back defaults)
781
+ const now = Date.now();
782
+ const lastSendTime = lastVarsSendTimeRef.current[i] || 0;
783
+ const timeSinceSend = now - lastSendTime;
784
+ const isWithinStaleWindow = timeSinceSend < STALE_VALUE_WINDOW_MS;
785
+ if (__DEV__) {
786
+ console.log("[Rampkit] stale check:", {
787
+ pageIndex: i,
788
+ isWithinStaleWindow,
789
+ timeSinceSend,
790
+ });
791
+ }
782
792
  let changed = false;
783
793
  const newVars = {};
784
794
  for (const [key, value] of Object.entries(data.vars)) {
785
795
  const hasHostVal = Object.prototype.hasOwnProperty.call(varsRef.current, key);
786
796
  const hostVal = varsRef.current[key];
797
+ // Stale value filtering (matches iOS SDK behavior):
798
+ // If we're within the stale window, don't let empty/default values
799
+ // overwrite existing non-empty host values.
800
+ // This prevents pages from clobbering user input with cached defaults
801
+ // when they first become active/visible.
802
+ if (isWithinStaleWindow && hasHostVal) {
803
+ const hostIsNonEmpty = hostVal !== "" && hostVal !== null && hostVal !== undefined;
804
+ const incomingIsEmpty = value === "" || value === null || value === undefined;
805
+ if (hostIsNonEmpty && incomingIsEmpty) {
806
+ if (__DEV__) {
807
+ console.log(`[Rampkit] filtering stale empty value for key "${key}": keeping "${hostVal}"`);
808
+ }
809
+ continue; // Skip this key, keep host value
810
+ }
811
+ }
812
+ // Accept the update if value is different
787
813
  if (!hasHostVal || hostVal !== value) {
788
814
  newVars[key] = value;
789
815
  changed = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "description": "The Expo SDK for RampKit. Build, test, and personalize app onboardings with instant updates.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",