@magicfeedback/popup-sdk 1.7.0 → 1.7.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/dist/index.d.mts CHANGED
@@ -856,6 +856,13 @@ declare class DeepdotsPopups {
856
856
  private safeParseUrl;
857
857
  private mapPopupTriggerType;
858
858
  private markSurveyProgress;
859
+ /**
860
+ * Rehidrata el estado de redisplay desde el storage. `answeredSurveys` se reconstruye
861
+ * desde las entradas COMPLETED: es exactamente lo que persiste `markSurveyAnswered`.
862
+ */
863
+ private loadPopupState;
864
+ /** Vuelca el estado de redisplay al storage. Sin storage (o bloqueado) degrada a memoria. */
865
+ private persistPopupState;
859
866
  private isPopupDefinition;
860
867
  private isPopupTrigger;
861
868
  private isPopupTriggerType;
package/dist/index.d.ts CHANGED
@@ -856,6 +856,13 @@ declare class DeepdotsPopups {
856
856
  private safeParseUrl;
857
857
  private mapPopupTriggerType;
858
858
  private markSurveyProgress;
859
+ /**
860
+ * Rehidrata el estado de redisplay desde el storage. `answeredSurveys` se reconstruye
861
+ * desde las entradas COMPLETED: es exactamente lo que persiste `markSurveyAnswered`.
862
+ */
863
+ private loadPopupState;
864
+ /** Vuelca el estado de redisplay al storage. Sin storage (o bloqueado) degrada a memoria. */
865
+ private persistPopupState;
859
866
  private isPopupDefinition;
860
867
  private isPopupTrigger;
861
868
  private isPopupTriggerType;
package/dist/index.js CHANGED
@@ -2355,9 +2355,9 @@ var init_logo = __esm({
2355
2355
  }
2356
2356
  });
2357
2357
 
2358
- // node_modules/@magicfeedback/native/dist/magicfeedback-sdk.browser.js
2358
+ // ../deepdots-popup-sdk/node_modules/@magicfeedback/native/dist/magicfeedback-sdk.browser.js
2359
2359
  var require_magicfeedback_sdk_browser = __commonJS({
2360
- "node_modules/@magicfeedback/native/dist/magicfeedback-sdk.browser.js"(exports, module2) {
2360
+ "../deepdots-popup-sdk/node_modules/@magicfeedback/native/dist/magicfeedback-sdk.browser.js"(exports, module2) {
2361
2361
  "use strict";
2362
2362
  !(function(e, t) {
2363
2363
  "object" == typeof exports && "object" == typeof module2 ? module2.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.magicfeedback = t() : e.magicfeedback = t();
@@ -7018,6 +7018,75 @@ var CrashReporter = class {
7018
7018
  }
7019
7019
  };
7020
7020
 
7021
+ // src/core/popup-state-store.ts
7022
+ var POPUP_STATE_STORAGE_KEY = "deepdots.popups.state";
7023
+ var MAX_TRACKED_POPUP_ENTRIES = 200;
7024
+ function emptyState() {
7025
+ return { lastShown: {}, progress: {} };
7026
+ }
7027
+ function isValidTimestamp(value) {
7028
+ return typeof value === "number" && Number.isFinite(value);
7029
+ }
7030
+ function capEntries(entries, timestampOf) {
7031
+ if (entries.length <= MAX_TRACKED_POPUP_ENTRIES) return entries;
7032
+ return [...entries].sort((a, b) => timestampOf(b[1]) - timestampOf(a[1])).slice(0, MAX_TRACKED_POPUP_ENTRIES);
7033
+ }
7034
+ function readPopupState(storage) {
7035
+ let raw = null;
7036
+ try {
7037
+ raw = storage.getItem(POPUP_STATE_STORAGE_KEY);
7038
+ } catch {
7039
+ return emptyState();
7040
+ }
7041
+ if (!raw) return emptyState();
7042
+ let parsed;
7043
+ try {
7044
+ parsed = JSON.parse(raw);
7045
+ } catch {
7046
+ return emptyState();
7047
+ }
7048
+ if (typeof parsed !== "object" || parsed === null) return emptyState();
7049
+ const source = parsed;
7050
+ const state = emptyState();
7051
+ if (typeof source.lastShown === "object" && source.lastShown !== null) {
7052
+ const valid = Object.entries(source.lastShown).filter((entry) => isValidTimestamp(entry[1]));
7053
+ capEntries(valid, (timestamp) => timestamp).forEach(([popupId, timestamp]) => {
7054
+ state.lastShown[popupId] = timestamp;
7055
+ });
7056
+ }
7057
+ if (typeof source.progress === "object" && source.progress !== null) {
7058
+ const valid = Object.entries(source.progress).filter((entry) => {
7059
+ const value = entry[1];
7060
+ if (typeof value !== "object" || value === null) return false;
7061
+ const candidate = value;
7062
+ return POPUP_TRIGGER_CONDITION_STATUSES.includes(candidate.status) && isValidTimestamp(candidate.timestamp);
7063
+ });
7064
+ capEntries(valid, (entry) => entry.timestamp).forEach(([surveyId, entry]) => {
7065
+ state.progress[surveyId] = { status: entry.status, timestamp: entry.timestamp };
7066
+ });
7067
+ }
7068
+ return state;
7069
+ }
7070
+ function writePopupState(storage, state) {
7071
+ const capped = emptyState();
7072
+ capEntries(Object.entries(state.lastShown), (timestamp) => timestamp).forEach(([popupId, timestamp]) => {
7073
+ capped.lastShown[popupId] = timestamp;
7074
+ });
7075
+ capEntries(Object.entries(state.progress), (entry) => entry.timestamp).forEach(([surveyId, entry]) => {
7076
+ capped.progress[surveyId] = entry;
7077
+ });
7078
+ try {
7079
+ storage.setItem(POPUP_STATE_STORAGE_KEY, JSON.stringify(capped));
7080
+ } catch {
7081
+ }
7082
+ }
7083
+ function clearPopupState(storage) {
7084
+ try {
7085
+ storage.removeItem(POPUP_STATE_STORAGE_KEY);
7086
+ } catch {
7087
+ }
7088
+ }
7089
+
7021
7090
  // src/core/deepdots-popups.ts
7022
7091
  init_logger();
7023
7092
 
@@ -7108,6 +7177,10 @@ var DeepdotsPopups = class {
7108
7177
  this.popupDefinitions = [];
7109
7178
  this.popupsLoaded = false;
7110
7179
  this.pendingAutoLaunch = false;
7180
+ // Estado que alimenta las reglas de redisplay. Copia de trabajo en memoria; la fuente
7181
+ // duradera es el storage (`popup-state-store`), rehidratada en `init()` — sin eso, una
7182
+ // recarga reiniciaba el cooldown y el popup volvía a salir. `answeredSurveys` se deriva
7183
+ // de las entradas COMPLETED de `surveyProgress` (los dos los escribe `markSurveyAnswered`).
7111
7184
  this.answeredSurveys = /* @__PURE__ */ new Set();
7112
7185
  this.surveyProgress = /* @__PURE__ */ new Map();
7113
7186
  this.lastShown = /* @__PURE__ */ new Map();
@@ -7183,6 +7256,7 @@ var DeepdotsPopups = class {
7183
7256
  };
7184
7257
  const storage = config.storage ?? createDefaultStorage();
7185
7258
  this.storage = storage;
7259
+ this.loadPopupState(storage);
7186
7260
  this.tracking = new TrackingManager({
7187
7261
  storage,
7188
7262
  clientUserId: this.config.userId,
@@ -7450,6 +7524,10 @@ var DeepdotsPopups = class {
7450
7524
  }) : null;
7451
7525
  this.analytics?.resetUserScope();
7452
7526
  this.messageGuard.reset();
7527
+ this.lastShown.clear();
7528
+ this.surveyProgress.clear();
7529
+ this.answeredSurveys.clear();
7530
+ clearPopupState(storage);
7453
7531
  this.log("tracking \xB7 user_change \xB7 user_id:", this.tracking.getUserId());
7454
7532
  this.openSession();
7455
7533
  }
@@ -7621,6 +7699,7 @@ var DeepdotsPopups = class {
7621
7699
  this.log("Showing popup (definition)", def);
7622
7700
  this.surveyToPopupId.set(def.surveyId, def.id);
7623
7701
  this.lastShown.set(def.id, Date.now());
7702
+ this.persistPopupState();
7624
7703
  this.renderPopup(def.surveyId, def.productId, def.actions, def.style, def.title);
7625
7704
  this.emitEvent("popup_shown", def.surveyId, { popupId: def.id });
7626
7705
  }
@@ -8100,6 +8179,29 @@ var DeepdotsPopups = class {
8100
8179
  return;
8101
8180
  }
8102
8181
  this.surveyProgress.set(surveyId, { status, timestamp: Date.now() });
8182
+ this.persistPopupState();
8183
+ }
8184
+ /**
8185
+ * Rehidrata el estado de redisplay desde el storage. `answeredSurveys` se reconstruye
8186
+ * desde las entradas COMPLETED: es exactamente lo que persiste `markSurveyAnswered`.
8187
+ */
8188
+ loadPopupState(storage) {
8189
+ const state = readPopupState(storage);
8190
+ Object.entries(state.lastShown).forEach(([popupId, timestamp]) => {
8191
+ this.lastShown.set(popupId, timestamp);
8192
+ });
8193
+ Object.entries(state.progress).forEach(([surveyId, entry]) => {
8194
+ this.surveyProgress.set(surveyId, { status: entry.status, timestamp: entry.timestamp });
8195
+ if (entry.status === "COMPLETED") this.answeredSurveys.add(surveyId);
8196
+ });
8197
+ }
8198
+ /** Vuelca el estado de redisplay al storage. Sin storage (o bloqueado) degrada a memoria. */
8199
+ persistPopupState() {
8200
+ if (!this.storage) return;
8201
+ writePopupState(this.storage, {
8202
+ lastShown: Object.fromEntries(this.lastShown),
8203
+ progress: Object.fromEntries(this.surveyProgress)
8204
+ });
8103
8205
  }
8104
8206
  isPopupDefinition(value) {
8105
8207
  if (typeof value !== "object" || value === null) return false;