From 43ddf60cdf27a865b7b1aa0d54a144a3e46c74cf Mon Sep 17 00:00:00 2001 From: Krzysztof Kotlarek Date: Mon, 25 Nov 2019 06:17:31 +1100 Subject: [PATCH] FIX: When dismissing category inform via MessageBus (#8371) When category is dismissed, `dismiss_new` message is sent to fronted to clean state. In addition, I noticed that when old dismiss new button is clicked, no message is sent so I decided to kill two birds with one stone. --- .../models/topic-tracking-state.js.es6 | 32 +++++++++++++++++-- app/controllers/topics_controller.rb | 6 ++-- app/models/topic_tracking_state.rb | 9 ++++++ spec/requests/topics_controller_spec.rb | 5 +++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 b/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 index 33a6d4d9d64..3d6ff774db5 100644 --- a/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 +++ b/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 @@ -14,7 +14,8 @@ function isNew(topic) { return ( topic.last_read_post_number === null && ((topic.notification_level !== 0 && !topic.notification_level) || - topic.notification_level >= NotificationLevels.TRACKING) + topic.notification_level >= NotificationLevels.TRACKING) && + isUnseen(topic) ); } @@ -26,6 +27,10 @@ function isUnread(topic) { ); } +function isUnseen(topic) { + return !topic.is_seen; +} + const TopicTrackingState = EmberObject.extend({ messageCount: 0, @@ -68,6 +73,22 @@ const TopicTrackingState = EmberObject.extend({ tracker.notify(data); } + if (data.message_type === "dismiss_new") { + Object.keys(tracker.states).forEach(k => { + const topic = tracker.states[k]; + if ( + !data.payload.category_id || + topic.category_id === parseInt(data.payload.category_id, 0) + ) { + tracker.states[k] = Object.assign({}, topic, { + is_seen: true + }); + } + }); + tracker.notifyPropertyChange("states"); + tracker.incrementMessageCount(); + } + if (["new_topic", "unread", "read"].includes(data.message_type)) { tracker.notify(data); const old = tracker.states["t" + data.topic_id]; @@ -215,7 +236,11 @@ const TopicTrackingState = EmberObject.extend({ if (state) { const lastRead = t.get("last_read_post_number"); - if (lastRead !== state.last_read_post_number) { + const isSeen = t.get("is_seen"); + if ( + lastRead !== state.last_read_post_number || + isSeen !== state.is_seen + ) { const postsCount = t.get("posts_count"); let newPosts = postsCount - state.highest_post_number, unread = postsCount - state.last_read_post_number; @@ -235,7 +260,8 @@ const TopicTrackingState = EmberObject.extend({ last_read_post_number: state.last_read_post_number, new_posts: newPosts, unread: unread, - unseen: !state.last_read_post_number + is_seen: state.is_seen, + unseen: !state.last_read_post_number && isUnseen(state) }); } } diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 2eda0820cbc..971974e95de 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -849,20 +849,20 @@ class TopicsController < ApplicationController def reset_new if params[:category_id].present? category_ids = [params[:category_id]] - if params[:include_subcategories] == 'true' category_ids = category_ids.concat(Category.where(parent_category_id: params[:category_id]).pluck(:id)) end - category_ids.each do |category_id| current_user .category_users .where(category_id: category_id) .first_or_initialize .update!(last_seen_at: Time.zone.now) + TopicTrackingState.publish_dismiss_new(current_user.id, category_id) end else - current_user.user_stat.update_column(:new_since, Time.now) + current_user.user_stat.update_column(:new_since, Time.zone.now) + TopicTrackingState.publish_dismiss_new(current_user.id) end render body: nil end diff --git a/app/models/topic_tracking_state.rb b/app/models/topic_tracking_state.rb index 8bfe76543ff..3118214f8c0 100644 --- a/app/models/topic_tracking_state.rb +++ b/app/models/topic_tracking_state.rb @@ -144,6 +144,15 @@ class TopicTrackingState MessageBus.publish(self.unread_channel_key(user_id), message.as_json, user_ids: [user_id]) end + def self.publish_dismiss_new(user_id, category_id = nil) + payload = category_id ? { category_id: category_id } : {} + message = { + message_type: "dismiss_new", + payload: payload + } + MessageBus.publish(self.unread_channel_key(user_id), message.as_json, user_ids: [user_id]) + end + def self.treat_as_new_topic_clause User.where("GREATEST(CASE WHEN COALESCE(uo.new_topic_duration_minutes, :default_duration) = :always THEN u.created_at diff --git a/spec/requests/topics_controller_spec.rb b/spec/requests/topics_controller_spec.rb index 32bfc6590c2..719a67537ba 100644 --- a/spec/requests/topics_controller_spec.rb +++ b/spec/requests/topics_controller_spec.rb @@ -2342,6 +2342,8 @@ RSpec.describe TopicsController do user.user_stat.update_column(:new_since, old_date) + TopicTrackingState.expects(:publish_dismiss_new).with(user.id) + put "/topics/reset-new.json" expect(response.status).to eq(200) user.reload @@ -2356,6 +2358,9 @@ RSpec.describe TopicsController do sign_in(user) category_user = CategoryUser.create!(category_id: category.id, user_id: user.id) subcategory_user = CategoryUser.create!(category_id: subcategory.id, user_id: user.id) + + TopicTrackingState.expects(:publish_dismiss_new).with(user.id, category.id.to_s) + put "/topics/reset-new.json?category_id=#{category.id}" expect(category_user.reload.last_seen_at).not_to be_nil