FEATURE: New and Unread messages for user personal messages. (#13603)

FEATURE: New and Unread messages for user personal messages. (#13603)

  • FEATURE: New and Unread messages for user personal messages.

Co-authored-by: awesomerobot kris.aubuchon@discourse.org

diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js
index ae881eb..f48dda9 100644
--- a/app/assets/javascripts/discourse/app/controllers/topic.js
+++ b/app/assets/javascripts/discourse/app/controllers/topic.js
@@ -154,10 +154,14 @@ export default Controller.extend(bufferedProperty("model"), {
   showCategoryChooser: not("model.isPrivateMessage"),
 
   gotoInbox(name) {
-    let url = userPath(this.get("currentUser.username_lower") + "/messages");
+    let url = userPath(`${this.get("currentUser.username_lower")}/messages`);
+
     if (name) {
-      url = url + "/group/" + name;
+      url = `${url}/group/${name}`;
+    } else {
+      url = `${url}/personal`;
     }
+
     DiscourseURL.routeTo(url);
   },
 
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 22f99d2..bcdece0 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
@@ -3,6 +3,10 @@ import { action } from "@ember/object";
 import { alias, and, equal } from "@ember/object/computed";
 import discourseComputed from "discourse-common/utils/decorators";
 import { VIEW_NAME_WARNINGS } from "discourse/routes/user-private-messages-warnings";
+import I18n from "I18n";
+
+export const PERSONAL_INBOX = "__personal_inbox__";
+const ALL_INBOX = "__all_inbox__";
 
 export default Controller.extend({
   user: controller(),
@@ -10,19 +14,101 @@ export default Controller.extend({
   pmView: false,
   viewingSelf: alias("user.viewingSelf"),
   isGroup: equal("pmView", "groups"),
+  group: null,
+  groupFilter: alias("group.name"),
   currentPath: alias("router._router.currentPath"),
   pmTaggingEnabled: alias("site.can_tag_pms"),
   tagId: null,
 
   showNewPM: and("user.viewingSelf", "currentUser.can_send_private_messages"),
 
+  @discourseComputed("inboxes", "isAllInbox")
+  displayGlobalFilters(inboxes, isAllInbox) {
+    if (inboxes.length === 0) {
+      return true;
+    }
+    if (inboxes.length && isAllInbox) {
+      return true;
+    }
+    return false;
+  },
+
+  @discourseComputed("inboxes")
+  sectionClass(inboxes) {
+    const defaultClass = "user-secondary-navigation user-messages";
+
+    return inboxes.length
+      ? `${defaultClass} user-messages-inboxes`
+      : defaultClass;
+  },
+
+  @discourseComputed("pmView")
+  isPersonalInbox(pmView) {
+    return pmView && pmView.startsWith("personal");
+  },
+
+  @discourseComputed("isPersonalInbox", "group.name")
+  isAllInbox(isPersonalInbox, groupName) {
+    return !this.isPersonalInbox && !groupName;
+  },
+
+  @discourseComputed("isPersonalInbox", "group.name")
+  selectedInbox(isPersonalInbox, groupName) {
+    if (groupName) {
+      return groupName;
+    }
+
+    return isPersonalInbox ? PERSONAL_INBOX : ALL_INBOX;
+  },
+
   @discourseComputed("viewingSelf", "pmView", "currentUser.admin")
   showWarningsWarning(viewingSelf, pmView, isAdmin) {
     return pmView === VIEW_NAME_WARNINGS && !viewingSelf && !isAdmin;
   },
 
+  @discourseComputed("model.groups")
+  inboxes(groups) {
+    const groupsWithMessages = groups?.filter((group) => {
+      return group.has_messages;
+    });
+
+    if (!groupsWithMessages || groupsWithMessages.length === 0) {
+      return [];
+    }
+
+    const inboxes = [];
+
+    inboxes.push({
+      id: ALL_INBOX,
+      name: I18n.t("user.messages.all"),
+    });
+
+    inboxes.push({
+      id: PERSONAL_INBOX,
+      name: I18n.t("user.messages.personal"),
+      icon: "envelope",
+    });
+
+    groupsWithMessages.forEach((group) => {
+      inboxes.push({ id: group.name, name: group.name, icon: "users" });
+    });
+
+    return inboxes;
+  },
+
   @action
   changeGroupNotificationLevel(notificationLevel) {
     this.group.setNotification(notificationLevel, this.get("user.model.id"));
   },
+
+  @action
+  updateInbox(inbox) {
+    if (inbox === ALL_INBOX) {
+      this.transitionToRoute("userPrivateMessages.index");
+    } else if (inbox === PERSONAL_INBOX) {
+      this.transitionToRoute("userPrivateMessages.personal");
+    } else {
+      this.transitionToRoute("userPrivateMessages.group", inbox);
+    }
+  },
 });
diff --git a/app/assets/javascripts/discourse/app/lib/cached-topic-list.js b/app/assets/javascripts/discourse/app/lib/cached-topic-list.js
index 9ff608c..3814831 100644
--- a/app/assets/javascripts/discourse/app/lib/cached-topic-list.js
+++ b/app/assets/javascripts/discourse/app/lib/cached-topic-list.js
@@ -1,5 +1,6 @@
 export function findOrResetCachedTopicList(session, filter) {
   const lastTopicList = session.get("topicList");
+
   if (lastTopicList && lastTopicList.filter === filter) {
     return lastTopicList;
   } else {
diff --git a/app/assets/javascripts/discourse/app/routes/app-route-map.js b/app/assets/javascripts/discourse/app/routes/app-route-map.js
index 9bbb446..42eb98b 100644
--- a/app/assets/javascripts/discourse/app/routes/app-route-map.js
+++ b/app/assets/javascripts/discourse/app/routes/app-route-map.js
@@ -140,11 +140,20 @@ export default function () {
         "userPrivateMessages",
         { path: "/messages", resetNamespace: true },
         function () {
-          this.route("sent");
+          this.route("new");
+          this.route("unread");
           this.route("archive");
+          this.route("sent");
+          this.route("personal");
+          this.route("personalSent", { path: "personal/sent" });
+          this.route("personalNew", { path: "personal/new" });
+          this.route("personalUnread", { path: "personal/unread" });
+          this.route("personalArchive", { path: "personal/archive" });
           this.route("warnings");
           this.route("group", { path: "group/:name" });
           this.route("groupArchive", { path: "group/:name/archive" });
+          this.route("groupNew", { path: "group/:name/new" });
+          this.route("groupUnread", { path: "group/:name/unread" });
           this.route("tags");
           this.route("tagsShow", { path: "tags/:id" });
         }
diff --git a/app/assets/javascripts/discourse/app/routes/build-private-messages-group-route.js b/app/assets/javascripts/discourse/app/routes/build-private-messages-group-route.js
new file mode 100644
index 0000000..d1aa356
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/routes/build-private-messages-group-route.js
@@ -0,0 +1,68 @@
+import I18n from "I18n";
+import createPMRoute from "discourse/routes/build-private-messages-route";
+import { findOrResetCachedTopicList } from "discourse/lib/cached-topic-list";
+
+export default (viewName, channel) => {
+  return createPMRoute("groups", "private-messages-groups").extend({
+    groupName: null,
+
+    titleToken() {
+      const groupName = this.groupName;
+
+      if (groupName) {
+        let title = groupName.capitalize();
+
+        if (viewName !== "index") {
+          title = `${title} ${I18n.t("user.messages." + viewName)}`;
+        }
+
+        return [title, I18n.t(`user.private_messages`)];
+      }
+    },
+
+    model(params) {
+      const username = this.modelFor("user").get("username_lower");
+      let filter = `topics/private-messages-group/${username}/${params.name}`;
+
+      if (viewName !== "index") {
+        filter = `${filter}/${viewName}`;
+      }
+
+      const lastTopicList = findOrResetCachedTopicList(this.session, filter);
+
+      return lastTopicList
+        ? lastTopicList
+        : this.store.findFiltered("topicList", { filter });
+    },
+
+    afterModel(model) {
+      const filters = model.get("filter").split("/");
+      let groupName;
+
+      if (viewName !== "index") {
+        groupName = filters[filters.length - 2];
+      } else {
+        groupName = filters.pop();
+      }
+
+      const group = this.modelFor("user")
+        .get("groups")

[... diff too long, it was truncated ...]

GitHub sha: 016efeadf6f242e04daf5ef8e18c2ca708a1392d

This commit appears in #13603 which was approved by martin and lis2. It was merged by tgxworld.