Emojis dans la section personnalisée

J’utilise des emojis dans la section Catégories de la barre latérale, mais j’ai aussi une section personnalisée qui est publique. Je voulais avoir les mêmes icônes colorées dans cette section pour qu’elle ne soit pas si « fade » par rapport à la section Catégories.

Est-ce possible ?

2 « J'aime »

Avec l’aide de ChatGPT et de Claude, j’ai réussi à le faire fonctionner et à le rendre très personnalisable :

Si vous souhaitez le faire, créez un nouveau composant et ajoutez ceci à l’onglet CSS :

.sidebar-section-link-prefix .emoji.prefix-emoji {
  width: 1rem !important;
  height: 1rem !important;
}

Dans mon cas particulier, 1rem fonctionne très bien. Adaptez-le à votre forum/communauté.

Ensuite, dans l’onglet JS :

import { apiInitializer } from "discourse/lib/api";
import { emojiUrlFor } from "discourse/lib/text";

export default apiInitializer("0.11.1", (api) => {
  // Mappe les noms de sections aux IDs
  const sectionIds = {
    "community": 1,
    "tiago": 2,
    "personal-section": 3,
    // Ajoutez d'autres sections ici
  };
  
  // Mappe [sectionId, itemName] aux noms d'emojis
  const iconReplacements = {
    // Section Communauté (ID: 1)
    "1,admin": "wrench",
    "1,review": "triangular_flag_on_post",
    "1,everything": "books",
    "1,my-posts": "writing_hand",
    "1,my-messages": "envelope_with_arrow",
    
    // Section Tiago (ID: 2)
    "2,Journal": "notebook_with_decorative_cover",
    "2,Music": "musical_note",
    "2,About": "bust_in_silhouette",
    
    // Section Personnelle (ID: 3)
    "3,Backups": "floppy_disk",
    "3,Scheduled": "clock3",
    "3,Staff": "lock",
    "3,Components": "electric_plug",
  };

  function replaceIcons() {
    Object.entries(sectionIds).forEach(([sectionName, sectionId]) => {
      Object.entries(iconReplacements).forEach(([key, emojiName]) => {
        const [keyId, itemName] = key.split(',');
        
        // Traite uniquement si ce remplacement concerne la section actuelle
        if (parseInt(keyId) === sectionId) {
          const url = emojiUrlFor(emojiName);
          
          // Essaye plusieurs sélecteurs pour attraper le menu hamburger et la barre latérale fixe
          const selectors = [
            // Sélecteur de barre latérale fixe
            `div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
            // Sélecteur de menu hamburger (plus spécifique)
            `.menu-panel div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
            // Solution de repli générique
            `[data-section-name="${sectionName}"] [data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`
          ];
          
          for (const selector of selectors) {
            const prefix = document.querySelector(selector);
            
            if (prefix && url) {
              // Vérifie s'il a déjà été remplacé pour éviter des manipulations DOM inutiles
              if (!prefix.querySelector('.prefix-emoji')) {
                prefix.innerHTML = `
                  <img src="${url}"
                       title="${emojiName}"
                       alt="${emojiName}"
                       class="emoji prefix-emoji">
                `;
              }
              break; // Sort de la boucle une fois l'icône trouvée et remplacée
            }
          }
        }
      });
    });
  }

  // Exécute lors du changement de page
  api.onPageChange(replaceIcons);
  
  // Exécute également avec un délai pour attraper le contenu chargé dynamiquement
  api.onPageChange(() => {
    setTimeout(replaceIcons, 100);
    setTimeout(replaceIcons, 500);
  });

  // MutationObserver amélioré pour attraper les changements de la barre latérale
  const observer = new MutationObserver((mutations) => {
    let shouldReplace = false;
    
    mutations.forEach((mutation) => {
      // Surveille les nœuds ajoutés (fonctionnalité d'origine)
      mutation.addedNodes.forEach((node) => {
        if (node.nodeType === Node.ELEMENT_NODE) {
          if (node.classList?.contains('menu-panel') || 
              node.querySelector?.('.sidebar-sections') ||
              node.classList?.contains('sidebar-sections') ||
              node.querySelector?.('[data-section-name]')) {
            shouldReplace = true;
          }
        }
      });
      
      // Surveille les changements d'attributs sur les sections de la barre latérale (réduction/expansion)
      if (mutation.type === 'attributes' && mutation.target.nodeType === Node.ELEMENT_NODE) {
        const target = mutation.target;
        if (target.matches('[data-section-name]') || 
            target.closest('[data-section-name]') ||
            target.matches('.sidebar-section') ||
            target.closest('.sidebar-section')) {
          shouldReplace = true;
        }
      }
      
      // Surveille les changements de childList dans les sections de la barre latérale
      if (mutation.type === 'childList' && mutation.target.nodeType === Node.ELEMENT_NODE) {
        const target = mutation.target;
        if (target.matches('[data-section-name]') || 
            target.closest('[data-section-name]') ||
            target.querySelector('[data-section-name]')) {
          shouldReplace = true;
        }
      }
    });
    
    if (shouldReplace) {
      setTimeout(replaceIcons, 50);
    }
  });

  // Commence l'observation avec des options améliorées
  observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: true, // Surveille les changements d'attributs
    attributeFilter: ['class', 'style', 'aria-expanded'], // Attributs courants qui changent lors de la réduction/expansion
  });

  // Écouteurs d'événements supplémentaires pour les interactions courantes de la barre latérale
  document.addEventListener('click', (event) => {
    // Vérifie si le clic a eu lieu sur un en-tête de section de la barre latérale ou un bouton de bascule
    if (event.target.closest('.sidebar-section-header') ||
        event.target.closest('[data-section-name]') ||
        event.target.matches('.sidebar-section-toggle')) {
      setTimeout(replaceIcons, 100);
    }
  });
});

J’ai fait en sorte de pouvoir facilement ajouter de nouvelles sections personnalisées par nom, en leur attribuant un id puis en créant la correspondance de chaque section.
La raison est que je peux avoir 2 sections avec le titre Journal, par exemple, mais je veux peut-être 2 emojis différents pour chacune.

Je suis à peu près sûr que quelqu’un dira qu’il existe un composant ou un plugin pour cela :wink: mais c’était quand même amusant d’échanger avec ChatGPT et Claude jusqu’à ce que tout fonctionne comme je le voulais.

J’espère que cela aidera d’autres utilisateurs.

Si vous voyez quelque chose qui peut être ajusté/amélioré, n’hésitez pas à partager :raising_hands:

3 « J'aime »

J’ai juste mis à jour le code JS, car j’avais remarqué qu’il affichait toujours les icônes par défaut sur mobile. Tout fonctionne comme prévu sur mobile et sur ordinateur.

Autre modification : lorsque je réduisais et agrandissais la section, les emojis disparaissaient et étaient remplacés par les icônes d’origine. Cela fonctionne maintenant et j’ai mis à jour le code JS.

Je suis content que vous ayez trouvé un moyen de faire cela – je pense que cela s’intégrerait naturellement à une fonctionnalité de base, maintenant que nous prenons en charge les emojis pour les catégories.

3 « J'aime »

Je suis d’accord. J’espère que cela deviendra une fonctionnalité native à terme. En attendant, ce composant personnalisé fait le travail :slight_smile:

2 « J'aime »

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.