diff --git a/app/assets/javascripts/discourse/app/controllers/user-private-messages.js b/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
index 2ca079d6a6e..45c37747bd2 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
@@ -2,11 +2,27 @@ import Controller, { inject as controller } from "@ember/controller";
import { action, computed } from "@ember/object";
import { inject as service } from "@ember/service";
import { alias, and, equal, readOnly } from "@ember/object/computed";
-import { tracked } from "@glimmer/tracking";
+import { cached, tracked } from "@glimmer/tracking";
import I18n from "I18n";
import DiscourseURL from "discourse/lib/url";
-export const PERSONAL_INBOX = "__personal_inbox__";
+const customUserNavMessagesDropdownRows = [];
+
+export function registerCustomUserNavMessagesDropdownRow(
+ routeName,
+ name,
+ icon
+) {
+ customUserNavMessagesDropdownRows.push({
+ routeName,
+ name,
+ icon,
+ });
+}
+
+export function resetCustomUserNavMessagesDropdownRows() {
+ customUserNavMessagesDropdownRows.length = 0;
+}
export default class extends Controller {
@service router;
@@ -25,19 +41,21 @@ export default class extends Controller {
@readOnly("site.can_tag_pms") pmTaggingEnabled;
get messagesDropdownValue() {
- const parentRoute = this.router.currentRoute.parent;
+ let value;
- if (Object.keys(parentRoute.params).length > 0) {
- return this.router.urlFor(
- parentRoute.name,
- this.model.username,
- parentRoute.params
- );
- } else {
- return this.router.urlFor(parentRoute.name, this.model.username);
+ for (let i = this.messagesDropdownContent.length - 1; i >= 0; i--) {
+ const row = this.messagesDropdownContent[i];
+
+ if (this.router.currentURL.includes(row.id)) {
+ value = row.id;
+ break;
+ }
}
+
+ return value;
}
+ @cached
get messagesDropdownContent() {
const content = [
{
@@ -66,6 +84,14 @@ export default class extends Controller {
});
}
+ customUserNavMessagesDropdownRows.forEach((row) => {
+ content.push({
+ id: this.router.urlFor(row.routeName, this.model.username),
+ name: row.name,
+ icon: row.icon,
+ });
+ });
+
return content;
}
diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js
index b55155b5b87..91e666becb6 100644
--- a/app/assets/javascripts/discourse/app/lib/plugin-api.js
+++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js
@@ -107,6 +107,7 @@ import DiscourseURL from "discourse/lib/url";
import { registerNotificationTypeRenderer } from "discourse/lib/notification-types-manager";
import { registerUserMenuTab } from "discourse/lib/user-menu/tab";
import { registerModelTransformer } from "discourse/lib/model-transformers";
+import { registerCustomUserNavMessagesDropdownRow } from "discourse/controllers/user-private-messages";
// If you add any methods to the API ensure you bump up the version number
// based on Semantic Versioning 2.0.0. Please update the changelog at
@@ -2018,6 +2019,19 @@ class PluginApi {
registerModelTransformer(modelName, transformer) {
registerModelTransformer(modelName, transformer);
}
+
+ /**
+ * EXPERIMENTAL. Do not use.
+ * Adds a row to the dropdown used on the `userPrivateMessages` route used to navigate between the different user
+ * messages pages.
+ *
+ * @param {string} routeName The Ember route name to transition to when the row is selected in the dropdown
+ * @param {string} name The text displayed to represent the row in the dropdown
+ * @param {string} [icon] The name of the icon that will be used when displaying the row in the dropdown
+ */
+ addUserMessagesNavigationDropdownRow(routeName, name, icon) {
+ registerCustomUserNavMessagesDropdownRow(routeName, name, icon);
+ }
}
// from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number
diff --git a/app/assets/javascripts/discourse/app/templates/user-private-messages-user.hbs b/app/assets/javascripts/discourse/app/templates/user-private-messages-user.hbs
index bc25f24dabb..125404af45f 100644
--- a/app/assets/javascripts/discourse/app/templates/user-private-messages-user.hbs
+++ b/app/assets/javascripts/discourse/app/templates/user-private-messages-user.hbs
@@ -39,8 +39,6 @@
{{i18n "user.messages.archive"}}
-
-
{{outlet}}
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-private-messages-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-private-messages-test.js
index 8dc4313df4d..9ac356da93e 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/user-private-messages-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-private-messages-test.js
@@ -17,6 +17,8 @@ import {
resetHighestReadCache,
setHighestReadCache,
} from "discourse/lib/topic-list-tracker";
+import { withPluginApi } from "discourse/lib/plugin-api";
+import { resetCustomUserNavMessagesDropdownRows } from "discourse/controllers/user-private-messages";
acceptance(
"User Private Messages - user with no group messages",
@@ -753,6 +755,30 @@ function testUserPrivateMessagesWithGroupMessages(needs, customUserProps) {
"All tags is still selected in dropdown"
);
});
+
+ test("addUserMessagesNavigationDropdownRow plugin api", async function (assert) {
+ try {
+ withPluginApi("1.5.0", (api) => {
+ api.addUserMessagesNavigationDropdownRow(
+ "preferences",
+ "test nav",
+ "arrow-left"
+ );
+ });
+
+ await visit("/u/eviltrout/messages");
+
+ const messagesDropdown = selectKit(".user-nav-messages-dropdown");
+ await messagesDropdown.expand();
+
+ const row = messagesDropdown.rowByName("test nav");
+
+ assert.strictEqual(row.value(), "/u/eviltrout/preferences");
+ assert.ok(row.icon().classList.contains("d-icon-arrow-left"));
+ } finally {
+ resetCustomUserNavMessagesDropdownRows();
+ }
+ });
}
}