nodebb-plugin-ezoic-infinite 1.7.96 → 1.7.98
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 +206 -150
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -79,15 +79,15 @@
|
|
|
79
79
|
|
|
80
80
|
const EMPTY_CHECK_MS = 20_000; // délai avant collapse d'un wrap vide post-show
|
|
81
81
|
const MIN_PRUNE_AGE_MS = 8_000; // délai de grâce avant pruning (stabilisation DOM)
|
|
82
|
-
const MAX_INSERTS_RUN =
|
|
82
|
+
const MAX_INSERTS_RUN = 6; // max insertions par appel runCore
|
|
83
83
|
const MAX_INFLIGHT = 4; // max showAds() simultanés
|
|
84
|
-
const
|
|
85
|
-
const
|
|
84
|
+
const MAX_SHOW_BATCH = 4; // ids max par appel showAds(...ids)
|
|
85
|
+
const SHOW_THROTTLE_MS = 900; // anti-spam showAds() par id
|
|
86
|
+
const BURST_COOLDOWN_MS = 200; // délai min entre deux déclenchements de burst
|
|
86
87
|
|
|
87
88
|
// Marges IO larges et fixes — observer créé une seule fois au boot
|
|
88
89
|
const IO_MARGIN_DESKTOP = '2500px 0px 2500px 0px';
|
|
89
90
|
const IO_MARGIN_MOBILE = '3500px 0px 3500px 0px';
|
|
90
|
-
const FAST_SHOW_MARGIN_PX = 900; // show immédiat si slot déjà proche viewport
|
|
91
91
|
|
|
92
92
|
const SEL = {
|
|
93
93
|
post: '[component="post"][data-pid]',
|
|
@@ -128,13 +128,16 @@
|
|
|
128
128
|
pending: [], // ids en attente de slot inflight
|
|
129
129
|
pendingSet: new Set(),
|
|
130
130
|
wrapByKey: new Map(), // anchorKey → wrap DOM node
|
|
131
|
+
ezActiveIds: new Set(), // ids déjà passés à showAds/displayMore
|
|
132
|
+
scrollDir: 1, // 1=bas, -1=haut
|
|
133
|
+
scrollSpeed: 0, // px/s approx (EMA)
|
|
134
|
+
lastScrollY: 0,
|
|
135
|
+
lastScrollTs: 0,
|
|
131
136
|
runQueued: false,
|
|
132
137
|
burstActive: false,
|
|
133
138
|
burstDeadline: 0,
|
|
134
139
|
burstCount: 0,
|
|
135
140
|
lastBurstTs: 0,
|
|
136
|
-
scrollDir: 1,
|
|
137
|
-
lastScrollY: 0,
|
|
138
141
|
};
|
|
139
142
|
|
|
140
143
|
let blockedUntil = 0;
|
|
@@ -145,10 +148,34 @@
|
|
|
145
148
|
const normBool = v => v === true || v === 'true' || v === 1 || v === '1' || v === 'on';
|
|
146
149
|
const isFilled = n => !!(n?.querySelector?.('iframe, ins, img, video, [data-google-container-id]'));
|
|
147
150
|
|
|
151
|
+
function getDynamicShowBatchMax() {
|
|
152
|
+
const speed = S.scrollSpeed || 0;
|
|
153
|
+
const pend = S.pending.length;
|
|
154
|
+
// Scroll très rapide => petits batches (réduit le churn/unused)
|
|
155
|
+
if (speed > 2600) return 2;
|
|
156
|
+
if (speed > 1400) return 3;
|
|
157
|
+
// Peu de candidats => flush plus vite, inutile d'attendre 4
|
|
158
|
+
if (pend <= 1) return 1;
|
|
159
|
+
if (pend <= 3) return 2;
|
|
160
|
+
// Par défaut compromis dynamique
|
|
161
|
+
return 3;
|
|
162
|
+
}
|
|
163
|
+
|
|
148
164
|
function mutate(fn) {
|
|
149
165
|
S.mutGuard++;
|
|
150
166
|
try { fn(); } finally { S.mutGuard--; }
|
|
151
167
|
}
|
|
168
|
+
function destroyEzoicId(id) {
|
|
169
|
+
if (!Number.isFinite(id) || id <= 0) return;
|
|
170
|
+
if (!S.ezActiveIds.has(id)) return;
|
|
171
|
+
try {
|
|
172
|
+
const ez = window.ezstandalone;
|
|
173
|
+
const run = () => { try { ez?.destroyPlaceholders?.([id]); } catch (_) {} };
|
|
174
|
+
try { (typeof ez?.cmd?.push === 'function') ? ez.cmd.push(run) : run(); } catch (_) {}
|
|
175
|
+
} catch (_) {}
|
|
176
|
+
S.ezActiveIds.delete(id);
|
|
177
|
+
}
|
|
178
|
+
|
|
152
179
|
|
|
153
180
|
// ── Config ─────────────────────────────────────────────────────────────────
|
|
154
181
|
|
|
@@ -310,84 +337,82 @@
|
|
|
310
337
|
* displayMore = API Ezoic prévue pour l'infinite scroll.
|
|
311
338
|
* Priorité : wraps vides d'abord, remplis si nécessaire.
|
|
312
339
|
*/
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
function recycleAndMove(klass, targetEl, newKey) {
|
|
341
|
+
const ez = window.ezstandalone;
|
|
342
|
+
if (typeof ez?.destroyPlaceholders !== 'function' ||
|
|
343
|
+
typeof ez?.define !== 'function' ||
|
|
344
|
+
typeof ez?.displayMore !== 'function') return null;
|
|
345
|
+
|
|
346
|
+
const vh = window.innerHeight || 800;
|
|
347
|
+
const preferAbove = S.scrollDir >= 0; // scroll bas => recycle en haut
|
|
348
|
+
const farAbove = -vh;
|
|
349
|
+
const farBelow = vh * 2;
|
|
350
|
+
|
|
351
|
+
let bestPrefEmpty = null, bestPrefMetric = Infinity;
|
|
352
|
+
let bestPrefFilled = null, bestPrefFilledMetric = Infinity;
|
|
353
|
+
let bestAnyEmpty = null, bestAnyMetric = Infinity;
|
|
354
|
+
let bestAnyFilled = null, bestAnyFilledMetric = Infinity;
|
|
355
|
+
|
|
356
|
+
document.querySelectorAll(`.${WRAP_CLASS}.${klass}`).forEach(wrap => {
|
|
357
|
+
try {
|
|
358
|
+
const rect = wrap.getBoundingClientRect();
|
|
359
|
+
const isAbove = rect.bottom <= farAbove;
|
|
360
|
+
const isBelow = rect.top >= farBelow;
|
|
361
|
+
const anyFar = isAbove || isBelow;
|
|
362
|
+
if (!anyFar) return;
|
|
363
|
+
|
|
364
|
+
const qualifies = preferAbove ? isAbove : isBelow;
|
|
365
|
+
const metric = preferAbove ? Math.abs(rect.bottom) : Math.abs(rect.top - vh);
|
|
366
|
+
const filled = isFilled(wrap);
|
|
367
|
+
|
|
368
|
+
if (qualifies) {
|
|
369
|
+
if (!filled) {
|
|
370
|
+
if (metric < bestPrefMetric) { bestPrefMetric = metric; bestPrefEmpty = wrap; }
|
|
342
371
|
} else {
|
|
343
|
-
if (
|
|
344
|
-
else if (farAbove) { score = Math.abs(rect.bottom); }
|
|
372
|
+
if (metric < bestPrefFilledMetric) { bestPrefFilledMetric = metric; bestPrefFilled = wrap; }
|
|
345
373
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
374
|
+
}
|
|
375
|
+
if (!filled) {
|
|
376
|
+
if (metric < bestAnyMetric) { bestAnyMetric = metric; bestAnyEmpty = wrap; }
|
|
377
|
+
} else {
|
|
378
|
+
if (metric < bestAnyFilledMetric) { bestAnyFilledMetric = metric; bestAnyFilled = wrap; }
|
|
379
|
+
}
|
|
380
|
+
} catch (_) {}
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
const best = bestPrefEmpty ?? bestPrefFilled ?? bestAnyEmpty ?? bestAnyFilled;
|
|
384
|
+
if (!best) return null;
|
|
385
|
+
const id = parseInt(best.getAttribute(A_WRAPID), 10);
|
|
386
|
+
if (!Number.isFinite(id)) return null;
|
|
387
|
+
|
|
388
|
+
const oldKey = best.getAttribute(A_ANCHOR);
|
|
389
|
+
try { const ph = best.querySelector(`#${PH_PREFIX}${id}`); if (ph) S.io?.unobserve(ph); } catch (_) {}
|
|
390
|
+
mutate(() => {
|
|
391
|
+
best.setAttribute(A_ANCHOR, newKey);
|
|
392
|
+
best.setAttribute(A_CREATED, String(ts()));
|
|
393
|
+
best.setAttribute(A_SHOWN, '0');
|
|
394
|
+
best.classList.remove('is-empty');
|
|
395
|
+
const ph = best.querySelector(`#${PH_PREFIX}${id}`);
|
|
396
|
+
if (ph) ph.innerHTML = '';
|
|
397
|
+
targetEl.insertAdjacentElement('afterend', best);
|
|
398
|
+
});
|
|
399
|
+
if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
|
|
400
|
+
S.wrapByKey.set(newKey, best);
|
|
401
|
+
|
|
402
|
+
const doDestroy = () => {
|
|
403
|
+
if (S.ezActiveIds.has(id)) {
|
|
404
|
+
try { ez.destroyPlaceholders([id]); } catch (_) {}
|
|
405
|
+
S.ezActiveIds.delete(id);
|
|
363
406
|
}
|
|
407
|
+
setTimeout(doDefine, 300);
|
|
408
|
+
};
|
|
409
|
+
const doDefine = () => { try { ez.define([id]); } catch (_) {} setTimeout(doDisplay, 300); };
|
|
410
|
+
const doDisplay = () => { try { ez.displayMore([id]); S.ezActiveIds.add(id); } catch (_) {} };
|
|
411
|
+
try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
|
|
364
412
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const id = parseInt(best.getAttribute(A_WRAPID), 10);
|
|
368
|
-
if (!Number.isFinite(id)) return null;
|
|
369
|
-
|
|
370
|
-
const oldKey = best.getAttribute(A_ANCHOR);
|
|
371
|
-
try { const ph = best.querySelector(`#${PH_PREFIX}${id}`); if (ph) S.io?.unobserve(ph); } catch (_) {}
|
|
372
|
-
mutate(() => {
|
|
373
|
-
best.setAttribute(A_ANCHOR, newKey);
|
|
374
|
-
best.setAttribute(A_CREATED, String(ts()));
|
|
375
|
-
best.setAttribute(A_SHOWN, '0');
|
|
376
|
-
best.classList.remove('is-empty');
|
|
377
|
-
const ph = best.querySelector(`#${PH_PREFIX}${id}`);
|
|
378
|
-
if (ph) ph.innerHTML = '';
|
|
379
|
-
targetEl.insertAdjacentElement('afterend', best);
|
|
380
|
-
});
|
|
381
|
-
if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
|
|
382
|
-
S.wrapByKey.set(newKey, best);
|
|
383
|
-
|
|
384
|
-
const doDestroy = () => { try { ez.destroyPlaceholders([id]); } catch (_) {} setTimeout(doDefine, 220); };
|
|
385
|
-
const doDefine = () => { try { ez.define([id]); } catch (_) {} setTimeout(doDisplay,220); };
|
|
386
|
-
const doDisplay = () => { try { ez.displayMore([id]); } catch (_) {} };
|
|
387
|
-
try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
|
|
413
|
+
return { id, wrap: best };
|
|
414
|
+
}
|
|
388
415
|
|
|
389
|
-
return { id, wrap: best };
|
|
390
|
-
}
|
|
391
416
|
|
|
392
417
|
// ── Wraps DOM — création / suppression ────────────────────────────────────
|
|
393
418
|
|
|
@@ -423,7 +448,7 @@
|
|
|
423
448
|
const ph = w.querySelector(`[id^="${PH_PREFIX}"]`);
|
|
424
449
|
if (ph instanceof Element) S.io?.unobserve(ph);
|
|
425
450
|
const id = parseInt(w.getAttribute(A_WRAPID), 10);
|
|
426
|
-
if (Number.isFinite(id)) S.mountedIds.delete(id);
|
|
451
|
+
if (Number.isFinite(id)) { destroyEzoicId(id); S.mountedIds.delete(id); }
|
|
427
452
|
const key = w.getAttribute(A_ANCHOR);
|
|
428
453
|
if (key && S.wrapByKey.get(key) === w) S.wrapByKey.delete(key);
|
|
429
454
|
w.remove();
|
|
@@ -530,72 +555,85 @@
|
|
|
530
555
|
|
|
531
556
|
function observePh(id) {
|
|
532
557
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
533
|
-
if (
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
558
|
+
if (ph?.isConnected) try { getIO()?.observe(ph); } catch (_) {}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function enqueueShow(id) {
|
|
562
|
+
if (!id || isBlocked()) return;
|
|
563
|
+
if (ts() - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) return;
|
|
564
|
+
if (!S.pendingSet.has(id)) { S.pending.push(id); S.pendingSet.add(id); }
|
|
565
|
+
drainQueue();
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function drainQueue() {
|
|
569
|
+
if (isBlocked()) return;
|
|
570
|
+
const free = Math.max(0, MAX_INFLIGHT - S.inflight);
|
|
571
|
+
if (!free || !S.pending.length) return;
|
|
572
|
+
|
|
573
|
+
const picked = [];
|
|
574
|
+
const seen = new Set();
|
|
575
|
+
const batchCap = Math.max(1, Math.min(MAX_SHOW_BATCH, free, getDynamicShowBatchMax()));
|
|
576
|
+
while (S.pending.length && picked.length < batchCap) {
|
|
577
|
+
const id = S.pending.shift();
|
|
578
|
+
S.pendingSet.delete(id);
|
|
579
|
+
if (!Number.isFinite(id) || id <= 0 || seen.has(id)) continue;
|
|
580
|
+
seen.add(id);
|
|
581
|
+
picked.push(id);
|
|
582
|
+
}
|
|
583
|
+
if (picked.length) startShowBatch(picked);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function startShowBatch(ids) {
|
|
587
|
+
if (!ids?.length || isBlocked()) return;
|
|
588
|
+
const reserve = ids.length;
|
|
589
|
+
S.inflight += reserve;
|
|
590
|
+
|
|
591
|
+
let done = false;
|
|
592
|
+
const release = () => {
|
|
593
|
+
if (done) return;
|
|
594
|
+
done = true;
|
|
595
|
+
S.inflight = Math.max(0, S.inflight - reserve);
|
|
596
|
+
drainQueue();
|
|
597
|
+
};
|
|
598
|
+
const timer = setTimeout(release, 7000);
|
|
554
599
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const id = S.pending.shift();
|
|
559
|
-
S.pendingSet.delete(id);
|
|
560
|
-
startShow(id);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
600
|
+
requestAnimationFrame(() => {
|
|
601
|
+
try {
|
|
602
|
+
if (isBlocked()) { clearTimeout(timer); return release(); }
|
|
563
603
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
S.inflight++;
|
|
567
|
-
let done = false;
|
|
568
|
-
const release = () => {
|
|
569
|
-
if (done) return;
|
|
570
|
-
done = true;
|
|
571
|
-
S.inflight = Math.max(0, S.inflight - 1);
|
|
572
|
-
drainQueue();
|
|
573
|
-
};
|
|
574
|
-
const timer = setTimeout(release, 7000);
|
|
604
|
+
const valid = [];
|
|
605
|
+
const t = ts();
|
|
575
606
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
if (
|
|
607
|
+
for (const raw of ids) {
|
|
608
|
+
const id = parseInt(raw, 10);
|
|
609
|
+
if (!Number.isFinite(id) || id <= 0) continue;
|
|
579
610
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
580
|
-
if (!ph?.isConnected || isFilled(ph))
|
|
611
|
+
if (!ph?.isConnected || isFilled(ph)) continue;
|
|
612
|
+
if (t - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) continue;
|
|
613
|
+
if (document.querySelectorAll(`#${PH_PREFIX}${id}`).length !== 1) continue;
|
|
581
614
|
|
|
582
|
-
const t = ts();
|
|
583
|
-
if (t - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) { clearTimeout(timer); return release(); }
|
|
584
615
|
S.lastShow.set(id, t);
|
|
585
|
-
|
|
586
616
|
try { ph.closest?.(`.${WRAP_CLASS}`)?.setAttribute(A_SHOWN, String(t)); } catch (_) {}
|
|
617
|
+
valid.push(id);
|
|
618
|
+
}
|
|
587
619
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
620
|
+
if (!valid.length) { clearTimeout(timer); return release(); }
|
|
621
|
+
|
|
622
|
+
window.ezstandalone = window.ezstandalone || {};
|
|
623
|
+
const ez = window.ezstandalone;
|
|
624
|
+
const doShow = () => {
|
|
625
|
+
try { ez.showAds(...valid); } catch (_) {}
|
|
626
|
+
for (const id of valid) {
|
|
627
|
+
S.ezActiveIds.add(id);
|
|
592
628
|
scheduleEmptyCheck(id, t);
|
|
593
|
-
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
});
|
|
598
|
-
}
|
|
629
|
+
}
|
|
630
|
+
setTimeout(() => { clearTimeout(timer); release(); }, 700);
|
|
631
|
+
};
|
|
632
|
+
Array.isArray(ez.cmd) ? ez.cmd.push(doShow) : doShow();
|
|
633
|
+
} catch (_) { clearTimeout(timer); release(); }
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
|
|
599
637
|
|
|
600
638
|
function scheduleEmptyCheck(id, showTs) {
|
|
601
639
|
setTimeout(() => {
|
|
@@ -625,14 +663,22 @@
|
|
|
625
663
|
const orig = ez.showAds.bind(ez);
|
|
626
664
|
ez.showAds = function (...args) {
|
|
627
665
|
if (isBlocked()) return;
|
|
628
|
-
const ids
|
|
666
|
+
const ids = args.length === 1 && Array.isArray(args[0]) ? args[0] : args;
|
|
667
|
+
const valid = [];
|
|
629
668
|
const seen = new Set();
|
|
630
669
|
for (const v of ids) {
|
|
631
670
|
const id = parseInt(v, 10);
|
|
632
671
|
if (!Number.isFinite(id) || id <= 0 || seen.has(id)) continue;
|
|
633
672
|
if (!document.getElementById(`${PH_PREFIX}${id}`)?.isConnected) continue;
|
|
673
|
+
if (document.querySelectorAll(`#${PH_PREFIX}${id}`).length !== 1) continue;
|
|
634
674
|
seen.add(id);
|
|
635
|
-
|
|
675
|
+
valid.push(id);
|
|
676
|
+
}
|
|
677
|
+
if (!valid.length) return;
|
|
678
|
+
try { orig(...valid); } catch (_) {
|
|
679
|
+
for (const id of valid) {
|
|
680
|
+
try { orig(id); } catch (_) {}
|
|
681
|
+
}
|
|
636
682
|
}
|
|
637
683
|
};
|
|
638
684
|
} catch (_) {}
|
|
@@ -715,7 +761,7 @@
|
|
|
715
761
|
S.burstCount++;
|
|
716
762
|
scheduleRun(n => {
|
|
717
763
|
if (!n && !S.pending.length) { S.burstActive = false; return; }
|
|
718
|
-
setTimeout(step, n > 0 ?
|
|
764
|
+
setTimeout(step, n > 0 ? 150 : 300);
|
|
719
765
|
});
|
|
720
766
|
};
|
|
721
767
|
step();
|
|
@@ -733,11 +779,15 @@
|
|
|
733
779
|
S.mountedIds.clear();
|
|
734
780
|
S.lastShow.clear();
|
|
735
781
|
S.wrapByKey.clear();
|
|
782
|
+
S.ezActiveIds.clear();
|
|
736
783
|
S.inflight = 0;
|
|
737
784
|
S.pending = [];
|
|
738
785
|
S.pendingSet.clear();
|
|
739
786
|
S.burstActive = false;
|
|
740
787
|
S.runQueued = false;
|
|
788
|
+
S.scrollSpeed = 0;
|
|
789
|
+
S.lastScrollY = 0;
|
|
790
|
+
S.lastScrollTs = 0;
|
|
741
791
|
}
|
|
742
792
|
|
|
743
793
|
// ── MutationObserver ───────────────────────────────────────────────────────
|
|
@@ -857,25 +907,31 @@
|
|
|
857
907
|
|
|
858
908
|
function bindScroll() {
|
|
859
909
|
let ticking = false;
|
|
910
|
+
try {
|
|
911
|
+
S.lastScrollY = window.scrollY || window.pageYOffset || 0;
|
|
912
|
+
S.lastScrollTs = ts();
|
|
913
|
+
} catch (_) {}
|
|
860
914
|
window.addEventListener('scroll', () => {
|
|
915
|
+
try {
|
|
916
|
+
const y = window.scrollY || window.pageYOffset || 0;
|
|
917
|
+
const t = ts();
|
|
918
|
+
const dy = y - (S.lastScrollY || 0);
|
|
919
|
+
const dt = Math.max(1, t - (S.lastScrollTs || t));
|
|
920
|
+
if (Math.abs(dy) > 1) S.scrollDir = dy >= 0 ? 1 : -1;
|
|
921
|
+
const inst = Math.abs(dy) * 1000 / dt;
|
|
922
|
+
S.scrollSpeed = S.scrollSpeed ? (S.scrollSpeed * 0.7 + inst * 0.3) : inst;
|
|
923
|
+
S.lastScrollY = y;
|
|
924
|
+
S.lastScrollTs = t;
|
|
925
|
+
} catch (_) {}
|
|
861
926
|
if (ticking) return;
|
|
862
927
|
ticking = true;
|
|
863
|
-
requestAnimationFrame(() => {
|
|
864
|
-
ticking = false;
|
|
865
|
-
try {
|
|
866
|
-
const y = window.scrollY || window.pageYOffset || 0;
|
|
867
|
-
S.scrollDir = (y < (S.lastScrollY || 0)) ? -1 : 1;
|
|
868
|
-
S.lastScrollY = y;
|
|
869
|
-
} catch (_) {}
|
|
870
|
-
requestBurst();
|
|
871
|
-
});
|
|
928
|
+
requestAnimationFrame(() => { ticking = false; requestBurst(); });
|
|
872
929
|
}, { passive: true });
|
|
873
930
|
}
|
|
874
931
|
|
|
875
932
|
// ── Boot ───────────────────────────────────────────────────────────────────
|
|
876
933
|
|
|
877
934
|
S.pageKey = pageKey();
|
|
878
|
-
try { S.lastScrollY = window.scrollY || window.pageYOffset || 0; } catch (_) {}
|
|
879
935
|
muteConsole();
|
|
880
936
|
ensureTcfLocator();
|
|
881
937
|
warmNetwork();
|