nodebb-plugin-ezoic-infinite 1.5.98 → 1.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.5.98",
3
+ "version": "1.6.0",
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
@@ -1344,70 +1344,114 @@ function buildOrdinalMap(items) {
1344
1344
 
1345
1345
 
1346
1346
 
1347
-
1348
-
1349
-
1350
- // ===== V7.1 soft up-scroll purge for ezoic-ad-between =====
1347
+ // ===== CLEAN REFRACTOR: visibility manager for Ezoic wraps =====
1351
1348
  (function () {
1352
- var lastY = window.pageYOffset || document.documentElement.scrollTop || 0;
1353
- var ticking = false;
1354
- var lastPurgeTs = 0;
1355
- var PURGE_COOLDOWN_MS = 350;
1356
-
1357
- function softPurgeBetweenWraps() {
1358
- var now = Date.now();
1359
- if (now - lastPurgeTs < PURGE_COOLDOWN_MS) return;
1360
- lastPurgeTs = now;
1349
+ var WRAP_SELECTOR = '.nodebb-ezoic-wrap.ezoic-ad-between, .nodebb-ezoic-wrap.ezoic-ad-message';
1350
+ var KEEP_MARGIN_PX_DESKTOP = 1600;
1351
+ var KEEP_MARGIN_PX_MOBILE = 1100;
1352
+ var MAX_REMOVALS_PER_SWEEP = 6;
1361
1353
 
1362
- var viewportTop = window.pageYOffset || document.documentElement.scrollTop || 0;
1363
- var keepBuffer = 240; // garde les pubs proches du viewport pour éviter le "clignotement"
1354
+ function isMobile() {
1355
+ try { return window.matchMedia && window.matchMedia('(max-width: 767px)').matches; } catch (e) { return false; }
1356
+ }
1357
+ function keepMargin() { return isMobile() ? KEEP_MARGIN_PX_MOBILE : KEEP_MARGIN_PX_DESKTOP; }
1358
+
1359
+ function removeFarWraps() {
1360
+ var margin = keepMargin();
1361
+ var removed = 0;
1362
+ var wraps;
1363
+ try { wraps = document.querySelectorAll(WRAP_SELECTOR); } catch (e) { return; }
1364
+ wraps.forEach(function (w) {
1365
+ if (removed >= MAX_REMOVALS_PER_SWEEP) return;
1366
+ try {
1367
+ var lv = parseInt(w.getAttribute('data-last-visible') || '0', 10);
1368
+ if (lv && (Date.now() - lv) < 8000) return;
1364
1369
 
1365
- try {
1366
- document.querySelectorAll('.nodebb-ezoic-wrap.ezoic-ad-between').forEach(function (w) {
1367
- try {
1368
- var r = w.getBoundingClientRect();
1369
- var absBottom = viewportTop + r.bottom;
1370
- // SOFT: supprimer uniquement les wraps largement au-dessus du viewport
1371
- if (absBottom < (viewportTop - keepBuffer)) {
1372
- w.remove();
1373
- }
1374
- } catch (e) {}
1375
- });
1376
- } catch (e) {}
1370
+ var r = w.getBoundingClientRect();
1371
+ if (r.bottom < -margin || r.top > ((window.innerHeight || 0) + margin)) {
1372
+ w.remove();
1373
+ removed += 1;
1374
+ }
1375
+ } catch (e) {}
1376
+ });
1377
1377
  }
1378
1378
 
1379
- function onScroll() {
1380
- if (ticking) return;
1381
- ticking = true;
1382
- requestAnimationFrame(function () {
1383
- var y = window.pageYOffset || document.documentElement.scrollTop || 0;
1384
- var dy = y - lastY;
1379
+ var io = null;
1380
+ function installIO() {
1381
+ if (io || typeof IntersectionObserver === 'undefined') return;
1382
+ io = new IntersectionObserver(function (entries) {
1383
+ try {
1384
+ entries.forEach(function (e) {
1385
+ if (e && e.target && e.isIntersecting) {
1386
+ try { e.target.setAttribute('data-last-visible', String(Date.now())); } catch (err) {}
1387
+ }
1388
+ });
1389
+ } catch (e) {}
1390
+ }, { root: null, rootMargin: '0px', threshold: 0.01 });
1385
1391
 
1386
- // uniquement quand on remonte franchement
1387
- if (dy < -12) {
1388
- softPurgeBetweenWraps();
1389
- }
1392
+ try { document.querySelectorAll(WRAP_SELECTOR).forEach(function (w) { try { io.observe(w); } catch(e) {} }); } catch (e) {}
1393
+ }
1390
1394
 
1391
- lastY = y;
1392
- ticking = false;
1395
+ var moInstalled = false;
1396
+ function installMO() {
1397
+ if (moInstalled || typeof MutationObserver === 'undefined') return;
1398
+ moInstalled = true;
1399
+ var mo = new MutationObserver(function (muts) {
1400
+ if (!io) return;
1401
+ try {
1402
+ for (var i = 0; i < muts.length; i++) {
1403
+ var m = muts[i];
1404
+ if (!m.addedNodes) continue;
1405
+ for (var j = 0; j < m.addedNodes.length; j++) {
1406
+ var n = m.addedNodes[j];
1407
+ if (!n || n.nodeType !== 1) continue;
1408
+ if (n.matches && n.matches(WRAP_SELECTOR)) {
1409
+ try { io.observe(n); } catch (e) {}
1410
+ } else if (n.querySelectorAll) {
1411
+ var inner = n.querySelectorAll(WRAP_SELECTOR);
1412
+ for (var k = 0; k < inner.length; k++) {
1413
+ try { io.observe(inner[k]); } catch (e) {}
1414
+ }
1415
+ }
1416
+ }
1417
+ }
1418
+ } catch (e) {}
1393
1419
  });
1420
+ try { mo.observe(document.documentElement || document.body, { childList: true, subtree: true }); } catch (e) {}
1394
1421
  }
1395
1422
 
1396
- window.addEventListener('scroll', onScroll, { passive: true });
1423
+ var sweepPending = false;
1424
+ var lastSweep = 0;
1425
+ var SWEEP_COOLDOWN_MS = 250;
1397
1426
 
1398
- // nettoyage doux après chargement infini / navigation ajax
1399
- function postLoadSoftPurge() {
1400
- setTimeout(softPurgeBetweenWraps, 0);
1401
- setTimeout(softPurgeBetweenWraps, 220);
1402
- setTimeout(softPurgeBetweenWraps, 600);
1427
+ function scheduleSweep() {
1428
+ var now = Date.now();
1429
+ if (now - lastSweep < SWEEP_COOLDOWN_MS) return;
1430
+ if (sweepPending) return;
1431
+ sweepPending = true;
1432
+ requestAnimationFrame(function () {
1433
+ sweepPending = false;
1434
+ lastSweep = Date.now();
1435
+ removeFarWraps();
1436
+ });
1403
1437
  }
1404
1438
 
1405
- if (window.jQuery) {
1406
- window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', postLoadSoftPurge);
1439
+ function init() {
1440
+ installIO();
1441
+ installMO();
1442
+ window.addEventListener('scroll', scheduleSweep, { passive: true });
1443
+ window.addEventListener('resize', scheduleSweep, { passive: true });
1444
+
1445
+ if (window.jQuery) {
1446
+ window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function () {
1447
+ setTimeout(function () { installIO(); scheduleSweep(); }, 0);
1448
+ });
1449
+ }
1450
+ setTimeout(function () { installIO(); scheduleSweep(); }, 0);
1407
1451
  }
1408
1452
 
1409
- // premier passage
1410
- setTimeout(softPurgeBetweenWraps, 0);
1453
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
1454
+ else init();
1411
1455
  })();
1412
- // ===== /V7.1 =====
1456
+ // ===== /CLEAN REFRACTOR =====
1413
1457
 
package/public/style.css CHANGED
@@ -79,3 +79,9 @@
79
79
  position: static !important;
80
80
  top: auto !important;
81
81
  }
82
+
83
+
84
+ /* ===== CLEAN REFRACTOR perf notes ===== */
85
+ .nodebb-ezoic-wrap { contain: content; }
86
+ /* ===== /CLEAN REFRACTOR ===== */
87
+