FIX: when category or tag is muted, update user (#9456)

FIX: when category or tag is muted, update user (#9456)

Currently, when category or tag is muted, only after hard refresh, these new muted categories are really muted. Without a hard refresh, you will still receive “new topic” messages.

Therefore, when tag or category is muted, we should update the user object right away.

diff --git a/app/assets/javascripts/discourse/controllers/tags-show.js b/app/assets/javascripts/discourse/controllers/tags-show.js
index a44cf85..e9bb719 100644
--- a/app/assets/javascripts/discourse/controllers/tags-show.js
+++ b/app/assets/javascripts/discourse/controllers/tags-show.js
@@ -155,7 +155,18 @@ export default Controller.extend(BulkTopicSelection, FilterModeMixin, {
     },
 
     changeTagNotificationLevel(notificationLevel) {
-      this.tagNotification.update({ notification_level: notificationLevel });
+      this.tagNotification
+        .update({ notification_level: notificationLevel })
+        .then(response => {
+          this.currentUser.set(
+            "muted_tag_ids",
+            this.currentUser.calculateMutedIds(
+              notificationLevel,
+              response.responseJson.tag_id,
+              "muted_tag_ids"
+            )
+          );
+        });
     }
   }
 });
diff --git a/app/assets/javascripts/discourse/models/category.js b/app/assets/javascripts/discourse/models/category.js
index f264248..d765f84 100644
--- a/app/assets/javascripts/discourse/models/category.js
+++ b/app/assets/javascripts/discourse/models/category.js
@@ -7,6 +7,7 @@ import PermissionType from "discourse/models/permission-type";
 import { NotificationLevels } from "discourse/lib/notification-levels";
 import deprecated from "discourse-common/lib/deprecated";
 import Site from "discourse/models/site";
+import User from "discourse/models/user";
 
 const Category = RestModel.extend({
   permissions: null,
@@ -241,6 +242,16 @@ const Category = RestModel.extend({
 
   setNotification(notification_level) {
     this.set("notification_level", notification_level);
+
+    User.currentProp(
+      "muted_category_ids",
+      User.current().calculateMutedIds(
+        notification_level,
+        this.id,
+        "muted_category_ids"
+      )
+    );
+
     const url = `/category/${this.id}/notifications`;
     return ajax(url, { data: { notification_level }, type: "POST" });
   },
diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js
index 7b106d9..9fff14f 100644
--- a/app/assets/javascripts/discourse/models/user.js
+++ b/app/assets/javascripts/discourse/models/user.js
@@ -25,6 +25,7 @@ import Category from "discourse/models/category";
 import { Promise } from "rsvp";
 import deprecated from "discourse-common/lib/deprecated";
 import Site from "discourse/models/site";
+import { NotificationLevels } from "discourse/lib/notification-levels";
 
 export const SECOND_FACTOR_METHODS = {
   TOTP: 1,
@@ -859,6 +860,15 @@ const User = RestModel.extend({
 
   changeTimezone(tz) {
     this._timezone = tz;
+  },
+
+  calculateMutedIds(notificationLevel, id, type) {
+    const muted_ids = this.get(type);
+    if (notificationLevel === NotificationLevels.MUTED) {
+      return muted_ids.concat(id).uniq();
+    } else {
+      return muted_ids.filter(existing_id => existing_id !== id);
+    }
   }
 });
 
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 25d8a15..72f5935 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -274,7 +274,7 @@ class TagsController < ::ApplicationController
     raise Discourse::NotFound unless tag
     level = params[:tag_notification][:notification_level].to_i
     TagUser.change(current_user.id, tag.id, level)
-    render json: { notification_level: level }
+    render json: { notification_level: level, tag_id: tag.id }
   end
 
   def check_hashtag
diff --git a/test/javascripts/models/user-test.js b/test/javascripts/models/user-test.js
index 4675043..90dcef5 100644
--- a/test/javascripts/models/user-test.js
+++ b/test/javascripts/models/user-test.js
@@ -104,3 +104,10 @@ QUnit.test("resolvedTimezone", assert => {
   );
   stub.restore();
 });
+
+QUnit.test("muted ids", assert => {
+  let user = User.create({ username: "chuck", muted_category_ids: [] });
+
+  assert.deepEqual(user.calculateMutedIds(0, 1, "muted_category_ids"), [1]);
+  assert.deepEqual(user.calculateMutedIds(1, 1, "muted_category_ids"), []);
+});

GitHub sha: e9f72628

This commit appears in #9456 which was approved by eviltrout. It was merged by lis2.