嵌入式评论也自动开启暗模式吗?

Automatic Dark Mode color scheme switching is a fantastic addition, thanks for integrating it!

With (automatic) color scheme switching available, I’m wondering if there might also be some way to switch back and forth between light and dark Discourse modes when embedded as comments in a blog. Specifically, my Ghost blog has a toggle that users can click on to manually switch back and forth between light and dark modes. I know that my blog’s CSS can’t effect the CSS within Discourse’s iframe, but with this new addition might there be another way that the toggle could also switch the Discourse color scheme? You can see an example post with comments at the bottom of this post.

11 个赞

This is potentially doable but a little tricky. At the moment, we haven’t added dark mode auto switching to the embedded comments endpoint. We can add that, and it would work if your Ghost site was auto-switching to dark mode when the browser switches to dark mode. But from what I can tell, your Ghost site uses a dark mode button, which won’t work with the Discourse implementation.

What you can do in your specific case, is toggle a class in the Discourse embedded comments iframe when clicking the button, and then use that class to toggle colors in your embedded stylesheet.

13 个赞

Sounds good. While I am currently putting together several dark mode utilizing (Ghost) themes for colleagues of mine, all of which will share a single Discourse instance, that’s still a bit further down the road.

I unfortunately don’t quite understand what you’re suggesting here. Currently, any elements that I want to utilize dark mode styling within my blog have their CSS doubled up by preceding such items with body.dark. As in

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

Might you be suggesting that I use that body.dark code to change things in the Discourse iframe? Because I tried inserting the following into Discourse’s Embedded CSS field, which unfortunately had no effect:

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

That being so, are you instead suggesting that I have some separate JS written so that the toggle will affect a separate change via specific targeting of a class in the iframe? Because like I stated in my previous comment, I didn’t think that external coding could affect CSS within an iframe, hence my confusion. But I’m very much solely an HTML/CSS amateur, so there’s no doubt that you know better than me and/or that I’m misunderstanding something else.

Thanks again for any hints.

6 个赞

Yes, that’s what I am suggesting. Your blog’s stylesheets cannot apply to the iframe, but you can use JS to toggle the dark class in the iframe’s html or body element, and then update your Discourse embedded stylesheet accordingly.

10 个赞

I’ve found two pages explaining how toggling between light and dark modes for Discourse’s embed might be done, but the guy who writes my JS is wondering if the method you’re suggesting entails using postMessage (which the pages I found state) or something else.

Here’s a page explaining how to implement cross-window messaging with postMessage

While this one is actually a tutorial on how to change the CSS within an iframe via postMessage, specifically for switching between light and dark modes:

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

Might I be on the right track with all this?

8 个赞

My apologies, I forgot to respond here, yes, I think postMessage can work for your use case.

11 个赞

您好,

抱歉挖出这么老的话题,但有没有计划为嵌入式评论端点实现自动切换到暗黑模式?

1 个赞

我们目前没有计划添加此功能。网站可以为其嵌入的样式表添加暗模式样式作为一种变通方法(或使用上面讨论的 postMessage 技术)。

7 个赞

postMessage 需要嵌入式 iframe 来处理 message 事件。
我应该在哪里向 iframe 添加代码来处理该事件?

2 个赞

我通过使用 postMessage 来实现。代码及其执行逻辑如下:

代码块 ① 在嵌入的 Discourse iframe 中添加了一个事件监听器,该监听器将在嵌入的 Discourse 加载完成后,向嵌入 Discourse iframe 的我的网站发送消息。

当我的网站收到来自嵌入 Discourse 的消息时,它将进行验证,如代码块 ② 所示,如果验证通过,则调用 setIframeStyle 函数来设置嵌入的 Discourse。

setIframeStyle 函数,如代码块 ③ 所示,通过调用 postMessage 将颜色模式(“dark”或“light”)传递给 iframe。此外,一旦切换到暗模式,就可以调用该函数来使嵌入的 Discourse 与我的网站保持相同的颜色模式。

代码块 ④ 允许嵌入的 Discourse 处理从我的网站发送的颜色模式消息。在这里,我通过切换 body 标签的类名来切换颜色模式。

此外,代码块 ① 和 ④ 是通过 Discourse 管理页面添加的,如下所示:

并且自定义 CSS 类应该如下添加:

12 个赞

有人知道如果无法编辑“嵌入式 CSS”(因为不是官方主题),可以在哪里进行编辑吗?

2 个赞

您刚创建了一个新组件并使用了它的嵌入式选项卡?

3 个赞

感谢上面 @mikeguo 提供的概述,解释得非常棒!

另外,请注意,您需要使用最新版本的 Discourse 才能实现此功能,嵌入式标题功能是几天前才添加的。

8 个赞

“**编辑:**我需要这样做 Structure of themes and theme components

这似乎是错的?

const handleMessageListener = (event:MessageEvent<any>)

2 个赞

我仍然无法启用此代码(!)有人可以帮忙修改一下吗?

我看到没有人能启用它,几乎所有人都使用强光,这对我们的眼睛非常不好 :frowning:

1 个赞

我确认上述方法仍然有效,但如果不用从截图中输入代码就好了 :slight_smile: 所以,这里是稍作更新的版本:

步骤

  1. 评论 iframe 渲染完成,并向主浏览器窗口发送消息,告知已完成。
  2. 浏览器查询其深色/浅色模式设置,并将值发送回 iframe。
  3. iframe 接收消息,并根据深色/浅色模式设置设置一个 data-attributeclass 或类似的属性。

代码

  1. iframe 加载后,向父窗口发送通知。这需要在 DiscourseAdmin -> Customize -> (选择主题) -> Edit CSS/HTML -> Embedded Header 中输入。
<script type="text/javascript">
    window.addEventListener("load", (event) => {
        window.parent.postMessage("iframe loaded", "*");
    }, false);
</script>
  1. 在主窗口中处理此传入的触发器。此代码位于您的博客网站
<script type="text/javascript">
  const discourse_url = "https://your.discourse-instance.org";

  // 在这里,我们确定主题,并向 iframe 发送消息,告知其主题是什么
  // 有关如何设置 notifyFrameStyle 的说明,请参阅下文
  const notifyIFrameOfTheme = () => {
    const iframe = document.getElementById("discourse-embed-frame");
    if (iframe && iframe.contentWindow) {
      iframe.contentWindow.postMessage(
        {
          // 根据您存储深色模式设置的方式,修改下面一行以获取深色模式设置
          theme: document.documentElement.getAttribute("data-theme")
        },
        discourse_url
      );
    }
  };

  // 在收到“iframe loaded”消息时调用 setFrameStyle
  const handleMessageListener = (event) => {
    var origin = event.origin;
    if ((origin === discourse_url) && (event.data == "iframe loaded")) {
      notifyIFrameOfTheme();
    }
  };
</script>
  1. 在 (1) 中的 <script> 块中,添加一个监听器来接收 notifyFrameStyle 发送的主题消息:
    window.addEventListener("message", (event) => {
        const payload = event.data;
        if (payload.theme) {
          // 使用主题设置执行某些操作;我将 `data-theme` 属性设置在 iframe 的 `<html>` 上,
          // 但您可能希望设置一个 class 属性或类似的属性
          document.documentElement.setAttribute("data-theme", payload.theme);
        }
    }, false);

样式

Admin -> Customize -> (选择主题) -> Edit CSS/HTML -> Embedded CSS 中,您现在可以为每种模式提供 CSS。例如,您可以覆盖 Discourse 的样式变量:

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

希望这有帮助!

6 个赞

上面可复制粘贴的代码缺少了嵌入式窗口中的事件监听器添加:

window.addEventListener("message", handleMessageListener);

以及一条说明:不需要特殊的 CORS 设置。

感谢您发现这一点!我无法再编辑上面的帖子了,但是 window.addEventListener 应该放在 (2) 下方的代码片段的底部。

请参阅此真实示例

5 个赞