nodebb-plugin-ezoic-infinite 1.4.3 → 1.4.5
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 +92 -3
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
pendingById: new Set(),
|
|
38
38
|
retryById: new Map(),
|
|
39
39
|
retryTimer: null,
|
|
40
|
+
retryQueue: [],
|
|
41
|
+
retryQueueSet: new Set(),
|
|
42
|
+
retryQueueRunning: false,
|
|
43
|
+
badIds: new Set(),
|
|
40
44
|
|
|
41
45
|
scheduled: false,
|
|
42
46
|
timer: null,
|
|
@@ -165,6 +169,34 @@
|
|
|
165
169
|
return { id: null, recycled: null };
|
|
166
170
|
}
|
|
167
171
|
|
|
172
|
+
|
|
173
|
+
function resetPlaceholderInWrap(wrap, id) {
|
|
174
|
+
try {
|
|
175
|
+
if (!wrap) return;
|
|
176
|
+
const old = wrap.querySelector && wrap.querySelector(`#${PLACEHOLDER_PREFIX}${id}`);
|
|
177
|
+
if (old) old.remove();
|
|
178
|
+
// Remove any leftover slot markup inside wrapper
|
|
179
|
+
wrap.querySelectorAll && wrap.querySelectorAll('iframe, ins, [id^="ezslot_"]').forEach(n => n.remove());
|
|
180
|
+
const ph = document.createElement('div');
|
|
181
|
+
ph.id = `${PLACEHOLDER_PREFIX}${id}`;
|
|
182
|
+
wrap.appendChild(ph);
|
|
183
|
+
} catch (e) {}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isAdjacentAd(target) {
|
|
187
|
+
if (!target || !target.nextElementSibling) return false;
|
|
188
|
+
const next = target.nextElementSibling;
|
|
189
|
+
if (next && next.classList && next.classList.contains(WRAP_CLASS)) return true;
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function isPrevAd(target) {
|
|
194
|
+
if (!target || !target.previousElementSibling) return false;
|
|
195
|
+
const prev = target.previousElementSibling;
|
|
196
|
+
if (prev && prev.classList && prev.classList.contains(WRAP_CLASS)) return true;
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
168
200
|
function buildWrap(id, kindClass, afterPos) {
|
|
169
201
|
const wrap = document.createElement('div');
|
|
170
202
|
wrap.className = `${WRAP_CLASS} ${kindClass}`;
|
|
@@ -251,6 +283,43 @@
|
|
|
251
283
|
state.retryTimer = setTimeout(refillUnfilled, delay);
|
|
252
284
|
}
|
|
253
285
|
|
|
286
|
+
function enqueueRetry(id) {
|
|
287
|
+
if (!id) return;
|
|
288
|
+
if (state.badIds && state.badIds.has(id)) return;
|
|
289
|
+
if (state.retryQueueSet.has(id)) return;
|
|
290
|
+
state.retryQueueSet.add(id);
|
|
291
|
+
state.retryQueue.push(id);
|
|
292
|
+
processRetryQueue();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function processRetryQueue() {
|
|
296
|
+
if (state.retryQueueRunning) return;
|
|
297
|
+
state.retryQueueRunning = true;
|
|
298
|
+
|
|
299
|
+
const step = () => {
|
|
300
|
+
const id = state.retryQueue.shift();
|
|
301
|
+
if (!id) {
|
|
302
|
+
state.retryQueueRunning = false;
|
|
303
|
+
state.badIds = new Set();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
state.retryQueueSet.delete(id);
|
|
307
|
+
// If this id was previously attempted and still empty, force a full reset before re-requesting.
|
|
308
|
+
const attempts = (state.retryById.get(id) || 0);
|
|
309
|
+
const phNow = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
310
|
+
const wrapNow = phNow && phNow.parentElement;
|
|
311
|
+
if (attempts > 0 && wrapNow && wrapNow.isConnected && !isPlaceholderFilled(id)) {
|
|
312
|
+
destroyPlaceholderIds([id]);
|
|
313
|
+
resetPlaceholderInWrap(wrapNow, id);
|
|
314
|
+
}
|
|
315
|
+
callShowAdsWhenReady(id);
|
|
316
|
+
setTimeout(step, 1100);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
step();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
|
|
254
323
|
function refillUnfilled() {
|
|
255
324
|
const wraps = Array.from(document.querySelectorAll(`.${WRAP_CLASS}`));
|
|
256
325
|
let scheduledAny = false;
|
|
@@ -267,13 +336,13 @@
|
|
|
267
336
|
}
|
|
268
337
|
|
|
269
338
|
const tries = (state.retryById.get(id) || 0);
|
|
270
|
-
if (tries >= 8) continue;
|
|
339
|
+
if (tries >= 8) { state.badIds && state.badIds.add(id); continue; }
|
|
271
340
|
|
|
272
341
|
const r = safeRect(wrap);
|
|
273
342
|
if (r && (r.top > window.innerHeight + 1200 || r.bottom < -1200)) continue;
|
|
274
343
|
|
|
275
344
|
state.retryById.set(id, tries + 1);
|
|
276
|
-
|
|
345
|
+
enqueueRetry(id);
|
|
277
346
|
scheduledAny = true;
|
|
278
347
|
}
|
|
279
348
|
|
|
@@ -392,6 +461,11 @@
|
|
|
392
461
|
const el = items[afterPos - 1];
|
|
393
462
|
if (!el || !el.isConnected) continue;
|
|
394
463
|
|
|
464
|
+
// Prevent adjacent ads (DOM-based, robust against virtualization)
|
|
465
|
+
if (isAdjacentAd(el) || isPrevAd(el)) {
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
|
|
395
469
|
// Prevent back-to-back at load
|
|
396
470
|
const prevWrap = findWrap(kindClass, afterPos - 1);
|
|
397
471
|
if (prevWrap) continue;
|
|
@@ -411,6 +485,8 @@
|
|
|
411
485
|
destroyPlaceholderIds([id]);
|
|
412
486
|
wrap = pick.recycled.wrap;
|
|
413
487
|
if (!moveWrapAfter(wrap, el, kindClass, afterPos)) continue;
|
|
488
|
+
resetPlaceholderInWrap(wrap, id);
|
|
489
|
+
setTimeout(() => { enqueueRetry(id); }, 450);
|
|
414
490
|
} else {
|
|
415
491
|
usedSet.add(id);
|
|
416
492
|
wrap = insertAfter(el, id, kindClass, afterPos);
|
|
@@ -418,7 +494,20 @@
|
|
|
418
494
|
}
|
|
419
495
|
|
|
420
496
|
liveArr.push({ id, wrap });
|
|
421
|
-
|
|
497
|
+
// If adjacency ended up happening (e.g. DOM shifts), rollback this placement.
|
|
498
|
+
if (wrap && (wrap.previousElementSibling && wrap.previousElementSibling.classList && wrap.previousElementSibling.classList.contains(WRAP_CLASS)) || (wrap.nextElementSibling && wrap.nextElementSibling.classList && wrap.nextElementSibling.classList.contains(WRAP_CLASS))) {
|
|
499
|
+
try { wrap.remove(); } catch (e) {}
|
|
500
|
+
// Put id back if it was newly consumed (not recycled)
|
|
501
|
+
if (!(pick.recycled && pick.recycled.wrap)) {
|
|
502
|
+
try { kindPool.unshift(id); } catch (e) {}
|
|
503
|
+
try { usedSet.delete(id); } catch (e) {}
|
|
504
|
+
}
|
|
505
|
+
inserted -= 0; // no-op
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (!(pick.recycled && pick.recycled.wrap)) {
|
|
509
|
+
callShowAdsWhenReady(id);
|
|
510
|
+
}
|
|
422
511
|
inserted += 1;
|
|
423
512
|
}
|
|
424
513
|
return inserted;
|