nodebb-plugin-ezoic-infinite 1.4.2 → 1.4.3

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 +64 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
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
@@ -35,6 +35,8 @@
35
35
 
36
36
  lastShowById: new Map(),
37
37
  pendingById: new Set(),
38
+ retryById: new Map(),
39
+ retryTimer: null,
38
40
 
39
41
  scheduled: false,
40
42
  timer: null,
@@ -234,6 +236,50 @@
234
236
  } catch (e) {}
235
237
  }
236
238
 
239
+
240
+ function isPlaceholderFilled(id) {
241
+ const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
242
+ if (!ph || !ph.isConnected) return false;
243
+ if (ph.childNodes && ph.childNodes.length > 0) return true;
244
+ const wrap = ph.parentElement;
245
+ if (wrap && wrap.querySelector && wrap.querySelector('iframe, ins, [id^="ezslot_"], [class*="ez"]')) return true;
246
+ return false;
247
+ }
248
+
249
+ function scheduleRefill(delay = 350) {
250
+ clearTimeout(state.retryTimer);
251
+ state.retryTimer = setTimeout(refillUnfilled, delay);
252
+ }
253
+
254
+ function refillUnfilled() {
255
+ const wraps = Array.from(document.querySelectorAll(`.${WRAP_CLASS}`));
256
+ let scheduledAny = false;
257
+
258
+ for (const wrap of wraps) {
259
+ const ph = wrap.querySelector && wrap.querySelector(`[id^="${PLACEHOLDER_PREFIX}"]`);
260
+ if (!ph) continue;
261
+ const id = parseInt(ph.id.replace(PLACEHOLDER_PREFIX, ''), 10);
262
+ if (!Number.isFinite(id) || id <= 0) continue;
263
+
264
+ if (isPlaceholderFilled(id)) {
265
+ state.retryById.delete(id);
266
+ continue;
267
+ }
268
+
269
+ const tries = (state.retryById.get(id) || 0);
270
+ if (tries >= 8) continue;
271
+
272
+ const r = safeRect(wrap);
273
+ if (r && (r.top > window.innerHeight + 1200 || r.bottom < -1200)) continue;
274
+
275
+ state.retryById.set(id, tries + 1);
276
+ callShowAdsWhenReady(id);
277
+ scheduledAny = true;
278
+ }
279
+
280
+ if (scheduledAny) scheduleRefill(700);
281
+ }
282
+
237
283
  function callShowAdsWhenReady(id) {
238
284
  if (!id) return;
239
285
 
@@ -465,6 +511,7 @@
465
511
  }
466
512
 
467
513
  enforceNoAdjacentAds();
514
+ scheduleRefill(250);
468
515
 
469
516
  // If nothing inserted and list isn't in DOM yet (first click), retry a bit
470
517
  let count = 0;
@@ -540,4 +587,20 @@
540
587
  state.pageKey = getPageKey();
541
588
  scheduleRun();
542
589
  setTimeout(scheduleRun, 250);
543
- })();
590
+ })()
591
+ function bindScroll() {
592
+ if (state.__scrollBound) return;
593
+ state.__scrollBound = true;
594
+ let ticking = false;
595
+ window.addEventListener('scroll', () => {
596
+ if (ticking) return;
597
+ ticking = true;
598
+ window.requestAnimationFrame(() => {
599
+ ticking = false;
600
+ enforceNoAdjacentAds();
601
+ scheduleRefill(200);
602
+ });
603
+ }, { passive: true });
604
+ }
605
+
606
+ ;