nodebb-plugin-ezoic-infinite 1.8.1 → 1.8.2

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/client.js +49 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
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
@@ -80,17 +80,19 @@
80
80
  // Tunables (stables en prod)
81
81
  const MIN_PRUNE_AGE_MS = 8_000; // délai de grâce avant pruning (stabilisation DOM)
82
82
  const MAX_INSERTS_RUN = 10; // plus réactif si NodeBB injecte en rafale
83
- const MAX_INFLIGHT = 2; // max showAds() simultanés (garde-fou)
83
+ const MAX_INFLIGHT = 4; // max showAds() simultanés (garde-fou)
84
84
  const MAX_SHOW_BATCH = 4; // ids max par appel showAds(...ids)
85
- const SHOW_THROTTLE_MS = 500; // anti-spam showAds() par id (plus réactif)
86
- const SHOW_RELEASE_MS = 300; // relâche inflight après showAds() batché
85
+ const SHOW_THROTTLE_MS = 600; // anti-spam showAds() par id (plus réactif)
86
+ const SHOW_RELEASE_MS = 700; // relâche inflight après showAds() batché
87
87
  const SHOW_FAILSAFE_MS = 7000; // relâche forcée si stack pub lente
88
- const BATCH_FLUSH_MS = 30; // micro-buffer pour regrouper les ids proches
89
- const BURST_COOLDOWN_MS = 100; // délai min entre deux déclenchements de burst
88
+ const BATCH_FLUSH_MS = 40; // micro-buffer pour regrouper les ids proches
89
+ const MAX_DESTROY_BATCH = 4; // ids max par destroyPlaceholders(...ids)
90
+ const DESTROY_FLUSH_MS = 30; // micro-buffer destroy pour lisser les rafales
91
+ const BURST_COOLDOWN_MS = 120; // délai min entre deux déclenchements de burst
90
92
 
91
93
  // Marges IO larges et fixes — observer créé une seule fois au boot
92
- const IO_MARGIN_DESKTOP = '3000px 0px 3000px 0px';
93
- const IO_MARGIN_MOBILE = '2000px 0px 2000px 0px';
94
+ const IO_MARGIN_DESKTOP = '2500px 0px 2500px 0px';
95
+ const IO_MARGIN_MOBILE = '3500px 0px 3500px 0px';
94
96
 
95
97
  const SEL = {
96
98
  post: '[component="post"][data-pid]',
@@ -131,6 +133,9 @@
131
133
  pending: [], // ids en attente de slot inflight
132
134
  pendingSet: new Set(),
133
135
  showBatchTimer: 0,
136
+ destroyBatchTimer: 0,
137
+ destroyPending: [],
138
+ destroyPendingSet: new Set(),
134
139
  sweepQueued: false,
135
140
  wrapByKey: new Map(), // anchorKey → wrap DOM node
136
141
  ezActiveIds: new Set(), // ids déjà passés à showAds/displayMore
@@ -197,15 +202,42 @@
197
202
  S.mutGuard++;
198
203
  try { fn(); } finally { S.mutGuard--; }
199
204
  }
205
+ function scheduleDestroyFlush() {
206
+ if (S.destroyBatchTimer) return;
207
+ S.destroyBatchTimer = setTimeout(() => {
208
+ S.destroyBatchTimer = 0;
209
+ flushDestroyBatch();
210
+ }, DESTROY_FLUSH_MS);
211
+ }
212
+
213
+ function flushDestroyBatch() {
214
+ if (!S.destroyPending.length) return;
215
+ const ids = [];
216
+ while (S.destroyPending.length && ids.length < MAX_DESTROY_BATCH) {
217
+ const id = S.destroyPending.shift();
218
+ S.destroyPendingSet.delete(id);
219
+ if (!Number.isFinite(id) || id <= 0) continue;
220
+ ids.push(id);
221
+ }
222
+ if (ids.length) {
223
+ try {
224
+ const ez = window.ezstandalone;
225
+ const run = () => { try { ez?.destroyPlaceholders?.(ids); } catch (_) {} };
226
+ try { (typeof ez?.cmd?.push === 'function') ? ez.cmd.push(run) : run(); } catch (_) {}
227
+ } catch (_) {}
228
+ }
229
+ if (S.destroyPending.length) scheduleDestroyFlush();
230
+ }
231
+
200
232
  function destroyEzoicId(id) {
201
233
  if (!Number.isFinite(id) || id <= 0) return;
202
234
  if (!S.ezActiveIds.has(id)) return;
203
- try {
204
- const ez = window.ezstandalone;
205
- const run = () => { try { ez?.destroyPlaceholders?.([id]); } catch (_) {} };
206
- try { (typeof ez?.cmd?.push === 'function') ? ez.cmd.push(run) : run(); } catch (_) {}
207
- } catch (_) {}
208
235
  S.ezActiveIds.delete(id);
236
+ if (!S.destroyPendingSet.has(id)) {
237
+ S.destroyPending.push(id);
238
+ S.destroyPendingSet.add(id);
239
+ }
240
+ scheduleDestroyFlush();
209
241
  }
210
242
 
211
243
 
@@ -452,11 +484,8 @@ function recycleAndMove(klass, targetEl, newKey) {
452
484
  S.wrapByKey.set(newKey, best);
453
485
 
454
486
  const doDestroy = () => {
455
- if (S.ezActiveIds.has(id)) {
456
- try { ez.destroyPlaceholders([id]); } catch (_) {}
457
- S.ezActiveIds.delete(id);
458
- }
459
- setTimeout(doDefine, 300);
487
+ if (S.ezActiveIds.has(id)) destroyEzoicId(id);
488
+ setTimeout(doDefine, 330);
460
489
  };
461
490
  const doDefine = () => { try { ez.define([id]); } catch (_) {} setTimeout(doDisplay, 300); };
462
491
  const doDisplay = () => { try { ez.displayMore([id]); S.ezActiveIds.add(id); } catch (_) {} };
@@ -843,6 +872,9 @@ function startShowBatch(ids) {
843
872
  S.pending = [];
844
873
  S.pendingSet.clear();
845
874
  if (S.showBatchTimer) { clearTimeout(S.showBatchTimer); S.showBatchTimer = 0; }
875
+ if (S.destroyBatchTimer) { clearTimeout(S.destroyBatchTimer); S.destroyBatchTimer = 0; }
876
+ S.destroyPending = [];
877
+ S.destroyPendingSet.clear();
846
878
  S.burstActive = false;
847
879
  S.runQueued = false;
848
880
  S.sweepQueued = false;