nodebb-plugin-ezoic-infinite 1.7.33 → 1.7.34

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 +62 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.7.33",
3
+ "version": "1.7.34",
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
@@ -32,13 +32,9 @@
32
32
  *
33
33
  * v34 moveDistantWrap — voir v38.
34
34
  *
35
- * v39 Recyclage réel des slots via l'API Ezoic complète :
36
- * destroyPlaceholders([id])déplacement DOM → define([id]) → displayMore([id]).
37
- * destroyPlaceholders() efface le slot de la registry Ezoic, define() le
38
- * réenregistre comme neuf, displayMore() est l'API infinite-scroll d'Ezoic
39
- * (contrairement à showAds() qui est pour le chargement initial).
40
- * Priorité de recyclage : wraps vides en premier (pas de pub visible perdue),
41
- * puis wraps remplis si nécessaire. Seuil : 4 viewports au-dessus.
35
+ * v40 Recyclage slots via destroyPlaceholders+define+displayMore avec délais.
36
+ * Séquence : destroy 300ms → define → 300ms → displayMore.
37
+ * Testé manuellement : fonctionne. displayMore = API Ezoic infinite scroll.
42
38
  *
43
39
  * v38 Pool épuisé = fin de quota Ezoic par page-view. ez.refresh() interdit
44
40
  * sur la même page que ez.enable() — supprimé. moveDistantWrap supprimé :
@@ -294,6 +290,64 @@
294
290
  return null;
295
291
  }
296
292
 
293
+ /**
294
+ * Pool épuisé : recycle un wrap loin au-dessus du viewport.
295
+ * Séquence avec délais (destroyPlaceholders est asynchrone) :
296
+ * destroy([id]) → 300ms → define([id]) → 300ms → displayMore([id])
297
+ * displayMore = API Ezoic prévue pour l'infinite scroll.
298
+ * Priorité : wraps vides d'abord, remplis si nécessaire.
299
+ */
300
+ function recycleAndMove(klass, targetEl, newKey) {
301
+ const ez = window.ezstandalone;
302
+ if (typeof ez?.destroyPlaceholders !== 'function' ||
303
+ typeof ez?.define !== 'function' ||
304
+ typeof ez?.displayMore !== 'function') return null;
305
+
306
+ const vh = window.innerHeight || 800;
307
+ const threshold = -vh * 4;
308
+ let bestEmpty = null, bestEmptyBottom = Infinity;
309
+ let bestFilled = null, bestFilledBottom = Infinity;
310
+
311
+ document.querySelectorAll(`.${WRAP_CLASS}.${klass}`).forEach(wrap => {
312
+ try {
313
+ const rect = wrap.getBoundingClientRect();
314
+ if (rect.bottom > threshold) return;
315
+ if (!isFilled(wrap)) {
316
+ if (rect.bottom < bestEmptyBottom) { bestEmptyBottom = rect.bottom; bestEmpty = wrap; }
317
+ } else {
318
+ if (rect.bottom < bestFilledBottom) { bestFilledBottom = rect.bottom; bestFilled = wrap; }
319
+ }
320
+ } catch (_) {}
321
+ });
322
+
323
+ const best = bestEmpty ?? bestFilled;
324
+ if (!best) return null;
325
+ const id = parseInt(best.getAttribute(A_WRAPID), 10);
326
+ if (!Number.isFinite(id)) return null;
327
+
328
+ const oldKey = best.getAttribute(A_ANCHOR);
329
+ mutate(() => {
330
+ best.setAttribute(A_ANCHOR, newKey);
331
+ best.setAttribute(A_CREATED, String(ts()));
332
+ best.setAttribute(A_SHOWN, '0');
333
+ best.classList.remove('is-empty');
334
+ const ph = best.querySelector(`#${PH_PREFIX}${id}`);
335
+ if (ph) ph.innerHTML = '';
336
+ targetEl.insertAdjacentElement('afterend', best);
337
+ });
338
+ if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
339
+ S.wrapByKey.set(newKey, best);
340
+
341
+ // Délais requis : destroyPlaceholders est asynchrone en interne
342
+ const doDestroy = () => { try { ez.destroyPlaceholders([id]); } catch (_) {} setTimeout(doDefine, 300); };
343
+ const doDefine = () => { try { ez.define([id]); } catch (_) {} setTimeout(doDisplay, 300); };
344
+ const doDisplay = () => { try { ez.displayMore([id]); } catch (_) {} };
345
+ try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
346
+
347
+ return { id, wrap: best };
348
+ }
349
+
350
+ // ── Wraps DOM — création / suppression ────────────────────────────────────
297
351
 
298
352
  function makeWrap(id, klass, key) {
299
353
  const w = document.createElement('div');
@@ -407,9 +461,8 @@
407
461
  const w = insertAfter(el, id, klass, key);
408
462
  if (w) { observePh(id); inserted++; }
409
463
  } else {
410
- // Pool épuisé : recycler un wrap distant via destroyPlaceholders+define+displayMore
411
464
  const recycled = recycleAndMove(klass, el, key);
412
- if (!recycled) break; // Aucun wrap recyclable → arrêt
465
+ if (!recycled) break;
413
466
  inserted++;
414
467
  }
415
468
  }