This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/widgets/user-menu.js.es6
Robin Ward 02f6db4e59 FIX: Back button shenanigans when redirecting from index routes
This is a problem that has long plagued Discourse. The root issue here
is that we have to implement our own link click handler, because
Discourse allows users to create HTML blobs of content with links, and
when those links are clicked they must be handled by the Ember router.

This always involved a certain amount of use of private Ember APIs which
of course evolved over time.

The API has more or less stabilized in the last two years, however we
have hacks in our URLs to handle a dynamic root path, depending on how
forums have set up their filters and in what order.

This patch adds a special case for the root path so we needn't update
the URL ourselves otherwise, which preserves the back button on index
routes. The update call would otherwise insert an extra history event if
a route redirected on transition, breaking the back button.
2019-06-21 14:42:01 -04:00

222 lines
5.1 KiB
JavaScript

import { createWidget } from "discourse/widgets/widget";
import { h } from "virtual-dom";
import { formatUsername } from "discourse/lib/utilities";
import hbs from "discourse/widgets/hbs-compiler";
let extraGlyphs;
export function addUserMenuGlyph(glyph) {
extraGlyphs = extraGlyphs || [];
extraGlyphs.push(glyph);
}
createWidget("user-menu-links", {
tagName: "div.menu-links-header",
html(attrs) {
const { currentUser, siteSettings } = this;
const isAnon = currentUser.is_anonymous;
const allowAnon =
(siteSettings.allow_anonymous_posting &&
currentUser.trust_level >=
siteSettings.anonymous_posting_min_trust_level) ||
isAnon;
const path = attrs.path;
const glyphs = [];
if (extraGlyphs) {
extraGlyphs.forEach(g => {
if (typeof g === "function") {
g = g(this);
}
if (g) {
glyphs.push(g);
}
});
}
glyphs.push({
label: "user.bookmarks",
className: "user-bookmarks-link",
icon: "bookmark",
href: `${path}/activity/bookmarks`
});
if (siteSettings.enable_personal_messages) {
glyphs.push({
label: "user.private_messages",
className: "user-pms-link",
icon: "envelope",
href: `${path}/messages`
});
}
const profileLink = {
route: "user",
model: currentUser,
className: "user-activity-link",
icon: "user",
rawLabel: formatUsername(currentUser.username)
};
if (currentUser.is_anonymous) {
profileLink.label = "user.profile";
profileLink.rawLabel = null;
}
const links = [profileLink];
if (allowAnon) {
if (!isAnon) {
glyphs.push({
action: "toggleAnonymous",
label: "switch_to_anon",
className: "enable-anonymous",
icon: "user-secret"
});
} else {
glyphs.push({
action: "toggleAnonymous",
label: "switch_from_anon",
className: "disable-anonymous",
icon: "ban"
});
}
}
// preferences always goes last
glyphs.push({
label: "user.preferences",
className: "user-preferences-link",
icon: "cog",
href: `${path}/preferences`
});
return h("ul.menu-links-row", [
links.map(l => h("li.user", this.attach("link", l))),
h(
"li.glyphs",
glyphs.map(l => this.attach("link", $.extend(l, { hideLabel: true })))
)
]);
}
});
createWidget("user-menu-dismiss-link", {
tagName: "div.dismiss-link",
template: hbs`
<ul class='menu-links'>
<li>
{{link action="dismissNotifications"
className="dismiss"
tabindex="0"
icon="check"
label="user.dismiss"
title="user.dismiss_notifications_tooltip"}}
</li>
</ul>
`
});
export default createWidget("user-menu", {
tagName: "div.user-menu",
buildKey: () => "user-menu",
settings: {
maxWidth: 320,
showLogoutButton: true
},
defaultState() {
return {
hasUnread: false,
markUnread: null
};
},
panelContents() {
const path = this.currentUser.get("path");
let result = [
this.attach("user-menu-links", { path }),
this.attach("user-notifications", { path })
];
if (this.settings.showLogoutButton || this.state.hasUnread) {
result.push(h("hr.bottom-area"));
}
if (this.settings.showLogoutButton) {
result.push(
h("div.logout-link", [
h(
"ul.menu-links",
h(
"li",
this.attach("link", {
action: "logout",
className: "logout",
icon: "sign-out-alt",
href: "",
label: "user.log_out"
})
)
)
])
);
}
if (this.state.hasUnread) {
result.push(this.attach("user-menu-dismiss-link"));
}
return result;
},
dismissNotifications() {
return this.state.markRead();
},
notificationsLoaded({ notifications, markRead }) {
this.state.hasUnread = notifications.filterBy("read", false).length > 0;
this.state.markRead = markRead;
},
html() {
return this.attach("menu-panel", {
maxWidth: this.settings.maxWidth,
contents: () => this.panelContents()
});
},
clickOutsideMobile(e) {
const $centeredElement = $(document.elementFromPoint(e.clientX, e.clientY));
if (
$centeredElement.parents(".panel").length &&
!$centeredElement.hasClass("header-cloak")
) {
this.sendWidgetAction("toggleUserMenu");
} else {
const $window = $(window);
const windowWidth = parseInt($window.width(), 10);
const $panel = $(".menu-panel");
$panel.addClass("animate");
$panel.css("right", -windowWidth);
const $headerCloak = $(".header-cloak");
$headerCloak.addClass("animate");
$headerCloak.css("opacity", 0);
Ember.run.later(() => this.sendWidgetAction("toggleUserMenu"), 200);
}
},
clickOutside(e) {
if (this.site.mobileView) {
this.clickOutsideMobile(e);
} else {
this.sendWidgetAction("toggleUserMenu");
}
}
});