Modo escuro automático para comentários incorporados também?

Automatic Dark Mode color scheme switching é uma adição fantástica, obrigado por integrá-la!

Com a troca de esquema de cores (automática) disponível, estou me perguntando se também poderia haver alguma maneira de alternar entre os modos claro e escuro do Discourse quando incorporado como comentários em um blog. Especificamente, meu blog Ghost possui um alternador que os usuários podem clicar para mudar manualmente entre os modos claro e escuro. Sei que o CSS do meu blog não pode afetar o CSS dentro do iframe do Discourse, mas com essa nova adição, poderia haver outra maneira de o alternador também mudar o esquema de cores do Discourse? Você pode ver um exemplo de post com comentários na parte inferior deste post.

11 curtidas

Isso é potencialmente viável, mas um pouco complicado. No momento, não adicionamos a troca automática do modo escuro ao endpoint de comentários incorporados. Podemos adicionar isso, e funcionaria se o seu site Ghost estivesse alternando automaticamente para o modo escuro quando o navegador muda para o modo escuro. Mas, pelo que pude perceber, o seu site Ghost usa um botão de modo escuro, o que não funcionará com a implementação do Discourse.

O que você pode fazer no seu caso específico é alternar uma classe no iframe de comentários incorporados do Discourse ao clicar no botão e, em seguida, usar essa classe para alternar as cores no seu estilo incorporado.

13 curtidas

Parece bom. Enquanto estou montando vários temas (Ghost) que utilizam modo escuro para colegas meus, todos os quais compartilharão uma única instância do Discourse, isso ainda está um pouco mais adiante no futuro.

Infelizmente, não entendi muito bem o que você está sugerindo aqui. Atualmente, todos os elementos que quero estilizar com modo escuro dentro do meu blog têm seu CSS duplicado ao preceder esses itens com body.dark. Ou seja:

p {
    color: #000;
}
body.dark p {
    color: #FFF;
}

Você está sugerindo que eu use esse código body.dark para alterar coisas no iframe do Discourse? Porque tentei inserir o seguinte no campo de CSS Incorporado do Discourse, o que, infelizmente, não teve efeito:

.FF2F-discourse p {
    color: #000;
}
body.dark .FF2F-discourse p {
    color: #FFF;
}

Dito isso, você está sugerindo que eu tenha algum JS separado escrito para que o botão alterne uma mudança específica ao direcionar uma classe dentro do iframe? Porque, como mencionei no meu comentário anterior, eu não achava que código externo pudesse afetar CSS dentro de um iframe, daí minha confusão. Mas sou apenas um amador em HTML/CSS, então sem dúvida você sabe mais do que eu e/ou estou entendendo algo errado.

Obrigado novamente por qualquer dica.

7 curtidas

Sim, é isso que estou sugerindo. As folhas de estilo do seu blog não podem ser aplicadas ao iframe, mas você pode usar JS para alternar a classe dark no elemento html ou body do iframe e, em seguida, atualizar sua folha de estilo incorporada do Discourse de acordo.

11 curtidas

Encontrei duas páginas explicando como alternar entre os modos claro e escuro para o embed do Discourse, mas o desenvolvedor que escreve meu JS está se perguntando se o método que você está sugerindo envolve o uso de postMessage (como as páginas que encontrei afirmam) ou algo diferente.

Aqui está uma página explicando como implementar comunicação entre janelas com postMessage:

Já esta outra é, na verdade, um tutorial sobre como alterar o CSS dentro de um iframe via postMessage, especificamente para alternar entre os modos claro e escuro:

https://cobwwweb.com/change-css-iframe

Será que estou no caminho certo com tudo isso?

8 curtidas

Peço desculpas, esqueci de responder aqui. Sim, acho que postMessage pode funcionar para o seu caso de uso.

11 curtidas

Olá,

Desculpe desenterrar um tópico tão antigo, mas há planos para implementar a troca automática de modo escuro para o endpoint de comentários incorporados?

1 curtida

No momento, não temos planos de adicionar esse recurso. Os sites podem adicionar estilos de modo escuro à sua folha de estilos incorporada como uma solução alternativa (ou usar a técnica postMessage discutida acima).

7 curtidas

postMessage precisa de um iframe incorporado para lidar com o evento message.
Onde adiciono código a um iframe para lidar com o evento?

2 curtidas

Eu implementei usando postMessage. Os códigos e sua lógica de execução são os seguintes:

O bloco de código ① adiciona um ouvinte de eventos no iframe incorporado do Discourse, que enviará uma mensagem para o meu site que contém o iframe incorporado do Discourse assim que o Discourse incorporado for carregado.

Quando meu site recebe a mensagem do Discourse incorporado, ele fará uma validação, como mostrado no bloco de código ②, e se aprovado, chamará a função setIframeStyle para definir o Discourse incorporado.

A função setIframeStyle, mostrada no bloco de código ③, passa o modo de cor, “dark” ou “light”, para o iframe chamando postMessage. Além disso, uma vez que o modo escuro é alternado, a função pode ser chamada para manter o Discourse incorporado com o mesmo modo de cor do meu site.

O bloco de código ④ permite que o Discourse incorporado possa processar a mensagem do modo de cor enviada do meu site. Aqui eu alterno o modo de cor trocando o nome da classe para a tag body.

Adicionalmente, os blocos de código ① e ④ são adicionados pela página de administração do Discourse, como abaixo:

E as classes CSS personalizadas devem ser adicionadas como abaixo:

12 curtidas

Alguém sabe onde editar se não pudermos editar “CSS incorporado” (porque não é um tema oficial)?

2 curtidas

Você acabou de criar um novo componente e usar sua aba Incorporado?

3 curtidas

Obrigado pelo esboço acima @mikeguo, isso foi maravilhosamente explicado!

Observe também que você precisa estar na versão mais recente do Discourse para realizar isso, a capacidade de cabeçalho incorporado foi adicionada apenas há alguns dias.

8 curtidas

EDIT: Era isso que eu precisava fazer Structure of themes and theme components

Isso parece estar errado?

const handleMessageListener = (event:MessageEvent<any>)

2 curtidas

Ainda não consigo ativar este código (!) Alguém poderia, por favor, revisá-lo?

Vejo que ninguém consegue ativar isto e quase todos estão usando o modo claro forçado, o que é muito ruim para os nossos olhos :frowning:

1 curtida

Posso confirmar que o método acima ainda funciona, mas teria sido bom não ter que digitar o código de uma captura de tela :slight_smile: Então, aqui está ele, ligeiramente atualizado:

Passos

  1. O iframe de comentários termina de renderizar e envia uma mensagem para a janela principal do navegador, informando isso.
  2. O navegador consulta sua configuração de modo escuro/claro e envia o valor de volta para o iframe.
  3. O iframe recebe a mensagem e define um atributo de dados, classe ou similar, com base na configuração de modo escuro/claro.

Código

  1. Assim que o iframe for carregado, envie uma notificação para a janela pai. Isso precisa ser inserido no Discourse, em Admin -> Personalizar -> (selecionar tema) -> Editar CSS/HTML -> Cabeçalho Embutido.
<script type="text/javascript">
    window.addEventListener("load", (event) => {
        window.parent.postMessage("iframe loaded", "*");
    }, false);
</script>
  1. Manipule este gatilho de entrada na janela principal. Este código fica no seu site de blog:
<script type="text/javascript">
  const discourse_url = "https://your.discourse-instance.org";

  // Aqui, determinamos o tema e enviamos uma mensagem para o iframe para informá-lo sobre o tema
  // Veja abaixo como configuramos notifyFrameStyle
  const notifyIFrameOfTheme = () => {
    const iframe = document.getElementById("discourse-embed-frame");
    if (iframe && iframe.contentWindow) {
      iframe.contentWindow.postMessage(
        {
          // Modifique a linha abaixo para capturar a configuração do modo escuro, dependendo de como você a armazena
          theme: document.documentElement.getAttribute("data-theme")
        },
        discourse_url
      );
    }
  };

  // Chama setFrameStyle quando recebemos a mensagem "iframe loaded"
  const handleMessageListener = (event) => {
    var origin = event.origin;
    if ((origin === discourse_url) && (event.data == "iframe loaded")) {
      notifyIFrameOfTheme();
    }
  };
</script>
  1. No bloco <script> de (1), adicione um listener para a mensagem de tema enviada por notifyFrameStyle:
    window.addEventListener("message", (event) => {
        const payload = event.data;
        if (payload.theme) {
          // Faça algo com a configuração do tema; eu defino o atributo `data-theme` no `<html>` do iframe,
          // mas você pode querer definir um atributo de classe ou similar
          document.documentElement.setAttribute("data-theme", payload.theme);
        }
    }, false);

Estilização

Em Admin -> Personalizar -> (selecionar tema) -> Editar CSS/HTML -> CSS Embutido, você agora pode fornecer CSS para cada modo. Por exemplo, você pode substituir as variáveis de estilo do Discourse:

html[data-theme="dark"] {
  --primary: #ced6dd;
  --primary-low: #48566b;
  --secondary: #14181e;
  --tertiary: #2b7e8d;
}

Espero que isso ajude!

6 curtidas

O código copiável acima está faltando a adição do ouvinte de eventos na janela de incorporação:

window.addEventListener("message", handleMessageListener);

E uma observação: Nenhuma configuração especial de CORS é necessária para isso.

Obrigado por perceber! Não posso mais editar a postagem acima, mas o window.addEventListener vai no final do trecho de código em (2).

Veja este exemplo real.

6 curtidas