nodebb-plugin-ezoic-infinite 1.5.32 → 1.5.33
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 +68 -7
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -14,19 +14,32 @@
|
|
|
14
14
|
const PRELOAD_MARGIN_DESKTOP = '2600px 0px 2600px 0px';
|
|
15
15
|
const PRELOAD_MARGIN_MOBILE = '1500px 0px 1500px 0px';
|
|
16
16
|
|
|
17
|
+
// When the user scrolls very fast, temporarily preload more aggressively.
|
|
18
|
+
// This helps ensure ads are already in-flight before the user reaches them.
|
|
19
|
+
const PRELOAD_MARGIN_DESKTOP_BOOST = '4200px 0px 4200px 0px';
|
|
20
|
+
const PRELOAD_MARGIN_MOBILE_BOOST = '2500px 0px 2500px 0px';
|
|
21
|
+
const BOOST_DURATION_MS = 2500;
|
|
22
|
+
const BOOST_SPEED_PX_PER_MS = 2.2; // ~2200px/s
|
|
23
|
+
|
|
17
24
|
const MAX_INFLIGHT_DESKTOP = 4;
|
|
18
25
|
const MAX_INFLIGHT_MOBILE = 3;
|
|
19
26
|
|
|
27
|
+
function isBoosted() {
|
|
28
|
+
try { return Date.now() < (state.scrollBoostUntil || 0); } catch (e) { return false; }
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
function isMobile() {
|
|
21
32
|
try { return window && window.innerWidth && window.innerWidth < 768; } catch (e) { return false; }
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
function getPreloadRootMargin() {
|
|
25
|
-
|
|
36
|
+
if (isMobile()) return isBoosted() ? PRELOAD_MARGIN_MOBILE_BOOST : PRELOAD_MARGIN_MOBILE;
|
|
37
|
+
return isBoosted() ? PRELOAD_MARGIN_DESKTOP_BOOST : PRELOAD_MARGIN_DESKTOP;
|
|
26
38
|
}
|
|
27
39
|
|
|
28
40
|
function getMaxInflight() {
|
|
29
|
-
|
|
41
|
+
const base = isMobile() ? MAX_INFLIGHT_MOBILE : MAX_INFLIGHT_DESKTOP;
|
|
42
|
+
return base + (isBoosted() ? 1 : 0);
|
|
30
43
|
}
|
|
31
44
|
|
|
32
45
|
const SELECTORS = {
|
|
@@ -71,13 +84,18 @@
|
|
|
71
84
|
pending: [],
|
|
72
85
|
pendingSet: new Set(),
|
|
73
86
|
|
|
87
|
+
// fast scroll boosting
|
|
88
|
+
scrollBoostUntil: 0,
|
|
89
|
+
lastScrollY: 0,
|
|
90
|
+
lastScrollTs: 0,
|
|
91
|
+
ioMargin: null,
|
|
92
|
+
|
|
74
93
|
// hero)
|
|
75
94
|
heroDoneForPage: false,
|
|
76
95
|
};
|
|
77
96
|
|
|
78
97
|
const insertingIds = new Set();
|
|
79
98
|
|
|
80
|
-
}
|
|
81
99
|
|
|
82
100
|
function markEmptyWrapper(id) {
|
|
83
101
|
try {
|
|
@@ -532,7 +550,14 @@ function startShow(id) {
|
|
|
532
550
|
// ---------- preload / above-the-fold ----------
|
|
533
551
|
|
|
534
552
|
function ensurePreloadObserver() {
|
|
535
|
-
|
|
553
|
+
const desiredMargin = getPreloadRootMargin();
|
|
554
|
+
if (state.io && state.ioMargin === desiredMargin) return state.io;
|
|
555
|
+
|
|
556
|
+
// Rebuild IO if margin changed (e.g., scroll boost toggled)
|
|
557
|
+
if (state.io) {
|
|
558
|
+
try { state.io.disconnect(); } catch (e) {}
|
|
559
|
+
state.io = null;
|
|
560
|
+
}
|
|
536
561
|
try {
|
|
537
562
|
state.io = new IntersectionObserver((entries) => {
|
|
538
563
|
for (const ent of entries) {
|
|
@@ -544,10 +569,20 @@ function startShow(id) {
|
|
|
544
569
|
const id = parseInt(idAttr, 10);
|
|
545
570
|
if (Number.isFinite(id) && id > 0) enqueueShow(id);
|
|
546
571
|
}
|
|
547
|
-
}, { root: null, rootMargin:
|
|
572
|
+
}, { root: null, rootMargin: desiredMargin, threshold: 0 });
|
|
573
|
+
state.ioMargin = desiredMargin;
|
|
548
574
|
} catch (e) {
|
|
549
575
|
state.io = null;
|
|
576
|
+
state.ioMargin = null;
|
|
550
577
|
}
|
|
578
|
+
|
|
579
|
+
// If we rebuilt the observer, re-observe existing placeholders so we don't miss them.
|
|
580
|
+
try {
|
|
581
|
+
if (state.io) {
|
|
582
|
+
const nodes = document.querySelectorAll(`[id^="${PLACEHOLDER_PREFIX}"]`);
|
|
583
|
+
nodes.forEach((n) => { try { state.io.observe(n); } catch (e) {} });
|
|
584
|
+
}
|
|
585
|
+
} catch (e) {}
|
|
551
586
|
return state.io;
|
|
552
587
|
}
|
|
553
588
|
|
|
@@ -560,7 +595,9 @@ function startShow(id) {
|
|
|
560
595
|
// If already above fold, fire immediately
|
|
561
596
|
try {
|
|
562
597
|
const r = ph.getBoundingClientRect();
|
|
563
|
-
|
|
598
|
+
const screens = isBoosted() ? 5.0 : 3.0;
|
|
599
|
+
const minBottom = isBoosted() ? -1500 : -800;
|
|
600
|
+
if (r.top < window.innerHeight * screens && r.bottom > minBottom) enqueueShow(id);
|
|
564
601
|
} catch (e) {}
|
|
565
602
|
}
|
|
566
603
|
|
|
@@ -581,9 +618,10 @@ function startShow(id) {
|
|
|
581
618
|
|
|
582
619
|
const targets = computeTargets(items.length, interval, showFirst);
|
|
583
620
|
let inserted = 0;
|
|
621
|
+
const maxInserts = MAX_INSERTS_PER_RUN + (isBoosted() ? 1 : 0);
|
|
584
622
|
|
|
585
623
|
for (const afterPos of targets) {
|
|
586
|
-
if (inserted >=
|
|
624
|
+
if (inserted >= maxInserts) break;
|
|
587
625
|
|
|
588
626
|
const el = items[afterPos - 1];
|
|
589
627
|
if (!el || !el.isConnected) continue;
|
|
@@ -818,6 +856,29 @@ function startShow(id) {
|
|
|
818
856
|
function bindScroll() {
|
|
819
857
|
let ticking = false;
|
|
820
858
|
window.addEventListener('scroll', () => {
|
|
859
|
+
// Detect very fast scrolling and temporarily boost preload/parallelism.
|
|
860
|
+
try {
|
|
861
|
+
const now = Date.now();
|
|
862
|
+
const y = window.scrollY || window.pageYOffset || 0;
|
|
863
|
+
if (state.lastScrollTs) {
|
|
864
|
+
const dt = now - state.lastScrollTs;
|
|
865
|
+
const dy = Math.abs(y - (state.lastScrollY || 0));
|
|
866
|
+
if (dt > 0) {
|
|
867
|
+
const speed = dy / dt; // px/ms
|
|
868
|
+
if (speed >= BOOST_SPEED_PX_PER_MS) {
|
|
869
|
+
const wasBoosted = isBoosted();
|
|
870
|
+
state.scrollBoostUntil = Math.max(state.scrollBoostUntil || 0, now + BOOST_DURATION_MS);
|
|
871
|
+
if (!wasBoosted) {
|
|
872
|
+
// margin changed -> rebuild IO so existing placeholders get earlier preload
|
|
873
|
+
ensurePreloadObserver();
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
state.lastScrollY = y;
|
|
879
|
+
state.lastScrollTs = now;
|
|
880
|
+
} catch (e) {}
|
|
881
|
+
|
|
821
882
|
if (ticking) return;
|
|
822
883
|
ticking = true;
|
|
823
884
|
window.requestAnimationFrame(() => {
|