Componente para adicionar uma mensagem personalizada ao Composer baseada no ID do usuário e categorias

Hoje enfrentei este problema:

https://meta.discourse.org/t/required-tags-should-only-be-required-based-on-type-of-user/392238

mas por enquanto, até que a equipe trabalhe nisso (esperançosamente), decidi pedir ajuda ao Claude para construir um Componente que me permite ter uma mensagem personalizada no Composer para me lembrar de adicionar uma tag. Posso adicionar um ou mais usuários, por ID, e posso limitar a certas categorias, também por ID.

Se o ID (usuário e categorias) NÃO estiver na lista, vejo isto:

image

Se o ID estiver na lista, vejo a mensagem:

image

Se isso for útil para outros, aqui está (basta criar um componente e adicionar o script na aba JS):

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

export default apiInitializer("0.8.31", (api) => {
  // Configuração: Adicione seus IDs de usuário e IDs de categoria aqui
  const TARGET_USER_IDS = [2]; // Substitua pelos IDs de usuário reais
  const TARGET_CATEGORY_IDS = [4,49]; // Substitua pelos IDs de categoria reais
  const REMINDER_MESSAGE = "🛑 Adicione a tag apropriada a esta postagem!";
  
  let previousCategoryId = null;
  let checkInterval = null;
  
  function checkAndUpdateMessage() {
    const composer = api.container.lookup("controller:composer");
    if (!composer || !composer.model) {
      // O Composer desapareceu, pare de verificar
      if (checkInterval) {
        clearInterval(checkInterval);
        checkInterval = null;
      }
      return;
    }
    
    const currentUser = api.getCurrentUser();
    if (!currentUser || !TARGET_USER_IDS.includes(currentUser.id)) return;
    
    const model = composer.model;
    const categoryId = model.categoryId;
    
    // Apenas age se a categoria mudou
    if (categoryId === previousCategoryId) return;
    previousCategoryId = categoryId;
    
    const currentReply = model.reply || "";
    
    // Remove a mensagem se ela foi adicionada
    if (currentReply.startsWith(REMINDER_MESSAGE)) {
      model.set("reply", currentReply.replace(REMINDER_MESSAGE, "").trim());
    }
    
    // Adiciona a mensagem se estiver na categoria de destino e o composer estiver vazio
    if (categoryId && TARGET_CATEGORY_IDS.includes(categoryId)) {
      const cleanReply = model.reply || "";
      if (cleanReply.trim().length === 0) {
        model.set("reply", REMINDER_MESSAGE);
      }
    }
  }
  
  // Verifica na abertura do composer
  api.onAppEvent("composer:opened", () => {
    previousCategoryId = null;
    checkAndUpdateMessage();
    
    // Inicia a verificação para mudanças de categoria
    if (checkInterval) clearInterval(checkInterval);
    checkInterval = setInterval(checkAndUpdateMessage, 300);
  });
  
  // Para de verificar quando o composer fecha
  api.onAppEvent("composer:closed", () => {
    if (checkInterval) {
      clearInterval(checkInterval);
      checkInterval = null;
    }
    previousCategoryId = null;
  });
});
1 curtida