diff --git a/src/popup/popup.js b/src/popup/popup.js index 5a480f574f6da5d3cf889332fc46e6717a6cc4ef..0a552d45e46e18073fb91990705c96816bdc992e 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -1,201 +1,380 @@ -// Écoute des messages depuis background.js === -// browser.runtime.onMessage.addListener((message) => { -// if (message.action === "updateUI") { -// console.log("📩 Mise à jour reçue : État connecté :", message.isLoggedIn); -// console.log("🔄 Actualisation du menu de l'extension déclenchée."); -// updateConnectionButton(); -// } -// }); - -// ───────────────────────────────────────────────────────────────────────────── -// Gestion des actions des boutons de la popup -// ───────────────────────────────────────────────────────────────────────────── - -// === Connexion/Déconnexion === -async function updateConnectionButton() { - const { accessToken } = await browser.storage.local.get("accessToken"); - const button = document.getElementById("auth-button"); +log("✅ popup.js chargé avec succès !"); - if (button) { - button.textContent = accessToken ? "Se déconnecter" : "Se connecter"; - button.onclick = async () => { - await browser.runtime.sendMessage({ action: "toggleAuth" }); - }; - } else { - console.error("⌠Le bouton de connexion n'a pas été trouvé."); - } +// ========================== +// Fonctions utilitaires +// ========================== +async function getAccessToken() { + const { accessToken } = await browser.storage.local.get("accessToken"); + return accessToken; } +// ========================== +// Gestion de la connexion +// ========================== +async function updateConnectionButton() { + const accessToken = await getAccessToken(); + const button = document.getElementById("auth-button"); -// === Activer/Désactiver l'extension (à faire: supprimer les variables du local storage sauf celle des fréquences) === -document.getElementById("toggleExtensionBtn").addEventListener("click", async () => { - const { extensionActive } = await browser.storage.local.get("extensionActive"); - const newState = !extensionActive; - await browser.storage.local.set({ extensionActive: newState }); - alert(`Extension ${newState ? "activée" : "désactivée"}.`); -}); - - -// === Activer/Désactiver les statistiques === - -document.getElementById("toggleStatsBtn").addEventListener("click", async () => { - const newState = !(await browser.storage.local.get("isTrackingActive")).isTrackingActive; - // Récupérer la valeur du local storage pour savoir si le tracking est actif ou non - await browser.storage.local.set({ isTrackingActive: newState }); - // Si false : désactiver et décocher l'ajout automatique, cacher le bouton valider - if (!newState) { - await browser.storage.local.set({ autoAdd: false }); - document.getElementById("auto-add").checked = false; - document.getElementById("auto-add-options").classList.add("hidden"); - document.getElementById("save-options").classList.add("hidden"); - } - // Inverser le texte lorsqu'on change d'état et cacher les options - document.getElementById("toggleStatsBtn").textContent = newState ? "Désactiver les statistiques" : "Activer les statistiques"; - document.getElementById("stats-options").classList.toggle("hidden", !newState); - // Mettre à jour l'affichage des options utilisateur - await updateOptionsUI() - // Envoi du message au background script : toggle-stats - browser.runtime.sendMessage({ command: "toggle-stats", isActive: newState }); - //pyodide-simplemma : récupère pyodide et simplemma si besoin - if (newState) { - console.log("[Popup] Initialisation de Pyodide et Simplemma"); - browser.runtime.sendMessage({ command: "pyodide-simplemma" }); } -}); - -// === Cocherajout automatique === -document.getElementById("auto-add").addEventListener("change", async () => { - const isChecked = document.getElementById("auto-add").checked; - // Affichage dynamique - 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 }); + if (!button) { + console.error("⌠Le bouton de connexion n'a pas été trouvé."); + return; } - -}); -// === Sauvegarder les options === -document.getElementById("save-options").addEventListener("click", async () => { - const autoAdd = document.getElementById("auto-add").checked; - const threshold = parseInt(document.getElementById("threshold").value, 10); - const selectedLanguages = Array.from(document.querySelectorAll("#language-selection .lang-option.selected")) - .map(option => option.dataset.value); - //Message d'erreur si une langue n'est pas au moins sélectionée - const errorMessage = document.getElementById("error-message"); - // Vérifier si au moins une langue est sélectionnée - if (autoAdd && selectedLanguages.length === 0) { - errorMessage.classList.remove("hidden"); // Afficher le message d'erreur - return; + if (accessToken) { + button.textContent = "Se déconnecter"; + button.title = "En vous déconnectant, vous perdrez l'accès à vos lexiques personnels, ainsi que les fonctionnalités d'ajout automatique et de statistiques d'utilisation."; + } else { + button.textContent = "Se connecter"; + button.title = "En vous connectant, vous pourrez accéder à vos lexiques personnels, ainsi qu'aux fonctionnalités d'ajout automatique et de statistiques d'utilisation."; } - // Masquer l'erreur si elle était affichée - errorMessage.classList.add("hidden"); - //Enregistrer les préférences - await browser.storage.local.set({ - autoAdd, - threshold, - trackedLanguages: selectedLanguages - }); - console.log("Options sauvegardées :", { autoAdd, threshold, trackedLanguages: selectedLanguages }); -}); - -// ───────────────────────────────────────────────────────────────────────────── -// Fonctions d'affichage et gestion des boutons pour les statistiques -// ───────────────────────────────────────────────────────────────────────────── -// === Bouton de statistiques === -async function updateStatsBtn() { - const toggleStatsBtn = document.getElementById("toggleStatsBtn"); - const { isTrackingActive } = await browser.storage.local.get("isTrackingActive") || { isTrackingActive: false }; - // Mettre à jour le bouton des statistiques - toggleStatsBtn.textContent = isTrackingActive ? "Désactiver les statistiques" : "Activer les statistiques"; + button.onclick = async () => { + await browser.runtime.sendMessage({ action: "toggleAuth" }); + }; } -// === Affichage et gestion de la sélection des langues de l'utilisateur === +// ========================== +// Gestion de la sélection des langues +// ========================== async function updateLanguageSelection() { const languageSelection = document.getElementById("language-selection"); languageSelection.innerHTML = "<p id='loading-languages' style='color: gray;'>Chargement...</p>"; - // Vérifier si l'utilisateur est connecté - const { accessToken } = await browser.storage.local.get("accessToken"); + + const accessToken = await getAccessToken(); if (!accessToken) { - languageSelection.innerHTML = "<p style='color: red;'>Veuillez vous connecter.</p>"; - return; + languageSelection.innerHTML = "<p style='color: red;'>Veuillez vous connecter.</p>"; + return; } - // Récupération des lexiques de l'utilisateur - const lexicons = await getUserLexicons(accessToken); + + // Utilisation de la fonction de récupération de lexiques + // Choisissez ici entre getLexicons et getUserLexicons en fonction de votre implémentation + const lexicons = await getLexicons(accessToken); const userLanguages = [...new Set(lexicons.map(lex => lex.language))]; - // Récupérer les langues actuellement suivies depuis le local storage - const storedData = await browser.storage.local.get("trackedLanguages"); - const trackedLanguages = storedData.trackedLanguages || []; - // Nettoyage de l'affichage + + // Récupérer les langues suivies depuis le stockage + const { trackedLanguages } = await browser.storage.local.get("trackedLanguages") || { trackedLanguages: [] }; + languageSelection.innerHTML = ""; if (userLanguages.length === 0) { - languageSelection.innerHTML = "<p style='color: red;'>Aucun lexique personnel trouvé.</p>"; - return; + languageSelection.innerHTML = "<p style='color: red;'>Aucun lexique personnel trouvé.</p>"; + return; } + userLanguages.forEach(lang => { - const langButton = document.createElement("div"); - langButton.classList.add("lang-option"); - langButton.textContent = lang.toUpperCase(); - langButton.dataset.value = lang; - // Vérifier si la langue est déjà suivie et ajouter la classe selected - if (trackedLanguages.includes(lang)) { - langButton.classList.add("selected"); - } - // Ajouter l'événement pour gérer la sélection/désélection - langButton.addEventListener("click", () => { - langButton.classList.toggle("selected"); - }); - languageSelection.appendChild(langButton); + const langButton = document.createElement("div"); + langButton.classList.add("lang-option"); + langButton.textContent = lang.toUpperCase(); + langButton.dataset.value = lang; + if (trackedLanguages && trackedLanguages.includes(lang)) { + langButton.classList.add("selected"); + } + langButton.addEventListener("click", () => { + langButton.classList.toggle("selected"); + }); + languageSelection.appendChild(langButton); }); - console.log("Sélection des langues :", userLanguages); + log("✅ Sélection des langues mise à jour avec :", userLanguages); } -// === Options des statistiques === +// ========================== +// Gestion des options et des statistiques +// ========================== async function updateOptionsUI() { - const { accessToken } = await browser.storage.local.get("accessToken"); - const isLoggedIn = !!accessToken; // Vérifie si l'utilisateur est connecté + const accessToken = await getAccessToken(); + const isLoggedIn = !!accessToken; const statsOptions = document.getElementById("stats-options"); - const autoAddContainer = document.getElementById("auto-add").parentElement; + const autoAddContainer = document.getElementById("auto-add")?.parentElement; const autoAddCheckbox = document.getElementById("auto-add"); const autoAddOptions = document.getElementById("auto-add-options"); const thresholdInput = document.getElementById("threshold"); const saveOptionsBtn = document.getElementById("save-options"); - // Masquer l'option "Ajout Automatique" si l'utilisateur n'est pas connecté - autoAddContainer.style.display = isLoggedIn ? "block" : "none"; - // Charger les préférences utilisateur + const toggleStatsBtn = document.getElementById("toggleStatsBtn"); + const openStats = document.getElementById("open-stats"); + + // 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([ - "isTrackingActive", - "autoAdd", - "threshold" + "isTrackingActive", + "autoAdd", + "threshold" ]) || { isTrackingActive: false }; - // Mettre à jour le bouton des statistiques - document.getElementById("toggleStatsBtn").textContent = isTrackingActive ? "Désactiver les statistiques" : "Activer les statistiques"; - statsOptions.classList.toggle("hidden", !isTrackingActive); + + // Gestion du bouton de statistiques + if (toggleStatsBtn) { + if (!isLoggedIn) { + toggleStatsBtn.style.opacity = "0.5"; + toggleStatsBtn.title = "Connectez-vous pour activer les statistiques"; + if (openStats) openStats.style.display = "none"; + } else { + toggleStatsBtn.style.opacity = "1"; + toggleStatsBtn.title = ""; + if (openStats) openStats.style.display = "block"; + } + toggleStatsBtn.textContent = isTrackingActive ? "Désactiver les statistiques" : "Activer les statistiques"; + } + + // Affichage des options statistiques + if (statsOptions) { + statsOptions.classList.toggle("hidden", !isTrackingActive); + } + if (isLoggedIn) { + if (autoAddCheckbox) { autoAddCheckbox.checked = autoAdd || false; - if (threshold !== undefined) thresholdInput.value = threshold; - // Afficher ou masquer les options d'ajout automatique en fonction de la case cochée + } + if (thresholdInput && threshold !== undefined) { + thresholdInput.value = threshold; + } + if (autoAddOptions) { autoAddOptions.classList.toggle("hidden", !autoAdd); + } + if (saveOptionsBtn) { saveOptionsBtn.classList.toggle("hidden", !autoAdd); + } } else { + if (autoAddCheckbox) { autoAddCheckbox.checked = false; + } + if (autoAddOptions) { autoAddOptions.classList.add("hidden"); + } + if (saveOptionsBtn) { saveOptionsBtn.classList.add("hidden"); + } + } +} + +// ========================== +// Gestion de l'activation/désactivation de l'extension +// ========================== +async function updateExtensionToggleButton() { + const { accessToken, extensionActive } = await browser.storage.local.get(["accessToken", "extensionActive"]); + const toggleButton = document.getElementById("toggleExtensionBtn"); + + if (!toggleButton) { + console.error("⌠Le bouton d'activation de l'analyse n'a pas été trouvé."); + return; + } + + if (!accessToken) { + toggleButton.textContent = "Activer l'analyse"; + toggleButton.style.opacity = "0.5"; + toggleButton.title = "Connectez-vous pour activer l'analyse"; + } else { + toggleButton.style.opacity = "1"; + toggleButton.textContent = extensionActive ? "Désactiver l'analyse" : "Activer l'analyse"; + toggleButton.title = ""; + } + + // Ajout d'un écouteur unique + if (!toggleButton.dataset.listenerAdded) { + toggleButton.addEventListener("click", handleToggleExtension); + toggleButton.dataset.listenerAdded = "true"; + } +} + +function handleToggleExtension() { + getAccessToken().then(accessToken => { + if (!accessToken) return; + proceedToggleExtension(); + }); +} + +async function proceedToggleExtension() { + const { extensionActive, isTrackingActive } = await browser.storage.local.get({ + extensionActive: false, + isTrackingActive: false + }); + const newState = !extensionActive; + await browser.storage.local.set({ extensionActive: newState }); + + const toggleButton = document.getElementById("toggleExtensionBtn"); + if (toggleButton) { + toggleButton.textContent = newState ? "Désactiver l'analyse" : "Activer l'analyse"; + } + + browser.runtime.sendMessage({ action: "toggleExtension", isActive: newState }); + + if (!newState) { + await browser.storage.local.set({ isTrackingActive: false }); + // Si les statistiques étaient activées, ouvrir la page stats + if (isTrackingActive) window.open("stats.html", "_blank"); + browser.runtime.sendMessage({ action: "closeSidebarBlocks" }); } + + await updateOptionsUI(); } -// ───────────────────────────────────────────────────────────────────────────── -// Mise à jour des boutons dans le menu d'extension -// ───────────────────────────────────────────────────────────────────────────── +// ========================== +// Écouteurs d'événements +// ========================== document.addEventListener("DOMContentLoaded", async () => { await updateConnectionButton(); - await updateStatsBtn(); await updateOptionsUI(); await updateLanguageSelection(); + await updateExtensionToggleButton(); +}); + +// Gestion des statistiques et options +document.getElementById("toggleStatsBtn")?.addEventListener("click", async () => { + const accessToken = await getAccessToken(); + if (!accessToken) return; + + const current = await browser.storage.local.get("isTrackingActive"); + const newState = !current.isTrackingActive; + await browser.storage.local.set({ isTrackingActive: newState }); + + // Si désactivation, désactiver aussi l'ajout automatique + if (!newState) { + await browser.storage.local.set({ autoAdd: false }); + document.getElementById("auto-add").checked = false; + document.getElementById("auto-add-options").classList.add("hidden"); + document.getElementById("save-options").classList.add("hidden"); + } + + document.getElementById("toggleStatsBtn").textContent = newState ? "Désactiver les statistiques" : "Activer les statistiques"; + document.getElementById("stats-options").classList.toggle("hidden", !newState); + + // Envoi du message au background pour le changement de tracking + browser.runtime.sendMessage({ command: "toggle-stats", isActive: newState }); + if (newState) { + log("[Popup] Demande d'initialisation de Pyodide et Simplemma"); + // Garder la commande de file 2 pour l'initialisation de Pyodide/Simplemma + browser.runtime.sendMessage({ command: "pyodide-simplemma" }); + } +}); + +// Gestion du changement de l'option d'ajout automatique +document.getElementById("auto-add")?.addEventListener("change", async () => { + const isChecked = document.getElementById("auto-add").checked; + 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 }); + } +}); + +// Sauvegarde des options utilisateur +document.getElementById("save-options")?.addEventListener("click", async () => { + const autoAdd = document.getElementById("auto-add").checked; + const threshold = parseInt(document.getElementById("threshold").value, 10); + const selectedLanguages = Array.from(document.querySelectorAll("#language-selection .lang-option.selected")) + .map(option => option.dataset.value); + + // 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) { + errorMessage?.classList.remove("hidden"); + return; + } + errorMessage?.classList.add("hidden"); + + await browser.storage.local.set({ + autoAdd, + threshold, + trackedLanguages: selectedLanguages + }); + log("Options sauvegardées :", { autoAdd, threshold, trackedLanguages: selectedLanguages }); }); +// Bouton pour ouvrir la page des statistiques +document.getElementById("open-stats")?.addEventListener("click", async () => { + await displayStatsSummary();//résumé dans la console + window.open("stats.html", "_blank"); +}); + + +async function displayStatsSummary() { + console.log("[Popup] Préparation du résumé des statistiques..."); + // Récupérer les données stockées + const { lemmaFrequencies, trackedLanguages, wordsAdded } = await browser.storage.local.get([ + "lemmaFrequencies", + "trackedLanguages", + "wordsAdded" + ]); + // Initialisation du résumé + let summary = { + totalWords: 0, // Nombre total de mots analysés + totalUniqueWords: 0, // Nombre total de mots uniques + languages: {}, // Nombre de mots analysés par langue + wordsAdded: wordsAdded || {} // Mots ajoutés classés par langue + }; + if (lemmaFrequencies) { + Object.entries(lemmaFrequencies).forEach(([lang, words]) => { + const wordCount = Object.values(words).reduce((sum, count) => sum + count, 0); + const uniqueWordCount = Object.keys(words).length; + + // Vérifier si la langue doit être suivie + if (!trackedLanguages || trackedLanguages.includes(lang)) { + summary.languages[lang] = { + totalWords: wordCount, + uniqueWords: uniqueWordCount + }; + + summary.totalWords += wordCount; + summary.totalUniqueWords += uniqueWordCount; + } + }); + } + + console.log("[Popup] Résumé des statistiques mis à jour:", summary); + + // Résumé dans le local storage + await browser.storage.local.set({ statsSummary: summary }); +} + + + +// ========================== +// Réception des messages du background +// ========================== +browser.runtime.onMessage.addListener(async (message) => { + log("📩 Message reçu dans popup.js :", message); + + if (message.action === "updateUI") { + log("🔄 Mise à jour de l'UI du popup..."); + await updateConnectionButton(); + await updateOptionsUI(); + await updateLanguageSelection(); + // Possibilité de mettre à jour d'autres éléments via le message + } else if (message.action === "showNotification") { + // Gestion des notifications si besoin + showNotification(message.text); + } +}); + +// Actualisation de l'UI en cas de changement dans le stockage local +browser.storage.onChanged.addListener((changes, area) => { + if (area === "local" && changes.accessToken) { + updateConnectionButton(); + updateExtensionToggleButton(); + } +}); + +// ========================== +// Gestion de l'affichage de notifications (optionnelle) +// ========================== +function showNotification(message) { + const notificationBox = document.getElementById("extension-notification"); + const notificationText = document.getElementById("notification-text"); + const closeButton = document.getElementById("close-notification"); + + if (notificationBox && notificationText && closeButton) { + notificationText.textContent = message; + notificationBox.classList.remove("hidden"); + closeButton.addEventListener("click", () => { + notificationBox.classList.add("hidden"); + }, { once: true }); + } else { + console.error("⌠Impossible d'afficher la notification : élément manquant."); + } +}