diff --git a/manifest.json b/manifest.json index 5817a844c640730cf92f218f1a8d4ba04e8302a2..0d06a6f6d9be2633c0feb0fbaea7f7e334fcb466 100644 --- a/manifest.json +++ b/manifest.json @@ -24,7 +24,8 @@ "src/background/background.js", "src/utils/definitions.js", "src/utils/api.js", - "src/context_menu/browser_context_menu.js" + "src/context_menu/browser_context_menu.js", + "src/utils/stats.js" ], "persistent": true }, diff --git a/src/background/background.js b/src/background/background.js index 2ad660a35280c702f3baba04c7e748145894c6d9..be3cfae4fa1afd38331d9898c5264449bc1beee2 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -53,7 +53,6 @@ browser.storage.onChanged.addListener((changes, area) => { if (!extensionActive) { log("Token ajouté, activation automatique de l'extension."); browser.storage.local.set({ extensionActive: true }); // Met à jour l'état de l'extension - updateExtension(); // Met à jour les fonctionnalités de l'extension // Envoie un message pour mettre à jour l'interface utilisateur browser.runtime.sendMessage({ action: "updateUI", @@ -773,7 +772,7 @@ browser.runtime.onConnect.addListener((port) => { * @returns {Promise<boolean>} - True si le surlignage a été effectué, false sinon. */ async function handleHighlighting(command, lexiconId, tabId) { - log(`🎯 Gestion du surlignage: ${command} pour le lexique ${lexiconId}`); + log(`Gestion du surlignage: ${command} pour le lexique ${lexiconId}`); try { // S'assurer que le script est injecté @@ -794,4 +793,4 @@ async function handleHighlighting(command, lexiconId, tabId) { log("Erreur lors de la gestion du surlignage:", error); return false; } -} \ No newline at end of file +} diff --git a/src/options/options.html b/src/options/options.html deleted file mode 100644 index 8b2bfa963d5f5369b8b67464fd9ac95a506d4253..0000000000000000000000000000000000000000 --- a/src/options/options.html +++ /dev/null @@ -1,38 +0,0 @@ -<!-- <!DOCTYPE html> -<html lang="fr"> -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Paramètres ff2BaLex</title> - <script src="../utils/logger.js"></script> - <style> - body { - font-family: Luciole; - padding: 20px; - background-color: #323046; - color: white; - } - button { - width: 100%; - padding: 10px; - margin-bottom: 10px; - font-size: 15px; - color: #94608a; - font-weight: bold; - border: none; - cursor: pointer; - } - button:hover { - background-color: #94608a; - color: white; - } - </style> -</head> -<body> - <h3>Paramètres BaLex</h3> - <button id="connectBtn">Se connecter</button> - <button id="toggleExtensionBtn">Activer/Désactiver l'extension</button> - <button id="toggleStatsBtn">Activer/Désactiver les statistiques</button> - <script src="options.js"></script> -</body> -</html> --> diff --git a/src/options/options.js b/src/options/options.js deleted file mode 100644 index da48f12e80a3aaf985363633861795ef709f6d89..0000000000000000000000000000000000000000 --- a/src/options/options.js +++ /dev/null @@ -1,28 +0,0 @@ -// document.getElementById('connectBtn').addEventListener('click', () => { -// browser.runtime.sendMessage({ action: "openLoginPage" }); -// }); - -// async function disconnectFromLexicalDB() { -// await browser.storage.local.remove("accessToken"); -// log("Token supprimé, déconnexion réussie."); -// alert("Déconnexion réussie."); -// updateContextMenu(); - -// // Envoi d'un message pour mettre à jour l'UI -// browser.runtime.sendMessage({ action: "updateUI" }); -// } - -// 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"}.`); -// }); - -// document.getElementById("toggleStatsBtn").addEventListener("click", async () => { -// const { statsActive } = await browser.storage.local.get("statsActive"); -// const newState = !statsActive; -// await browser.storage.local.set({ statsActive: newState }); -// alert(`Statistiques ${newState ? "activées" : "désactivées"}.`); -// }); - diff --git a/src/plugin/plugin.html b/src/plugin/plugin.html index ca17e78d592e801a20fe1145af7ac348e654abf3..8db7d83258925205e7b8227a586ec5781482eff3 100644 --- a/src/plugin/plugin.html +++ b/src/plugin/plugin.html @@ -5,6 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Extension BaLex</title> <script src="../utils/logger.js"></script> + <link rel="stylesheet" href="../css/plugin.css"> </head> <body> @@ -70,7 +71,8 @@ <button id="close-notification">OK</button> </div> - <script src="../utils/api.js"></script> - <script src="plugin.js"></script> + <script src="../utils/api.js" defer></script> + <script src="plugin.js" defer></script> + <script src="../utils/stats.js" defer></script> </body> </html> diff --git a/src/plugin/plugin.js b/src/plugin/plugin.js index 57f873074c478b902f3d8ebe9c61e6a6aa86a046..8d07f221682df8752de105a995c8a3e6b932da12 100644 --- a/src/plugin/plugin.js +++ b/src/plugin/plugin.js @@ -1,4 +1,4 @@ -log("plugin chargé avec succès !"); +log("plugin.js chargé."); // fetchExtensionState() : fonction qui se charge de récupérer les valeurs du local storage // updateUI(): utilise les états récupérés par fetchExtensionState pour appeler d'autres fonctions // ex. actualisation du bouton de connexion, bouton activer l'extension, les stats... @@ -9,6 +9,7 @@ log("plugin chargé avec succès !"); // ==================================================================================== // Fonctions utilitaires // ==================================================================================== +let isUpdatingLexicons = false; //Obtenir le token async function getAccessToken() { diff --git a/src/popup/popup.html b/src/popup/popup.html deleted file mode 100644 index e4b7b95dfa114df2781a2cb06102b8bb1c8ade21..0000000000000000000000000000000000000000 --- a/src/popup/popup.html +++ /dev/null @@ -1,416 +0,0 @@ -<!DOCTYPE html> -<html lang="fr"> -<head> - <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> - @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: visibility 0.3s ease; - } - #extension-notification.hidden { - 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: 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: #dddedd; - color: #8d5c70; - } - #auth-button { - width: auto; - display: inline-flex; - padding: 6px 12px; - font-size: 16px; - 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; - } - #auth-button:hover { - background: rgba(255,255,255,0.2); - } - #auth-button svg { - width: 18px; - height: 18px; - fill: white; - transition: transform 0.3s ease-in-out; - } - #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: 8px; - border-radius: 10px; - box-shadow: 0 2px 6px rgba(0,0,0,0.2); - } - .option-row { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: nowrap; - padding: 12px; - border-radius: 6px; - background-color: #444; - color: white; - 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: 13px; - 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: 13px; - box-sizing: border-box; - background: #fff; - color: #333; - } - #save-options { - border: none; - background: #8d5c70; - border-radius: 6px; - color: white; - padding: 8px 12px; - font-size: 14px; - 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; - gap: 8px; - } - .lang-option { - padding: 4px 10px; - border: 2px solid #8d5c70; - border-radius: 16px; - background: rgb(152, 152, 152); - color: #8d5c70; - cursor: pointer; - 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: #8d5c70; - color: white; - border-color: #8d5c70; - } - .option-row.auto-add-row { - position: relative; - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 12px; - margin-bottom: 0; - background: transparent; - border-bottom: 1px solid #555; - } - .option-row.auto-add-row span { - font-size: 14px; - font-weight: lighter; - } - .option-row.stopwords { - position: relative; - display: flex; - align-items: center; - justify-content: space-between; - font-size: 13px; - font-weight: lighter; - } - #open-stats { - padding: 6px; - font-weight: lighter; - width: auto; - display: block; - margin: 0 auto; - margin-bottom: 10px; - background-color: #525877; - color: white; - border: 2px solid #8d5c70; - border-radius: 8px; - } - .hidden { - display: none; - } - #error-message { - font-size: 13px; - font-style: italic; - text-align: center; - color: white; - } - .tooltip-container { - position: relative; - display: inline-block; - pointer-events: auto !important; - } - .tooltip { - all: unset; - display: block; - box-sizing: border-box; - position: absolute; - left: 50%; - transform: translateX(-50%); - color: #fff !important; - font-size: 12px !important; - font-weight: lighter !important; - padding: 6px 10px; - border-radius: 5px; - white-space: normal; - overflow-wrap: break-word; - width: 200px; - text-align: center; - visibility: hidden; - transition: visibility 0.3s ease-in-out, transform 0.3s ease-in-out; - pointer-events: none; - z-index: 1000; - line-height: normal; - } - /* Règle générique pour les tooltips */ - .tooltip-container .tooltip { - bottom: 120%; - transform: translateX(-50%); - background-color: rgba(0,0,0,0.9) !important; - visibility: hidden; - pointer-events: auto !important; - } - .tooltip-container:hover .tooltip { - visibility: visible !important; - transform: translateX(-50%) translateY(-5px); - pointer-events: auto !important; - } - /* Style spécifique pour le bouton de connexion */ - #auth-button .tooltip { - top: 120%; - bottom: auto; - } - #auth-button.tooltip-container:hover .tooltip { - visibility: visible !important; - transform: translateX(-50%) translateY(5px); - } - /* Permettre l'interaction avec les tooltips même sur les boutons désactivés */ - button:disabled .tooltip { - pointer-events: auto !important; - } - </style> -</head> -<body> - <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="pyodide-loading"></div> - - <div id="stats-options" class="option-container"> - <div id="auto-add-container" 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> - </div> - <!-- Message d'erreur si aucune langue sélectionnée --> - <div id="error-message" class="hidden"> - <p>Veuillez sélectionner une ou plusieurs langue(s).</p> - </div> - <button id="save-options" class="hidden">Valider</button> - </div> - </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> diff --git a/src/popup/popup.js b/src/popup/popup.js deleted file mode 100644 index 6cc4015222f93d5aa8930308672b75132d8c0efd..0000000000000000000000000000000000000000 --- a/src/popup/popup.js +++ /dev/null @@ -1,577 +0,0 @@ -log("✅ popup.js chargé avec succès !"); -// fetchExtensionState() : fonction qui se charge de récupérer les valeurs du local storage -// updateUI(): utilise les états récupérés par fetchExtensionState pour appeler d'autres fonctions -// ex. actualisation du bouton de connexion, bouton activer l'extension, les stats... -// setupEventListeners() : fonction qui regroupe les écouteurs d'évènement -// handleEvent() : une description de chaque évènement avec les changements de valeur du local storage - - -// ==================================================================================== -// Fonctions utilitaires -// ==================================================================================== - -//Obtenir le token -async function getAccessToken() { - const { accessToken } = await browser.storage.local.get("accessToken"); - return accessToken; -} - -// ========= -// Fonction d'actualisation générale de la popup : 1. Récupération des valeurs 2. Mà j UI -async function updateExtension() { - states = await fetchExtensionState(); //Récupérer les valeurs - updateUI(states); // Selon les valeurs, mettre à jour l'UI -} - -// ========= -// 1. Récupérer les valeurs du local storage -async function fetchExtensionState() { - const accessToken = await getAccessToken(); - const storedValues = await browser.storage.local.get([ - "extensionActive", - "isTrackingActive", - "autoAdd", - "threshold", - "pyodideSimplemmaReady", - "includeStopwords" - ]); - return { - isLoggedIn: !!accessToken, - extensionActive: storedValues.extensionActive ?? false, - isTrackingActive: storedValues.isTrackingActive ?? false, - autoAdd: storedValues.autoAdd ?? false, - threshold: storedValues.threshold ?? 10, - pyodideSimplemmaReady: storedValues.pyodideSimplemmaReady ?? false, - includeStopwords: storedValues.includeStopwords ?? false - }; -} - -// ========= -// 2.Fonction de mise à jour de l'UI -async function updateUI(states) { - await updateConnectionButton(states.isLoggedIn); //Actualisation du bouton de connexion - await updateToggleExtensionButton(states.isLoggedIn, states.extensionActive, states.autoAdd, states.isTrackingActive, states.pyodideSimplemmaReady, states.includeStopwords); - // éventuellement ajouter des fonctions issues du toggleExtensionButton pour la lisibilité : - //await updateStatsButtons(states.isLoggedIn, states.extensionActive, states.isTrackingActive); - // await updateAutoAddOptions(states.isLoggedIn, states.extensionActive, states.autoAdd); - // await updatePyodideStatus(states.isLoggedIn, states.extensionActive, states.isTrackingActive, state.pyodideSimplemmaReady); - await updateLanguageSelection(); - await updateStopwordsOption(states.includeStopwords); - console.log("✅ Interface mise à jour :", states); -} - - - -// ==================================================================================== -// Fonction contenant les écouteurs d'évènements et gestion des valeurs du local storage -// ==================================================================================== -function setupEventListeners() { - // Bouton Connexion / Déconnexion - document.getElementById("auth-button")?.addEventListener("click", handleAuthToggle); - - // Bouton activer l'extension - document.getElementById("toggleExtensionBtn")?.addEventListener("click", handleToggleExtension); - - // Bouton de gestion des statistiques - document.getElementById("toggleStatsBtn")?.addEventListener("click", handleStatsToggle); - - // Gestion de l'ajout automatique - document.getElementById("auto-add")?.addEventListener("change", handleAutoAddToggle); - - //Activation/désactivation des stopwords - document.getElementById("include-stopwords")?.addEventListener("change", handleStopwordsToggle); - - // Sauvegarde des options - document.getElementById("save-options")?.addEventListener("click", handleSaveOptions); - - // Ouverture de la page des statistiques - // TODO : ajouter l'évènement - document.getElementById("open-stats")?.addEventListener("click", () => { - window.open("stats.html", "_blank"); - }); -} - -// =========== -//Description de chaque évènement - -//Connexion / Déconnexion -async function handleAuthToggle() { - const accessToken = await getAccessToken(); - if (!accessToken) { - console.log("🔓 Connexion demandée..."); - await browser.runtime.sendMessage({ action: "toggleAuth" }); - } else { - console.log("🔒 Déconnexion demandée..."); - await browser.storage.local.set({ - accessToken: null, - autoAdd: false, - includeStopwords: false, - isTrackingActive: false - }); - browser.runtime.sendMessage({ - command: "update-preferences", - autoAdd: false, - includeStopwords: false, - isTrackingActive: false - }); - console.log("✅ Paramètres réinitialisés après déconnexion."); - } - await updateExtension(); -} - -//Statistiques -async function handleStatsToggle() { - const accessToken = await getAccessToken(); - if (!accessToken) return; - // Récupérer l'état actuel des statistiques - const { isTrackingActive } = await browser.storage.local.get({ isTrackingActive: false }); - const newState = !isTrackingActive; - // Mise à jour uniquement de `isTrackingActive` - await browser.storage.local.set({ isTrackingActive: newState }); - console.log("📊 Nouvel état des statistiques :", newState); - // Envoi du message de mise à jour - browser.runtime.sendMessage({ command: "toggle-stats", isActive: newState }); - // Exécution de Pyodide si nécessaire - if (newState) { - browser.runtime.sendMessage({ command: "pyodide-simplemma" }); - } - - if (isUpdatingLexicons) return; - isUpdatingLexicons = true; - await updateLexiconsDisplay(); - isUpdatingLexicons = false; - await updateExtension(); -} - -// Activer l'extension -async function handleToggleExtension() { - const accessToken = await getAccessToken(); - if (!accessToken) return; - - const { extensionActive, isTrackingActive } = await browser.storage.local.get({ extensionActive: false, isTrackingActive: false }); - const newState = !extensionActive; - - await browser.storage.local.set({ extensionActive: newState }); - - if (!newState) { - await browser.storage.local.set({ isTrackingActive: false }); - if (isTrackingActive) window.open("stats.html", "_blank"); - browser.runtime.sendMessage({ action: "closeSidebarBlocks" }); - } - - browser.runtime.sendMessage({ action: "toggleExtension", isActive: newState }); - await updateExtension(); -} - - -//Ajout automatique -function handleAutoAddToggle() { - const autoAddCheckbox = document.getElementById("auto-add"); - const autoAddOptions = document.getElementById("auto-add-options"); - const saveOptionsBtn = document.getElementById("save-options"); - - if (!autoAddCheckbox || !autoAddOptions || !saveOptionsBtn) return; - - const isAutoAddEnabled = autoAddCheckbox.checked; - - // Juste afficher ou cacher les options, mais ne pas sauvegarder dans le local storage - autoAddOptions.classList.toggle("hidden", !isAutoAddEnabled); - saveOptionsBtn.classList.toggle("hidden", !isAutoAddEnabled); - - // Si on décoche, désactiver immédiatement et forcer la sauvegarde - if (!isAutoAddEnabled) { - browser.storage.local.set({ autoAdd: false, includeStopwords: false }); - document.getElementById("include-stopwords").checked = false; - console.log("Ajout automatique désactivé → Stopwords désactivés immédiatement."); - } -} - - -// Gestion de l'activation/désactivation des stopwords -function handleStopwordsToggle() { - const stopwordsCheckbox = document.getElementById("include-stopwords"); - if (!stopwordsCheckbox) return; - - // Si décoché, forcer immédiatement la mise à jour du local storage - if (!stopwordsCheckbox.checked) { - browser.storage.local.set({ includeStopwords: false }); - console.log("Stopwords désactivés immédiatement."); - } -} - - - -// Sauvegarde des options utilisateur -async function handleSaveOptions() { - const autoAddCheckbox = document.getElementById("auto-add"); - const stopwordsCheckbox = document.getElementById("include-stopwords"); - 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 errorMessage = document.getElementById("error-message"); - - if (autoAddCheckbox.checked && selectedLanguages.length === 0) { - errorMessage?.classList.remove("hidden"); - return; - } - errorMessage?.classList.add("hidden"); - - // Seule la validation met à jour le stockage local - await browser.storage.local.set({ - autoAdd: autoAddCheckbox.checked, - includeStopwords: stopwordsCheckbox.checked, - threshold, - trackedLanguages: selectedLanguages - }); - - browser.runtime.sendMessage({ - command: "update-preferences", - autoAdd: autoAddCheckbox.checked, - includeStopwords: stopwordsCheckbox.checked - }); - - await updateExtension(); - console.log("✅ Options sauvegardées."); -} - - -//Ouverture de la page des statistiques - -// ==================================================================================== -// Fonction actualisation UI des boutons -// ==================================================================================== - -// Gestion de la connexion -async function updateConnectionButton() { - const accessToken = await getAccessToken(); - //Vérification du bouton de connexion - const button = document.getElementById("auth-button"); - if (!button) { - console.error("⌠Le bouton de connexion n'a pas été trouvé."); - return; - } - if (accessToken) { - button.textContent = "Se déconnecter"; - button.style.position = "relative"; - button.className = "tooltip-container"; - const tooltip = document.createElement("span"); - tooltip.className = "tooltip"; - tooltip.textContent = "En vous déconnectant, vous perdrez l'accès à vos lexiques personnels, ainsi qu'aux fonctionnalités d'ajout automatique et de statistiques d'utilisation."; - button.appendChild(tooltip); - } else { - button.textContent = "Se connecter"; - button.style.position = "relative"; - button.className = "tooltip-container"; - const tooltip = document.createElement("span"); - tooltip.className = "tooltip"; - tooltip.textContent = "En vous connectant, vous pourrez accéder à vos lexiques personnels, ainsi qu'aux fonctionnalités d'ajout automatique et de statistiques d'utilisation."; - button.appendChild(tooltip); - } -} - -// 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>"; - - const storedData = await browser.storage.local.get("lexicons"); - const lexicons = storedData.lexicons || []; // Ne pas utiliser JSON.parse() - - if (!Array.isArray(lexicons) || lexicons.length === 0) { - log("Lexiques non trouvés, attente de la mise à jour..."); - languageSelection.innerHTML = "<p style='color: gray;'>En attente des lexiques...</p>"; - - // Écouteur pour détecter quand les lexiques sont stockés - const listener = (changes, area) => { - if (area === "local" && changes.lexicons) { - log("Lexiques détectés dans le stockage, mise à jour de la sélection !"); - browser.storage.onChanged.removeListener(listener); - updateLanguageSelection(); // Recharger l'affichage des langues - } - }; - browser.storage.onChanged.addListener(listener); - return; - } - - // Extraire les langues uniques - const userLanguages = [...new Set(lexicons.map(lex => lex.language))]; - - // Récupérer les langues suivies depuis le stockage - const { trackedLanguages } = (await browser.storage.local.get("trackedLanguages")) || { trackedLanguages: [] }; - - // Affichage des langues sous forme de boutons - languageSelection.innerHTML = ""; - userLanguages.forEach(lang => { - 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); - }); - - log("Sélection des langues mise à jour avec :", userLanguages); -} - -// ========= -// Gestion bouton d'activation de l'extension -async function updateToggleExtensionButton(isLoggedIn, extensionActive, autoAdd, isTrackingActive, pyodideSimplemmaReady, includeStopwords) { - const toggleExtensionBtn = document.getElementById("toggleExtensionBtn"); - - if (toggleExtensionBtn) { - toggleExtensionBtn.textContent = extensionActive ? "Désactiver l'analyse" : "Activer l'analyse"; - toggleExtensionBtn.style.pointerEvents = isLoggedIn ? "auto" : "none"; - toggleExtensionBtn.disabled = !isLoggedIn; - toggleExtensionBtn.style.position = "relative"; - toggleExtensionBtn.className = "tooltip-container"; - - const existingTooltipExt = toggleExtensionBtn.querySelector('.tooltip'); - if (existingTooltipExt) { - existingTooltipExt.remove(); - } - const tooltipExt = document.createElement("span"); - tooltipExt.className = "tooltip"; - tooltipExt.style.opacity = "1 !important"; - if (!isLoggedIn) { - tooltipExt.textContent = "Connectez-vous pour activer l'analyse"; - tooltipExt.style.display = "block"; - } else if (!extensionActive) { - tooltipExt.textContent = "Activer les fonctionnalités de l'extension : affichage des mots et des définitions de vos lexiques, ajout de mots, etc."; - tooltipExt.style.display = "block"; - } else { - tooltipExt.style.display = "none"; - } - toggleExtensionBtn.appendChild(tooltipExt); - } - - // Mise à jour des options de statistiques - const statsOptions = document.getElementById("stats-options"); - const toggleStatsBtn = document.getElementById("toggleStatsBtn"); - const openStats = document.getElementById("open-stats"); - if (statsOptions) { - statsOptions.style.display = (isLoggedIn && extensionActive) ? "block" : "none"; - } - - // Mise à jour du bouton des statistiques - if (toggleStatsBtn) { - const isEnabled = isLoggedIn && extensionActive; - toggleStatsBtn.textContent = isEnabled && isTrackingActive ? "Désactiver les statistiques" : "Activer les statistiques"; - toggleStatsBtn.style.pointerEvents = isEnabled ? "auto" : "none"; - toggleStatsBtn.disabled = !isEnabled; - toggleStatsBtn.style.position = "relative"; - toggleStatsBtn.className = "tooltip-container"; - const existingTooltipStats = toggleStatsBtn.querySelector('.tooltip'); - if (existingTooltipStats) { existingTooltipStats.remove(); } - const tooltipStats = document.createElement("span"); - tooltipStats.className = "tooltip"; - tooltipStats.style.opacity = "1 !important"; - if (!isLoggedIn) { - tooltipStats.textContent = "Connectez-vous pour accéder aux statistiques"; - tooltipStats.style.display = "block"; - } else if (!extensionActive) { - tooltipStats.textContent = "Veuillez activer l'analyse pour utiliser les statistiques"; - tooltipStats.style.display = "block"; - } else { - tooltipStats.style.display = "none"; - } - toggleStatsBtn.appendChild(tooltipStats); - } - if (openStats) { - openStats.style.display = (isLoggedIn && extensionActive && isTrackingActive) ? "block" : "none"; - } - - // Mise à jour des options d'ajout automatique - const autoAddContainer = document.getElementById("auto-add")?.parentElement; - const autoAddCheckbox = document.getElementById("auto-add"); - const autoAddOptions = document.getElementById("auto-add-options"); - const saveOptionsBtn = document.getElementById("save-options"); - - if (autoAddContainer) { - autoAddContainer.style.display = (isLoggedIn && extensionActive) ? "block" : "none"; - } - if (autoAddCheckbox && isLoggedIn) { - autoAddCheckbox.checked = autoAdd; - } - if (autoAddOptions) { - autoAddOptions.classList.toggle("hidden", !autoAdd); - } - if (saveOptionsBtn) { - saveOptionsBtn.classList.toggle("hidden", !autoAdd); - } - - // Mise à jour du message de chargement Pyodide - const statusContainer = document.getElementById('pyodide-loading'); - if (statusContainer) { - if (!isLoggedIn) { - statusContainer.innerHTML = ""; - } else if (!pyodideSimplemmaReady && extensionActive && isTrackingActive) { - statusContainer.innerHTML = "<p style='color: black; text-align: center; font-size: 11px;'>Chargement de l'extension en cours, veuillez patienter...</p>"; - } else if (pyodideSimplemmaReady && extensionActive && isTrackingActive) { - statusContainer.innerHTML = "<p style='color: black; text-align: center; font-size: 11px;'>C'est prêt !</p>"; - setTimeout(() => { - statusContainer.innerHTML = ""; - }, 2000); - } else { - statusContainer.innerHTML = ""; - } - } - - // Mise à jour de la sélection des langues - await updateLanguageSelection(); - - log("Interface mise à jour complètement", { - isLoggedIn, - extensionActive, - isTrackingActive, - autoAdd, - pyodideSimplemmaReady, - includeStopwords - }); -} - -//Activer/désactiver les stoplists -async function updateStopwordsOption(includeStopwords) { - const stopwordsCheckbox = document.getElementById("include-stopwords"); - if (stopwordsCheckbox) { - stopwordsCheckbox.checked = includeStopwords; - } -} - - - -// ✅ Actualisation de l'UI au chargement de la page -document.addEventListener("DOMContentLoaded", async () => { - await updateExtension(); // Mise à jour de l'extension selon les valeurs du local storage - setupEventListeners(); // Configuration des écouteurs d'événements -}); - -// !! boucle infinie ??? -// // Actualisation de l'UI en cas de changement dans le stockage local : ça c'est dans background qu'il faut le mettre xd -// browser.storage.onChanged.addListener((changes, area) => { -// if (area === "local" && changes.accessToken) { -// updateExtension(); -// } -// }); - -// ========================== -// Gestion des messages et du stockage -// ========================== -browser.runtime.onMessage.addListener(async (message) => { - log("📩 Message reçu dans popup.js :", message); - if (message.action === "updateUI") { - await updateExtension(); - } else if (message.action === "notify") { - alert(message.message); - } -}); - -browser.storage.onChanged.addListener((changes, area) => { - if (area === "local") { - updateExtension(); - } -}); - -// ========================== -// Gestion des notifications -// ========================== -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 { - log("⌠Impossible d'afficher la notification : élément manquant."); - } -} - -function handleWorkerMessage(event) { - const data = event.data; - log("[Background] Message du WebWorker :", data); - - if (data.type === "process-text" && data.status === "error") { - browser.runtime.sendMessage({ - action: "notify", - message: data.message - }); - return; - }} - - - - - - - - - - - - - - - - - - -// // 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 }); -// }