diff --git a/src/assets/lexicon_icon.js b/src/assets/lexicon_icon.js index 9228f8209695dfa6931826f36f70c8859eca452e..394d73da5a4d0592e866d1e1d57e8e4b36b36665 100644 --- a/src/assets/lexicon_icon.js +++ b/src/assets/lexicon_icon.js @@ -49,11 +49,12 @@ async function getOrCreateLexiconColor(lexiconId, forceReset = false) { */ function createColorCircle(color, size = 32) { const circle = document.createElement("div"); + circle.className = "color-circle"; circle.style.width = `${size}px`; circle.style.height = `${size}px`; circle.style.borderRadius = "50%"; circle.style.backgroundColor = color; - circle.style.border = "1px solid black"; // Optionnel + circle.style.border = "1px solid black"; return circle; } diff --git a/src/context_menu/custom_context_menu.css b/src/context_menu/custom_context_menu.css index 30f66dff8a4f8213de33088ddb3387a077852f4f..7bc2f23ca51e607b6c31aaac03ddc048b362a7c4 100644 --- a/src/context_menu/custom_context_menu.css +++ b/src/context_menu/custom_context_menu.css @@ -1,81 +1,156 @@ /* === Conteneur principal du menu contextuel === */ #whiteBox { - position: absolute; - display: none; - min-width: 50px; - max-width: 300px; - background-color: white; - color: #323046; - border: 2px solid #323046; - border-radius: 10px; - padding: 10px; - box-shadow: 0 4px 12px rgba(0,0,0,0.2); - font-family: "Helvetica", sans-serif; - z-index: 10000; - } - - /* === Titre/texte indiquant le mot sélectionné === */ - #whiteBox #selectedWord { - margin: 0; - margin-bottom: 8px; - font-size: 14px; - line-height: 1.3; - color: #323046; - font-weight: bold; - text-align: center; - } - - /* === Conteneur des icônes === */ - #whiteBox .icon-container { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - margin: 0; - padding: 0; - } - - #whiteBox .icon-container:hover { - background-color: rgba(255, 255, 255, 0.1); - border-radius: 6px; - } - - /* === Les icônes elles-mêmes === */ - #whiteBox .icon { - width: 40px; - height: 40px; - transition: transform 0.2s ease; - margin : 0 auto; - display: block; - } - - #whiteBox .icon:hover { - transform: scale(1.15); - } - - /* === Message (tooltips) === */ - #whiteBox .tooltip { - visibility: hidden; - background-color: #333; - color: #fff; - text-align: center; - padding: 6px; - border-radius: 5px; - position: absolute; - bottom: -34px; - left: 50%; - transform: translateX(-50%); - white-space: nowrap; - font-size: 12px; - opacity: 0; - transition: opacity 0.2s ease, visibility 0.2s ease; - z-index: 1000; - } - - #whiteBox .icon-container:hover .tooltip { - visibility: visible; - opacity: 1; - } - \ No newline at end of file + position: absolute; + display: none; + min-width: 50px; + max-width: 300px; + background-color: white; + color: #323046; + border: 2px solid #323046; + border-radius: 10px; + padding: 10px; + box-shadow: 0 4px 12px rgba(0,0,0,0.2); + font-family: "Helvetica", sans-serif; + z-index: 10000; +} + +/* === Titre/texte indiquant le mot sélectionné === */ +#whiteBox #selectedWord { + margin: 0; + margin-bottom: 8px; + font-size: 14px; + line-height: 1.3; + color: #323046; + font-weight: bold; + text-align: center; +} + +/* === Conteneur des icônes === */ +#whiteBox .icon-container { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + cursor: pointer; + margin: 0; + padding: 0; +} + +#whiteBox .icon-container:hover { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 6px; +} + +/* === Les icônes elles-mêmes === */ +#whiteBox .icon { + width: 40px; + height: 40px; + transition: transform 0.2s ease; + margin : 0 auto; + display: block; +} + +#whiteBox .icon:hover { + transform: scale(1.15); +} + +/* === Message (tooltips) === */ +#whiteBox .tooltip { + visibility: hidden; + background-color: #333; + color: #fff; + text-align: center; + padding: 6px; + border-radius: 5px; + position: absolute; + bottom: -34px; + left: 50%; + transform: translateX(-50%); + white-space: nowrap; + font-size: 12px; + opacity: 0; + transition: opacity 0.2s ease, visibility 0.2s ease; + z-index: 1000; +} + +#whiteBox .icon-container:hover .tooltip { + visibility: visible; + opacity: 1; +} + +/* === Style global du lexiconPicker === */ +#lexiconPicker { + position: absolute; + z-index: 10000; + background-color: rgba(255, 255, 255, 0.98); + border: 1px solid #ddd; + padding: 4px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + width: 150px; + font-family: Arial, sans-serif; + font-size: 10px; + display: flex !important; + flex-direction: row !important; + flex-wrap: wrap !important; + align-items: center; + justify-content: center; + gap: 2px; +} + +/* Style pour les icônes de lexique */ +#lexiconPicker .lexicon-option { + cursor: pointer; + display: inline-flex !important; + flex-direction: row !important; + align-items: center; + justify-content: center; + border: 2px solid transparent; + border-radius: 50%; + width: 40px; + height: 40px; + transition: border 0.2s ease; + flex: 0 0 auto; +} + +/* Effet au survol pour les icônes */ +#lexiconPicker .lexicon-option:hover { + border: 2px solid #6e76c7; +} + +/* Classe pour indiquer qu'une icône est sélectionnée */ +#lexiconPicker .lexicon-option.selected { + border: 2px solid #323046; +} + +/* Style pour le cercle de couleur (icône interne) */ +#lexiconPicker .color-circle { + width: 28px; /* ajustez la taille si besoin */ + height: 28px; + border-radius: 50%; + display: inline-block; + /* La couleur de fond sera définie dynamiquement via JS */ + border: 1px solid black; /* optionnel */ +} + +/* Style pour le bouton de confirmation */ +#lexiconPicker button.confirmButton { + font-style: italic; + font-size: 10px; + padding: 6px 10px; + cursor: pointer; + border: none; + border-radius: 4px; + background-color: #323046; + color: white; + flex-basis: 100%; /* force le bouton à occuper toute la largeur et à passer à la ligne */ + margin-top: 8px; +} + +#lexiconPicker p { + font-size: 12px; + font-weight: bold; + text-align: center; +} + diff --git a/src/context_menu/custom_context_menu.js b/src/context_menu/custom_context_menu.js index b9f66179b3bfd1428129e5926c4b2ba7d408708c..91e117b9645a68deaed3acd4b621c8c1874be275 100644 --- a/src/context_menu/custom_context_menu.js +++ b/src/context_menu/custom_context_menu.js @@ -237,93 +237,80 @@ function createPicker() { picker.id = "lexiconPicker"; picker.style.position = "absolute"; picker.style.zIndex = "10000"; - picker.style.backgroundColor = "rgba(255, 255, 255, 0.95)"; - picker.style.border = "1px solid #ccc"; - picker.style.padding = "5px"; - picker.style.borderRadius = "4px"; - picker.style.boxShadow = "0 2px 10px rgba(0,0,0,0.3)"; - picker.style.display = "none"; - + picker.style.backgroundColor = "rgba(255, 255, 255, 0.98)"; + picker.style.border = "1px solid #ddd"; + picker.style.padding = "8px"; + picker.style.borderRadius = "8px"; + picker.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.1)"; + picker.style.width = "220px"; // largeur adaptée pour afficher les icônes sur une ligne + picker.style.fontFamily = "Arial, sans-serif"; + picker.style.fontSize = "10px"; + // Définir le picker en flex avec direction horizontale picker.style.display = "flex"; - picker.style.flexWrap = "wrap"; - picker.style.gap = "10px"; - picker.style.alignItems = "center"; - + picker.style.flexDirection = "row"; // IMPORTANT : aligne les éléments en ligne + picker.style.flexWrap = "wrap"; // autorise le retour à la ligne si nécessaire + picker.style.alignItems = "center"; + picker.style.justifyContent = "center"; + picker.style.gap = "5px"; document.body.appendChild(picker); } return picker; } - /** * Affiche le picker pour choisir le lexique dans lequel ajouter le mot. - * Pour chaque lexique, vérifie si le mot existe déjà dans ce lexique en appelant fetchLexiconDefinitions. - * S'il n'existe pas, appelle window.AddWord pour l'ajouter. */ async function showPicker(event, selectedText) { - console.log("showPicker appelé avec", event, selectedText); - const picker = createPicker(); - picker.innerHTML = ""; // Vider le picker - const selectedLexicons = new Set(); // Stocke les lexiques sélectionnés + let picker = document.getElementById("lexiconPicker"); + if (!picker) { + picker = document.createElement("div"); + picker.id = "lexiconPicker"; + document.body.appendChild(picker); + } + picker.innerHTML = ""; + + const selectedLexicons = new Set(); try { const lexicons = await getLexicons(authToken, "fr"); console.log("Lexicons récupérés :", lexicons); if (!Array.isArray(lexicons) || lexicons.length === 0) { - picker.innerHTML = "<p>Aucun lexique trouvé.</p>"; + picker.innerHTML = "<p style='color:#333;'>Aucun lexique trouvé.</p>"; } else { + // Ajout des icônes directement dans le picker for (const lex of lexicons) { const id = lex.id; const name = lex.category === "User" ? `Lexique personnel : ${lex.user?.pseudo || "Inconnu"} (${lex.id})` : `Lexique de groupe : ${lex.group?.name || "Inconnu"} (${lex.id})`; - // Obtenir la couleur et créer le cercle + // Obtenir la couleur et créer un cercle (l'icône) const color = await getOrCreateLexiconColor(id); - const circleIcon = createColorCircle(color, 32); + const circleIcon = createColorCircle(color, 28); - // Créer un conteneur pour l'icône + // Création du conteneur pour l'icône const iconContainer = document.createElement("div"); iconContainer.className = "lexicon-option"; iconContainer.dataset.lexiconId = id; - iconContainer.style.margin = "5px"; - iconContainer.style.cursor = "pointer"; iconContainer.title = name; - iconContainer.style.display = "inline-flex"; - iconContainer.style.flexDirection = "row"; - iconContainer.style.alignItems = "center"; - iconContainer.style.justifyContent = "center"; - iconContainer.style.border = "2px solid transparent"; - - // Ajoute le cercle coloré au conteneur - iconContainer.appendChild(circleIcon); - picker.appendChild(iconContainer); - - // Écouteur de clic pour sélectionner/désélectionner le lexique iconContainer.addEventListener("click", () => { if (selectedLexicons.has(id)) { selectedLexicons.delete(id); - iconContainer.style.border = "2px solid transparent"; + iconContainer.classList.remove("selected"); } else { selectedLexicons.add(id); - iconContainer.style.border = "2px solid black"; + iconContainer.classList.add("selected"); } }); + iconContainer.appendChild(circleIcon); + picker.appendChild(iconContainer); } - // Ajouter un bouton de validation + // Création du bouton de validation qui passera sur une nouvelle ligne const confirmButton = document.createElement("button"); - confirmButton.textContent = "Ajouter aux lexiques sélectionnés"; - confirmButton.style.fontStyle = "italic"; - confirmButton.style.fontSize = "8px"; - confirmButton.style.marginTop = "10px"; - confirmButton.style.padding = "5px 10px"; - confirmButton.style.cursor = "pointer"; - confirmButton.style.border = "none"; - confirmButton.style.borderRadius = "4px"; - confirmButton.style.backgroundColor = "#6e76c7"; - confirmButton.style.color = "white"; + confirmButton.className = "confirmButton"; + confirmButton.textContent = "Ajouter le mot"; confirmButton.addEventListener("click", async () => { if (selectedLexicons.size === 0) { @@ -349,40 +336,32 @@ async function showPicker(event, selectedText) { } } - // Affichage des lexiques où le mot existe déjà if (existingLexiconIds.size > 0) { alert(`âš ï¸ Le mot "${selectedText}" existe déjà dans les lexiques suivants : ${Array.from(existingLexiconIds).join(", ")}`); } - // Filtrer les lexiques où le mot n'existe pas encore const lexiconsToAdd = [...selectedLexicons].filter(id => !existingLexiconIds.has(id)); - if (lexiconsToAdd.length === 0) { alert(`✅ Le mot "${selectedText}" est déjà présent dans tous les lexiques sélectionnés.`); return; } - // Envoi de la requête d'ajout try { console.log(`📡 Ajout du mot "${selectedText}" dans les lexiques :`, lexiconsToAdd); const result = await AddWord(authToken, selectedText, lexiconsToAdd, false); console.log("✅ Réponse API :", result); - // Rafraîchir l'UI après l'ajout await new Promise(resolve => setTimeout(resolve, 300)); browser.runtime.sendMessage({ action: "refreshUI" }); - // Affichage du message de confirmation dans le picker picker.innerHTML = `<p style="color: green;">✅ Mot ajouté avec succès dans : ${lexiconsToAdd.join(", ")}.</p>`; setTimeout(() => picker.style.display = "none", 2000); browser.runtime.sendMessage({ action: "addWordResult", - lexicons:`✅ Mot ajouté avec succès dans : ${lexiconsToAdd.join(", ")}.` + lexicons: `✅ Mot ajouté avec succès dans : ${lexiconsToAdd.join(", ")}.` }); } catch (error) { console.error("⌠Erreur lors de l'ajout du mot :", error); - - // Affichage du message d'erreur dans le picker picker.innerHTML = `<p style="color: red;">⌠Erreur : ${error.message}</p>`; setTimeout(() => picker.style.display = "none", 3000); browser.runtime.sendMessage({ @@ -401,15 +380,11 @@ async function showPicker(event, selectedText) { picker.style.display = "block"; } catch (error) { console.error("⌠Erreur lors de la récupération des lexiques :", error); - picker.innerHTML = "<p>Erreur lors du chargement des lexiques.</p>"; + picker.innerHTML = "<p style='color:#333;'>Erreur lors du chargement des lexiques.</p>"; picker.style.display = "block"; } } - - - - function hideLexiconPicker() { const picker = document.getElementById("lexiconPicker"); if (picker) {