FEATURE: Mute topics tagged with both muted and unmuted tags.

FEATURE: Mute topics tagged with both muted and unmuted tags.

diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index d5df29b..e9eb27f 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -2015,7 +2015,8 @@ en:
     allow_staff_to_tag_pms: "Allow staff members to tag any personal message"
     min_trust_level_to_tag_topics: "Minimum trust level required to tag topics"
     suppress_overlapping_tags_in_list: "If tags match exact words in topic titles, don't show the tag"
-    remove_muted_tags_from_latest: "Don't show topics tagged with muted tags in the latest topic list."
+    remove_muted_tags_from_latest: "Don't show topics tagged only with muted tags in the latest topic list."
+    mute_other_present_tags: "Don't show topics tagged with both muted and unmuted tags in the latest topic list."
     force_lowercase_tags: "Force all new tags to be entirely lowercase."
 
     company_name: "Company Name"
diff --git a/config/site_settings.yml b/config/site_settings.yml
index aefa536..4616e7c 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -2059,6 +2059,8 @@ tags:
     client: true
   remove_muted_tags_from_latest:
     default: false
+  mute_other_present_tags:
+    default: true
   force_lowercase_tags:
     default: true
     client: true
diff --git a/lib/topic_query.rb b/lib/topic_query.rb
index 10646e3..34b4c26 100644
--- a/lib/topic_query.rb
+++ b/lib/topic_query.rb
@@ -876,31 +876,41 @@ class TopicQuery
   end
   def remove_muted_tags(list, user, opts = nil)
     if user.nil? || !SiteSetting.tagging_enabled || !SiteSetting.remove_muted_tags_from_latest
-      list
+      return list
+    end
+
+    muted_tag_ids = TagUser.lookup(user, :muted).pluck(:tag_id)
+    if muted_tag_ids.blank?
+      return list
+    end
+
+    showing_tag = if opts[:filter]
+      f = opts[:filter].split('/')
+      f[0] == 'tags' ? f[1] : nil
     else
-      if !TagUser.lookup(user, :muted).exists?
-        list
-      else
-        showing_tag = if opts[:filter]
-          f = opts[:filter].split('/')
-          f[0] == 'tags' ? f[1] : nil
-        else
-          nil
-        end
+      nil
+    end
 
-        if TagUser.lookup(user, :muted).joins(:tag).where('tags.name = ?', showing_tag).exists?
-          list # if viewing the topic list for a muted tag, show all the topics
-        else
-          muted_tag_ids = TagUser.lookup(user, :muted).pluck(:tag_id)
-          list = list.where("
-            EXISTS (
-              SELECT 1
-                FROM topic_tags tt
-               WHERE tt.tag_id NOT IN (:tag_ids)
-                 AND tt.topic_id = topics.id
-            ) OR NOT EXISTS (SELECT 1 FROM topic_tags tt WHERE tt.topic_id = topics.id)", tag_ids: muted_tag_ids)
-        end
-      end
+    # if viewing the topic list for a muted tag, show all the topics
+    if showing_tag.present? && TagUser.lookup(user, :muted).joins(:tag).where('tags.name = ?', showing_tag).exists?
+      return list
+    end
+
+    if SiteSetting.mute_other_present_tags
+      list = list.where("
+        NOT EXISTS(
+          SELECT 1
+            FROM topic_tags tt
+           WHERE tt.tag_id IN (:tag_ids)
+             AND tt.topic_id = topics.id)", tag_ids: muted_tag_ids)
+    else
+      list = list.where("
+        EXISTS (
+          SELECT 1
+            FROM topic_tags tt
+           WHERE tt.tag_id NOT IN (:tag_ids)
+             AND tt.topic_id = topics.id
+        ) OR NOT EXISTS (SELECT 1 FROM topic_tags tt WHERE tt.topic_id = topics.id)", tag_ids: muted_tag_ids)
     end
   end
 
diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb
index 32eb7ec..56b8b6c 100644
--- a/spec/components/topic_query_spec.rb
+++ b/spec/components/topic_query_spec.rb
@@ -250,6 +250,7 @@ describe TopicQuery do
 
       muted_topic = Fabricate(:topic, tags: [muted_tag])
       tagged_topic = Fabricate(:topic, tags: [other_tag])
+      muted_tagged_topic = Fabricate(:topic, tags: [muted_tag, other_tag])
       untagged_topic = Fabricate(:topic)
 
       TagUser.create!(user_id: user.id,
@@ -257,12 +258,18 @@ describe TopicQuery do
                       notification_level: CategoryUser.notification_levels[:muted])
 
       topic_ids = topic_query.list_latest.topics.map(&:id)
-
       expect(topic_ids).to contain_exactly(tagged_topic.id, untagged_topic.id)
 
       topic_ids = topic_query.list_new.topics.map(&:id)
-
       expect(topic_ids).to contain_exactly(tagged_topic.id, untagged_topic.id)
+
+      SiteSetting.mute_other_present_tags = false
+
+      topic_ids = topic_query.list_latest.topics.map(&:id)
+      expect(topic_ids).to contain_exactly(muted_tagged_topic.id, tagged_topic.id, untagged_topic.id)
+
+      topic_ids = topic_query.list_new.topics.map(&:id)
+      expect(topic_ids).to contain_exactly(muted_tagged_topic.id, tagged_topic.id, untagged_topic.id)
     end
   end

GitHub sha: 87288504

1 Like

Adding the word “only” here makes these two settings sound mutually exclusive, but the logic is that “remove_muted_tags_from_latest” must be enabled otherwise “mute_other_present_tags” is ignored. So the wording of the two settings need to complement each other somehow.

“Don’t show topics tagged with muted tags in the latest topic list.” followed by “Also don’t show topics tagged with both muted and unmuted tags” or something like that…

1 Like

Sorry, I have missed this comment.

I kind of followed up on this in

2 Likes