Emojis im benutzerdefinierten Abschnitt

Ich verwende Emojis im Abschnitt „Kategorien“ in der Seitenleiste, aber ich habe auch einen benutzerdefinierten Abschnitt, der öffentlich ist. Ich wollte die gleichen bunten Symbole in diesem Abschnitt haben, damit er im Vergleich zum Abschnitt „Kategorien“ nicht so „langweilig“ wirkt.

Ist das möglich?

2 „Gefällt mir“

Mit Hilfe von ChatGPT und Claude konnte ich es zum Laufen bringen und sehr anpassbar gestalten:

Wenn Sie dies tun möchten, erstellen Sie eine neue Komponente und fügen Sie Folgendes zum CSS-Tab hinzu:

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

In meinem speziellen Fall funktioniert 1rem hervorragend. Passen Sie es an Ihr Forum/Ihre Community an.

Dann im JS-Tab:

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

export default apiInitializer("0.11.1", (api) => {
  // Map section names to IDs
  const sectionIds = {
    "community": 1,
    "tiago": 2,
    "personal-section": 3,
    // Add more sections here
  };
  
  // Map of [sectionId, itemName] to emoji names
  const iconReplacements = {
    // Community section (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",
    
    // Tiago section (ID: 2)
    "2,Journal": "notebook_with_decorative_cover",
    "2,Music": "musical_note",
    "2,About": "bust_in_silhouette",
    
    // Personal section (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(',');
        
        // Only process if this replacement is for the current section
        if (parseInt(keyId) === sectionId) {
          const url = emojiUrlFor(emojiName);
          
          // Try multiple selectors to catch both hamburger menu and fixed sidebar
          const selectors = [
            // Fixed sidebar selector
            `div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
            // Hamburger menu selector (more specific)
            `.menu-panel div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
            // Generic fallback
            `[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) {
              // Check if it's already replaced to avoid unnecessary DOM manipulation
              if (!prefix.querySelector('.prefix-emoji')) {
                prefix.innerHTML = `
                  <img src="${url}"
                       title="${emojiName}"
                       alt="${emojiName}"
                       class="emoji prefix-emoji">
                `;
              }
              break; // Exit loop once we find and replace the icon
            }
          }
        }
      });
    });
  }

  // Run on page change
  api.onPageChange(replaceIcons);
  
  // Also run with delay to catch dynamically loaded content
  api.onPageChange(() => {
    setTimeout(replaceIcons, 100);
    setTimeout(replaceIcons, 500);
  });

  // Enhanced MutationObserver to catch sidebar changes
  const observer = new MutationObserver((mutations) => {
    let shouldReplace = false;
    
    mutations.forEach((mutation) => {
      // Watch for added nodes (original functionality)
      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;
          }
        }
      });
      
      // Watch for attribute changes on sidebar sections (collapse/expand)
      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;
        }
      }
      
      // Watch for childList changes in sidebar sections
      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);
    }
  });

  // Start observing with enhanced options
  observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: true, // Watch for attribute changes
    attributeFilter: ['class', 'style', 'aria-expanded'], // Common attributes that change on collapse/expand
  });

  // Additional event listeners for common sidebar interactions
  document.addEventListener('click', (event) => {
    // Check if click was on a sidebar section header or toggle button
    if (event.target.closest('.sidebar-section-header') ||
        event.target.closest('[data-section-name]') ||
        event.target.matches('.sidebar-section-toggle')) {
      setTimeout(replaceIcons, 100);
    }
  });
});

Ich habe es so gemacht, dass ich einfach neue benutzerdefinierte Abschnitte nach Namen hinzufügen kann, ihnen eine id zuweisen und dann die Zuordnung für jeden Abschnitt erstellen kann.
Der Grund dafür ist, dass ich möglicherweise 2 Abschnitte mit dem Titel Journal habe, aber vielleicht möchte ich für jeden ein anderes Emoji.

Ich bin mir ziemlich sicher, dass jemand sagen wird, dass es eine Komponente oder ein Plugin dafür gibt :wink: aber es hat trotzdem Spaß gemacht, mit ChatGPT und Claude hin und her zu gehen, bis alles so funktionierte, wie ich es wollte.

Ich hoffe, das hilft anderen Benutzern.

Wenn Sie etwas sehen, das angepasst/verbessert werden kann, teilen Sie es bitte mit :raising_hands:

3 „Gefällt mir“

Ich habe gerade den JS-Code aktualisiert, da mir aufgefallen ist, dass auf Mobilgeräten immer noch die Standard-Icons angezeigt wurden. Alles funktioniert wie erwartet, sowohl auf Mobilgeräten als auch auf Desktops.

Weitere Bearbeitung: Wenn ich den Abschnitt einklappe und wieder aufklappe, verschwanden die Emojis und wurden durch die ursprünglichen Symbole ersetzt. Es funktioniert jetzt und ich habe den JS-Code erneut aktualisiert.

Schön, dass Sie einen Weg gefunden haben, dies zu tun – ich denke, dies wäre eine ziemlich natürliche Ergänzung für eine Kernfunktion, da wir jetzt Emoji für Kategorien unterstützen.

3 „Gefällt mir“

Ich stimme zu. Hoffentlich wird dies irgendwann zu einer nativen Funktion. Bis dahin erfüllt diese benutzerdefinierte Komponente ihren Zweck :slight_smile:

2 „Gefällt mir“

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