FEATURE: Dismiss new and unread for PM inboxes.

FEATURE: Dismiss new and unread for PM inboxes.

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 bcdece0..f50f9ba 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-private-messages.js
@@ -44,7 +44,7 @@ export default Controller.extend({
 
   @discourseComputed("pmView")
   isPersonalInbox(pmView) {
-    return pmView && pmView.startsWith("personal");
+    return pmView && pmView.startsWith("user");
   },
 
   @discourseComputed("isPersonalInbox", "group.name")
diff --git a/app/assets/javascripts/discourse/app/controllers/user-topics-list.js b/app/assets/javascripts/discourse/app/controllers/user-topics-list.js
index 61b3c11..4b3adfb 100644
--- a/app/assets/javascripts/discourse/app/controllers/user-topics-list.js
+++ b/app/assets/javascripts/discourse/app/controllers/user-topics-list.js
@@ -1,6 +1,16 @@
 import Controller, { inject as controller } from "@ember/controller";
-import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import discourseComputed, {
+  observes,
+  on,
+} from "discourse-common/utils/decorators";
 import BulkTopicSelection from "discourse/mixins/bulk-topic-selection";
+import { action } from "@ember/object";
+import Topic from "discourse/models/topic";
+
+import {
+  NEW_FILTER,
+  UNREAD_FILTER,
+} from "discourse/routes/build-private-messages-route";
 
 // Lists of topics on a user's page.
 export default Controller.extend(BulkTopicSelection, {
@@ -12,18 +22,17 @@ export default Controller.extend(BulkTopicSelection, {
   channel: null,
   tagsForUser: null,
 
-  init() {
-    this._super(...arguments);
-
+  @on("init")
+  _initialize() {
     this.newIncoming = [];
   },
 
-  saveScrollPosition: function () {
+  saveScrollPosition() {
     this.session.set("topicListScrollPosition", $(window).scrollTop());
   },
 
   @observes("model.canLoadMore")
-  _showFooter: function () {
+  _showFooter() {
     this.set("application.showFooter", !this.get("model.canLoadMore"));
   },
 
@@ -32,6 +41,16 @@ export default Controller.extend(BulkTopicSelection, {
     return incomingCount > 0;
   },
 
+  @discourseComputed("filter", "model.topics.length")
+  showResetNew(filter, hasTopics) {
+    return filter === NEW_FILTER && hasTopics;
+  },
+
+  @discourseComputed("filter", "model.topics.length")
+  showDismissRead(filter, hasTopics) {
+    return filter === UNREAD_FILTER && hasTopics;
+  },
+
   subscribe(channel) {
     this.set("channel", channel);
 
@@ -59,15 +78,35 @@ export default Controller.extend(BulkTopicSelection, {
     });
   },
 
-  actions: {
-    loadMore: function () {
-      this.model.loadMore();
-    },
+  @action
+  resetNew() {
+    const topicIds = this.selected
+      ? this.selected.map((topic) => topic.id)
+      : null;
 
-    showInserted() {
-      this.model.loadBefore(this.newIncoming);
-      this._resetTracking();
-      return false;
-    },
+    const opts = {
+      inbox: this.inbox,
+      topicIds: topicIds,
+    };
+
+    if (this.group) {
+      opts.groupName = this.group.name;
+    }
+
+    Topic.pmResetNew(opts).then(() => {
+      this.send("refresh");
+    });
+  },
+
+  @action
+  loadMore() {
+    this.model.loadMore();
+  },
+
+  @action
+  showInserted() {
+    this.model.loadBefore(this.newIncoming);
+    this._resetTracking();
+    return false;
   },
 });
diff --git a/app/assets/javascripts/discourse/app/models/topic.js b/app/assets/javascripts/discourse/app/models/topic.js
index a603aee..d15d70e 100644
--- a/app/assets/javascripts/discourse/app/models/topic.js
+++ b/app/assets/javascripts/discourse/app/models/topic.js
@@ -747,6 +747,14 @@ Topic.reopenClass({
       if (options.tagName) {
         data.tag_name = options.tagName;
       }
+
+      if (options.private_message_inbox) {
+        data.private_message_inbox = options.private_message_inbox;
+
+        if (options.group_name) {
+          data.group_name = options.group_name;
+        }
+      }
     }
 
     return ajax("/topics/bulk", {
@@ -778,6 +786,24 @@ Topic.reopenClass({
     return ajax("/topics/reset-new", { type: "PUT", data });
   },
 
+  pmResetNew(opts = {}) {
+    const data = {};
+
+    if (opts.topicIds) {
+      data.topic_ids = opts.topicIds;
+    }
+
+    if (opts.inbox) {
+      data.inbox = opts.inbox;
+
+      if (opts.groupName) {
+        data.group_name = opts.groupName;
+      }
+    }
+
+    return ajax("/topics/pm-reset-new", { type: "PUT", data });
+  },
+
   idForSlug(slug) {
     return ajax(`/t/id_for/${slug}`);
   },
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
index d1aa356..c82d36c 100644
--- 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
@@ -2,8 +2,8 @@ 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({
+export default (inboxType, filter) => {
+  return createPMRoute(inboxType, "private-messages-groups", filter).extend({
     groupName: null,
 
     titleToken() {
@@ -12,8 +12,8 @@ export default (viewName, channel) => {
       if (groupName) {
         let title = groupName.capitalize();
 
-        if (viewName !== "index") {
-          title = `${title} ${I18n.t("user.messages." + viewName)}`;
+        if (filter !== "inbox") {
+          title = `${title} ${I18n.t("user.messages." + filter)}`;
         }
 
         return [title, I18n.t(`user.private_messages`)];
@@ -22,24 +22,27 @@ export default (viewName, channel) => {
 
     model(params) {
       const username = this.modelFor("user").get("username_lower");
-      let filter = `topics/private-messages-group/${username}/${params.name}`;
+      let topicListFilter = `topics/private-messages-group/${username}/${params.name}`;
 
-      if (viewName !== "index") {
-        filter = `${filter}/${viewName}`;
+      if (filter !== "inbox") {
+        topicListFilter = `${topicListFilter}/${filter}`;
       }
 
-      const lastTopicList = findOrResetCachedTopicList(this.session, filter);
+      const lastTopicList = findOrResetCachedTopicList(
+        this.session,
+        topicListFilter
+      );
 
       return lastTopicList
         ? lastTopicList
-        : this.store.findFiltered("topicList", { filter });
+        : this.store.findFiltered("topicList", { filter: topicListFilter });
     },
 
     afterModel(model) {
       const filters = model.get("filter").split("/");
       let groupName;
 
-      if (viewName !== "index") {
+      if (filter !== "inbox") {
         groupName = filters[filters.length - 2];
       } else {
         groupName = filters.pop();
@@ -55,14 +58,21 @@ export default (viewName, channel) => {
     setupController() {
       this._super.apply(this, arguments);
       this.controllerFor("user-private-messages").set("group", this.group);
+      this.controllerFor("user-topics-list").set("group", this.group);
 
-      if (channel) {
+      if (filter) {
         this.controllerFor("user-topics-list").subscribe(
           `/private-messages/group/${this.get(
             "groupName"
-          ).toLowerCase()}/${channel}`
+          ).toLowerCase()}/${filter}`
         );
       }
     },
+
+    dismissReadOptions() {
+      return {
+        group_name: this.get("groupName"),
+      };
+    },
   });
 };
diff --git a/app/assets/javascripts/discourse/app/routes/build-private-messages-route.js b/app/assets/javascripts/discourse/app/routes/build-private-messages-route.js
index 2eed30a..cf2a8c8 100644

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

GitHub sha: 2c046cc670161e3b9f998edcc7500d18bcfd8f9a

This commit appears in #13911 which was approved by eviltrout and martin. It was merged by tgxworld.