stromfeldt
(Allan Strømfeldt Christensen)
1
Automatic Dark Mode color scheme switching 是一个出色的功能,感谢你们将其集成进来!
既然已经支持(自动)配色方案切换,我想知道在将 Discourse 嵌入博客作为评论时,是否也有办法在亮色和暗色模式之间来回切换?具体来说,我的 Ghost 博客有一个切换按钮,用户可以点击它手动在亮色和暗色模式之间切换。我知道我博客的 CSS 无法影响 Discourse iframe 内部的 CSS,但有了这个新功能,是否还有其他方式可以让该切换按钮同时切换 Discourse 的配色方案?您可以在 这篇文章 底部的示例帖子中看到带评论的示例。
11 个赞
pmusaraj
(Penar Musaraj)
2
这在理论上是可行的,但有点棘手。目前,我们尚未在嵌入式评论端点添加深色模式自动切换功能。我们可以添加该功能,前提是你的 Ghost 网站能够在浏览器切换到深色模式时自动切换为深色模式。但据我所知,你的 Ghost 网站使用的是深色模式按钮,这与 Discourse 的实现方式不兼容。
针对你的具体情况,你可以在点击按钮时切换 Discourse 嵌入式评论 iframe 中的一个类,然后利用该类在你的嵌入式样式表中切换颜色。
13 个赞
stromfeldt
(Allan Strømfeldt Christensen)
3
听起来不错。虽然我目前正在为我的同事准备几个利用暗色模式的(Ghost)主题,所有这些主题都将共享一个 Discourse 实例,但那还是稍后的事情。
遗憾的是,我不太明白您的建议。目前,我博客中任何希望应用暗色模式样式的元素,其 CSS 都通过在这些元素前加上 body.dark 来重复定义。例如:
p {
color: #000;
}
body.dark p {
color: #FFF;
}
您是否建议我使用那个 body.dark 代码来更改 Discourse iframe 中的内容?因为我尝试在 Discourse 的“嵌入 CSS"字段中插入以下代码,但遗憾的是没有产生任何效果:
.FF2F-discourse p {
color: #000;
}
body.dark .FF2F-discourse p {
color: #FFF;
}
既然如此,您是否建议我编写一些独立的 JavaScript,以便切换按钮能通过针对 iframe 中特定类的方式触发相应的变化?正如我在上一条评论中提到的,我以为外部代码无法影响 iframe 内的 CSS,因此感到困惑。但我只是一个 HTML/CSS 业余爱好者,毫无疑问您比我更懂,或者是我误解了其他某些内容。
再次感谢您提供的任何提示。
7 个赞
pmusaraj
(Penar Musaraj)
4
是的,这正是我的建议。您的博客样式表无法应用于 iframe,但您可以使用 JavaScript 切换 iframe 中 html 或 body 元素的 dark 类,并相应地更新您的 Discourse 嵌入样式表。
11 个赞
stromfeldt
(Allan Strømfeldt Christensen)
5
我找到了两篇介绍如何实现 Discourse 嵌入内容在亮色和暗色模式之间切换的文章,但负责我 JavaScript 代码的同事想知道,您建议的方法是否涉及使用 postMessage(我找到的文章都提到了这一点),还是另有其他方法。
这是一篇介绍如何使用 postMessage 实现跨窗口通信的文章:
而这一篇实际上是关于如何通过 postMessage 在 iframe 中更改 CSS 的教程,专门用于切换亮色和暗色模式:
https://cobwwweb.com/change-css-iframe
我目前的思路是否正确?
8 个赞
pmusaraj
(Penar Musaraj)
6
非常抱歉,我忘了在这里回复。是的,我认为 postMessage 可以满足您的使用场景。
11 个赞
您好,
抱歉挖出这么老的话题,但有没有计划为嵌入式评论端点实现自动切换到暗黑模式?
1 个赞
pmusaraj
(Penar Musaraj)
8
我们目前没有计划添加此功能。网站可以为其嵌入的样式表添加暗模式样式作为一种变通方法(或使用上面讨论的 postMessage 技术)。
7 个赞
mikeguo
(Mike)
9
postMessage 需要嵌入式 iframe 来处理 message 事件。
我应该在哪里向 iframe 添加代码来处理该事件?
2 个赞
mikeguo
(Mike)
10
我通过使用 postMessage 来实现。代码及其执行逻辑如下:
代码块 ① 在嵌入的 Discourse iframe 中添加了一个事件监听器,该监听器将在嵌入的 Discourse 加载完成后,向嵌入 Discourse iframe 的我的网站发送消息。
当我的网站收到来自嵌入 Discourse 的消息时,它将进行验证,如代码块 ② 所示,如果验证通过,则调用 setIframeStyle 函数来设置嵌入的 Discourse。
setIframeStyle 函数,如代码块 ③ 所示,通过调用 postMessage 将颜色模式(“dark”或“light”)传递给 iframe。此外,一旦切换到暗模式,就可以调用该函数来使嵌入的 Discourse 与我的网站保持相同的颜色模式。
代码块 ④ 允许嵌入的 Discourse 处理从我的网站发送的颜色模式消息。在这里,我通过切换 body 标签的类名来切换颜色模式。
此外,代码块 ① 和 ④ 是通过 Discourse 管理页面添加的,如下所示:
并且自定义 CSS 类应该如下添加:
12 个赞
有人知道如果无法编辑“嵌入式 CSS”(因为不是官方主题),可以在哪里进行编辑吗?
2 个赞
pmusaraj
(Penar Musaraj)
16
感谢上面 @mikeguo 提供的概述,解释得非常棒!
另外,请注意,您需要使用最新版本的 Discourse 才能实现此功能,嵌入式标题功能是几天前才添加的。
8 个赞
“**编辑:**我需要这样做 Structure of themes and theme components
这似乎是错的?
const handleMessageListener = (event:MessageEvent<any>)”
2 个赞
我仍然无法启用此代码(!)有人可以帮忙修改一下吗?
我看到没有人能启用它,几乎所有人都使用强光,这对我们的眼睛非常不好 
1 个赞
我确认上述方法仍然有效,但如果不用从截图中输入代码就好了
所以,这里是稍作更新的版本:
步骤
- 评论 iframe 渲染完成,并向主浏览器窗口发送消息,告知已完成。
- 浏览器查询其深色/浅色模式设置,并将值发送回 iframe。
- iframe 接收消息,并根据深色/浅色模式设置设置一个
data-attribute、class 或类似的属性。
代码
- iframe 加载后,向父窗口发送通知。这需要在 Discourse 的
Admin -> Customize -> (选择主题) -> Edit CSS/HTML -> Embedded Header 中输入。
<script type="text/javascript">
window.addEventListener("load", (event) => {
window.parent.postMessage("iframe loaded", "*");
}, false);
</script>
- 在主窗口中处理此传入的触发器。此代码位于您的博客网站:
<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) 中的
<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 个赞
n1bff
20
上面可复制粘贴的代码缺少了嵌入式窗口中的事件监听器添加:
window.addEventListener("message", handleMessageListener);
以及一条说明:不需要特殊的 CORS 设置。
感谢您发现这一点!我无法再编辑上面的帖子了,但是 window.addEventListener 应该放在 (2) 下方的代码片段的底部。
请参阅此真实示例。
6 个赞