两次点击其实不算什么麻烦事,但这正是一个绝佳的契机,可以提供一个通用的说明,文档化如何操作 Composer 按钮,并聚焦于你想要实现的目标。
向工具栏添加按钮是通过另一个 pluginAPI 方法完成的。
工具栏使用的是这个方法 plugin-api.js.es6#L375-L391,而弹出菜单使用的是这个方法 plugin-api.js.es6#L396-L411。
预设回复插件使用的是弹出菜单方法,如下所示:
除非你 fork 该插件,否则无法移动按钮——我们非常不推荐这样做。
你可以做的是在工具栏中添加另一个执行相同操作的按钮,并隐藏旧的按钮。为了在工具栏中创建按钮,你需要参考其他按钮是如何添加的。
工具栏中有两种类型的按钮。第一种是处理格式化的按钮,例如 粗体 和 斜体。由于它们与你的目标不太相似,我们先暂时忽略它们。
另一种是插入内容的按钮,例如日期和表情符号。让我们看看“日期 - 日历”按钮。
现在我们有了一个可以借鉴的示例。让我们尝试创建新按钮。
我们从这里开始:
api.onToolbarCreate(toolbar => {
toolbar.addButton({
});
});
然后逐个添加预设回复按钮的属性。作为参考,这些属性是:
id: "canned_replies_button",
icon: "far-clipboard",
action: "showCannedRepliesButton",
label: "canned_replies.composer_button_text"
id:这允许你为按钮添加 CSS 类——我们将使用 custom-canned-button。
icon:按钮将使用的图标——我们将保持原样。
label:弹出按钮有文本,而 Composer 按钮没有,因此我们需要将其改为 title 并使用相同的值。
action:这是你定义按钮行为的地方。让我们把这些整合起来:
api.onToolbarCreate(toolbar => {
toolbar.addButton({
id: "custom-canned-replies",
icon: "far-clipboard",
action: "showCannedRepliesButton",
title: "canned_replies.composer_button_text"
});
});
如果你尝试这样做,你会在工具栏中看到按钮,但点击它不会有任何反应。这是因为 showCannedRepliesButton 动作未定义。这是由于不同的上下文——因为你是在主题中执行此操作。
如果你查看预设回复插件,你会发现该动作是在 Composer 控制器中定义的:
所以下一步是引用 Composer 控制器,以便在按钮点击时能够发送该动作。你可以这样做:
const composerController = api.container.lookup("controller:composer");
api.onToolbarCreate(toolbar => {
toolbar.addButton({
title: "canned_replies.composer_button_text",
id: "custom-canned-replies",
group: "extras",
icon: "far-clipboard",
sendAction: () => composerController.send("showCannedRepliesButton")
});
});
请注意,我们使用了与 日历按钮 相同的 sendAction 模式。唯一的两个例外是:
我们使用 composerController.send 而不是 toolbar.context.send
并且我们没有传递事件,因为我认为这并不需要。
这应该能让你在工具栏中获得一个完全功能的按钮:
但我们还没有完成,因为这个按钮现在对所有成员都可见。使用权限仍然适用,如果无权用户尝试点击它,他们只会收到错误。然而,一个损坏的按钮并不好,所以让我们修复它。
使用预设回复的权限设置在这里:
因此,我们只需要将这些作为按钮添加的条件进行复制。类似于这样:
const currentUser = api.getCurrentUser();
const canUseCannedReplies = currentUser
? currentUser.can_use_canned_replies
: false;
if (!canUseCannedReplies) return;
这将确保只有在拥有所需权限时才会显示该按钮。
那么,让我们把所有内容整合起来:
import { withPluginApi } from "discourse/lib/plugin-api";
export default {
name: "move-canned-button",
initialize() {
withPluginApi("0.8.7", api => {
const currentUser = api.getCurrentUser();
const canUseCannedReplies = currentUser
? currentUser.can_use_canned_replies
: false;
if (!canUseCannedReplies) return;
const composerController = api.container.lookup("controller:composer");
api.onToolbarCreate(toolbar => {
toolbar.addButton({
title: "canned_replies.composer_button_text",
id: "custom-canned-replies",
group: "extras",
icon: "far-clipboard",
sendAction: () => composerController.send("showCannedRepliesButton")
});
});
});
}
};
这应该放入主题组件中的以下文件:
javascripts/discourse/initializers/move-canned-button.js.es6
如果你使用的是新功能 https://meta.discourse.org/t/splitting-up-theme-javascript-into-multiple-files/119369——非常推荐。
或者,如果你是在管理后台操作,只需将此脚本添加到主题的“头部”选项卡中即可。
旧语法
<script type="text/discourse-plugin"
version="0.8">
const currentUser = api.getCurrentUser();
const canUseCannedReplies = currentUser
? currentUser.can_use_canned_replies
: false;
if (!canUseCannedReplies) return;
const composerController = api.container.lookup("controller:composer");
api.onToolbarCreate(toolbar => {
toolbar.addButton({
title: "canned_replies.composer_button_text",
id: "custom-canned-replies",
group: "extras",
icon: "far-clipboard",
sendAction: () => composerController.send("showCannedRepliesButton")
});
});
</script>
你最后需要做的就是隐藏旧按钮,你可以这样做:
.toolbar-popup-menu-options {
[data-name="Canned replies"] {
display: none;
}
}