Skip to content
Snippets Groups Projects
Commit 49b767ca authored by Prénom Nom's avatar Prénom Nom
Browse files

bouton stoplist + correction worker

parent 58603353
No related branches found
No related tags found
1 merge request!9Affichage stats
......@@ -543,16 +543,18 @@ async function notifyAllTabs(message) {
// Écoute du changement des préférences et envoi des valeurs au Worker
// ─────────────────────────────────────────────────────────────────────────────
browser.storage.onChanged.addListener(async (changes, area) => {
if (area === "local" && (changes.isTrackingActive || changes.pyodideSimplemmaReady)) {
checkAndUpdateTracking();
}
if (area === "local" && (changes.accessToken || changes.threshold || changes.trackedLanguages || changes.autoAdd)) {
console.log("[Background] Mise à jour des préférences détectée.");
const { accessToken, trackedLanguages, threshold, autoAdd} = await browser.storage.local.get([
"accessToken", "trackedLanguages", "threshold", "autoAdd"
]);
const isAuthenticated = !!accessToken;
worker.postMessage({
command: "update-preferences",
isAuthenticated,
......@@ -561,6 +563,17 @@ browser.storage.onChanged.addListener(async (changes, area) => {
autoAdd: autoAdd || false
});
}
if (area === "local" && changes.includeStopwords) {
const includeStopwords = changes.includeStopwords.newValue;
console.log(`[Background] Inclusion des mots outils activé/désactivé: ${includeStopwords}`);
if (worker) {
worker.postMessage({ command: "update-include-stopwords", includeStopwords });
}
}
});
// ─────────────────────────────────────────────────────────────────────────────
......
......@@ -4,123 +4,397 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Extension BaLex</title>
<script src="../utils/logger.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
width: 200px;
background-color: #323046;
@font-face {
font-family: 'Luciole';
src: url('../fonts/Luciole-Regular/Luciole-Regular.woff2') format('woff2'),
url('../fonts/Luciole-Regular/Luciole-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
}
#extension-notification {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.85);
color: white;
padding: 15px;
border-radius: 8px;
text-align: center;
width: 80%;
max-width: 250px;
z-index: 1000;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
transition: opacity 0.3s ease, visibility 0.3s ease;
}
#extension-notification.hidden {
opacity: 0;
visibility: hidden;
}
#close-notification {
margin-top: 10px;
padding: 5px 10px;
background-color: #8d5c70;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
font-weight: bold;
}
#close-notification:hover {
background-color: #dddedd;
color: #8d5c70;
}
body {
font-family: Luciole;
font-size: medium;
margin: 0;
padding: 8px;
background-color: #525877;
color: #323046;
border-radius: 10px;
width: 200px;
}
button {
font-family: Luciole;
width: 100%;
padding: 10px;
margin-bottom: 10px;
font-size: 15px;
color: #94608a;
padding: 12px;
margin-bottom: 8px;
font-size: 14px;
font-weight: bold;
border: none;
cursor: pointer;
border-radius: 6px;
transition: background 0.3s, transform 0.2s;
background-color: #a08e9f;
color: white;
}
button:hover {
background-color: #94608a;
background-color: #dddedd;
color: #8d5c70;
}
#auth-button {
width: auto;
display: inline-flex;
padding: 6px 12px;
font-size: 18px;
font-family: Luciole;
background: none;
border: none;
color: white;
align-items: center;
gap: 6px;
border-radius: 20px;
cursor: pointer;
transition: background 0.3s;
text-align: center;
}
.hidden {
display: none;
#auth-button:hover {
background: rgba(255,255,255,0.2);
}
#stats-options {
text-align: left;
margin-top: 15px;
#auth-button svg {
width: 18px;
height: 18px;
fill: white;
transition: transform 0.3s ease-in-out;
}
#auto-add-options {
margin-top: 15px;
#auth-button:hover svg {
transform: scale(1.1);
}
#auth-section {
display: flex;
justify-content: center;
margin-bottom: 10px;
}
#extension-name {
font-family: Luciole;
text-align: center;
font-size: 23px;
font-weight: bold;
padding: 5px;
color: #8d5c70;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: white;
}
.option-container {
background: #444;
padding: 12px;
border-radius: 10px;
margin-top: 4px;
margin-bottom: 4px;
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}
.option-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
width: 100%;
flex-wrap: nowrap;
padding: 12px;
margin-bottom: 4px;
border-radius: 6px;
background-color: #444;
color: white;
font-size: 0.6rem;
transition: transform 0.2s, box-shadow 0.2s;
}
.option-row:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.option-row label {
font-weight: lighter;
flex: 1;
margin: 0;
font-size: 0.9rem;
align-items: center;
}
.option-row input[type="checkbox"],
.option-row input[type="number"] {
appearance: none;
width: 20px;
height: 20px;
border: 2px solid #8d5c70;
border-radius: 50%;
background-color: #fff;
cursor: pointer;
transition: background-color 0.3s, border-color 0.3s;
}
.option-row input[type="checkbox"]:checked {
background-color: #8d5c70;
border-color: #8d5c70;
}
.toggle-switch {
position: absolute;
display: inline-block;
width: 30px;
height: 16px;
right: 0;
left: auto;
}
.toggle-switch .slider:before {
position: absolute;
content: "";
width: 12px;
height: 12px;
left: 2px;
bottom: 2px;
background-color: white;
transition: 0.4s;
border-radius: 50%;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: 0.4s;
border-radius: 24px;
}
input:checked + .slider {
background-color: #8d5c70;
}
input:checked + .slider:before {
transform: translateX(14px);
}
.threshold-container input[type="number"] {
width: 45px;
height: 45px;
line-height: 50px;
text-align: center;
border-radius: 50%;
border: 2px solid #8d5c70;
font-size: 0.8rem;
box-sizing: border-box;
background: #fff;
color: #333;
}
#save-options {
border: none;
background: #8d5c70;
border-radius: 6px;
color: white;
padding: 8px 12px;
font-size: 0.9rem;
cursor: pointer;
transition: background 0.3s, transform 0.2s;
}
#save-options:hover {
background: #ccc;
color: #8d5c70;
transform: translateY(-2px);
}
.language-selection {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
margin-top: 5px;
gap: 8px;
}
.lang-option {
padding: 8px 12px;
background-color: #323046;
color: white;
border: 2px solid #94608a;
border-radius: 5px;
padding: 4px 10px;
border: 2px solid #8d5c70;
border-radius: 16px;
background: rgb(152, 152, 152);
color: #8d5c70;
cursor: pointer;
transition: all 0.3s ease;
font-size: 0.85rem;
transition: background 0.3s, color 0.3s, transform 0.2s;
}
.lang-option:hover {
background: #8d5c70;
color: white;
transform: scale(1.05);
}
.lang-option.selected {
background-color: #94608a;
background: #8d5c70;
color: white;
border-color: #8d5c70;
}
.threshold-container {
/* #stats-options {
border: 1px solid #555;
border-radius: 8px;
align-items: center;
} */
.option-row.auto-add-row {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin-top: 15px;
padding: 10px 12px;
margin-bottom: 0;
background: transparent;
border-bottom: 1px solid #555;
}
.threshold-container label {
flex: 1;
.option-row.auto-add-row span {
font-size: 16px;
font-weight: lighter;
}
.threshold-container input {
width: 60px;
text-align: center;
padding: 5px;
}
#auto-add {
margin-right: 10px;
.option-row.stopwords {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 0.9rem;
font-weight: lighter;
}
#error-message {
color: rgb(255, 0, 0);
padding: 10px;
text-align: center;
}
/* .option-row.auto-add-row input[type="checkbox"] {
appearance: none;
width: 24px;
margin-left: 10px;
height: 24px;
border: 2px solid #8d5c70;
border-radius: 4px;
background: #fff;
cursor: pointer;
transition: background 0.3s;
} */
/* .option-row.auto-add-row input[type="checkbox"]:checked {
background: #8d5c70;
} */
#open-stats {
padding: 6px;
font-weight: lighter;
width: auto;
display: block;
margin: 0 auto;
background-color: #525877;
color: white;
border: 2px solid #8d5c70;
border-radius: 8px;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<h3>Extension BaLex</h3>
<button id="auth-button">Se connecter</button>
<button id="toggleExtensionBtn">Activer/Désactiver l'extension</button>
<button id="toggleStatsBtn">Activer les statistiques</button>
<div id="stats-options" class="hidden">
<label for="auto-add" style="margin-top: 15px; display: flex; align-items: center;">
<input type="checkbox" id="auto-add"/> Ajout Automatique
</label>
<div id="auto-add-options" class="hidden">
<div class="threshold-container">
<label for="threshold">Seuil</label>
<input type="number" id="threshold" value="10" min="1" />
</div>
<div class="option-row">
<label>Langues suivies</label>
<div id="language-selection" class="language-selection">
<p id="loading-languages" style="color: gray;">Chargement...</p>
</div>
<div id="extension-name">Extension BaLex</div>
<div id="auth-section">
<button id="auth-button">
<span id="auth-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M10 2a1 1 0 0 1 1 1v2h2V3a1 1 0 0 1 2 0v2h2a2 2 0 0 1 2 2v3h-2V7h-2v3a1 1 0 1 1-2 0V7h-2v3a1 1 0 1 1-2 0V7H6v3H4V7a2 2 0 0 1 2-2h2V3a1 1 0 0 1 1-1Z"/>
</svg>
</span>
<span id="auth-text">Se connecter</span>
</button>
</div>
<button id="toggleExtensionBtn">Activer/Désactiver</button>
<button id="toggleStatsBtn">Statistiques</button>
<button id="open-stats">Afficher les statistiques</button>
<div id="stats-options" class="option-container">
<div class="option-row auto-add-row">
<span>Ajout automatique</span>
<label class="toggle-switch">
<input type="checkbox" id="auto-add">
<span class="slider"></span>
</label>
</div>
<div id="auto-add-options" class="hidden">
<div class="option-row stopwords">
<span>Inclure mots outils</span>
<label class="toggle-switch">
<input type="checkbox" id="include-stopwords" />
<span class="slider"></span>
</label>
</div>
<div class="option-row threshold-container">
<label for="threshold">Seuil d'ajout d'un mot</label>
<input type="number" id="threshold" value="10" min="1" />
</div>
<div class="option-row">
<label>Langues suivies</label>
<div id="language-selection" class="language-selection">
<p id="loading-languages" style="color: gray;">Chargement...</p>
</div>
<!-- Message d'erreur si on ne sélectionne pas une langue à suivre-->
<div id="error-message" class="hidden">
<p>Veuillez sélectionner au moins une langue avant de sauvegarder.</p>
</div>
<button id="save-options" class="hidden">Valider</button>
</div>
<!-- Message d'erreur si on ne sélectionne pas une langue à suivre-->
<div id="error-message" class="hidden">
<p>Veuillez sélectionner au moins une langue avant de sauvegarder.</p>
</div>
<button id="save-options" class="hidden">Valider</button>
</div>
<script src="popup.js"></script>
<script src="../utils/api.js"></script>
</div>
<div id="extension-notification" class="hidden">
<p id="notification-text"></p>
<button id="close-notification">OK</button>
</div>
<script src="../utils/api.js"></script>
<script src="popup.js"></script>
</body>
</html>
......@@ -29,6 +29,36 @@ async function updateConnectionButton() {
}
button.onclick = async () => {
const isConnected = !!accessToken;
// Gestion de la déconnexion
if (isConnected) {
console.log("[Popup] Déconnexion détectée, réinitialisation des options...");
await browser.storage.local.set({
accessToken: null,
autoAdd: false,
includeStopwords: false,
isTrackingActive: false
});
// Envoyer les mises à jour au worker
browser.runtime.sendMessage({
command: "update-preferences",
autoAdd: false,
includeStopwords: false,
isTrackingActive: false
});
console.log("✅ Paramètres réinitialisés après déconnexion.");
// Mettre à jour l'interface
await updateOptionsUI();
await updateLanguageSelection();
await updateExtensionToggleButton();
}
// Envoyer le message pour basculer l'authentification
await browser.runtime.sendMessage({ action: "toggleAuth" });
};
}
......@@ -91,18 +121,20 @@ async function updateOptionsUI() {
const saveOptionsBtn = document.getElementById("save-options");
const toggleStatsBtn = document.getElementById("toggleStatsBtn");
const openStats = document.getElementById("open-stats");
const includeStopwordsCheckbox = document.getElementById("include-stopwords");
// Affichage de l'option "Ajout automatique" selon la connexion
if (autoAddContainer) {
autoAddContainer.style.display = isLoggedIn ? "block" : "none";
}
// Chargement des préférences
const { isTrackingActive, autoAdd, threshold } = await browser.storage.local.get([
const { isTrackingActive, autoAdd, threshold, includeStopwords} = await browser.storage.local.get([
"isTrackingActive",
"autoAdd",
"threshold"
]) || { isTrackingActive: false };
"threshold",
"includeStopwords"
]) || { isTrackingActive: false, includeStopwords: false };
// Gestion du bouton de statistiques
if (toggleStatsBtn) {
......@@ -118,15 +150,18 @@ async function updateOptionsUI() {
toggleStatsBtn.textContent = isTrackingActive ? "Désactiver les statistiques" : "Activer les statistiques";
}
// Affichage des options statistiques
// Gestion des boutons d'options de statistiques
if (statsOptions) {
statsOptions.classList.toggle("hidden", !isTrackingActive);
}
//Si l'utilsateur est connecté : afficher les options
if (isLoggedIn) {
if (autoAddCheckbox) {
autoAddCheckbox.checked = autoAdd || false;
}
if (includeStopwordsCheckbox) {
includeStopwordsCheckbox.checked = includeStopwords || false;
}
if (thresholdInput && threshold !== undefined) {
thresholdInput.value = threshold;
}
......@@ -136,10 +171,14 @@ async function updateOptionsUI() {
if (saveOptionsBtn) {
saveOptionsBtn.classList.toggle("hidden", !autoAdd);
}
//Si l'utilsateur n'est connecté : masquer les options
} else {
if (autoAddCheckbox) {
autoAddCheckbox.checked = false;
}
if (includeStopwordsCheckbox) {
includeStopwordsCheckbox.checked = false;
}
if (autoAddOptions) {
autoAddOptions.classList.add("hidden");
}
......@@ -149,6 +188,22 @@ async function updateOptionsUI() {
}
}
// ==========================
// Gestion des stoplists
// ==========================
document.getElementById("include-stopwords")?.addEventListener("change", async () => {
const includeStopwords = document.getElementById("include-stopwords").checked;
// Si on décoche, on met immédiatement à jour le stockage
if (!includeStopwords) {
await browser.storage.local.set({ includeStopwords: false });
console.log("[Popup] Option 'Inclure mots outils' désactivée immédiatement.");
browser.runtime.sendMessage({ command: "update-include-stopwords", includeStopwords: false });
}
});
// ==========================
// Gestion de l'activation/désactivation de l'extension
// ==========================
......@@ -231,8 +286,13 @@ document.getElementById("toggleStatsBtn")?.addEventListener("click", async () =>
// Si désactivation, désactiver aussi l'ajout automatique
if (!newState) {
await browser.storage.local.set({ autoAdd: false });
// Si désactivation, désactiver aussi l'ajout automatique et includeStopwords
await browser.storage.local.set({
autoAdd: false,
includeStopwords: false
});
document.getElementById("auto-add").checked = false;
document.getElementById("include-stopwords").checked = false;
document.getElementById("auto-add-options").classList.add("hidden");
document.getElementById("save-options").classList.add("hidden");
}
......@@ -255,7 +315,13 @@ document.getElementById("auto-add")?.addEventListener("change", async () => {
document.getElementById("auto-add-options").classList.toggle("hidden", !isChecked);
document.getElementById("save-options").classList.toggle("hidden", !isChecked);
if (!isChecked) {
await browser.storage.local.set({ autoAdd: false });
log("[Popup] Désactivation de l'ajout automatique -> Désactivation des options");
await browser.storage.local.set({
autoAdd: false, //Désactiver l'ajout automatique
includeStopwords: false // Désactiver includeStopwords
});
// Mettre à jour l'affichage du bouton
document.getElementById("include-stopwords").checked = false;
}
});
......@@ -265,7 +331,8 @@ document.getElementById("save-options")?.addEventListener("click", async () => {
const threshold = parseInt(document.getElementById("threshold").value, 10);
const selectedLanguages = Array.from(document.querySelectorAll("#language-selection .lang-option.selected"))
.map(option => option.dataset.value);
const includeStopwords = document.getElementById("include-stopwords").checked;
// Vérification : si auto-add est activé, au moins une langue doit être sélectionnée
const errorMessage = document.getElementById("error-message");
if (autoAdd && selectedLanguages.length === 0) {
......@@ -277,9 +344,20 @@ document.getElementById("save-options")?.addEventListener("click", async () => {
await browser.storage.local.set({
autoAdd,
threshold,
trackedLanguages: selectedLanguages
trackedLanguages: selectedLanguages,
includeStopwords
});
log("Options sauvegardées :", { autoAdd, threshold, trackedLanguages: selectedLanguages, includeStopwords});
// Envoyer les nouvelles préférences au Worker
browser.runtime.sendMessage({
command: "update-preferences",
autoAdd,
threshold,
trackedLanguages: selectedLanguages,
includeStopwords
});
log("Options sauvegardées :", { autoAdd, threshold, trackedLanguages: selectedLanguages });
});
// Bouton pour ouvrir la page des statistiques
......@@ -288,8 +366,6 @@ document.getElementById("open-stats")?.addEventListener("click", async () => {
window.open("stats.html", "_blank");
});
async function displayStatsSummary() {
console.log("[Popup] Préparation du résumé des statistiques...");
......
......@@ -16,7 +16,7 @@ window.lexiconMap = new Map();
*/
async function fetchLexiconDefinitions(word) {
try {
console.log(`🔍 Recherche des définitions de '${word}' dans les lexiques de l'utilisateur...`);
log(`🔍 Recherche des définitions de '${word}' dans les lexiques de l'utilisateur...`);
if (!authToken) {
console.warn("Aucun token disponible, impossible de requêter l'API protégée.");
......@@ -24,8 +24,7 @@ async function fetchLexiconDefinitions(word) {
}
// 1) Récupérer la liste complète des lexiques de l'utilisateur
const userId = 4;
const lexUrl = `https://babalex.lezinter.net/api/lexicon/search?user_id=${userId}&language=fr`;
const lexUrl = `https://babalex.lezinter.net/api/lexicon/search?`;
const lexResponse = await fetch(lexUrl, {
headers: { Authorization: `Bearer ${authToken}` }
});
......@@ -33,7 +32,7 @@ async function fetchLexiconDefinitions(word) {
throw new Error(`❌ Erreur API lors de la récupération des lexiques: ${lexResponse.statusText}`);
}
const userLexicons = await lexResponse.json();
console.log("🗂️ Lexiques de l'utilisateur :", userLexicons);
log("🗂️ Lexiques de l'utilisateur :", userLexicons);
if (!Array.isArray(userLexicons) || userLexicons.length === 0) {
console.warn("⚠️ Aucun lexique trouvé pour cet utilisateur.");
......@@ -49,12 +48,12 @@ async function fetchLexiconDefinitions(word) {
: `Lexique de groupe : ${lex.group?.name || "Inconnu"}`;
lexiconMap.set(lex.id, lexiconName);
});
console.log("📌 LexiconMap :", lexiconMap);
log("📌 LexiconMap :", lexiconMap);
// 2) Pour chaque lexique, rechercher le mot en ajoutant target_lex
const definitionsPromises = userLexicons.map(async (lex) => {
const searchUrl = `https://babalex.lezinter.net/api/entry/search?graphy=${encodeURIComponent(word)}&language=fr&target_lex=${lex.id}`;
console.log(`🔎 Appel API pour le lexique ${lex.id} avec l'URL : ${searchUrl}`);
log(`🔎 Appel API pour le lexique ${lex.id} avec l'URL : ${searchUrl}`);
const searchResponse = await fetch(searchUrl, {
headers: { Authorization: `Bearer ${authToken}` }
......@@ -71,7 +70,7 @@ async function fetchLexiconDefinitions(word) {
return Number(entry.lexicon.id) === Number(lex.id);
});
console.log(`Pour le lexique ${lex.id} (${lexiconMap.get(lex.id)}), entrées filtrées :`, filteredEntries);
log(`Pour le lexique ${lex.id} (${lexiconMap.get(lex.id)}), entrées filtrées :`, filteredEntries);
return { lexiconId: lex.id, entries: filteredEntries };
});
......@@ -81,7 +80,7 @@ async function fetchLexiconDefinitions(word) {
// 3) Parcourir les résultats et extraire les définitions
let allDefinitions = [];
results.forEach(result => {
console.log(`Pour le lexique ${result.lexiconId}, entrées filtrées :`, result.entries);
log(`Pour le lexique ${result.lexiconId}, entrées filtrées :`, result.entries);
const lexiconId = result.lexiconId;
const sourceName = lexiconMap.get(lexiconId) || `Lexique #${lexiconId}`;
......@@ -114,7 +113,7 @@ async function fetchLexiconDefinitions(word) {
});
});
console.log("Résultat final filtré :", allDefinitions);
log("Résultat final filtré :", allDefinitions);
return allDefinitions;
} catch (error) {
console.error("❌ Erreur générale lors de la récupération des définitions :", error);
......@@ -128,7 +127,7 @@ async function fetchLexiconDefinitions(word) {
*/
// async function fetchWiktionaryDefinition(word) {
// try {
// console.log(`🔍 Requête Wiktionnaire pour "${word}"...`);
// log(`🔍 Requête Wiktionnaire pour "${word}"...`);
// if (!word || word.trim() === "") {
// throw new Error("⚠️ Mot vide, impossible d'envoyer la requête.");
// }
......@@ -138,7 +137,7 @@ async function fetchLexiconDefinitions(word) {
// throw new Error(`❌ Erreur API Wiktionnaire: ${response.statusText}`);
// }
// const data = await response.json();
// console.log("📖 Réponse API (Wiktionnaire) :", data);
// log("📖 Réponse API (Wiktionnaire) :", data);
// const pages = data.query?.pages;
// const page = pages ? Object.values(pages)[0] : null;
......@@ -147,7 +146,7 @@ async function fetchLexiconDefinitions(word) {
// ? page.extract.trim()
// : "⚠️ Aucune définition trouvée sur le Wiktionnaire.";
// console.log("🌍 Définition Wiktionnaire extraite :", definitionText);
// log("🌍 Définition Wiktionnaire extraite :", definitionText);
// return [
// {
......@@ -269,8 +268,6 @@ async function fetchWiktionaryDefinition(word) {
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Affichage des définitions dans la barre latérale
// ─────────────────────────────────────────────────────────────────────────────
......@@ -281,7 +278,7 @@ const MAX_LENGTH = 200;
* Affiche les définitions dans la barre latérale.
*/
function displayDefinitions(definitions) {
console.log("📖 Affichage des définitions reçues :", definitions);
log("📖 Affichage des définitions reçues :", definitions);
if (!Array.isArray(definitions)) return;
const mesLexiquesList = document.getElementById("mesLexiquesList");
......@@ -419,7 +416,7 @@ function closeDefinitionPopup() {
* Puis fusionne les résultats.
*/
async function combineDefinitions(word) {
console.log(`[combineDefinitions] Récupération des définitions pour "${word}"...`);
log(`[combineDefinitions] Récupération des définitions pour "${word}"...`);
const results = await Promise.allSettled([
fetchLexiconDefinitions(word),
......@@ -431,23 +428,18 @@ async function combineDefinitions(word) {
const wiktionaryDefinitions =
results[1].status === "fulfilled" ? results[1].value : [];
// Assurer que c'est bien un tableau
if (!Array.isArray(lexiconDefinitions)) lexiconDefinitions = [];
if (!Array.isArray(wiktionaryDefinitions)) wiktionaryDefinitions = [];
const allDefinitions = [...lexiconDefinitions, ...wiktionaryDefinitions];
console.log("📚 [combineDefinitions] Résultat fusionné :", allDefinitions);
log("📚 [combineDefinitions] Résultat fusionné :", allDefinitions);
return allDefinitions;
}
/**
* Récupère et affiche toutes les définitions (lexiques + Wiktionnaire).
*/
async function showDefinitions(word) {
console.log(`[showDefinitions] Recherche + affichage pour "${word}"...`);
log(`[showDefinitions] Recherche + affichage pour "${word}"...`);
const noDefinitionsContainer = document.getElementById("noDefinitionsContainer");
if (noDefinitionsContainer) {
......@@ -458,7 +450,7 @@ async function showDefinitions(word) {
try {
const allDefinitions = await combineDefinitions(word);
console.log("[showDefinitions] Définitions récupérées :", allDefinitions);
log("[showDefinitions] Définitions récupérées :", allDefinitions);
if (!allDefinitions || allDefinitions.length === 0) {
if (noDefinitionsContainer) {
......@@ -491,7 +483,7 @@ async function showDefinitions(word) {
* (sans Wiktionnaire), puis gérer l’affichage d’erreur ou non.
*/
async function fetchDefinition(word) {
console.log(`🔍 Recherche de la définition pour '${word}'...`);
log(`🔍 Recherche de la définition pour '${word}'...`);
const noDefinitionsContainer = document.getElementById("noDefinitionsContainer");
if (!noDefinitionsContainer) {
......@@ -501,7 +493,7 @@ async function fetchDefinition(word) {
try {
const definition = await fetchLexiconDefinitions(word);
console.log("🔍 Résultat API :", definition);
log("🔍 Résultat API :", definition);
if (!definition || definition.length === 0) {
console.warn(`⚠️ Aucune définition trouvée pour '${word}'`);
......@@ -552,7 +544,7 @@ function displayLexiconResults(lexicons) {
li.innerHTML = `<strong>${lexiconName}</strong>`;
ul.appendChild(li);
console.log(`✅ Lexique ajouté : ${lexiconName} (ID: ${lexicon.id})`);
log(`✅ Lexique ajouté : ${lexiconName} (ID: ${lexicon.id})`);
});
resultDiv.appendChild(ul);
......
/**
* Mode debug : affiche les logs dans la console
* Mode prod : masque les logs
*/
const DEBUG = false; // false en prod
function log(...args) {
if (DEBUG) {
console.log(...args);
}
}
......@@ -14,11 +14,13 @@ let userThreshold = 10; // Seuil par défaut
let trackedLanguages = []; // Aucune langue suivie par défaut
let notifiedWords = {}; // Stockage des mots déjà signalés (pour éviter les doublons)
let stoplistFr = new Set(); // Stockage optimisé de la stoplist
let includeStopwords = false; // Stocker l'état de l'inclusion des mots outils
let userLexicons = [] //Contient les lexiques et leurs ID (lexiques personnels)
let authToken = null; // Stockage local du token
// --- Attente de la mise à jour de la stoplist ---
let stoplistReady = new Promise((resolve) => resolve());
// Écouteur des messages reçus du background script
self.onmessage = async (event) => {
......@@ -95,9 +97,10 @@ await main()
}
console.log("[Worker] Texte reçu pour analyse :", data.text);
try {
const stoplistArray = Array.from(stoplistFr);
console.log("Stoplist utilisée :", stoplistArray);
const result = await pyodide.runPythonAsync(`
const stoplistArray = stoplistFr && stoplistFr.size > 0 ? Array.from(stoplistFr) : null;
console.log("[Worker] Stoplist chargée avec process-text ?", stoplistArray ? `Oui (${stoplistArray.length} mots)` : "Non (aucun filtrage)");
const result = await pyodide.runPythonAsync(`
import json
import re
import simplemma
......@@ -119,15 +122,15 @@ if detected_lang == "unk":
detected_lang = "other"
tokens = tokenize(text)
if detected_lang == "fr":
tokens = [token.lower().strip() for token in tokens if token.lower().strip() not in stoplist]
lemmatized_tokens = [simplemma.lemmatize(token, lang=detected_lang) for token in tokens]
freq = {}
for token in lemmatized_tokens:
if token not in stoplist:
freq[token] = freq.get(token, 0) + 1
freq[token] = freq.get(token, 0) + 1
#Si on veut éventuellement ne pas compter du tout les fréquences des mots de la stoplist
#if token not in stoplist:
#freq[token] = freq.get(token, 0) + 1
json.dumps({"lang": detected_lang, "frequencies": freq}, ensure_ascii=False)
`);
......@@ -166,10 +169,23 @@ json.dumps({"lang": detected_lang, "frequencies": freq}, ensure_ascii=False)
console.log("[Worker] 🔑 Token mis à jour :", authToken ? "Disponible" : "Aucun token reçu");
}
if (data.command === "update-stoplist") {
stoplistFr = new Set(data.stoplist.map(word => word.toLowerCase().trim()));
console.log("[Worker] Stoplist FR mise à jour :", stoplistFr);
}
if (data.command === "update-stoplist") {
stoplistReady = new Promise((resolve) => {
if (data.stoplist && Array.isArray(data.stoplist)) {
stoplistFr = new Set(data.stoplist.map(word => word.toLowerCase().trim()));
console.log(`[Worker] ✅ Stoplist mise à jour avec ${stoplistFr.size} mots.`);
} else {
console.warn("[Worker] ⚠ Stoplist reçue incorrecte ou vide.");
stoplistFr = new Set();
}
resolve(); // Indiquer que la stoplist est prête
});
}
if (data.command === "update-include-stopwords") {
includeStopwords = data.includeStopwords;
console.log(`[Worker] Mise à jour de includeStopwords : ${includeStopwords}`);
}
};
// --- Vérification du seuil et notification ---
......@@ -177,6 +193,9 @@ let pendingWords = {}; // Stocker temporairement les mots en attente d'ajout
let addWordTimeout = null; // Timer pour regrouper les ajouts
async function checkThreshold(lang) {
// // Vérifier si la stoplist est définie et contient des mots
await stoplistReady; // Attendre que la stoplist soit chargée
console.log("[Worker] Stoplist chargée avec checkThreshold ?", stoplistFr.size > 0 ? `Oui (${stoplistFr.size} mots)` : "Non (aucun filtrage)");
if (!autoAddEnabled || !isAuthenticated) {
console.log("[Worker] Auto-Add désactivé ou utilisateur non connecté.");
return;
......@@ -190,21 +209,48 @@ async function checkThreshold(lang) {
if (!storedFrequencies[lang]) return;
// Vérifier si la stoplist a bien été chargée
if (!stoplistFr || !(stoplistFr instanceof Set)) {
console.warn("[Worker] ⚠ La stoplist n'est pas disponible ou mal initialisée. Aucun filtrage appliqué.");
}
// Vérifier si une stoplist est disponible et si l'utilisateur veut exclure les stopwords
const shouldFilterStopwords = stoplistFr && stoplistFr.size > 0 && (includeStopwords === true);
if (shouldFilterStopwords) {
console.log("[Worker] Filtrage des mots outils activé.");
} else {
console.log("[Worker] Aucune stoplist détectée ou filtrage désactivé. Tous les mots seront pris en compte.");
}
const exceededWords = Object.entries(storedFrequencies[lang])
.filter(([word, count]) => count >= userThreshold && !(notifiedWords[lang] && notifiedWords[lang].includes(word)))
.map(([word]) => word);
if (exceededWords.length === 0) return;
// Appliquer le filtrage si nécessaire
//const finalWords = shouldFilterStopwords ? exceededWords.filter(word => !stoplistFr.has(word)) : exceededWords;
const finalWords = exceededWords.filter(word => {
if (shouldFilterStopwords) {
const isInStoplist = stoplistFr.has(word);
console.log(`[Worker] Mot "${word}" ${isInStoplist ? "EXCLU (dans la stoplist)" : "CONSERVÉ (pas dans la stoplist)"}`);
return !isInStoplist;
}
return true; // Si on ne filtre pas, garder tous les mots
});
if (finalWords.length === 0) return;
if (!notifiedWords[lang]) notifiedWords[lang] = [];
notifiedWords[lang].push(...exceededWords);
notifiedWords[lang].push(...finalWords);
console.log("Mots dépassant le seuil :", finalWords);
self.postMessage({ type: "threshold-exceeded", wordsAboveThreshold: finalWords });
console.log("Mots dépassant le seuil :", exceededWords);
self.postMessage({ type: "threshold-exceeded", wordsAboveThreshold: exceededWords });
// Stocker les mots détectés pour un ajout groupé
if (!pendingWords[lang]) pendingWords[lang] = [];
pendingWords[lang].push(...exceededWords);
pendingWords[lang].push(...finalWords);
// Déclencher un envoi groupé après un délai (3 secondes)
if (!addWordTimeout) {
......@@ -214,6 +260,7 @@ async function checkThreshold(lang) {
}
}
//Traiter les ajouts groupés
async function processPendingWords() {
console.log("Traitement des mots à ajouter en lot...");
......@@ -239,10 +286,19 @@ async function addWordToLexicon(lang, word) {
console.log(`Tentative d'ajout du mot '${word}' pour la langue '${lang}'`);
// Vérifier si on a une stoplist et si l'utilisateur veut exclure les stopwords
const shouldFilterStopwords = stoplistFr && stoplistFr.size > 0 && !includeStopwords;
// Si le filtrage est activé et que le mot est un stopword, on ne l'ajoute pas
if (shouldFilterStopwords && stoplistFr.has(word)) {
console.log(`🔹 Mot '${word}' ignoré car présent dans la stoplist.`);
return;
}
// Trouver les lexiques correspondant à la langue détectée
const targetLexicons = userLexicons
.filter(lexicon => lexicon.language === lang && lexicon.category === "User")
.map(lexicon => lexicon.id);
.filter(lexicon => lexicon.language === lang && lexicon.category === "User")
.map(lexicon => lexicon.id);
if (targetLexicons.length === 0) {
console.warn(`Aucun lexique trouvé pour la langue '${lang}'. Impossible d'ajouter '${word}'.`);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment