FEATURE: add tracked filter to topic lists

FEATURE: add tracked filter to topic lists

This adds a special filter to topic lists that will filter to tracked and watched categories.

To use it you can visit:

https://sitename/?filter=tracked https://sitename/unread?filter=tracked

and so on

Note, we do not include explicitly tracked and watched topics outside of the tracked categories and tags.

We can consider a filter=all_tracked to cover this edge case.

diff --git a/lib/topic_query.rb b/lib/topic_query.rb
index f030c83..a838e79 100644
--- a/lib/topic_query.rb
+++ b/lib/topic_query.rb
@@ -824,6 +824,33 @@ class TopicQuery
                                action: action
                            )
       end
+
+      if filter == "tracked"
+        sql = +<<~SQL
+          topics.category_id IN (
+            SELECT cu.category_id FROM category_users cu
+            WHERE cu.user_id = :user_id AND cu.notification_level >= :tracking
+          )
+        SQL
+
+        if SiteSetting.tagging_enabled
+          sql << <<~SQL
+            OR topics.id IN (
+              SELECT tt.topic_id FROM topic_tags tt WHERE tt.tag_id IN (
+                SELECT tu.tag_id
+                FROM tag_users tu
+                WHERE tu.user_id = :user_id AND tu.notification_level >= :tracking
+              )
+            )
+          SQL
+        end
+
+        result = result.where(
+          sql,
+          user_id: @user.id,
+          tracking: NotificationLevels.all[:tracking]
+        )
+      end
     end
 
     result = result.where('topics.deleted_at IS NULL') if require_deleted_clause
diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb
index 6d97abf..fdfd67d 100644
--- a/spec/components/topic_query_spec.rb
+++ b/spec/components/topic_query_spec.rb
@@ -118,6 +118,39 @@ describe TopicQuery do
     end
   end
 
+  context 'tracked' do
+    it "filters tracked topics correctly" do
+      SiteSetting.tagging_enabled = true
+
+      tag = Fabricate(:tag)
+      Fabricate(:topic, tags: [tag])
+      topic2 = Fabricate(:topic)
+
+      query = TopicQuery.new(user, filter: 'tracked').list_latest
+      expect(query.topics.length).to eq(0)
+
+      TagUser.create!(
+        tag_id: tag.id,
+        user_id: user.id,
+        notification_level: NotificationLevels.all[:watching]
+      )
+
+      cu = CategoryUser.create!(
+        category_id: topic2.category_id,
+        user_id: user.id,
+        notification_level: NotificationLevels.all[:regular]
+      )
+
+      query = TopicQuery.new(user, filter: 'tracked').list_latest
+      expect(query.topics.length).to eq(1)
+
+      cu.update!(notification_level: NotificationLevels.all[:tracking])
+
+      query = TopicQuery.new(user, filter: 'tracked').list_latest
+      expect(query.topics.length).to eq(2)
+    end
+  end
+
   context 'deleted filter' do
     it "filters deleted topics correctly" do
       _topic = Fabricate(:topic, deleted_at: 1.year.ago)

GitHub sha: 88dcdf77

1 Like