@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 +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +104 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +104 -2
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +7 -0
- package/dist/react-native.d.ts +7 -0
- package/dist/react-native.js +102 -0
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +102 -0
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-IHGYFMXO.mjs → renderPopup-HHQMAW3G.mjs} +3 -3
- package/dist/renderPopup-HHQMAW3G.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/renderPopup-IHGYFMXO.mjs.map +0 -1
package/dist/react-native.mjs
CHANGED
|
@@ -1565,6 +1565,75 @@ var CrashReporter = class {
|
|
|
1565
1565
|
}
|
|
1566
1566
|
};
|
|
1567
1567
|
|
|
1568
|
+
// src/core/popup-state-store.ts
|
|
1569
|
+
var POPUP_STATE_STORAGE_KEY = "deepdots.popups.state";
|
|
1570
|
+
var MAX_TRACKED_POPUP_ENTRIES = 200;
|
|
1571
|
+
function emptyState() {
|
|
1572
|
+
return { lastShown: {}, progress: {} };
|
|
1573
|
+
}
|
|
1574
|
+
function isValidTimestamp(value) {
|
|
1575
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
1576
|
+
}
|
|
1577
|
+
function capEntries(entries, timestampOf) {
|
|
1578
|
+
if (entries.length <= MAX_TRACKED_POPUP_ENTRIES) return entries;
|
|
1579
|
+
return [...entries].sort((a, b) => timestampOf(b[1]) - timestampOf(a[1])).slice(0, MAX_TRACKED_POPUP_ENTRIES);
|
|
1580
|
+
}
|
|
1581
|
+
function readPopupState(storage) {
|
|
1582
|
+
let raw = null;
|
|
1583
|
+
try {
|
|
1584
|
+
raw = storage.getItem(POPUP_STATE_STORAGE_KEY);
|
|
1585
|
+
} catch {
|
|
1586
|
+
return emptyState();
|
|
1587
|
+
}
|
|
1588
|
+
if (!raw) return emptyState();
|
|
1589
|
+
let parsed;
|
|
1590
|
+
try {
|
|
1591
|
+
parsed = JSON.parse(raw);
|
|
1592
|
+
} catch {
|
|
1593
|
+
return emptyState();
|
|
1594
|
+
}
|
|
1595
|
+
if (typeof parsed !== "object" || parsed === null) return emptyState();
|
|
1596
|
+
const source = parsed;
|
|
1597
|
+
const state = emptyState();
|
|
1598
|
+
if (typeof source.lastShown === "object" && source.lastShown !== null) {
|
|
1599
|
+
const valid = Object.entries(source.lastShown).filter((entry) => isValidTimestamp(entry[1]));
|
|
1600
|
+
capEntries(valid, (timestamp) => timestamp).forEach(([popupId, timestamp]) => {
|
|
1601
|
+
state.lastShown[popupId] = timestamp;
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
if (typeof source.progress === "object" && source.progress !== null) {
|
|
1605
|
+
const valid = Object.entries(source.progress).filter((entry) => {
|
|
1606
|
+
const value = entry[1];
|
|
1607
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1608
|
+
const candidate = value;
|
|
1609
|
+
return POPUP_TRIGGER_CONDITION_STATUSES.includes(candidate.status) && isValidTimestamp(candidate.timestamp);
|
|
1610
|
+
});
|
|
1611
|
+
capEntries(valid, (entry) => entry.timestamp).forEach(([surveyId, entry]) => {
|
|
1612
|
+
state.progress[surveyId] = { status: entry.status, timestamp: entry.timestamp };
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1615
|
+
return state;
|
|
1616
|
+
}
|
|
1617
|
+
function writePopupState(storage, state) {
|
|
1618
|
+
const capped = emptyState();
|
|
1619
|
+
capEntries(Object.entries(state.lastShown), (timestamp) => timestamp).forEach(([popupId, timestamp]) => {
|
|
1620
|
+
capped.lastShown[popupId] = timestamp;
|
|
1621
|
+
});
|
|
1622
|
+
capEntries(Object.entries(state.progress), (entry) => entry.timestamp).forEach(([surveyId, entry]) => {
|
|
1623
|
+
capped.progress[surveyId] = entry;
|
|
1624
|
+
});
|
|
1625
|
+
try {
|
|
1626
|
+
storage.setItem(POPUP_STATE_STORAGE_KEY, JSON.stringify(capped));
|
|
1627
|
+
} catch {
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
function clearPopupState(storage) {
|
|
1631
|
+
try {
|
|
1632
|
+
storage.removeItem(POPUP_STATE_STORAGE_KEY);
|
|
1633
|
+
} catch {
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1568
1637
|
// src/analytics/messaging.ts
|
|
1569
1638
|
var MESSAGE_CHANNELS = ["push", "in_app"];
|
|
1570
1639
|
function buildMessageParams(stage, o) {
|
|
@@ -1652,6 +1721,10 @@ var DeepdotsPopups = class {
|
|
|
1652
1721
|
this.popupDefinitions = [];
|
|
1653
1722
|
this.popupsLoaded = false;
|
|
1654
1723
|
this.pendingAutoLaunch = false;
|
|
1724
|
+
// Estado que alimenta las reglas de redisplay. Copia de trabajo en memoria; la fuente
|
|
1725
|
+
// duradera es el storage (`popup-state-store`), rehidratada en `init()` — sin eso, una
|
|
1726
|
+
// recarga reiniciaba el cooldown y el popup volvía a salir. `answeredSurveys` se deriva
|
|
1727
|
+
// de las entradas COMPLETED de `surveyProgress` (los dos los escribe `markSurveyAnswered`).
|
|
1655
1728
|
this.answeredSurveys = /* @__PURE__ */ new Set();
|
|
1656
1729
|
this.surveyProgress = /* @__PURE__ */ new Map();
|
|
1657
1730
|
this.lastShown = /* @__PURE__ */ new Map();
|
|
@@ -1727,6 +1800,7 @@ var DeepdotsPopups = class {
|
|
|
1727
1800
|
};
|
|
1728
1801
|
const storage = config.storage ?? createDefaultStorage();
|
|
1729
1802
|
this.storage = storage;
|
|
1803
|
+
this.loadPopupState(storage);
|
|
1730
1804
|
this.tracking = new TrackingManager({
|
|
1731
1805
|
storage,
|
|
1732
1806
|
clientUserId: this.config.userId,
|
|
@@ -1994,6 +2068,10 @@ var DeepdotsPopups = class {
|
|
|
1994
2068
|
}) : null;
|
|
1995
2069
|
this.analytics?.resetUserScope();
|
|
1996
2070
|
this.messageGuard.reset();
|
|
2071
|
+
this.lastShown.clear();
|
|
2072
|
+
this.surveyProgress.clear();
|
|
2073
|
+
this.answeredSurveys.clear();
|
|
2074
|
+
clearPopupState(storage);
|
|
1997
2075
|
this.log("tracking \xB7 user_change \xB7 user_id:", this.tracking.getUserId());
|
|
1998
2076
|
this.openSession();
|
|
1999
2077
|
}
|
|
@@ -2165,6 +2243,7 @@ var DeepdotsPopups = class {
|
|
|
2165
2243
|
this.log("Showing popup (definition)", def);
|
|
2166
2244
|
this.surveyToPopupId.set(def.surveyId, def.id);
|
|
2167
2245
|
this.lastShown.set(def.id, Date.now());
|
|
2246
|
+
this.persistPopupState();
|
|
2168
2247
|
this.renderPopup(def.surveyId, def.productId, def.actions, def.style, def.title);
|
|
2169
2248
|
this.emitEvent("popup_shown", def.surveyId, { popupId: def.id });
|
|
2170
2249
|
}
|
|
@@ -2644,6 +2723,29 @@ var DeepdotsPopups = class {
|
|
|
2644
2723
|
return;
|
|
2645
2724
|
}
|
|
2646
2725
|
this.surveyProgress.set(surveyId, { status, timestamp: Date.now() });
|
|
2726
|
+
this.persistPopupState();
|
|
2727
|
+
}
|
|
2728
|
+
/**
|
|
2729
|
+
* Rehidrata el estado de redisplay desde el storage. `answeredSurveys` se reconstruye
|
|
2730
|
+
* desde las entradas COMPLETED: es exactamente lo que persiste `markSurveyAnswered`.
|
|
2731
|
+
*/
|
|
2732
|
+
loadPopupState(storage) {
|
|
2733
|
+
const state = readPopupState(storage);
|
|
2734
|
+
Object.entries(state.lastShown).forEach(([popupId, timestamp]) => {
|
|
2735
|
+
this.lastShown.set(popupId, timestamp);
|
|
2736
|
+
});
|
|
2737
|
+
Object.entries(state.progress).forEach(([surveyId, entry]) => {
|
|
2738
|
+
this.surveyProgress.set(surveyId, { status: entry.status, timestamp: entry.timestamp });
|
|
2739
|
+
if (entry.status === "COMPLETED") this.answeredSurveys.add(surveyId);
|
|
2740
|
+
});
|
|
2741
|
+
}
|
|
2742
|
+
/** Vuelca el estado de redisplay al storage. Sin storage (o bloqueado) degrada a memoria. */
|
|
2743
|
+
persistPopupState() {
|
|
2744
|
+
if (!this.storage) return;
|
|
2745
|
+
writePopupState(this.storage, {
|
|
2746
|
+
lastShown: Object.fromEntries(this.lastShown),
|
|
2747
|
+
progress: Object.fromEntries(this.surveyProgress)
|
|
2748
|
+
});
|
|
2647
2749
|
}
|
|
2648
2750
|
isPopupDefinition(value) {
|
|
2649
2751
|
if (typeof value !== "object" || value === null) return false;
|