nodebb-plugin-ezoic-infinite 1.7.46 → 1.7.47

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/client.js +14 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.7.46",
3
+ "version": "1.7.47",
4
4
  "description": "Production-ready Ezoic infinite ads integration for NodeBB 4.x",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -39,7 +39,6 @@
39
39
  const A_SHOWN = 'data-ezoic-shown'; // timestamp dernier showAds ms
40
40
 
41
41
  const EMPTY_CHECK_MS = 20_000; // délai avant collapse d'un wrap vide post-show
42
- const MIN_PRUNE_AGE_MS = 8_000; // délai de grâce avant pruning (stabilisation DOM)
43
42
  const MAX_INSERTS_RUN = 6; // max insertions par appel runCore
44
43
  const MAX_INFLIGHT = 4; // max showAds() simultanés
45
44
  const SHOW_THROTTLE_MS = 900; // anti-spam showAds() par id
@@ -88,6 +87,7 @@
88
87
  pending: [], // ids en attente de slot inflight
89
88
  pendingSet: new Set(),
90
89
  wrapByKey: new Map(), // anchorKey → wrap DOM node
90
+ recycling: new Set(), // ids en cours de séquence destroy→define→displayMore
91
91
  tcfObs: null, // MutationObserver TCF locator
92
92
  runQueued: false,
93
93
  burstActive: false,
@@ -112,7 +112,7 @@
112
112
  // ── Config ─────────────────────────────────────────────────────────────────
113
113
 
114
114
  // Fix #2 : backoff 10s sur échec pour éviter de spammer l'API
115
- // si le réseau est lent ou la route indisponible.
115
+ // Fix #3 : _cfgErrorUntil au scope IIFE pour être réinitialisé dans cleanup()
116
116
  let _cfgErrorUntil = 0;
117
117
  async function fetchConfig() {
118
118
  if (S.cfg) return S.cfg;
@@ -258,6 +258,9 @@
258
258
  function pickId(poolKey) {
259
259
  const pool = S.pools[poolKey];
260
260
  if (!pool.length) return null;
261
+ // Fix #2 : early-exit si tous les ids sont déjà montés — évite O(n) inutile
262
+ if (S.mountedIds.size >= pool.length &&
263
+ pool.every(id => S.mountedIds.has(id))) return null;
261
264
  for (let t = 0; t < pool.length; t++) {
262
265
  const i = S.cursors[poolKey] % pool.length;
263
266
  S.cursors[poolKey] = (S.cursors[poolKey] + 1) % pool.length;
@@ -303,6 +306,9 @@
303
306
  if (!best) return null;
304
307
  const id = parseInt(best.getAttribute(A_WRAPID), 10);
305
308
  if (!Number.isFinite(id)) return null;
309
+ // Fix #1 : éviter de recycler un slot dont la séquence Ezoic est en cours
310
+ if (S.recycling.has(id)) return null;
311
+ S.recycling.add(id);
306
312
 
307
313
  const oldKey = best.getAttribute(A_ANCHOR);
308
314
  // Neutraliser l'IO sur ce wrap avant déplacement — évite un showAds
@@ -327,6 +333,7 @@
327
333
  // si la pub ne charge pas (détection wrap vide).
328
334
  const doDisplay = () => {
329
335
  try { ez.displayMore([id]); } catch (_) {}
336
+ S.recycling.delete(id); // Fix #1 : séquence terminée
330
337
  observePh(id);
331
338
  const t = ts();
332
339
  try { best.setAttribute(A_SHOWN, String(t)); } catch (_) {}
@@ -641,6 +648,7 @@
641
648
  blockedUntil = ts() + 1500;
642
649
  mutate(() => document.querySelectorAll(`.${WRAP_CLASS}`).forEach(dropWrap));
643
650
  S.cfg = null;
651
+ _cfgErrorUntil = 0; // Fix #3 : réinitialiser le backoff entre les pages
644
652
  S.poolsReady = false;
645
653
  S.pools = { topics: [], posts: [], categories: [] };
646
654
  S.cursors = { topics: 0, posts: 0, categories: 0 };
@@ -652,6 +660,7 @@
652
660
  S.pendingSet.clear();
653
661
  S.burstActive = false;
654
662
  S.runQueued = false;
663
+ S.recycling.clear();
655
664
  if (S.domObs) { S.domObs.disconnect(); S.domObs = null; }
656
665
  if (S.tcfObs) { S.tcfObs.disconnect(); S.tcfObs = null; }
657
666
  }
@@ -751,7 +760,9 @@
751
760
  $(window).on('action:ajaxify.end.nbbEzoic', () => {
752
761
  S.pageKey = pageKey();
753
762
  blockedUntil = 0;
754
- muteConsole(); ensureTcfLocator(); warmNetwork();
763
+ // Fix #4 : muteConsole/ensureTcfLocator/warmNetwork déjà appelés au boot
764
+ // et sont idempotents — pas besoin de les rappeler à chaque navigation.
765
+ muteConsole();
755
766
  patchShowAds(); getIO(); ensureDomObserver(); requestBurst();
756
767
  });
757
768