nodebb-plugin-ezoic-infinite 1.6.58 → 1.6.59

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 +46 -113
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.6.58",
3
+ "version": "1.6.59",
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
@@ -2,153 +2,86 @@
2
2
  'use strict';
3
3
 
4
4
  const WRAP_CLASS = 'nodebb-ezoic-wrap';
5
- const PINNED_ATTR = 'data-ezoic-pinned';
6
5
  const PLACEHOLDER_PREFIX = 'ezoic-pub-ad-placeholder-';
7
6
 
8
7
  let config = null;
9
8
  let usedIds = new Set();
10
- let scheduleTimer = null;
11
9
  let isEzoicEnabled = false;
10
+ let isRefreshing = false;
12
11
 
13
- // --- SÉLECTEURS COMPATIBLES HARMONY ---
14
- function getTopicList() {
15
- return document.querySelector('[component="topic/list"], [component="category"], [component="categories"]');
16
- }
17
-
18
- function getPostList() {
19
- return document.querySelector('[component="topic"], [component="post/list"]');
20
- }
21
-
22
- // --- GESTION DU SDK EZOIC (SÉCURISÉE) ---
23
- function callEzoic(idsToDefine) {
24
- if (!window.ezstandalone || !idsToDefine.length) return;
12
+ // --- LOGIQUE SDK EZOIC ---
13
+ function callEzoic(newIds) {
14
+ if (!window.ezstandalone || !newIds.length) return;
25
15
 
26
16
  try {
27
- // 1. On définit les nouveaux placeholders
28
- window.ezstandalone.define(idsToDefine);
17
+ window.ezstandalone.define(newIds);
29
18
 
30
- // 2. On gère le cycle de vie (Correction de tes erreurs de log)
19
+ // Si c'est le TOUT PREMIER appel sur la page
31
20
  if (!isEzoicEnabled && !window.ezstandalone.enabled) {
32
21
  window.ezstandalone.enable();
33
22
  window.ezstandalone.display();
34
23
  isEzoicEnabled = true;
35
- } else {
36
- // Si déjà activé, on attend un cycle CPU pour refresh proprement
24
+ }
25
+ // Sinon, on utilise refresh MAIS avec un verrou de sécurité
26
+ else if (isEzoicEnabled && !isRefreshing) {
27
+ isRefreshing = true;
37
28
  setTimeout(() => {
38
- if (window.ezstandalone.enabled) {
39
- window.ezstandalone.refresh();
40
- }
41
- }, 200);
29
+ window.ezstandalone.refresh();
30
+ isRefreshing = false;
31
+ }, 500); // Délai de 500ms pour laisser le SDK respirer
42
32
  }
43
- } catch (e) {
44
- console.warn('[Ezoic] SDK Error:', e);
45
- }
33
+ } catch (e) { console.warn('[Ezoic] Error:', e); }
46
34
  }
47
35
 
48
- function getNextId(poolStr) {
49
- if (!poolStr) return null;
50
- const ids = poolStr.split(/[\s,]+/).filter(Boolean);
51
- for (const id of ids) {
52
- const num = id.replace(/[^\d]/g, '');
53
- if (num && !usedIds.has(num)) {
54
- usedIds.add(num);
55
- return num;
56
- }
57
- }
58
- return null;
59
- }
60
-
61
- // --- LOGIQUE D'INJECTION ---
36
+ // --- INJECTION ---
62
37
  function inject() {
63
38
  if (!config || config.excluded) return;
64
- const newIds = [];
65
- const ul = getTopicList();
39
+ const ul = document.querySelector('[component="topic/list"], [component="category"]');
40
+ if (!ul) return;
66
41
 
67
- // A. LISTE DES SUJETS
68
- if (ul && config.enableBetweenAds) {
69
- // Nettoyage des blocs vides qui pourraient traîner
70
- ul.querySelectorAll('.' + WRAP_CLASS).forEach(w => {
71
- if (!w.previousElementSibling || w.previousElementSibling.tagName !== 'LI') w.remove();
72
- });
42
+ const items = Array.from(ul.children).filter(c => c.tagName === 'LI' && !c.classList.contains(WRAP_CLASS));
43
+ const newIdsFound = [];
44
+ const interval = parseInt(config.intervalPosts, 10) || 5;
73
45
 
74
- const items = Array.from(ul.children).filter(c => c.tagName === 'LI' && !c.classList.contains(WRAP_CLASS));
75
-
76
- // Pub n°1 (Après le premier sujet)
77
- if (config.showFirstTopicAd && !ul.querySelector(`[${PINNED_ATTR}="true"]`)) {
46
+ items.forEach((li, idx) => {
47
+ const pos = idx + 1;
48
+ if (pos % interval === 0 && !li.nextElementSibling?.classList.contains(WRAP_CLASS)) {
78
49
  const id = getNextId(config.placeholderIds);
79
50
  if (id) {
80
- insertAd(items[0], id, true);
81
- newIds.push(parseInt(id, 10));
51
+ const wrap = document.createElement('div');
52
+ wrap.className = WRAP_CLASS;
53
+ wrap.innerHTML = `<div id="${PLACEHOLDER_PREFIX}${id}"></div>`;
54
+ li.after(wrap);
55
+ newIdsFound.push(parseInt(id, 10));
82
56
  }
83
57
  }
58
+ });
84
59
 
85
- // Intervalles
86
- const interval = parseInt(config.intervalPosts, 10) || 5;
87
- items.forEach((li, idx) => {
88
- if ((idx + 1) % interval === 0 && idx > 0) {
89
- if (!li.nextElementSibling || !li.nextElementSibling.classList.contains(WRAP_CLASS)) {
90
- const id = getNextId(config.placeholderIds);
91
- if (id) {
92
- insertAd(li, id, false);
93
- newIds.push(parseInt(id, 10));
94
- }
95
- }
96
- }
97
- });
60
+ if (newIdsFound.length > 0) {
61
+ callEzoic(newIdsFound);
98
62
  }
63
+ }
99
64
 
100
- // B. LISTE DES MESSAGES (Sujets ouverts)
101
- const postList = getPostList();
102
- if (postList && config.enableMessageAds) {
103
- const posts = Array.from(postList.querySelectorAll('[component="post"]'));
104
- if (config.showFirstMessageAd && posts.length > 0 && !postList.querySelector('.ezoic-msg-first')) {
105
- const id = getNextId(config.messagePlaceholderIds);
106
- if (id) {
107
- insertAd(posts[0], id, false, 'ezoic-msg-first');
108
- newIds.push(parseInt(id, 10));
109
- }
65
+ function getNextId(pool) {
66
+ const ids = pool.split(/[\s,]+/).filter(Boolean);
67
+ for (const id of ids) {
68
+ const n = id.trim();
69
+ if (n && !usedIds.has(n)) {
70
+ usedIds.add(n);
71
+ return n;
110
72
  }
111
73
  }
112
-
113
- if (newIds.length > 0) {
114
- callEzoic(newIds);
115
- }
116
- }
117
-
118
- function insertAd(target, id, isPinned, extraClass = '') {
119
- if (!target) return;
120
- const wrap = document.createElement('div');
121
- wrap.className = `${WRAP_CLASS} ezoic-ad-between ${extraClass}`;
122
- if (isPinned) wrap.setAttribute(PINNED_ATTR, 'true');
123
- wrap.innerHTML = `<div id="${PLACEHOLDER_PREFIX}${id}"></div>`;
124
- target.after(wrap);
74
+ return null;
125
75
  }
126
76
 
127
- // --- INITIALISATION ---
128
77
  async function init() {
129
- try {
130
- const res = await fetch('/api/plugins/ezoic-infinite/config');
131
- config = await res.json();
132
-
133
- inject();
78
+ const res = await fetch('/api/plugins/ezoic-infinite/config');
79
+ config = await res.json();
80
+ inject();
134
81
 
135
- // MutationObserver pour détecter le scroll infini
136
- const observer = new MutationObserver((mutations) => {
137
- if (mutations.some(m => m.addedNodes.length > 0)) {
138
- if (scheduleTimer) clearTimeout(scheduleTimer);
139
- scheduleTimer = setTimeout(inject, 300);
140
- }
141
- });
142
- observer.observe(document.body, { childList: true, subtree: true });
143
-
144
- if (window.jQuery) {
145
- window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', () => {
146
- setTimeout(inject, 500);
147
- });
148
- }
149
- } catch (e) {}
82
+ // Ecoute du scroll infini NodeBB
83
+ $(window).on('action:infiniteScroll.loaded', () => setTimeout(inject, 100));
150
84
  }
151
85
 
152
- if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
153
- else init();
86
+ $(document).ready(init);
154
87
  })();