您好,我正在尝试重现 Meta 上的 Central 主题中标题菜单与用户和通知分离的效果。我曾在主题帖中询问过,但没有得到回复。
如果我想做同样的事情,我需要编辑哪些文件?是将文件放在我的主题中还是通过主题组件重新创建更好?
您好,我正在尝试重现 Meta 上的 Central 主题中标题菜单与用户和通知分离的效果。我曾在主题帖中询问过,但没有得到回复。
如果我想做同样的事情,我需要编辑哪些文件?是将文件放在我的主题中还是通过主题组件重新创建更好?
如果您检查页面并查看“Sources”选项卡,您可以看到它是如何构建的。
基本上:
api.addToHeaderIcons 添加header-notifications 小部件的内容,用铃铛图标替换了头像。一如既往地感谢您的协助,我将设置一个暂存开发环境来解决这个问题。再次感谢。
您好 @digitaldominica!抱歉我没有及时查看此线程,因为我很快就要发布下一个更新了。大家的反馈都很有价值,但如果我一直盯着看,就容易把它们添加到当前列表中,而不是留到下一个更新。![]()
@Arkshine 说得对。这是一个相当hacky的方法,在主题的限制下工作(Central 的很多内容只是原型设计,因为我首先是设计师,其次才是设计师,最后才是开发者)。
我将提供一个分步指南,介绍我如何在 Central 中实现这个粗略的原型。但请注意,如果将来我们对用户菜单进行核心更新,此解决方案可能无法保持未来兼容性,而且可能有一种更优化的方法来创建该组件。
创建这些文件—
/javascripts/discourse/components/header-user-new.js
/javascripts/discourse/components/header-user-new.hbs
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
export default class HeaderUserNew extends Component {
@service currentUser;
@tracked isActive = false;
constructor() {
super(...arguments);
this.handleDocumentClick = this.handleDocumentClick.bind(this);
}
@action
toggleDropdown() {
this.isActive = !this.isActive;
if (this.isActive) {
setTimeout(() => {
document.addEventListener("click", this.handleDocumentClick);
}, 0);
} else {
document.removeEventListener("click", this.handleDocumentClick);
}
}
handleDocumentClick(event) {
const dropdown = document.querySelector(".header-user-new__menu");
const isClickInside = dropdown.contains(event.target);
if (!isClickInside) {
this.isActive = false;
document.removeEventListener("click", this.handleDocumentClick);
}
}
willDestroy() {
super.willDestroy();
document.removeEventListener("click", this.handleDocumentClick);
}
}
<div class={{concatClass "header-user-new" (if isActive "active")}}>
<button class="header-user-new__button" type="button" {{on "click" this.toggleDropdown}}>
{{avatar currentUser}}
</button>
<div class="header-user-new__menu">
<LinkTo class="header-user-new__profile" @route="user.summary" @model={{this.currentUser}}>
{{avatar currentUser}}
<div class="header-user-new__profile-info">
<span class="header-user-new__profile-name">
{{#if currentUser.name}}
{{currentUser.name}}
{{else}}
{{currentUser.username}}
{{/if}}
</span>
<span class="header-user-new__profile-view">
View Profile
</span>
</div>
</LinkTo>
<ul>
<li>
<LinkTo @route="userActivity.bookmarks" @model={{this.currentUser}}>
{{d-icon "bookmark"}}
<span>
{{i18n "js.user.bookmarks"}}
</span>
</LinkTo>
</li>
<li>
<LinkTo @route="preferences" @model={{this.currentUser}}>
{{d-icon "cog"}}
<span>
{{i18n "user.preferences"}}
</span>
</LinkTo>
</li>
<li>
<DButton @action={{route-action "logout"}}>
{{d-icon "sign-out-alt"}}
<span>
{{i18n "user.log_out"}}
</span>
</DButton>
</li>
</ul>
</div>
</div>
目前,CSS 样式由您自行决定,但包含以下内容对于实现切换效果很重要—
.header-user-new {
&.active {
.header-user-new__menu {
display: flex;
}
}
.header-user-new__menu {
display: none;
}
}
创建此文件—
/javascripts/discourse/widgets/header-user-new.js
import { hbs } from "ember-cli-htmlbars";
import RenderGlimmer from "discourse/widgets/render-glimmer";
import { createWidget } from "discourse/widgets/widget";
export default createWidget("header-user-new", {
tagName: "li.header-dropdown-toggle.header-user-new",
html() {
return [new RenderGlimmer(this, "div", hbs`<HeaderUserNew />`)];
},
});
创建此文件—
/javascripts/discourse/initializers/header-edit.js
import { h } from "virtual-dom";
import { withPluginApi } from "discourse/lib/plugin-api";
import { iconNode } from "discourse-common/lib/icon-library";
import I18n from "discourse-i18n";
export default {
initialize() {
withPluginApi("0.8", (api) => {
api.reopenWidget("header-notifications", {
html(attrs) {
const { user } = attrs;
let avatarAttrs = {
template: user.get("avatar_template"),
username: user.get("username"),
};
if (this.siteSettings.enable_names) {
avatarAttrs.name = user.get("name");
}
const contents = [h("div", iconNode("bell"))];
if (this.currentUser.status) {
contents.push(this.attach("user-status-bubble", this.currentUser.status));
}
if (user.isInDoNotDisturb()) {
contents.push(h("div.do-not-disturb-background", iconNode("moon")));
} else {
if (user.new_personal_messages_notifications_count) {
contents.push(
this.attach("link", {
action: attrs.action,
className: "badge-notification with-icon new-pms",
icon: "envelope",
omitSpan: true,
title: "notifications.tooltip.new_message_notification",
titleOptions: {
count: user.new_personal_messages_notifications_count,
},
attributes: {
"aria-label": I18n.t("notifications.tooltip.new_message_notification", {
count: user.new_personal_messages_notifications_count,
}),
},
})
);
} else if (user.unseen_reviewable_count) {
contents.push(
this.attach("link", {
action: attrs.action,
className: "badge-notification with-icon new-reviewables",
icon: "flag",
omitSpan: true,
title: "notifications.tooltip.new_reviewable",
titleOptions: { count: user.unseen_reviewable_count },
attributes: {
"aria-label": I18n.t("notifications.tooltip.new_reviewable", {
count: user.unseen_reviewable_count,
}),
},
})
);
} else if (user.all_unread_notifications_count) {
contents.push(
this.attach("link", {
action: attrs.action,
className: "badge-notification unread-notifications",
rawLabel: user.all_unread_notifications_count,
omitSpan: true,
title: "notifications.tooltip.regular",
titleOptions: { count: user.all_unread_notifications_count },
attributes: {
"aria-label": I18n.t("user.notifications"),
},
})
);
}
}
return contents;
},
});
const currentUser = api.container.lookup("service:current-user");
if (currentUser !== null) {
api.addToHeaderIcons("header-user-new");
}
});
},
};
主要的变化是用 iconNode 替换了 avatarImg(...),以便使用通知图标而不是用户头像,通过编辑(或“重新打开”)现有的 header-notifications 小部件来实现。
原始 header-notifications 代码供参考:discourse/app/assets/javascripts/discourse/app/widgets/header.js at 9bc78625af1d54693bc4f1bad3eaa9161ae030b6 · discourse/discourse · GitHub
正如 @Arkshine 所提到的,我也通过 CSS 隐藏了通知菜单中的用户部分。
.d-header .panel {
.user-menu.revamped .bottom-tabs, #user-menu-button-profile {
display: none;
}
}
您好,我已经成功将用户头像 img 替换为铃铛图标,但是
api.addToHeaderIcons(“new-user-icon”);
移除了整个页眉,而不是显示带有下拉菜单的用户头像。
我的疏忽,那段代码有个拼写错误,应该是——
api.addToHeaderIcons(“header-user-new”);
因为该小部件在第 2 步中注册为 header-user-new。
谢谢,这奏效了。
如果我可以问另一个独立的问题;
中央主题列表模板如何在用户发帖和用户回复之间切换?
我试过 {{#if topic.replies}} 和 {{#if topic.posters.[0]}}
但那不管用。
没问题!topic.posters.1.user 就是您要找的(第一个回复)。如果存在,就使用它,否则就使用 OP(原始发帖人)。
在 Central 中,它目前是这样构建的:
{{#if topic.posters.1.user}}
<span>
{{d-icon "reply"}}
<a href="{{topic.lastPoster.user.userPath}}" data-user-card="{{topic.lastPoster.user.username}}">
{{~topic.lastPoster.user.username~}}
</a>
{{theme-i18n "topic_list_item.replied"}}
<a href={{topic.lastPostUrl}}>
{{format-date topic.bumpedAt format="medium" leaveAgo="true"}}
</a>
</span>
{{else}}
<span>
{{d-icon "m-post_add"}}
<a href="{{topic.posters.0.user.userPath}}" data-user-card="{{topic.posters.0.user.username}}">
{{~topic.posters.0.user.username~}}
</a>
posted
<a href={{topic.lastPostUrl}}>
{{format-date topic.bumpedAt format="medium" leaveAgo="true"}}
</a>
</span>
{{/if}}
那么 topic.posters.1.user 是帖子的作者吗?
哦,不,topic.posters.0.user 是作者,topic.posters.1.user 是第一个回复的用户(如果存在)。![]()
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.