nodebb-plugin-ezoic-infinite 1.7.88 → 1.7.90

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 +44 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.7.88",
3
+ "version": "1.7.90",
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
@@ -132,6 +132,8 @@
132
132
  burstDeadline: 0,
133
133
  burstCount: 0,
134
134
  lastBurstTs: 0,
135
+ lastScrollY: 0,
136
+ scrollDir: 1, // 1=down, -1=up
135
137
  };
136
138
 
137
139
  let blockedUntil = 0;
@@ -313,26 +315,49 @@
313
315
  typeof ez?.define !== 'function' ||
314
316
  typeof ez?.displayMore !== 'function') return null;
315
317
 
316
- const vh = window.innerHeight || 800;
317
- // Seuil : -1vh (hors viewport visible). On appelle unobserve(ph) juste
318
- // après pour neutraliser l'IO — plus de showAds parasite possible.
319
- const threshold = -vh;
320
- let bestEmpty = null, bestEmptyBottom = Infinity;
321
- let bestFilled = null, bestFilledBottom = Infinity;
318
+ const vh = window.innerHeight || 800;
319
+ const targetRect = targetEl?.getBoundingClientRect?.() || { top: vh, bottom: vh };
320
+
321
+ // Recyclage bidirectionnel :
322
+ // - scroll vers le bas -> recycle préférentiellement des wraps loin au-dessus
323
+ // - scroll vers le haut -> recycle préférentiellement des wraps loin en-dessous
324
+ // Fallback sur l'autre côté si aucun candidat.
325
+ const aboveThreshold = -vh; // wrap entièrement/suffisamment au-dessus
326
+ const belowThreshold = vh * 2; // wrap loin sous le viewport
327
+
328
+ let aboveEmpty = null, aboveEmptyBottom = Infinity;
329
+ let aboveFilled = null, aboveFilledBottom = Infinity;
330
+ let belowEmpty = null, belowEmptyTop = -Infinity;
331
+ let belowFilled = null, belowFilledTop = -Infinity;
322
332
 
323
333
  document.querySelectorAll(`.${WRAP_CLASS}.${klass}`).forEach(wrap => {
324
334
  try {
335
+ if (!wrap?.isConnected) return;
325
336
  const rect = wrap.getBoundingClientRect();
326
- if (rect.bottom > threshold) return;
327
- if (!isFilled(wrap)) {
328
- if (rect.bottom < bestEmptyBottom) { bestEmptyBottom = rect.bottom; bestEmpty = wrap; }
329
- } else {
330
- if (rect.bottom < bestFilledBottom) { bestFilledBottom = rect.bottom; bestFilled = wrap; }
337
+
338
+ if (rect.bottom < aboveThreshold) {
339
+ if (!isFilled(wrap)) {
340
+ if (rect.bottom < aboveEmptyBottom) { aboveEmptyBottom = rect.bottom; aboveEmpty = wrap; }
341
+ } else {
342
+ if (rect.bottom < aboveFilledBottom) { aboveFilledBottom = rect.bottom; aboveFilled = wrap; }
343
+ }
344
+ return;
345
+ }
346
+
347
+ if (rect.top > belowThreshold) {
348
+ if (!isFilled(wrap)) {
349
+ if (rect.top > belowEmptyTop) { belowEmptyTop = rect.top; belowEmpty = wrap; }
350
+ } else {
351
+ if (rect.top > belowFilledTop) { belowFilledTop = rect.top; belowFilled = wrap; }
352
+ }
331
353
  }
332
354
  } catch (_) {}
333
355
  });
334
356
 
335
- const best = bestEmpty ?? bestFilled;
357
+ const preferBelow = (S.scrollDir < 0) || (targetRect.top < vh * 0.5);
358
+ const pickAbove = () => aboveEmpty ?? aboveFilled;
359
+ const pickBelow = () => belowEmpty ?? belowFilled;
360
+ const best = preferBelow ? (pickBelow() ?? pickAbove()) : (pickAbove() ?? pickBelow());
336
361
  if (!best) return null;
337
362
  const id = parseInt(best.getAttribute(A_WRAPID), 10);
338
363
  if (!Number.isFinite(id)) return null;
@@ -822,6 +847,12 @@
822
847
  function bindScroll() {
823
848
  let ticking = false;
824
849
  window.addEventListener('scroll', () => {
850
+ try {
851
+ const y = window.scrollY || window.pageYOffset || 0;
852
+ const dy = y - (S.lastScrollY || 0);
853
+ if (Math.abs(dy) > 2) S.scrollDir = dy > 0 ? 1 : -1;
854
+ S.lastScrollY = y;
855
+ } catch (_) {}
825
856
  if (ticking) return;
826
857
  ticking = true;
827
858
  requestAnimationFrame(() => { ticking = false; requestBurst(); });
@@ -831,6 +862,7 @@
831
862
  // ── Boot ───────────────────────────────────────────────────────────────────
832
863
 
833
864
  S.pageKey = pageKey();
865
+ try { S.lastScrollY = window.scrollY || window.pageYOffset || 0; } catch (_) { S.lastScrollY = 0; }
834
866
  muteConsole();
835
867
  ensureTcfLocator();
836
868
  warmNetwork();