Con l’aiuto di ChatGPT e Claude, sono riuscito a farlo funzionare e a renderlo molto personalizzabile:
Se vuoi farlo, crea un nuovo componente e aggiungi questo alla scheda CSS:
.sidebar-section-link-prefix .emoji.prefix-emoji {
width: 1rem !important;
height: 1rem !important;
}
Nel mio caso particolare 1rem funziona benissimo. Adatta al tuo forum/community
Poi nella scheda JS:
import { apiInitializer } from "discourse/lib/api";
import { emojiUrlFor } from "discourse/lib/text";
export default apiInitializer("0.11.1", (api) => {
// Mappa i nomi delle sezioni agli ID
const sectionIds = {
"community": 1,
"tiago": 2,
"personal-section": 3,
// Aggiungi altre sezioni qui
};
// Mappa di [sectionId, itemName] ai nomi delle emoji
const iconReplacements = {
// Sezione Community (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",
// Sezione Tiago (ID: 2)
"2,Journal": "notebook_with_decorative_cover",
"2,Music": "musical_note",
"2,About": "bust_in_silhouette",
// Sezione Personale (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(',');
// Elabora solo se questa sostituzione è per la sezione corrente
if (parseInt(keyId) === sectionId) {
const url = emojiUrlFor(emojiName);
// Prova più selettori per catturare sia il menu hamburger che la barra laterale fissa
const selectors = [
// Selettore barra laterale fissa
`div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
// Selettore menu hamburger (più specifico)
`.menu-panel div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
// Fallback generico
`[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) {
// Controlla se è già stato sostituito per evitare manipolazioni non necessarie del DOM
if (!prefix.querySelector('.prefix-emoji')) {
prefix.innerHTML = `
<img src="${url}"
title="${emojiName}"
alt="${emojiName}"
class="emoji prefix-emoji">
`;
}
break; // Esci dal ciclo una volta trovata e sostituita l'icona
}
}
}
});
});
}
// Esegui al cambio pagina
api.onPageChange(replaceIcons);
// Esegui anche con un ritardo per catturare contenuti caricati dinamicamente
api.onPageChange(() => {
setTimeout(replaceIcons, 100);
setTimeout(replaceIcons, 500);
});
// MutationObserver potenziato per catturare le modifiche alla barra laterale
const observer = new MutationObserver((mutations) => {
let shouldReplace = false;
mutations.forEach((mutation) => {
// Osserva i nodi aggiunti (funzionalità originale)
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;
}
}
});
// Osserva le modifiche agli attributi nelle sezioni della barra laterale (espandi/comprimi)
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;
}
}
// Osserva le modifiche a childList nelle sezioni della barra laterale
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);
}
});
// Avvia l'osservazione con opzioni potenziate
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true, // Osserva le modifiche agli attributi
attributeFilter: ['class', 'style', 'aria-expanded'], // Attributi comuni che cambiano con espandi/comprimi
});
// Listener di eventi aggiuntivi per interazioni comuni della barra laterale
document.addEventListener('click', (event) => {
// Controlla se il clic è avvenuto sull'intestazione di una sezione della barra laterale o su un pulsante di attivazione
if (event.target.closest('.sidebar-section-header') ||
event.target.closest('[data-section-name]') ||
event.target.matches('.sidebar-section-toggle')) {
setTimeout(replaceIcons, 100);
}
});
});
Ho fatto in modo di poter aggiungere facilmente nuove sezioni personalizzate per nome, attribuendogli un id e creando poi la mappatura di ciascuna sezione.
Il motivo è che potrei avere 2 sezioni con il titolo Journal, ad esempio, ma magari voglio 2 emoji diverse per ciascuna.
Sono abbastanza sicuro che qualcuno dirà che esiste un componente o un plugin per questo
ma è stato comunque divertente andare avanti e indietro con ChatGPT e Claude finché tutto non ha funzionato come volevo.
Spero che questo aiuti altri utenti.
Se vedi qualcosa che può essere modificato/migliorato, per favore condividilo 