Skip to content
Snippets Groups Projects
Commit 5b0fff98 authored by Lucie Bader's avatar Lucie Bader
Browse files

Merge branch 'definitions' into 'main'

Définitions (lexiques de l'utilisateur + Wiktionnaire)

See merge request !4
parents 0fb286e1 9869fa75
No related branches found
No related tags found
1 merge request!4Définitions (lexiques de l'utilisateur + Wiktionnaire)
console.log("api.js chargé correctement"); console.log("✅ api.js chargé correctement");
// Fonction pour récupérer les lexiques (personnels) de l'utilisateur // ─────────────────────────────────────────────────────────────────────────────
async function getUserLexicons(authToken) { // ▌ Sélection de texte sur la page
const lexiconsApiUrl = 'https://babalex.lezinter.net/api/user/lexicons'; // ─────────────────────────────────────────────────────────────────────────────
try { document.addEventListener("mouseup", () => {
const response = await fetch(lexiconsApiUrl, { const selectedText = window.getSelection().toString().trim();
method: 'GET', if (selectedText) {
headers: { browser.runtime.sendMessage({
Authorization: `Bearer ${authToken}`, action: "mot_selectionne",
'Content-Type': 'application/json', selectedText
},
}); });
if (!response.ok) {
throw new Error(`Erreur lors de la récupération des lexiques : ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('Erreur lors de la récupération des lexiques :', error);
throw error;
} }
} });
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Fonction utilitaire pour appeler l’API
// ─────────────────────────────────────────────────────────────────────────────
/**
* Effectue une requête API
* @param {string} url - L'URL de l'API à appeler.
* @param {string|null} authToken - Le token d'authentification.
* @param {string} [method='GET'] - La méthode HTTP.
* @returns {Promise<any>} - La réponse en JSON.
* @throws {Error} - En cas d'échec.
*/
async function callApi(url, authToken = null, method = 'GET') {
const headers = { 'Content-Type': 'application/json' };
if (authToken) headers.Authorization = `Bearer ${authToken}`;
// Fonction pour récupérer les lexiques de l'utilisateur (ici utilisateur test)
async function getLexicons(authToken, userId = 52, language = 'fr') {
const lexiconsApiUrl = `https://babalex.lezinter.net/api/lexicon/search?user_id=${userId}&language=${language}`;
try { try {
const response = await fetch(lexiconsApiUrl, { const response = await fetch(url, { method, headers });
method: 'GET',
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) { if (!response.ok) {
throw new Error(`Erreur lors de la récupération des lexiques : ${response.statusText}`); throw new Error(`Erreur API (${response.status}): ${response.statusText}`);
} }
return await response.json(); return await response.json();
} catch (error) { } catch (error) {
console.error('Erreur lors de la récupération des lexiques :', error); console.error(`🚨 Erreur lors de l'appel API [${url}]:`, error);
throw error; throw error;
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Récupération des lexiques de l'utilisateur
// ─────────────────────────────────────────────────────────────────────────────
/**
* Récupère les lexiques pour l’utilisateur 4,
* en langue par défaut "fr".
*
* @param {string} authToken - Le token d'authentification.
* @param {string} [language='fr'] - La langue (optionnel).
* @returns {Promise<any[]>} - Liste des lexiques trouvés.
*/
async function getLexicons(authToken, language = 'fr') {
const userId = 4;
const baseUrl = "https://babalex.lezinter.net/api/lexicon/search";
const url = `${baseUrl}?user_id=${userId}&language=${encodeURIComponent(language)}`;
return callApi(url, authToken);
}
// Fonction pour récupérer les entrées d'un lexique donné (simple liste des mots) /**
async function getLexiconEntries(authToken, idLexicon) { * Récupère tous les lexiques pour l’utilisateur 4
const entriesApiUrl = `https://babalex.lezinter.net/api/lexicon/extract/0?lexiconId=${idLexicon}`; */
async function getAllCategoriesLexicons(authToken) {
const categories = ["User", "Group", "Zero", "New words"];
try { const userId = 4;
const response = await fetch(entriesApiUrl, { const groupId = 1;
method: 'GET',
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) { const promises = categories.map(async (category) => {
throw new Error(`Erreur lors de la récupération des entrées du lexique : ${response.statusText}`); const baseUrl = "https://babalex.lezinter.net/api/lexicon/search";
} const url = `${baseUrl}?user_id=${userId}&group_id=${groupId}&category=${encodeURIComponent(category)}&language=fr`;
const data = await response.json(); try {
if (Array.isArray(data)) { return await callApi(url, authToken);
console.log(`Entrées récupérées pour le lexique ID ${idLexicon} :`, data); } catch (error) {
return data; // Retourne un tableau de mots ex. ["raquette", "chat", "science"] console.warn(`⚠️ Aucune donnée trouvée (ou accès refusé) pour la catégorie "${category}" :`, error.message);
} else {
console.warn('Le format des données retournées est inattendu.', data);
return []; return [];
} }
} catch (error) { });
console.error('Erreur lors de la récupération des entrées du lexique :', error);
throw error;
}
}
// Fonction pour récupérer les graphies et leurs ID
async function getLexiconEntriesID(authToken, idLexicon) {
const entriesApiUrl = `https://babalex.lezinter.net/api/lexicon/entries/${idLexicon}`;
try { try {
const response = await fetch(entriesApiUrl, { const resultsByCategory = await Promise.all(promises);
method: 'GET', const combined = resultsByCategory.flat();
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Erreur lors de la récupération des graphies : ${response.statusText}`);
}
return await response.json(); console.log("✅ Lexiques récupérés (toutes catégories confondues) :", combined);
return combined;
} catch (error) { } catch (error) {
console.error('Erreur lors de la récupération des graphies :', error); console.error("Erreur lors de la récupération multi-catégories :", error);
throw error; return [];
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Récupération des entrées d'un lexique
// ─────────────────────────────────────────────────────────────────────────────
// Fonction pour obtenir les informations d'un mot par la graphie (dans quels lexiques utilisateur ou de groupe la graphie est présente) /**
async function getGraphyInfo(authToken, word) { * Récupère les entrées d'un lexique donné.
const definitionApiUrl = `https://babalex.lezinter.net/api/entry/search?graphy=${encodeURIComponent(word)}&language=fr&target_lex=3&target_lex=4`; */
async function getLexiconEntries(authToken, lexiconId) {
try { const url = `https://babalex.lezinter.net/api/lexicon/entries/${lexiconId}`;
const response = await fetch(definitionApiUrl, { return callApi(url, authToken);
method: 'GET',
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Erreur lors de la récupération de la définition : ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('Erreur lors de la récupération de la définition :', error);
throw error;
}
} }
/**
// Fonction pour obtenir les informations sur un mot par son ID * Récupère toutes les graphies présentes dans tous les lexiques de l'utilisateur.
async function getDefinition(authToken, entryId) { */
const entryInfoApiUrl = `https://babalex.lezinter.net/api/entry/get/${entryId}`; async function getAllLexiconWords(authToken) {
const searchUrl = "https://babalex.lezinter.net/api/lexicon/search"
+ "?user_id=4"
+ "&language=fr";
try { try {
const response = await fetch(entryInfoApiUrl, { // 1) Récupération de la liste des lexiques
method: 'GET', const lexicons = await callApi(searchUrl, authToken);
headers: {
Authorization: `Bearer ${authToken}`, if (!Array.isArray(lexicons) || lexicons.length === 0) {
'Content-Type': 'application/json', console.warn("⚠️ Aucun lexique retourné par l’API pour ces paramètres.");
}, return {};
}); }
if (!response.ok) { // 2) Pour chaque lexique, on récupère ses entrées via /api/lexicon/entries/{id}
throw new Error(`Erreur lors de la récupération des informations sur l'entrée : ${response.statusText}`); const allGraphiesByLexicon = {};
for (const lexicon of lexicons) {
const entries = await getLexiconEntries(authToken, lexicon.id);
const allGraphies = entries.map(entry => entry.graphy);
// Création d'un libellé unique pour le lexique
const lexiconName =
lexicon.category === "User"
? `Lexique personnel (${lexicon.user?.pseudo || "Inconnu"}) [${lexicon.id}]`
: `Lexique de groupe (${lexicon.group?.name || "Inconnu"}) [${lexicon.id}]`;
allGraphiesByLexicon[lexiconName] = allGraphies;
} }
const data = await response.json(); console.log("✅ Toutes les graphies récupérées :", allGraphiesByLexicon);
console.log(`Informations pour l'entrée ID ${entryId} :`, data); return allGraphiesByLexicon;
return data;
} catch (error) { } catch (error) {
console.error('Erreur lors de la récupération des informations sur l’entrée :', error); console.error("Erreur lors de la récupération des graphies des lexiques :", error);
throw error; return {};
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Récupération de définition du Wiktionnaire
// ─────────────────────────────────────────────────────────────────────────────
// Fonction pour obtenir une définition depuis le Wiktionnaire /**
async function getWiktionaryDefinition(authToken, word) { * Récupère une définition du Wiktionnaire.
// Construire l'URL de l'API avec le mot sélectionné */
const wiktionaryApiUrl = `https://babalex.lezinter.net/api/wiktionary/search?graphy=${encodeURIComponent(word)}&language=fr`; async function getWiktionaryDefinition(word) {
try { try {
const response = await fetch(wiktionaryApiUrl, { const url = `https://fr.wiktionary.org/w/api.php?action=query&format=json&origin=*&prop=extracts&exintro=true&titles=${encodeURIComponent(word)}`;
method: 'GET', const response = await fetch(url);
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) { if (!response.ok) {
throw new Error(`Erreur lors de la récupération de la définition depuis le Wiktionnaire : ${response.statusText}`); throw new Error(`Erreur API Wiktionnaire: ${response.statusText}`);
} }
const data = await response.json(); const data = await response.json();
console.log(`Résultats du Wiktionnaire pour le mot "${word}" :`, data); const pages = data.query?.pages;
return data; const page = pages ? Object.values(pages)[0] : null;
const definition = page?.extract?.trim() || "Aucune définition trouvée.";
console.log(`📖 Définition trouvée pour '${word}':`, definition);
return [definition];
} catch (error) { } catch (error) {
console.error('Erreur lors de la récupération de la définition depuis le Wiktionnaire :', error); console.error("Erreur lors de la récupération du Wiktionnaire :", error);
throw error; return ["Erreur : " + error.message];
} }
} }
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Exposition des fonctions pour un usage global
// ─────────────────────────────────────────────────────────────────────────────
window.callApi = callApi;
window.getLexicons = getLexicons;
// METTRE LES FONCTIONS GLOBALES window.getAllCategoriesLexicons = getAllCategoriesLexicons;
window.getUserLexicons = getUserLexicons;
window.getLexiconEntries = getLexiconEntries; window.getLexiconEntries = getLexiconEntries;
window.getLexiconEntriesID = getLexiconEntriesID; window.getAllLexiconWords = getAllLexiconWords;
window.getGraphyInfo = getGraphyInfo; window.getWiktionaryDefinition = getWiktionaryDefinition;
window.getDefinition = getDefinition; \ No newline at end of file
window.getWiktionaryDefinition = getWiktionaryDefinition;
// === Variables globales / de configuration === // ─────────────────────────────────────────────────────────────────────────────
let isExtensionActive = true; // Activation globale de l'extension // Variables globales
// ─────────────────────────────────────────────────────────────────────────────
let isExtensionActive = true;
let areStatsActive = false; let areStatsActive = false;
let originalTabId = null; let originalTabId = null;
let loginTabId = null; let loginTabId = null;
const AUTH_LOGIN_URL = "https://prisms.lezinter.net/fr/login"; const AUTH_LOGIN_URL = "https://prisms.lezinter.net/fr/login";
const AUTH_BALEX_URL = "https://prisms.lezinter.net/fr/headquarters/balex"; const AUTH_BALEX_URL = "https://prisms.lezinter.net/fr/headquarters/balex";
// === Logs de démarrage === // ─────────────────────────────────────────────────────────────────────────────
// Logs de démarrage
// ─────────────────────────────────────────────────────────────────────────────
console.log("🚀 ff2BaLex (background) chargé."); console.log("🚀 ff2BaLex (background) chargé.");
browser.runtime.onInstalled.addListener((details) => { browser.runtime.onInstalled.addListener((details) => {
...@@ -19,7 +22,9 @@ browser.runtime.onStartup.addListener(() => { ...@@ -19,7 +22,9 @@ browser.runtime.onStartup.addListener(() => {
console.log("🔄 Extension démarrée (onStartup)."); console.log("🔄 Extension démarrée (onStartup).");
}); });
// === Suivi des changements dans le stockage (extensionActive, statsActive) === // ─────────────────────────────────────────────────────────────────────────────
// Suivi des changements dans le stockage
// ─────────────────────────────────────────────────────────────────────────────
browser.storage.onChanged.addListener((changes) => { browser.storage.onChanged.addListener((changes) => {
if (changes.extensionActive) { if (changes.extensionActive) {
isExtensionActive = changes.extensionActive.newValue; isExtensionActive = changes.extensionActive.newValue;
...@@ -29,58 +34,75 @@ browser.storage.onChanged.addListener((changes) => { ...@@ -29,58 +34,75 @@ browser.storage.onChanged.addListener((changes) => {
areStatsActive = changes.statsActive.newValue; areStatsActive = changes.statsActive.newValue;
console.log("📊 Statistiques activées :", areStatsActive); console.log("📊 Statistiques activées :", areStatsActive);
} }
// Recréer le menu contextuel du navigateur quand l'état change (ex: extension désactivée) refreshAllUI();
createBrowserContextMenu();
}); });
// === Vérifie si l'utilisateur est connecté (token présent) === // ─────────────────────────────────────────────────────────────────────────────
// Fonctions utilitaires
// ─────────────────────────────────────────────────────────────────────────────
async function isUserConnected() { async function isUserConnected() {
const { accessToken } = await browser.storage.local.get("accessToken"); const { accessToken } = await browser.storage.local.get("accessToken");
return !!accessToken; return !!accessToken;
} }
// === Ouvre la page de login BaLex === async function refreshAllUI() {
async function openLoginPage() { console.log("🔄 Rafraîchissement global de l'UI...");
browser.runtime.sendMessage({ action: "refreshUI" });
}
// ─────────────────────────────────────────────────────────────────────────────
// Fonctions d'authentification & de redirection
// ─────────────────────────────────────────────────────────────────────────────
browser.runtime.onConnect.addListener((port) => {
if (port.name === "auth") {
port.onMessage.addListener(async (message) => {
if (message.action === "toggleAuth") {
console.log("🔄 toggleAuth reçu via port dans le background.");
const isConnected = await isUserConnected();
if (isConnected) {
await disconnectFromLexicalDB();
} else {
// Ouvre directement la page de connexion
actuallyOpenLoginPage();
}
}
});
}
});
// Ouvre directement la page de connexion
async function actuallyOpenLoginPage() {
console.log("🔗 Ouverture de la page de connexion."); console.log("🔗 Ouverture de la page de connexion.");
// 1) Retrouver l'onglet actuellement actif (pour y revenir plus tard) // Mémoriser l'onglet actif
const [currentTab] = await browser.tabs.query({ active: true, currentWindow: true }); const [currentTab] = await browser.tabs.query({ active: true, currentWindow: true });
if (currentTab) { if (currentTab) {
originalTabId = currentTab.id; originalTabId = currentTab.id;
console.log("✅ Onglet courant mémorisé, ID =", originalTabId); console.log("✅ Onglet courant mémorisé, ID =", originalTabId);
} }
// Ouvre un nouvel onglet pour la page de connexion et l'active
// 2) Créer l’onglet de login const loginTab = await browser.tabs.create({ url: AUTH_LOGIN_URL, active: true });
const loginTab = await browser.tabs.create({ url: AUTH_LOGIN_URL });
loginTabId = loginTab.id; loginTabId = loginTab.id;
console.log("✅ Onglet de login créé, ID =", loginTabId); console.log("✅ Onglet de login créé, ID =", loginTabId);
// Notifie que l'authentification est en cours
// Notifie (éventuellement) qu'on est “en cours” de connexion
browser.runtime.sendMessage({ action: "authStatusChanged", isLoggedIn: false }); browser.runtime.sendMessage({ action: "authStatusChanged", isLoggedIn: false });
} }
// === Déconnecte l'utilisateur (supprime le token) === // Déconnecte l'utilisateur (sans notification)
async function disconnectFromLexicalDB() { async function disconnectFromLexicalDB() {
console.log("🔓 Déconnexion en cours..."); console.log("🔓 Déconnexion en cours...");
await browser.storage.local.remove("accessToken"); await browser.storage.local.remove("accessToken");
console.log("🔓 Token supprimé avec succès."); console.log("🔓 Token supprimé avec succès.");
setTimeout(async () => {
showNotification( await refreshAllUI();
"Déconnexion réussie", }, 500);
"Vous êtes maintenant déconnecté(e).",
"icons/logout.png"
);
// On effectue un rafraîchissement global
await refreshAllUI();
} }
// === Sauvegarde du token et finalisation de la connexion === // Sauvegarde le token et ferme l'onglet de login si nécessaire
async function saveToken(token) { async function saveToken(token) {
console.log("✅ Sauvegarde du token :", token); console.log("✅ Sauvegarde du token :", token);
await browser.storage.local.set({ accessToken: token }); await browser.storage.local.set({ accessToken: token });
// On ferme la page de login si encore ouverte
if (loginTabId) { if (loginTabId) {
try { try {
await browser.tabs.remove(loginTabId); await browser.tabs.remove(loginTabId);
...@@ -88,10 +110,8 @@ async function saveToken(token) { ...@@ -88,10 +110,8 @@ async function saveToken(token) {
} catch (err) { } catch (err) {
console.warn("Impossible de fermer l'onglet de login :", err); console.warn("Impossible de fermer l'onglet de login :", err);
} }
loginTabId = null; // Reset l'identifiant loginTabId = null;
} }
// On refait apparaître l’onglet initial, s'il existe encore
if (originalTabId) { if (originalTabId) {
try { try {
await browser.tabs.update(originalTabId, { active: true }); await browser.tabs.update(originalTabId, { active: true });
...@@ -99,56 +119,54 @@ async function saveToken(token) { ...@@ -99,56 +119,54 @@ async function saveToken(token) {
} catch (err) { } catch (err) {
console.warn("Impossible de basculer sur l'onglet initial :", err); console.warn("Impossible de basculer sur l'onglet initial :", err);
} }
originalTabId = null; // Reset l'identifiant originalTabId = null;
} }
// Et on rafraîchit toute l’UI
await refreshAllUI(); await refreshAllUI();
} }
// === Fonction de REFRESH centralisée === // ─────────────────────────────────────────────────────────────────────────────
async function refreshAllUI() { // Gestion des messages reçus
console.log("🔄 Rafraîchissement global de l'UI..."); // ─────────────────────────────────────────────────────────────────────────────
// 1) Recrée le menu contextuel “navigateur” (clic-droit)
createBrowserContextMenu();
// 2) Envoie un message unique “refreshUI” à toutes les parties
// (sidebar, popup, content script) pour qu'elles se mettent à jour.
browser.runtime.sendMessage({ action: "refreshUI" });
}
// === Gestion des messages reçus ===
browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
console.log("📩 Message reçu dans background.js :", message); console.log("📩 Message reçu dans background.js :", message);
switch (message.action) { switch (message.action) {
// --- Authentification ---
case "toggleAuth": { case "toggleAuth": {
console.log("Action toggleAuth reçue");
const isConnected = await isUserConnected(); const isConnected = await isUserConnected();
if (isConnected) { if (isConnected) {
await disconnectFromLexicalDB(); await disconnectFromLexicalDB();
} else { } else {
await openLoginPage(); actuallyOpenLoginPage();
}
break;
}
case "getDefinitionWiki": {
if (message.selectedText && message.selectedText.trim() !== "") {
console.log("🌐 Requête Wiktionnaire pour :", message.selectedText);
const definition = await window.fetchWiktionaryDefinition(message.selectedText.trim());
browser.runtime.sendMessage({
action: "fetchWiktionaryDefinitionResponse",
selectedText: message.selectedText,
definitions: [{
source: "Wiktionnaire",
text: definition,
}],
});
} else {
console.warn("⚠️ Texte sélectionné vide. Annulation de la requête.");
} }
break; break;
} }
case "checkAuthStatus": { case "checkAuthStatus": {
const connected = await isUserConnected(); const connected = await isUserConnected();
sendResponse(connected); sendResponse(connected);
break; break;
} }
case "authStatusChanged": { case "authStatusChanged": {
console.log("🔄 Mise à jour de l'état d'authentification :", message.isLoggedIn); console.log("🔄 Mise à jour de l'état d'authentification :", message.isLoggedIn);
// Éventuellement on peut relancer un refreshAllUI() si souhaité
break; break;
} }
case "saveToken": { case "saveToken": {
// Lorsqu'on reçoit le token depuis la page BaLex
if (message.token) { if (message.token) {
await saveToken(message.token); await saveToken(message.token);
} else { } else {
...@@ -156,58 +174,57 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { ...@@ -156,58 +174,57 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
} }
break; break;
} }
// (Optionnel) Si d’autres messages…
// ex: "toggleLexiconHighlight", etc.
default: default:
break; break;
} }
return true; return true;
}); });
// === Navigation : injection / récupération token sur la page BaLex === // ─────────────────────────────────────────────────────────────────────────────
// Web Navigation : Injection de scripts et récupération du token
// ─────────────────────────────────────────────────────────────────────────────
browser.webNavigation.onCompleted.addListener(async (details) => { browser.webNavigation.onCompleted.addListener(async (details) => {
if (!isExtensionActive) { if (!isExtensionActive) {
console.log("🚫 Extension désactivée, aucune injection script."); console.log("🚫 Extension désactivée, aucune injection script.");
return; return;
} }
const url = new URL(details.url); const url = new URL(details.url);
// Sur la page de login : injecter un petit popup dinstruction // Injection d'un popup d'instruction sur la page de login
if (url.hostname === "prisms.lezinter.net" && url.pathname === "/fr/login") { if (url.hostname === "prisms.lezinter.net" && url.pathname === "/fr/login") {
console.log("📘 Injection du popup d'instruction sur la page de login Prisms."); console.log("📘 Injection du popup d'instruction sur la page de login Prisms.");
showInstructionPopup(details); showInstructionPopup(details);
} }
// Récupération du token sur la page /balex
// Sur la page /balex : tenter de récupérer le token
if (url.hostname === "prisms.lezinter.net" && url.pathname === "/fr/headquarters/balex") { if (url.hostname === "prisms.lezinter.net" && url.pathname === "/fr/headquarters/balex") {
console.log("🟢 Page /balex détectée. Tentative de récupération du token."); console.log("🟢 Page /balex détectée. Tentative de récupération du token.");
try { try {
await new Promise(resolve => setTimeout(resolve, 3000)); // Attendre 3s await new Promise(resolve => setTimeout(resolve, 3000));
await browser.tabs.executeScript(details.tabId, { await browser.tabs.executeScript(details.tabId, {
code: ` code: `
console.log("🔍 Recherche du token..."); (function() {
const tokenElement = document.getElementById("accesToken"); console.log("🔍 Recherche du token...");
if (tokenElement) { const tokenElement = document.getElementById("accessToken") || document.getElementById("accesToken");
const token = tokenElement.innerText.trim(); if (tokenElement) {
console.log("🔐 Token détecté :", token); const token = tokenElement.innerText.trim();
browser.runtime.sendMessage({ action: "saveToken", token }); console.log("🔐 Token détecté :", token);
} else { browser.runtime.sendMessage({ action: "saveToken", token });
console.error("❌ Token introuvable."); } else {
} console.error("❌ Token introuvable.");
}
return null;
})();
` `
}); });
} catch (error) { } catch (error) {
console.error("❌ Erreur lors de la récupération du token :", error); console.error("❌ Erreur lors de la récupération du token :", error);
} }
} }
}, { }, { url: [{ hostContains: "prisms.lezinter.net" }] });
url: [{ hostContains: "prisms.lezinter.net" }]
});
// === Redirection automatique vers /balex (facultatif) === // ─────────────────────────────────────────────────────────────────────────────
// Web Request : Redirection automatique vers /balex
// ─────────────────────────────────────────────────────────────────────────────
browser.webRequest.onBeforeRequest.addListener( browser.webRequest.onBeforeRequest.addListener(
function(details) { function(details) {
if (details.url === "https://prisms.lezinter.net/fr/headquarters/") { if (details.url === "https://prisms.lezinter.net/fr/headquarters/") {
...@@ -219,7 +236,9 @@ browser.webRequest.onBeforeRequest.addListener( ...@@ -219,7 +236,9 @@ browser.webRequest.onBeforeRequest.addListener(
["blocking"] ["blocking"]
); );
// === Affichage d'un popup d’instruction sur /fr/login === // ─────────────────────────────────────────────────────────────────────────────
// Affichage d'un popup d'instruction sur /fr/login
// ─────────────────────────────────────────────────────────────────────────────
function showInstructionPopup(details) { function showInstructionPopup(details) {
browser.tabs.executeScript(details.tabId, { browser.tabs.executeScript(details.tabId, {
code: ` code: `
...@@ -240,7 +259,7 @@ function showInstructionPopup(details) { ...@@ -240,7 +259,7 @@ function showInstructionPopup(details) {
popup.style.fontSize = "14px"; popup.style.fontSize = "14px";
popup.style.width = "300px"; popup.style.width = "300px";
popup.style.textAlign = "center"; popup.style.textAlign = "center";
popup.innerHTML = \` popup.innerHTML = \`
<h5 style="color: #fff; font-weight: bold; margin-top: 0;">🔑 Connexion à l'extension</h5> <h5 style="color: #fff; font-weight: bold; margin-top: 0;">🔑 Connexion à l'extension</h5>
<p style="margin: 15px 0;"> <p style="margin: 15px 0;">
...@@ -259,108 +278,12 @@ function showInstructionPopup(details) { ...@@ -259,108 +278,12 @@ function showInstructionPopup(details) {
border-radius: 5px; border-radius: 5px;
">Fermer</button> ">Fermer</button>
\`; \`;
document.body.appendChild(popup); document.body.appendChild(popup);
const closeBtn = document.getElementById("close-popup-btn"); const closeBtn = document.getElementById("close-popup-btn");
closeBtn.onclick = () => popup.remove(); closeBtn.onclick = () => popup.remove();
} }
` `
}); });
} }
// === Création du menu contextuel (navigateur) standard ===
async function createBrowserContextMenu() {
// Supprimer les items existants
browser.contextMenus.removeAll();
const isConnected = await isUserConnected();
// Si connecté : options supplémentaires
if (isConnected) {
browser.contextMenus.create({
id: "searchLexicon",
title: "Vérifier si le mot est dans le lexique personnel",
contexts: ["selection"],
});
browser.contextMenus.create({
id: "checkLexicon",
title: "Afficher dans quels lexiques le mot est présent",
contexts: ["selection"],
});
browser.contextMenus.create({
id: "getDefinition",
title: "Obtenir une définition à partir de mes lexiques",
contexts: ["selection"],
});
}
// Option accessible à tout le monde
browser.contextMenus.create({
id: "getDefinitionWiki",
title: "Rechercher une définition sur le Wiktionnaire",
contexts: ["selection"],
});
// Bouton de connexion/déconnexion
browser.contextMenus.create({
id: "login",
title: isConnected ? "Se déconnecter de BaLex" : "Se connecter à BaLex",
contexts: ["all"],
});
}
// Initialise le menu contextuel du navigateur une première fois
createBrowserContextMenu();
// Gère les clics sur les items du menu contextuel du navigateur
browser.contextMenus.onClicked.addListener(async (info, tab) => {
console.log("📦 Menu contextuel - item cliqué :", info.menuItemId);
switch (info.menuItemId) {
case "searchLexicon":
browser.tabs.sendMessage(tab.id, {
action: "searchLexicon",
selectedText: info.selectionText,
});
break;
case "checkLexicon":
browser.tabs.sendMessage(tab.id, {
action: "checkLexicon",
selectedText: info.selectionText,
});
break;
case "getDefinition":
browser.tabs.sendMessage(tab.id, {
action: "getDefinition",
selectedText: info.selectionText,
});
break;
case "getDefinitionWiki":
browser.tabs.sendMessage(tab.id, {
action: "getDefinitionWiki",
selectedText: info.selectionText,
});
break;
case "login": {
const connected = await isUserConnected();
if (connected) {
await disconnectFromLexicalDB();
} else {
await openLoginPage();
}
break;
}
default:
console.warn(`Aucune action définie pour l'élément : ${info.menuItemId}`);
}
});
// === Exemple de notification ===
function showNotification(title, message, iconPath) {
console.log(`🔔 NOTIFICATION: [${title}] ${message}`);
}
console.log("browser_context_menu.js chargé correctement"); // Vérifie que le script est correctement chargé
// Variable globale qui contient le token pour les requêtes API
let authToken = null;
// Fonction pour charger le token depuis le stockage local
async function loadAuthToken() {
try {
const result = await browser.storage.local.get("accessToken");
authToken = result.accessToken;
console.log("🔑 Token chargé au démarrage :", authToken);
} catch (error) {
console.error("❌ Erreur lors de la récupération du token :", error);
}
}
// Charger le token dès le démarrage du script
loadAuthToken();
// Création des options du menu contextuel du navigateur
browser.contextMenus.create({
id: "searchLexicon",
title: "Ce mot est-il dans mon lexique ?",
contexts: ["selection"], // Affiché uniquement lorsqu'un texte est sélectionné
icons: {
"16": "icons/recherche_lexique.png"
},
});
browser.contextMenus.create({
id: "checkLexicon",
title: "Afficher dans quel(s) lexique(s) ce mot est présent",
contexts: ["selection"],
icons: {
"16": "icons/quel_lexique.png"
},
});
browser.contextMenus.create({
id: "addtoLexicon",
title: "Ajouter ce mot à mon lexique",
contexts: ["selection"],
icons: {
"16": "icons/ajout_lexique.png"
},
});
browser.contextMenus.create({
id: "separatorExtension",
type: "separator",
contexts: ["all"],
});
browser.contextMenus.create({
id: "getDefinition",
title: "Obtenir une définition à partir de mes lexiques",
contexts: ["selection"],
icons: {
"16": "icons/definition.png"
},
});
browser.contextMenus.create({
id: "getDefinitionWiki",
title: "Rechercher une définition dans le Wiktionnaire",
contexts: ["selection"],
icons: {
"16": "icons/definition_wiktionnaire.png"
},
});
// Ajouter un séparateur après les options de l'extension pour les distinguer des autres éléments du menu
browser.contextMenus.create({
id: "separatorAfterExtension",
type: "separator",
contexts: ["all"],
});
// Gestion des clics sur les options du menu contextuel
browser.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.selectionText) {
console.log(`📩 Texte sélectionné dans le menu du navigateur : ${info.selectionText}`);
// Vérifier quelle option a été cliquée
switch (info.menuItemId) {
case "searchLexicon":
console.log("🔍 Recherche dans le lexique :", info.selectionText);
if (authToken) {
await searchLexicon(info.selectionText);
} else {
alert("⚠️ Vous devez être connecté pour utiliser cette fonction.");
}
break;
case "checkLexicon":
console.log("📋 Vérification des lexiques :", info.selectionText);
if (authToken) {
await checkLexicon(info.selectionText);
} else {
alert("⚠️ Vous devez être connecté pour utiliser cette fonction.");
}
break;
case "getDefinition":
console.log("📖 Recherche des définitions :", info.selectionText);
if (authToken) {
await getDefinition(info.selectionText);
} else {
alert("⚠️ Vous devez être connecté pour utiliser cette fonction.");
}
break;
case "getDefinitionWiki":
console.log("🌐 Recherche sur le Wiktionnaire :", info.selectionText);
await getDefinitionWiki(info.selectionText);
break;
default:
console.error(`❌ Action inconnue : ${info.menuItemId}`);
}
}
});
// Fonction pour rechercher un mot dans le lexique personnel
async function searchLexicon(selectedText) {
try {
const lexicons = await getUserLexicons(authToken);
console.log("📚 Lexiques récupérés :", lexicons);
const frenchLexicon = lexicons.find((lexicon) => lexicon.language === "fr");
if (!frenchLexicon) {
alert("⚠️ Aucun lexique français trouvé.");
return;
}
const entries = await getLexiconEntriesID(authToken, frenchLexicon.id);
const isWordPresent = entries.some(
(entry) => entry.graphy.toLowerCase() === selectedText.toLowerCase()
);
if (isWordPresent) {
alert(`✅ Le mot "${selectedText}" est présent dans votre lexique personnel.`);
} else {
alert(`❌ Le mot "${selectedText}" n'est pas présent dans votre lexique personnel.`);
}
} catch (error) {
console.error("❌ Erreur lors de la recherche dans le lexique :", error);
}
}
// Fonction pour vérifier dans quels lexiques un mot est présent
async function checkLexicon(selectedText) {
try {
const lexicons = await getLexicons(authToken);
const results = lexicons.map((lexicon) => ({
name: lexicon.name,
isPresent: lexicon.entries.some(
(entry) => entry.graphy.toLowerCase() === selectedText.toLowerCase()
),
}));
console.log("📋 Résultats des lexiques :", results);
let message = `Résultats pour "${selectedText}":\n\n`;
results.forEach(({ name, isPresent }) => {
message += `- ${name}: ${isPresent ? "✅ Présent" : "❌ Non présent"}\n`;
});
alert(message);
} catch (error) {
console.error("❌ Erreur lors de la vérification des lexiques :", error);
}
}
// Fonction pour obtenir les définitions d'un mot
async function getDefinition(selectedText) {
try {
const lexicons = await getLexicons(authToken);
let definitions = [];
for (const lexicon of lexicons) {
const entries = await getLexiconEntriesID(authToken, lexicon.id);
const entry = entries.find(
(entry) => entry.graphy.toLowerCase() === selectedText.toLowerCase()
);
if (entry) {
const definitionData = await getDefinition(authToken, entry.id);
definitions.push(...extractDefinitions(definitionData));
}
}
console.log("📖 Définitions trouvées :", definitions);
if (definitions.length > 0) {
alert(`📖 Définitions pour "${selectedText}":\n\n` + definitions.join("\n"));
} else {
alert(`❌ Aucune définition trouvée pour "${selectedText}".`);
}
} catch (error) {
console.error("❌ Erreur lors de la récupération des définitions :", error);
}
}
// Fonction pour rechercher une définition sur le Wiktionnaire
async function getDefinitionWiki(selectedText) {
try {
const result = await fetch(`https://fr.wiktionary.org/wiki/${encodeURIComponent(selectedText)}`);
if (result.ok) {
alert(`🌐 Définition trouvée pour "${selectedText}". Consultez le Wiktionnaire.`);
} else {
alert(`❌ Aucune définition trouvée sur le Wiktionnaire pour "${selectedText}".`);
}
} catch (error) {
console.error("❌ Erreur lors de la recherche sur le Wiktionnaire :", error);
}
}
// Fonction pour extraire les définitions d'une réponse API
function extractDefinitions(response) {
if (!response || !response.attributes || !response.attributes.Items) {
console.warn("⚠️ Structure de réponse inattendue.");
return [];
}
const items = response.attributes.Items;
return items
.flatMap((item) =>
item.Sense?.Definitions?.map((def) => def.Def || "Définition non disponible") || []
)
.filter(Boolean);
}
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BaLex - Barre Latérale</title> <title>BaLex - Barre Latérale</title>
<script src="sidebar.js"></script> <script src="../api.js" defer></script>
<script src="../definitions.js" defer></script>
<script src="sidebar.js" defer></script>
<style> <style>
/* Style global */ /* Style global */
body { body {
...@@ -16,20 +19,50 @@ ...@@ -16,20 +19,50 @@
color: #323046; color: #323046;
} }
/* Conteneurs */ /* Conteneurs principaux */
#menu, #etat { #menu, #etat, #definitionContainer {
padding: 10px; padding: 10px;
margin-bottom: 0px; margin-bottom: 10px;
border-radius: 10px; border-radius: 10px;
background-color: #a08e9f; background-color: #a08e9f;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
} }
/* Titre */ /* En-têtes de blocs */
h3 { .block-header {
position: relative;
text-align: center;
margin-top: 2px;
}
.block-header h3 {
display: inline-block;
margin-top: 5px;
margin-bottom: 0;
}
/* Utilisation de la classe pour les boutons de bascule */
.toggle-btn {
position: absolute;
right: 8px;
background: none;
margin: 0;
border: none;
color: #fff; color: #fff;
text-align: center; font-size: 15px;
font-weight: bold; padding: 3px 5px;
cursor: pointer;
width: auto;
display: inline-block;
}
/* Contenu des blocs */
.block-content {
padding-top: 2px;
}
.hidden {
display: none;
} }
/* Boutons */ /* Boutons */
...@@ -97,23 +130,101 @@ ...@@ -97,23 +130,101 @@
/* Espace pour les pictogrammes */ /* Espace pour les pictogrammes */
.lexique-icon { .lexique-icon {
width: 25px; width: 25px;
height: 25px; height: 25px;
border-radius: 50%; border-radius: 50%;
background-color: #ccc; background-color: #ccc;
margin-right: 10px; margin-right: 10px;
flex-shrink: 0; flex-shrink: 0;
} }
.lexicon-section {
margin-bottom: 10px;
}
.lexicon-header {
font-weight: bold;
cursor: pointer;
padding: 5px;
background-color: #8d5c70;
border-radius: 5px;
text-align: center;
}
.lexicon-header:hover {
background-color: #dddedd;
color: #8d5c70;
}
.lexicon-content {
margin-top: 5px;
}
#mesLexiquesList {
display: inline;
padding: 0;
align-items: center;
}
#mesLexiquesContainer h4 {
margin-bottom: 5px;
}
/* Définition */ /* Définition */
#definition { #definitionContainer {
margin-top: 10px;
background-color: #444; background-color: #444;
padding: 10px; padding: 10px;
border-radius: 5px; border-radius: 10px;
color: white; color: white;
} }
#definitionsList {
list-style: none;
padding: 0;
}
#definitionsList li {
margin-bottom: 10px;
}
.definition-source {
font-weight: bold;
color: #ffa500;
}
/* Popup (modal) caché par défaut */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.5);
display: none;
align-items: center;
justify-content: center;
z-index: 9999;
}
.modal-content {
background: white;
color: #8d5c70;
padding: 1rem;
max-width: 600px;
max-height: 80vh;
overflow-y: auto;
border-radius: 8px;
}
.close-button {
float: right;
cursor: pointer;
font-weight: bold;
color: #666;
}
.close-button:hover {
color: #000;
}
/* Activer/désactiver le surlignage */ /* Activer/désactiver le surlignage */
#highlighting-options p { #highlighting-options p {
...@@ -121,41 +232,89 @@ ...@@ -121,41 +232,89 @@
font-size: small; font-size: small;
color: #333; color: #333;
} }
#noDefinitionsContainer {
display: block !important;
color: red !important;
font-weight: bold;
}
</style> </style>
</head> </head>
<body> <body>
<!-- Menu des lexiques --> <!-- Bloc 1 : Menu des lexiques -->
<div id="menu"> <div id="menu">
<h3>Lexiques</h3> <div class="block-header">
<p id="highlight-note" style="display: none;">Cochez un/des lexique(s) pour activer le surlignage des mots sur la page.</p> <h3>Lexiques</h3>
<div id="lexiques">Chargement...</div> <button class="toggle-btn"></button>
</div>
<div id="auth-section"> <div id="menuContent" class="block-content">
<button id="auth-button">Se connecter</button> <p id="highlight-note" style="display: none;">Cochez un/des lexique(s) pour activer le surlignage des mots sur la page.</p>
<div id="lexiques">Chargement...</div>
<div id="auth-section">
<button id="auth-button">Se connecter</button>
</div>
</div> </div>
</div> </div>
<!-- État de la sélection --> <!-- Bloc 2 : État de la sélection -->
<hr>
<div id="etat"> <div id="etat">
<h3>Mot sélectionné</h3> <div class="block-header">
<p id="motSelectionne">Aucun mot sélectionné</p> <h3>Mot sélectionné</h3>
<div id="add-to-lexiques" style="display: none;"> <button class="toggle-btn"></button>
<button id="add-word-button">Ajouter le mot sélectionné</button>
</div> </div>
<div id="etatContent" class="block-content">
<button id="chercherDef">Chercher la/les définition(s)</button> <p id="motSelectionne">Aucun mot sélectionné</p>
<div id="possible-definitions" style="display: none;"> <p id="lexiconResult"></p>
<label style="font-size: small;"> <div id="add-to-lexiques" style="display: none;">
<input type="checkbox" id="toggle-definitions"> <button id="add-word-button">Ajouter le mot sélectionné</button>
Afficher toutes les définitions </div>
</label> <button id="chercherDef">Rechercher une définition</button>
<div id="possible-definitions" style="display: none;"></div>
</div> </div>
</div> </div>
<!-- Bloc 3 : Définitions -->
<div id="definitionContainer">
<div class="block-header">
<h3>Définitions</h3>
<button class="toggle-btn"></button>
</div>
<div id="definitionContent" class="block-content">
<!-- Définitions des lexiques de l'utilisateur -->
<div id="mesLexiquesContainer">
<h4>📚 Mes lexiques</h4>
<label style="font-size: small;">
<input type="checkbox" id="toggle-definitions">
Afficher toutes les définitions
</label>
<ul id="mesLexiquesList"></ul>
</div>
<div id="noLexiconDefinitionsContainer" style="display: none; color: #8d5c70;">
<p>Aucune définition trouvée dans les lexiques.</p>
</div>
<div id="noWiktionaryDefinitionsContainer" style="display: none; color: #8d5c70;">
<p>Aucune définition trouvée dans le Wiktionnaire.</p>
</div>
<!-- Définitions issues du Wiktionnaire -->
<div id="wiktionnaireContainer">
<h4>🌍 Wiktionnaire</h4>
<ul id="wiktionnaireList"></ul>
</div>
<!-- Définition affichée --> <!-- Fenêtre modale cachée -->
<div id="definition"></div> <div id="modalOverlay" class="modal-overlay">
<div class="modal-content">
<span id="closeModalBtn" class="close-button">X</span>
<div id="modalFullText"></div>
</div>
</div>
</div>
</div>
</body> </body>
</html> </html>
This diff is collapsed.
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Fonctions pour récupérer/afficher les définitions
// ─────────────────────────────────────────────────────────────────────────────
const lexiconMap = new Map();
/**
* Récupère les définitions d'un mot dans les lexiques de l'utilisateur (ex. user_id=4),
* en effectuant un appel global à l'API pour le mot recherché, puis en filtrant
* les entrées pour ne conserver que celles dont le lexicon.id est présent dans la liste
* des lexiques de l'utilisateur.
*
* Retourne un tableau d'objets { source, text } où:
* - source = nom du lexique (ou "Lexique #ID")
* - text = texte de la définition
*/
async function fetchLexiconDefinitions(word) {
try {
console.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.");
return [];
}
// 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 lexResponse = await fetch(lexUrl, {
headers: { Authorization: `Bearer ${authToken}` }
});
if (!lexResponse.ok) {
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);
if (!Array.isArray(userLexicons) || userLexicons.length === 0) {
console.warn("⚠️ Aucun lexique trouvé pour cet utilisateur.");
return [];
}
// Mise à jour de lexiconMap avec des libellés uniques (ajout de l'ID)
lexiconMap.clear();
userLexicons.forEach((lex) => {
const lexiconName =
lex.category === "User"
? `Lexique personnel : ${lex.user?.pseudo || "Inconnu"}`
: `Lexique de groupe : ${lex.group?.name || "Inconnu"}`;
lexiconMap.set(lex.id, lexiconName);
});
console.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}`);
const searchResponse = await fetch(searchUrl, {
headers: { Authorization: `Bearer ${authToken}` }
});
if (!searchResponse.ok) {
console.warn(`⚠️ Erreur pour le lexique ${lex.id} : ${searchResponse.statusText}`);
return { lexiconId: lex.id, entries: [] };
}
const entries = await searchResponse.json();
// Filtrage côté client : ne garder que les entrées dont entry.lexicon.id correspond exactement à lex.id
const filteredEntries = entries.filter(entry => {
if (!entry.lexicon) return false;
return Number(entry.lexicon.id) === Number(lex.id);
});
console.log(`Pour le lexique ${lex.id} (${lexiconMap.get(lex.id)}), entrées filtrées :`, filteredEntries);
return { lexiconId: lex.id, entries: filteredEntries };
});
const results = await Promise.all(definitionsPromises);
// 3) Parcourir les résultats et extraire les définitions
let allDefinitions = [];
results.forEach(result => {
const lexiconId = result.lexiconId;
const sourceName = lexiconMap.get(lexiconId) || `Lexique #${lexiconId}`;
result.entries.forEach(entry => {
if (!entry.lexicon || Number(entry.lexicon.id) !== Number(lexiconId)) return;
let items = entry.attributes?.Items;
if (!Array.isArray(items)) {
if (typeof items === 'object' && items !== null) {
items = Object.values(items);
} else {
return;
}
}
items.forEach(item => {
const definitionsArray = item.Sense?.Definitions;
if (!Array.isArray(definitionsArray)) return;
definitionsArray.forEach(defObj => {
if (defObj.Def) {
allDefinitions.push({
source: sourceName,
text: defObj.Def,
lexiconId: lexiconId
});
}
});
});
});
});
console.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);
return [];
}
}
/**
* Récupère la définition d'un mot depuis le Wiktionnaire (fr).
* Retourne un tableau d'objets : [{ source: 'Wiktionnaire', text: '...' }]
*/
async function fetchWiktionaryDefinition(word) {
try {
console.log(`🔍 Requête Wiktionnaire pour "${word}"...`);
if (!word || word.trim() === "") {
throw new Error("⚠️ Mot vide, impossible d'envoyer la requête.");
}
const wiktionaryURL = `https://fr.wiktionary.org/w/api.php?action=query&format=json&origin=*&prop=extracts&explaintext=true&redirects=1&titles=${encodeURIComponent(word)}`;
const response = await fetch(wiktionaryURL);
if (!response.ok) {
throw new Error(`❌ Erreur API Wiktionnaire: ${response.statusText}`);
}
const data = await response.json();
console.log("📖 Réponse API (Wiktionnaire) :", data);
const pages = data.query?.pages;
const page = pages ? Object.values(pages)[0] : null;
const definitionText = page && page.extract
? page.extract.trim()
: "⚠️ Aucune définition trouvée sur le Wiktionnaire.";
console.log("🌍 Définition Wiktionnaire extraite :", definitionText);
return [
{
source: "Wiktionnaire",
text: definitionText
}
];
} catch (error) {
console.error("❌ Erreur Wiktionnaire :", error);
return [
{
source: "Wiktionnaire",
text: "⚠️ Erreur lors de la récupération sur le Wiktionnaire."
}
];
}
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Affichage des définitions dans la barre latérale
// ─────────────────────────────────────────────────────────────────────────────
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);
if (!Array.isArray(definitions)) return;
const mesLexiquesList = document.getElementById("mesLexiquesList");
const wiktionnaireList = document.getElementById("wiktionnaireList");
const noLexiconDefinitionsContainer = document.getElementById("noLexiconDefinitionsContainer");
const noWiktionaryDefinitionsContainer = document.getElementById("noWiktionaryDefinitionsContainer");
mesLexiquesList.innerHTML = "";
wiktionnaireList.innerHTML = "";
if (noLexiconDefinitionsContainer) noLexiconDefinitionsContainer.style.display = "none";
if (noWiktionaryDefinitionsContainer) noWiktionaryDefinitionsContainer.style.display = "none";
let hasLexiconDefinitions = false;
let hasWiktionaryDefinitions = false;
const lexiconGroups = {};
definitions.forEach(({ source, text }) => {
if (!source || !text) return;
const li = document.createElement("li");
let displayedText = text;
if (text.length > MAX_LENGTH) {
displayedText = text.slice(0, MAX_LENGTH) + "... ";
const readMoreLink = document.createElement("a");
readMoreLink.href = "#";
readMoreLink.textContent = "[Lire la suite]";
readMoreLink.style.marginLeft = "5px";
readMoreLink.style.color = "#8d5c70";
readMoreLink.style.textDecoration = "underline";
readMoreLink.style.cursor = "pointer";
readMoreLink.addEventListener("click", (event) => {
event.preventDefault();
openDefinitionPopup(text);
});
li.appendChild(document.createTextNode(displayedText));
li.appendChild(readMoreLink);
} else {
li.textContent = displayedText;
}
// Vérifier la source : Wiktionnaire/Lexiques
if (source === "Wiktionnaire") {
wiktionnaireList.appendChild(li);
hasWiktionaryDefinitions = true;
} else {
if (!lexiconGroups[source]) {
lexiconGroups[source] = [];
}
lexiconGroups[source].push(li);
hasLexiconDefinitions = true;
}
});
Object.entries(lexiconGroups).forEach(([lexiconName, definitionItems]) => {
const lexiconContainer = document.createElement("div");
lexiconContainer.className = "lexicon-section";
const lexiconHeader = document.createElement("div");
lexiconHeader.className = "lexicon-header";
lexiconHeader.textContent = lexiconName;
lexiconHeader.addEventListener("click", () => {
lexiconContent.classList.toggle("hidden");
});
const lexiconContent = document.createElement("ul");
lexiconContent.className = "lexicon-content hidden";
definitionItems.forEach(li => lexiconContent.appendChild(li));
lexiconContainer.appendChild(lexiconHeader);
lexiconContainer.appendChild(lexiconContent);
mesLexiquesList.appendChild(lexiconContainer);
});
if (!hasLexiconDefinitions && noLexiconDefinitionsContainer) {
if (!authToken) {
noLexiconDefinitionsContainer.textContent = "Veuillez vous connecter pour accéder aux définitions de vos lexiques.";
noLexiconDefinitionsContainer.style.textAlign = "center";
noLexiconDefinitionsContainer.style.fontStyle = "italic";
} else {
noLexiconDefinitionsContainer.textContent = "Aucune définition trouvée dans les lexiques.";
}
noLexiconDefinitionsContainer.style.display = "block";
}
if (!hasWiktionaryDefinitions && noWiktionaryDefinitionsContainer) {
noWiktionaryDefinitionsContainer.style.display = "block";
}
const mesLexiquesContainer = document.getElementById("mesLexiquesContainer");
if (mesLexiquesContainer) {
mesLexiquesContainer.style.display = hasLexiconDefinitions ? "block" : "none";
}
const wiktionnaireContainer = document.getElementById("wiktionnaireContainer");
if (wiktionnaireContainer) {
wiktionnaireContainer.style.display = hasWiktionaryDefinitions ? "block" : "none";
}
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Gestion du popup pour afficher la définition complète du Wiktionnaire
// ─────────────────────────────────────────────────────────────────────────────
function openDefinitionPopup(fullText) {
const modalOverlay = document.getElementById("modalOverlay");
const modalFullText = document.getElementById("modalFullText");
if (!modalOverlay || !modalFullText) {
console.error("Modal elements not found!");
return;
}
modalFullText.innerHTML = "<p>" + fullText.replace(/\n/g, "<br>") + "</p>";
modalOverlay.style.display = "flex";
}
/**
* Ferme le popup et nettoie le contenu
*/
function closeDefinitionPopup() {
const modalOverlay = document.getElementById("modalOverlay");
const modalFullText = document.getElementById("modalFullText");
if (!modalOverlay || !modalFullText) return;
modalOverlay.style.display = "none";
modalFullText.innerHTML = "";
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Affichage des définitions Babalex + Wiktionnaire
// ─────────────────────────────────────────────────────────────────────────────
/**
* Récupère en parallèle :
* - les définitions des lexiques de l'utilisateur (fetchLexiconDefinitions)
* - la définition Wiktionnaire (fetchWiktionaryDefinition)
* Puis fusionne les résultats.
*/
async function combineDefinitions(word) {
console.log(`[combineDefinitions] Récupération des définitions pour "${word}"...`);
const results = await Promise.allSettled([
fetchLexiconDefinitions(word),
fetchWiktionaryDefinition(word)
]);
const lexiconDefinitions =
results[0].status === "fulfilled" ? results[0].value : [];
const wiktionaryDefinitions =
results[1].status === "fulfilled" ? results[1].value : [];
const allDefinitions = [...lexiconDefinitions, ...wiktionaryDefinitions];
console.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}"...`);
const noDefinitionsContainer = document.getElementById("noDefinitionsContainer");
if (noDefinitionsContainer) {
noDefinitionsContainer.textContent = "Chargement des définitions...";
noDefinitionsContainer.style.display = "block";
}
try {
const allDefinitions = await combineDefinitions(word);
console.log("[showDefinitions] Définitions récupérées :", allDefinitions);
if (!allDefinitions || allDefinitions.length === 0) {
if (noDefinitionsContainer) {
noDefinitionsContainer.textContent = "⚠️ Aucune définition trouvée.";
}
return;
}
displayDefinitions(allDefinitions);
if (noDefinitionsContainer) {
noDefinitionsContainer.style.display = "none";
}
return allDefinitions;
} catch (error) {
console.error("❌ [showDefinitions] Erreur : ", error);
if (noDefinitionsContainer) {
noDefinitionsContainer.textContent =
"❌ Une erreur est survenue lors de la récupération des définitions.";
noDefinitionsContainer.style.display = "block";
}
return [];
}
}
/**
* Appel direct pour récupérer les définitions d’un mot uniquement via l’API
* (sans Wiktionnaire), puis gérer l’affichage d’erreur ou non.
*/
async function fetchDefinition(word) {
console.log(`🔍 Recherche de la définition pour '${word}'...`);
const noDefinitionsContainer = document.getElementById("noDefinitionsContainer");
if (!noDefinitionsContainer) {
console.error("❌ Élément #noDefinitionsContainer introuvable.");
return;
}
try {
const definition = await fetchLexiconDefinitions(word);
console.log("🔍 Résultat API :", definition);
if (!definition || definition.length === 0) {
console.warn(`⚠️ Aucune définition trouvée pour '${word}'`);
noDefinitionsContainer.style.display = "block";
return;
}
noDefinitionsContainer.style.display = "none";
} catch (error) {
console.error("❌ Erreur lors de la récupération de la définition :", error);
noDefinitionsContainer.style.display = "block";
}
}
/**
* Affiche les lexiques où le mot sélectionné est présent.
*/
function displayLexiconResults(lexicons) {
const resultDiv = document.getElementById("lexiconResult");
if (!resultDiv) return;
resultDiv.innerHTML = "";
if (!lexicons || lexicons.length === 0) {
resultDiv.textContent = "❌ Ce mot n'est présent dans aucun lexique.";
return;
}
const title = document.createElement("p");
title.innerHTML = "Ce mot est présent dans le(s) lexique(s) suivant(s) :";
title.style.fontSize = "12px";
resultDiv.appendChild(title);
const ul = document.createElement("ul");
ul.style.paddingLeft = "20px";
lexicons.forEach((lexicon) => {
if (!lexicon) {
console.warn("⚠️ Lexique incorrect :", lexicon);
return;
}
if (!lexicon.id) {
console.warn("ID non défini :", lexicon.id);
return;
}
const lexiconName = lexicon.name || `Lexique #${lexicon.id}`;
const li = document.createElement("li");
li.innerHTML = `<strong>${lexiconName}</strong>`;
ul.appendChild(li);
console.log(`✅ Lexique ajouté : ${lexiconName} (ID: ${lexicon.id})`);
});
resultDiv.appendChild(ul);
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Utilisation des fonctions dans d'autres scripts
// ─────────────────────────────────────────────────────────────────────────────
window.fetchLexiconDefinitions = fetchLexiconDefinitions;
window.fetchWiktionaryDefinition = fetchWiktionaryDefinition;
window.displayDefinitions = displayDefinitions;
window.openDefinitionPopup = openDefinitionPopup;
window.closeDefinitionPopup = closeDefinitionPopup;
window.combineDefinitions = combineDefinitions;
window.showDefinitions = showDefinitions;
window.fetchDefinition = fetchDefinition;
window.displayLexiconResults = displayLexiconResults;
...@@ -14,11 +14,16 @@ ...@@ -14,11 +14,16 @@
"notifications", "notifications",
"*://babalex.lezinter.net/*", "*://babalex.lezinter.net/*",
"*://prisms.lezinter.net/*", "*://prisms.lezinter.net/*",
"*://fr.wiktionary.org/*" "*://fr.wiktionary.org/*",
"<all_urls>"
], ],
"background": { "background": {
"scripts": ["background/background.js", "background/browser_context_menu.js"], "scripts": [
"background/background.js",
"definitions.js",
"menu_contextuel/browser_context_menu.js",
"api.js"],
"persistent": true "persistent": true
}, },
...@@ -39,7 +44,7 @@ ...@@ -39,7 +44,7 @@
"default_title": "BaLex", "default_title": "BaLex",
"default_panel": "barre_latérale/sidebar.html", "default_panel": "barre_latérale/sidebar.html",
"default_icon": { "default_icon": {
"16": "icons/icon-16.png", "16": "icons/logo.png",
"48": "icons/icon-48.png" "48": "icons/icon-48.png"
} }
}, },
......
console.log("browser_context_menu.js chargé correctement");
let authToken = null;
/**
* Charge le token depuis le stockage local et le stocke dans la variable globale authToken.
*/
async function loadAuthToken() {
try {
const result = await browser.storage.local.get("accessToken");
authToken = result.accessToken;
console.log("🔑 Token chargé au démarrage :", authToken);
} catch (error) {
console.error("❌ Erreur lors de la récupération du token :", error);
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Création du menu contextuel en fonction de l'authentification
// ─────────────────────────────────────────────────────────────────────────────
async function createContextMenu() {
await browser.contextMenus.removeAll();
if (authToken) {
// Item 1 : Recherche dans les lexiques de l’utilisateur
browser.contextMenus.create({
id: "searchInLexicons",
title: "Rechercher dans mes lexiques",
contexts: ["selection"],
icons: { "16": "icons/quel_lexique.png" },
});
// Item 2 : Ajouter un mot au lexique personnel
browser.contextMenus.create({
id: "addtoLexicon",
title: "Ajouter ce mot à mon lexique",
contexts: ["selection"],
icons: { "16": "icons/ajout_lexique.png" },
});
}
browser.contextMenus.create({
id: "separatorExtension",
type: "separator",
contexts: ["all"],
});
// Item 3 : Recherche globale de définition (Lexiques + Wiktionnaire)
browser.contextMenus.create({
id: "getDefinition",
title: "Obtenir une définition",
contexts: ["selection"],
icons: { "16": "icons/definition.png" },
});
browser.contextMenus.create({
id: "separatorAfterExtension",
type: "separator",
contexts: ["all"],
});
browser.contextMenus.create({
id: "login",
title: authToken ? "Se déconnecter de BaLex" : "Se connecter à BaLex",
contexts: ["all"],
});
}
loadAuthToken().then(createContextMenu);
browser.runtime.onMessage.addListener((message) => {
if (message.action === "refreshUI") {
console.log("🔄 refreshUI reçu dans browser_context_menu.js");
loadAuthToken().then(createContextMenu);
}
});
browser.storage.onChanged.addListener((changes, area) => {
if (area === "local" && changes.accessToken) {
console.log("🔄 Token modifié, actualisation du menu contextuel.");
loadAuthToken().then(createContextMenu);
}
});
// ─────────────────────────────────────────────────────────────────────────────
// Gestion des clics sur le menu contextuel
// ─────────────────────────────────────────────────────────────────────────────
browser.contextMenus.onClicked.addListener(async (info, tab) => {
console.log("Item de menu cliqué :", info.menuItemId);
if (info.menuItemId === "login") {
console.log("🔄 Action login/déconnexion demandée.");
if (typeof actuallyOpenLoginPage === "function") {
actuallyOpenLoginPage();
} else {
console.error("La fonction actuallyOpenLoginPage n'est pas accessible.");
}
return;
}
if (!info.selectionText) {
console.warn("Aucun texte sélectionné pour cette action :", info.menuItemId);
return;
}
console.log(`📩 Texte sélectionné : ${info.selectionText}`);
switch (info.menuItemId) {
case "searchInLexicons":
if (!authToken) {
alert("⚠️ Vous devez être connecté pour utiliser cette fonction.");
return;
}
await searchInLexicons(info.selectionText);
break;
case "addtoLexicon":
if (!authToken) {
alert("⚠️ Vous devez être connecté pour utiliser cette fonction.");
return;
}
await addWordToLexicon(info.selectionText);
break;
case "getDefinition":
await getDefinition(info.selectionText);
break;
default:
console.error(`❌ Action inconnue : ${info.menuItemId}`);
}
});
// ─────────────────────────────────────────────────────────────────────────────
// Fonctions liées aux définitions (definitions.js)
// ─────────────────────────────────────────────────────────────────────────────
/**
* 1) Recherche de la définition combinée (lexiques + Wiktionnaire)
* et envoi des résultats pour affichage.
*/
async function getDefinition(selectedText) {
try {
let lexiconDefs = [];
if (authToken) {
lexiconDefs = await fetchLexiconDefinitions(selectedText);
}
const wikiDefs = await fetchWiktionaryDefinition(selectedText);
const allDefinitions = [...lexiconDefs, ...wikiDefs];
console.log("📝 Définitions combinées :", allDefinitions);
browser.runtime.sendMessage({
action: "showDefinitions",
selectedText,
definitions: allDefinitions,
});
} catch (error) {
console.error("❌ Erreur lors de la recherche combinée des définitions :", error);
}
}
/**
* 2) Recherche dans les lexiques pour savoir dans quels lexiques se trouve le mot.
*/
async function searchInLexicons(selectedText) {
try {
console.log("🔎 Recherche dans mes lexiques :", selectedText);
const allDefinitions = await fetchLexiconDefinitions(selectedText);
if (!allDefinitions || allDefinitions.length === 0) {
console.log("❌ Aucun lexique trouvé pour ce mot.");
browser.runtime.sendMessage({
action: "showLexiconResult",
lexicons: [],
selectedText,
});
return;
}
const lexMap = new Map();
for (const def of allDefinitions) {
if (def.lexiconId) {
lexMap.set(def.lexiconId, def.source);
}
}
const foundInLexicons = [];
for (const [id, name] of lexMap.entries()) {
foundInLexicons.push({ id, name });
}
console.log("📩 Envoi du message 'showLexiconResult' avec :", foundInLexicons);
browser.runtime.sendMessage({
action: "showLexiconResult",
lexicons: foundInLexicons,
selectedText,
});
} catch (error) {
console.error("❌ Erreur lors de la recherche dans les lexiques :", error);
browser.runtime.sendMessage({
action: "showLexiconResult",
lexicons: [],
selectedText,
});
}
}
/**
* 3) Ajouter un mot dans le lexique personnel.
*/
async function addWordToLexicon(selectedText) {
try {
console.log("🔍 Ajout du mot à mon lexique :", selectedText);
alert(`(Exemple) Le mot "${selectedText}" a été ajouté à votre lexique personnel !`);
} catch (error) {
console.error("❌ Erreur lors de l'ajout au lexique :", error);
alert("❌ Impossible d'ajouter ce mot au lexique.");
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Écouteur interne pour d’autres messages éventuels
// ─────────────────────────────────────────────────────────────────────────────
browser.runtime.onMessage.addListener(async (message) => {
if (message.action === "getDefinitionAll") {
await getDefinition(message.selectedText);
}
});
...@@ -2,7 +2,17 @@ console.log("custom_context_menu.js chargé correctement"); ...@@ -2,7 +2,17 @@ console.log("custom_context_menu.js chargé correctement");
// === Variables globales === // === Variables globales ===
let authToken = null; let authToken = null;
const WHITE_BOX_ID = "whiteBox"; // Pour éviter les "magic strings" const WHITE_BOX_ID = "whiteBox";
// Fonction utilitaire pour envoyer une notification via le background
function sendNotification(title, message, iconPath) {
browser.runtime.sendMessage({
action: "showNotification",
title,
message,
iconPath
});
}
// Récupère le token depuis le stockage local et le stocke dans authToken // Récupère le token depuis le stockage local et le stocke dans authToken
async function loadAuthToken() { async function loadAuthToken() {
...@@ -16,170 +26,168 @@ async function loadAuthToken() { ...@@ -16,170 +26,168 @@ async function loadAuthToken() {
} }
} }
// Crée le menu contextuel personnalisé s'il n'existe pas déjà /**
* Crée le menu contextuel personnalisé (whiteBox) s'il n'existe pas déjà.
*/
function injectWhiteBox() { function injectWhiteBox() {
if (!document.getElementById(WHITE_BOX_ID)) { let whiteBox = document.getElementById(WHITE_BOX_ID);
const whiteBox = document.createElement("div"); if (!whiteBox) {
whiteBox = document.createElement("div");
whiteBox.id = WHITE_BOX_ID; whiteBox.id = WHITE_BOX_ID;
// Exemple pour générer toutes les URLs // Définition de styles essentiels pour le positionnement et la visibilité
whiteBox.style.position = "absolute";
whiteBox.style.zIndex = "9999";
whiteBox.style.backgroundColor = "#fff";
whiteBox.style.border = "1px solid #ccc";
whiteBox.style.padding = "5px";
whiteBox.style.borderRadius = "4px";
whiteBox.style.boxShadow = "0px 2px 10px rgba(0,0,0,0.2)";
// Génération des URLs des icônes
const addLexiconPath = browser.runtime.getURL("icons/ajout_lexique.png"); const addLexiconPath = browser.runtime.getURL("icons/ajout_lexique.png");
const getDefinitionPath = browser.runtime.getURL("icons/definition.png"); const getDefinitionPath = browser.runtime.getURL("icons/definition.png");
const getDefinitionWikiPath = browser.runtime.getURL("icons/definition_wiktionnaire.png");
const loginPath = browser.runtime.getURL("icons/connexion.png"); const loginPath = browser.runtime.getURL("icons/connexion.png");
// Construction du HTML // Construction du HTML
whiteBox.innerHTML = ` whiteBox.innerHTML = `
<p id="selectedWord">Mot sélectionné : Aucun</p> <p id="selectedWord" style="margin: 0; padding: 0;">Mot sélectionné : Aucun</p>
<hr style="border: 0; height: 1px; background-color: #323046; margin: 8px 0;"> <hr style="border: 0; height: 1px; background-color: #323046; margin: 8px 0;">
<div style="display: flex; flex-wrap: wrap; justify-content: center;"> <div style="display: flex; flex-wrap: wrap; justify-content: center;">
<!-- Bouton 1 - Ajouter au lexique -->
<!-- Bouton 1 - Ajout lexique --> <div class="icon-container" title="Ajouter ce mot à un lexique">
<div class="icon-container" title="Ajoutez ce mot à votre lexique">
<img src="${addLexiconPath}" alt="Ajouter au lexique" class="icon" id="addLexiconButton"> <img src="${addLexiconPath}" alt="Ajouter au lexique" class="icon" id="addLexiconButton">
</div> </div>
<!-- Bouton 2 - Définition (Babalex + Wiki) -->
<!-- Bouton 2 - Définition interne --> <div class="icon-container" title="Obtenir la définition">
<div class="icon-container" title="Obtenez la définition de ce mot">
<img src="${getDefinitionPath}" alt="Obtenir la définition" class="icon" id="getDefinitionButton"> <img src="${getDefinitionPath}" alt="Obtenir la définition" class="icon" id="getDefinitionButton">
</div> </div>
<!-- Bouton 3 - Connexion -->
<!-- Bouton 3 - Wiktionnaire -->
<div class="icon-container" title="Rechercher dans le Wiktionnaire">
<img src="${getDefinitionWikiPath}" alt="Wiktionnaire" class="icon" id="getDefinitionWikiButton">
</div>
<!-- Bouton 4 - Connexion -->
<div class="icon-container" title="Connectez-vous à BaLex"> <div class="icon-container" title="Connectez-vous à BaLex">
<img src="${loginPath}" alt="Se connecter" class="icon" id="loginButton" style="display: none;"> <img src="${loginPath}" alt="Se connecter" class="icon" id="loginButton" style="display: none;">
</div> </div>
</div> </div>
`; `;
document.body.appendChild(whiteBox); document.body.appendChild(whiteBox);
// Configure les actions de chaque bouton
setupWhiteBoxActions(); setupWhiteBoxActions();
} else {
console.log(`#${WHITE_BOX_ID} déjà présent dans le DOM.`);
} }
return whiteBox;
}
/**
* Renvoie le whiteBox s'il existe, ou le crée via injectWhiteBox().
*/
function getOrCreateWhiteBox() {
return document.getElementById(WHITE_BOX_ID) || injectWhiteBox();
} }
// Configure les actions/boutons du menu /**
* Configure les actions/boutons du menu contextuel.
*/
function setupWhiteBoxActions() { function setupWhiteBoxActions() {
const addLexiconBtn = document.getElementById("addLexiconButton"); const addLexiconBtn = document.getElementById("addLexiconButton");
const getDefinitionBtn = document.getElementById("getDefinitionButton"); const getDefinitionBtn = document.getElementById("getDefinitionButton");
const getDefinitionWikiBtn = document.getElementById("getDefinitionWikiButton");
const loginBtn = document.getElementById("loginButton"); const loginBtn = document.getElementById("loginButton");
// Ajout au lexique // Bouton : Ajouter le mot au lexique personnel
addLexiconBtn.onclick = async () => { addLexiconBtn.onclick = async () => {
const selectedText = getSelectedWord(); const selectedText = getSelectedWord();
console.log("🔍 Ajout au lexique :", selectedText); console.log("🔍 Ajout au lexique :", selectedText);
if (!selectedText) return;
if (authToken) { if (authToken) {
await searchLexicon(selectedText); await searchLexicon(selectedText);
} else { } else {
alert("⚠️ Veuillez vous connecter pour utiliser cette fonction."); sendNotification(
"Connexion requise",
"⚠️ Veuillez vous connecter pour utiliser cette fonction.",
"icons/connexion.png"
);
} }
}; };
// Obtenir la définition // Bouton : Obtenir une définition (Babalex + Wiktionnaire)
getDefinitionBtn.onclick = async () => { getDefinitionBtn.onclick = () => {
const selectedText = getSelectedWord(); const selectedText = getSelectedWord().trim();
console.log("📖 Recherche des définitions :", selectedText); if (selectedText) {
if (authToken) { browser.runtime.sendMessage({
await getDefinition(selectedText); action: "getDefinition",
} else { selectedText
alert("⚠️ Veuillez vous connecter pour utiliser cette fonction."); });
} }
}; };
// Définition Wiktionnaire // Bouton : Connexion
getDefinitionWikiBtn.onclick = () => {
const selectedText = getSelectedWord();
console.log("🌐 Recherche sur le Wiktionnaire :", selectedText);
alert(`Recherche sur le Wiktionnaire pour "${selectedText}".`);
};
// Login
loginBtn.onclick = () => { loginBtn.onclick = () => {
alert("Vous allez être redirigé(e) vers la page de connexion."); sendNotification(
"Redirection",
"Vous allez être redirigé(e) vers la page de connexion.",
"icons/connexion.png"
);
browser.runtime.sendMessage({ action: "toggleAuth" }); browser.runtime.sendMessage({ action: "toggleAuth" });
}; };
} }
// Met à jour la visibilité des boutons en fonction de l'état de connexion /**
* Met à jour la visibilité des boutons en fonction de l'état d'authentification.
*/
function updateMenuVisibility() { function updateMenuVisibility() {
// S'assurer que la whiteBox est injectée // S'assurer que le whiteBox existe
injectWhiteBox(); getOrCreateWhiteBox();
const addLexiconBtn = document.getElementById("addLexiconButton"); const addLexiconBtn = document.getElementById("addLexiconButton");
const getDefinitionBtn = document.getElementById("getDefinitionButton"); const getDefinitionBtn = document.getElementById("getDefinitionButton");
const getDefinitionWikiBtn = document.getElementById("getDefinitionWikiButton");
const loginBtn = document.getElementById("loginButton"); const loginBtn = document.getElementById("loginButton");
if (!addLexiconBtn || !getDefinitionBtn || !getDefinitionWikiBtn || !loginBtn) { if (!addLexiconBtn || !getDefinitionBtn || !loginBtn) {
console.warn("⚠️ Un des boutons n'a pas été trouvé dans le DOM."); console.warn("⚠️ Un des boutons n'a pas été trouvé dans le DOM.");
return; return;
} }
if (authToken) { if (authToken) {
// Utilisateur connecté // Utilisateur connecté => afficher "Ajouter" et "Définition", masquer "Connexion"
addLexiconBtn.style.display = "inline-block"; addLexiconBtn.style.display = "inline-block";
getDefinitionBtn.style.display = "inline-block"; getDefinitionBtn.style.display = "inline-block";
getDefinitionWikiBtn.style.display = "inline-block";
loginBtn.style.display = "none"; loginBtn.style.display = "none";
} else { } else {
// Utilisateur déconnecté // Utilisateur déconnecté => masquer "Ajouter", afficher "Définition" et "Connexion"
addLexiconBtn.style.display = "none"; addLexiconBtn.style.display = "none";
getDefinitionBtn.style.display = "none"; getDefinitionBtn.style.display = "inline-block";
getDefinitionWikiBtn.style.display = "inline-block";
loginBtn.style.display = "inline-block"; loginBtn.style.display = "inline-block";
} }
} }
// Récupère le mot affiché dans #selectedWord. /**
* Récupère le mot affiché dans #selectedWord.
*/
function getSelectedWord() { function getSelectedWord() {
const selectedWordElement = document.getElementById("selectedWord"); const selectedWordElement = document.getElementById("selectedWord");
if (!selectedWordElement) { return selectedWordElement ? selectedWordElement.textContent.trim() : "";
return "";
}
return selectedWordElement.textContent.split(": ")[1] || "";
} }
// Affiche le menu contextuel (whiteBox) à la position du clic en mettant à jour le mot sélectionné. /**
* Affiche le menu contextuel à la position du clic.
*/
function showWhiteBox(event, selectedText) { function showWhiteBox(event, selectedText) {
const whiteBox = document.getElementById(WHITE_BOX_ID); const whiteBox = getOrCreateWhiteBox();
if (!whiteBox) { const selectedWordElement = document.getElementById("selectedWord");
console.error(`#${WHITE_BOX_ID} introuvable dans le DOM.`); selectedWordElement.textContent = `${selectedText}`;
return;
}
if (selectedText) { // Calculer la position du menu en fonction de la sélection
// Met à jour l'affichage du mot sélectionné const selection = window.getSelection();
const selectedWordElement = document.getElementById("selectedWord"); if (!selection.rangeCount) return; // sécurité au cas où
selectedWordElement.textContent = `${selectedText}`; const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// Récupère la position de la sélection const top = rect.bottom + window.scrollY;
const selection = window.getSelection(); const left = rect.right + window.scrollX;
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect(); // Obtenez la position et taille du mot sélectionné whiteBox.style.left = `${left}px`;
whiteBox.style.top = `${top}px`;
// Calcule la position du menu en bas à droite du mot sélectionné whiteBox.style.display = "block";
const top = rect.bottom + window.scrollY; // Bas du mot + défilement vertical
const left = rect.right + window.scrollX; // Droite du mot + défilement horizontal console.log("Affichage du menu contextuel avec le mot :", selectedText);
updateMenuVisibility();
// Positionne la whiteBox
whiteBox.style.left = `${left}px`;
whiteBox.style.top = `${top}px`;
whiteBox.style.display = "block";nsole.log("Affichage du menu contextuel avec le mot :", selectedText);
// Mettre à jour la visibilité des boutons
updateMenuVisibility();
}
} }
// Masque la whiteBox.
function hideWhiteBox() { function hideWhiteBox() {
const whiteBox = document.getElementById(WHITE_BOX_ID); const whiteBox = document.getElementById(WHITE_BOX_ID);
if (whiteBox) { if (whiteBox) {
...@@ -187,44 +195,53 @@ function hideWhiteBox() { ...@@ -187,44 +195,53 @@ function hideWhiteBox() {
} }
} }
// === Écoute les événements de sélection de texte (mouseup) === // === Écoute des événements de sélection de texte (mouseup) ===
document.addEventListener("mouseup", (event) => { document.addEventListener("mouseup", (event) => {
const selectedText = window.getSelection().toString().trim(); const selectedText = window.getSelection().toString().trim();
if (selectedText) { if (selectedText) {
console.log("Événement de sélection détecté. Texte sélectionné :", selectedText); console.log("Événement de sélection détecté. Texte sélectionné :", selectedText);
injectWhiteBox(); getOrCreateWhiteBox();
showWhiteBox(event, selectedText); showWhiteBox(event, selectedText);
// Envoie le mot sélectionné à la barre latérale // Envoi du mot sélectionné au background
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: "mot_selectionne", action: "mot_selectionne",
selectedText, selectedText,
}); });
} else { } else {
// Masquer le menu si rien n'est sélectionné
hideWhiteBox(); hideWhiteBox();
} }
}); });
// Réécouter les messages envoyés par le background script // Réécoute des messages envoyés
browser.runtime.onMessage.addListener((message) => { browser.runtime.onMessage.addListener((message) => {
if (message.action === "refreshUI") { if (message.action === "refreshUI") {
console.log("🔄 Mise à jour du menu contextuel personnalisé (double-clic/sélection)."); console.log("🔄 Mise à jour du menu contextuel personnalisé.");
// Recharger le token puis mettre à jour l'affichage
loadAuthToken().then(() => { loadAuthToken().then(() => {
updateMenuVisibility(); updateMenuVisibility();
}); });
} }
}); });
// === Charger le token au démarrage, puis mettre à jour le menu === // Initialisation au démarrage
loadAuthToken().then(() => { loadAuthToken().then(() => {
injectWhiteBox(); getOrCreateWhiteBox();
updateMenuVisibility(); updateMenuVisibility();
}); });
browser.storage.onChanged.addListener((changes) => {
if (changes.accessToken) {
console.log("🔄 Token changé dans le stockage, mise à jour du menu personnalisé.");
loadAuthToken().then(() => {
updateMenuVisibility();
});
}
});
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Fonctions d'API Babalex pour l'ajout ou la vérification d'un mot
// ─────────────────────────────────────────────────────────────────────────────
// Recherche un mot dans le lexique personnel
async function searchLexicon(selectedText) { async function searchLexicon(selectedText) {
console.log("🔄 Recherche dans le lexique personnel pour :", selectedText); console.log("🔄 Recherche dans le lexique personnel pour :", selectedText);
try { try {
...@@ -252,73 +269,3 @@ async function searchLexicon(selectedText) { ...@@ -252,73 +269,3 @@ async function searchLexicon(selectedText) {
alert(`Erreur lors de la recherche : ${error.message}`); alert(`Erreur lors de la recherche : ${error.message}`);
} }
} }
// Vérifie dans quels lexiques le mot est présent
async function checkLexicon(selectedText) {
try {
const lexicons = await getLexicons(authToken);
const results = lexicons.map((lexicon) => ({
name: lexicon.name,
isPresent: lexicon.entries.some(
(entry) => entry.graphy.toLowerCase() === selectedText.toLowerCase()
),
}));
console.log("📋 Résultats des lexiques :", results);
let message = `Résultats pour "${selectedText}":\n\n`;
results.forEach(({ name, isPresent }) => {
message += `- ${name}: ${isPresent ? "✅ Présent" : "❌ Non présent"}\n`;
});
alert(message);
} catch (error) {
console.error("❌ Erreur lors de la vérification des lexiques :", error);
alert(`Erreur lors de la vérification : ${error.message}`);
}
}
// Obtenir les définitions d'un mot à partir de plusieurs lexiques.
async function getDefinition(selectedText) {
try {
const lexicons = await getLexicons(authToken);
let definitions = [];
for (const lexicon of lexicons) {
const entries = await getLexiconEntriesID(authToken, lexicon.id);
const entry = entries.find(
(e) => e.graphy.toLowerCase() === selectedText.toLowerCase()
);
if (entry) {
const definitionData = await getDefinitionAPI(authToken, entry.id);
// Remarque: j'ai renommé en getDefinitionAPI pour éviter
// la confusion avec la fonction "getDefinition" ci-dessus.
definitions.push(...extractDefinitions(definitionData));
}
}
console.log("📖 Définitions trouvées :", definitions);
if (definitions.length > 0) {
alert(`📖 Définitions pour "${selectedText}":\n\n` + definitions.join("\n"));
} else {
alert(`❌ Aucune définition trouvée pour "${selectedText}".`);
}
} catch (error) {
console.error("❌ Erreur lors de la récupération des définitions :", error);
alert(`Erreur lors de la récupération des définitions : ${error.message}`);
}
}
// Extrait un tableau de définitions à partir d'une réponse JSON de l'API.
function extractDefinitions(response) {
if (!response || !response.attributes || !response.attributes.Items) {
console.warn("⚠️ Structure de réponse inattendue.");
return [];
}
const items = response.attributes.Items;
return items.flatMap((item) => {
const defs = item.Sense?.Definitions?.map((def) => def.Def || "Définition non disponible");
return defs || [];
});
}
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