nodebb-plugin-ezoic-infinite 1.7.90 → 1.7.91
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 +1 -1
- package/public/client.js +74 -20
- package/public/style.css +0 -14
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -77,7 +77,6 @@
|
|
|
77
77
|
const A_CREATED = 'data-ezoic-created'; // timestamp création ms
|
|
78
78
|
const A_SHOWN = 'data-ezoic-shown'; // timestamp dernier showAds ms
|
|
79
79
|
|
|
80
|
-
const EMPTY_CHECK_MS = 20_000; // délai avant collapse d'un wrap vide post-show
|
|
81
80
|
const MIN_PRUNE_AGE_MS = 8_000; // délai de grâce avant pruning (stabilisation DOM)
|
|
82
81
|
const MAX_INSERTS_RUN = 6; // max insertions par appel runCore
|
|
83
82
|
const MAX_INFLIGHT = 4; // max showAds() simultanés
|
|
@@ -127,6 +126,7 @@
|
|
|
127
126
|
pending: [], // ids en attente de slot inflight
|
|
128
127
|
pendingSet: new Set(),
|
|
129
128
|
wrapByKey: new Map(), // anchorKey → wrap DOM node
|
|
129
|
+
fillObsById: new Map(), // id -> MutationObserver
|
|
130
130
|
runQueued: false,
|
|
131
131
|
burstActive: false,
|
|
132
132
|
burstDeadline: 0,
|
|
@@ -144,6 +144,33 @@
|
|
|
144
144
|
const normBool = v => v === true || v === 'true' || v === 1 || v === '1' || v === 'on';
|
|
145
145
|
const isFilled = n => !!(n?.querySelector?.('iframe, ins, img, video, [data-google-container-id]'));
|
|
146
146
|
|
|
147
|
+
|
|
148
|
+
function unwatchPlaceholderFillById(id) {
|
|
149
|
+
const obs = S.fillObsById.get(id);
|
|
150
|
+
if (obs) { try { obs.disconnect(); } catch (_) {} S.fillObsById.delete(id); }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function uncollapseIfFilled(ph) {
|
|
154
|
+
try {
|
|
155
|
+
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
156
|
+
if (!wrap) return false;
|
|
157
|
+
if (!isFilled(ph)) return false;
|
|
158
|
+
wrap.classList.remove('is-empty');
|
|
159
|
+
return true;
|
|
160
|
+
} catch (_) { return false; }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function watchPlaceholderFill(id) {
|
|
164
|
+
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
165
|
+
if (!ph?.isConnected || S.fillObsById.has(id)) return;
|
|
166
|
+
try {
|
|
167
|
+
const obs = new MutationObserver(() => { try { uncollapseIfFilled(ph); } catch (_) {} });
|
|
168
|
+
obs.observe(ph, { childList: true, subtree: true, attributes: true });
|
|
169
|
+
S.fillObsById.set(id, obs);
|
|
170
|
+
uncollapseIfFilled(ph);
|
|
171
|
+
} catch (_) {}
|
|
172
|
+
}
|
|
173
|
+
|
|
147
174
|
function mutate(fn) {
|
|
148
175
|
S.mutGuard++;
|
|
149
176
|
try { fn(); } finally { S.mutGuard--; }
|
|
@@ -284,6 +311,26 @@
|
|
|
284
311
|
return (w?.isConnected) ? w : null;
|
|
285
312
|
}
|
|
286
313
|
|
|
314
|
+
function sweepDeadWraps() {
|
|
315
|
+
let freed = 0;
|
|
316
|
+
for (const [key, wrap] of Array.from(S.wrapByKey.entries())) {
|
|
317
|
+
if (wrap?.isConnected) continue;
|
|
318
|
+
const id = parseInt(wrap?.getAttribute?.(A_WRAPID) || '0', 10);
|
|
319
|
+
if (Number.isFinite(id) && id > 0) {
|
|
320
|
+
S.mountedIds.delete(id);
|
|
321
|
+
unwatchPlaceholderFillById(id);
|
|
322
|
+
S.lastShow.delete(id);
|
|
323
|
+
S.pendingSet.delete(id);
|
|
324
|
+
}
|
|
325
|
+
S.wrapByKey.delete(key);
|
|
326
|
+
freed++;
|
|
327
|
+
}
|
|
328
|
+
if (freed && S.pending.length) {
|
|
329
|
+
S.pending = S.pending.filter(id => !S.mountedIds.has(id));
|
|
330
|
+
}
|
|
331
|
+
return freed;
|
|
332
|
+
}
|
|
333
|
+
|
|
287
334
|
// ── Pool ───────────────────────────────────────────────────────────────────
|
|
288
335
|
|
|
289
336
|
/**
|
|
@@ -330,9 +377,10 @@
|
|
|
330
377
|
let belowEmpty = null, belowEmptyTop = -Infinity;
|
|
331
378
|
let belowFilled = null, belowFilledTop = -Infinity;
|
|
332
379
|
|
|
333
|
-
|
|
380
|
+
for (const wrap of S.wrapByKey.values()) {
|
|
381
|
+
if (!wrap?.classList?.contains?.(klass)) continue;
|
|
334
382
|
try {
|
|
335
|
-
if (!wrap?.isConnected)
|
|
383
|
+
if (!wrap?.isConnected) continue;
|
|
336
384
|
const rect = wrap.getBoundingClientRect();
|
|
337
385
|
|
|
338
386
|
if (rect.bottom < aboveThreshold) {
|
|
@@ -341,7 +389,7 @@
|
|
|
341
389
|
} else {
|
|
342
390
|
if (rect.bottom < aboveFilledBottom) { aboveFilledBottom = rect.bottom; aboveFilled = wrap; }
|
|
343
391
|
}
|
|
344
|
-
|
|
392
|
+
continue;
|
|
345
393
|
}
|
|
346
394
|
|
|
347
395
|
if (rect.top > belowThreshold) {
|
|
@@ -352,7 +400,7 @@
|
|
|
352
400
|
}
|
|
353
401
|
}
|
|
354
402
|
} catch (_) {}
|
|
355
|
-
}
|
|
403
|
+
}
|
|
356
404
|
|
|
357
405
|
const preferBelow = (S.scrollDir < 0) || (targetRect.top < vh * 0.5);
|
|
358
406
|
const pickAbove = () => aboveEmpty ?? aboveFilled;
|
|
@@ -413,6 +461,7 @@
|
|
|
413
461
|
mutate(() => el.insertAdjacentElement('afterend', w));
|
|
414
462
|
S.mountedIds.add(id);
|
|
415
463
|
S.wrapByKey.set(key, w);
|
|
464
|
+
watchPlaceholderFill(id);
|
|
416
465
|
return w;
|
|
417
466
|
}
|
|
418
467
|
|
|
@@ -421,7 +470,7 @@
|
|
|
421
470
|
const ph = w.querySelector(`[id^="${PH_PREFIX}"]`);
|
|
422
471
|
if (ph instanceof Element) S.io?.unobserve(ph);
|
|
423
472
|
const id = parseInt(w.getAttribute(A_WRAPID), 10);
|
|
424
|
-
if (Number.isFinite(id)) S.mountedIds.delete(id);
|
|
473
|
+
if (Number.isFinite(id)) { S.mountedIds.delete(id); unwatchPlaceholderFillById(id); S.lastShow.delete(id); S.pendingSet.delete(id); }
|
|
425
474
|
const key = w.getAttribute(A_ANCHOR);
|
|
426
475
|
if (key && S.wrapByKey.get(key) === w) S.wrapByKey.delete(key);
|
|
427
476
|
w.remove();
|
|
@@ -496,7 +545,8 @@
|
|
|
496
545
|
const key = anchorKey(klass, el);
|
|
497
546
|
if (findWrap(key)) continue;
|
|
498
547
|
|
|
499
|
-
|
|
548
|
+
let id = pickId(poolKey);
|
|
549
|
+
if (!id) { sweepDeadWraps(); id = pickId(poolKey); }
|
|
500
550
|
if (id) {
|
|
501
551
|
const w = insertAfter(el, id, klass, key);
|
|
502
552
|
if (w) { observePh(id); inserted++; }
|
|
@@ -528,7 +578,9 @@
|
|
|
528
578
|
|
|
529
579
|
function observePh(id) {
|
|
530
580
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
531
|
-
if (ph?.isConnected)
|
|
581
|
+
if (!ph?.isConnected) return;
|
|
582
|
+
watchPlaceholderFill(id);
|
|
583
|
+
try { getIO()?.observe(ph); } catch (_) {}
|
|
532
584
|
}
|
|
533
585
|
|
|
534
586
|
function enqueueShow(id) {
|
|
@@ -568,6 +620,8 @@
|
|
|
568
620
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
569
621
|
if (!ph?.isConnected || isFilled(ph)) { clearTimeout(timer); return release(); }
|
|
570
622
|
|
|
623
|
+
try { ph.closest?.(`.${WRAP_CLASS}`)?.classList.remove('is-empty'); } catch (_) {}
|
|
624
|
+
|
|
571
625
|
const t = ts();
|
|
572
626
|
if (t - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) { clearTimeout(timer); return release(); }
|
|
573
627
|
S.lastShow.set(id, t);
|
|
@@ -578,7 +632,6 @@
|
|
|
578
632
|
const ez = window.ezstandalone;
|
|
579
633
|
const doShow = () => {
|
|
580
634
|
try { ez.showAds(id); } catch (_) {}
|
|
581
|
-
scheduleEmptyCheck(id, t);
|
|
582
635
|
setTimeout(() => { clearTimeout(timer); release(); }, 700);
|
|
583
636
|
};
|
|
584
637
|
Array.isArray(ez.cmd) ? ez.cmd.push(doShow) : doShow();
|
|
@@ -586,17 +639,6 @@
|
|
|
586
639
|
});
|
|
587
640
|
}
|
|
588
641
|
|
|
589
|
-
function scheduleEmptyCheck(id, showTs) {
|
|
590
|
-
setTimeout(() => {
|
|
591
|
-
try {
|
|
592
|
-
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
593
|
-
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
594
|
-
if (!wrap || !ph?.isConnected) return;
|
|
595
|
-
if (parseInt(wrap.getAttribute(A_SHOWN) || '0', 10) > showTs) return;
|
|
596
|
-
wrap.classList.toggle('is-empty', !isFilled(ph));
|
|
597
|
-
} catch (_) {}
|
|
598
|
-
}, EMPTY_CHECK_MS);
|
|
599
|
-
}
|
|
600
642
|
|
|
601
643
|
// ── Patch Ezoic showAds ────────────────────────────────────────────────────
|
|
602
644
|
//
|
|
@@ -638,6 +680,7 @@
|
|
|
638
680
|
async function runCore() {
|
|
639
681
|
if (isBlocked()) return 0;
|
|
640
682
|
patchShowAds();
|
|
683
|
+
sweepDeadWraps();
|
|
641
684
|
|
|
642
685
|
const cfg = await fetchConfig();
|
|
643
686
|
if (!cfg || cfg.excluded) return 0;
|
|
@@ -722,6 +765,8 @@
|
|
|
722
765
|
S.mountedIds.clear();
|
|
723
766
|
S.lastShow.clear();
|
|
724
767
|
S.wrapByKey.clear();
|
|
768
|
+
for (const obs of S.fillObsById.values()) { try { obs.disconnect(); } catch (_) {} }
|
|
769
|
+
S.fillObsById.clear();
|
|
725
770
|
S.inflight = 0;
|
|
726
771
|
S.pending = [];
|
|
727
772
|
S.pendingSet.clear();
|
|
@@ -737,6 +782,15 @@
|
|
|
737
782
|
S.domObs = new MutationObserver(muts => {
|
|
738
783
|
if (S.mutGuard > 0 || isBlocked()) return;
|
|
739
784
|
for (const m of muts) {
|
|
785
|
+
let sawWrapRemoval = false;
|
|
786
|
+
for (const n of m.removedNodes || []) {
|
|
787
|
+
if (n.nodeType !== 1) continue;
|
|
788
|
+
try {
|
|
789
|
+
if (n.matches?.(`.${WRAP_CLASS}`) || n.querySelector?.(`.${WRAP_CLASS}`)) { sawWrapRemoval = true; }
|
|
790
|
+
} catch (_) {}
|
|
791
|
+
}
|
|
792
|
+
if (sawWrapRemoval) sweepDeadWraps();
|
|
793
|
+
|
|
740
794
|
for (const n of m.addedNodes) {
|
|
741
795
|
if (n.nodeType !== 1) continue;
|
|
742
796
|
// matches() d'abord (O(1)), querySelector() seulement si nécessaire
|
package/public/style.css
CHANGED
|
@@ -56,20 +56,6 @@
|
|
|
56
56
|
top: auto !important;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
/* ── État vide ────────────────────────────────────────────────────────────── */
|
|
60
|
-
/*
|
|
61
|
-
Ajouté 20s après showAds si aucun fill détecté.
|
|
62
|
-
Collapse à 1px (pas 0) : reste observable par l'IO si le fill arrive tard.
|
|
63
|
-
*/
|
|
64
|
-
.nodebb-ezoic-wrap.is-empty {
|
|
65
|
-
display: block !important;
|
|
66
|
-
height: 1px !important;
|
|
67
|
-
min-height: 1px !important;
|
|
68
|
-
max-height: 1px !important;
|
|
69
|
-
margin: 0 !important;
|
|
70
|
-
padding: 0 !important;
|
|
71
|
-
overflow: hidden !important;
|
|
72
|
-
}
|
|
73
59
|
|
|
74
60
|
/* ── Ezoic global (hors de nos wraps) ────────────────────────────────────── */
|
|
75
61
|
.ezoic-ad {
|