diff --git a/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 b/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 index 907c2135993..10a73fcd5ec 100644 --- a/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 +++ b/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 @@ -22,6 +22,11 @@ const DiscoveryTopicsListComponent = Ember.Component.extend( } }, + @observes("topicTrackingState.states") + _updateTopics() { + this.topicTrackingState.updateTopics(this.model.topics); + }, + @observes("incomingCount") _updateTitle() { Discourse.updateContextCount(this.incomingCount); 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 0b4ef2ca93c..5c726069d37 100644 --- a/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 +++ b/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 @@ -69,13 +69,10 @@ const TopicTrackingState = Discourse.Model.extend({ if (["new_topic", "unread", "read"].includes(data.message_type)) { tracker.notify(data); const old = tracker.states["t" + data.topic_id]; - - // don't add tracking state for read stuff that was not tracked in first place - if (old || data.message_type !== "read") { - if (!_.isEqual(old, data.payload)) { - tracker.states["t" + data.topic_id] = data.payload; - tracker.incrementMessageCount(); - } + if (!_.isEqual(old, data.payload)) { + tracker.states["t" + data.topic_id] = data.payload; + tracker.notifyPropertyChange("states"); + tracker.incrementMessageCount(); } } }; diff --git a/test/javascripts/acceptance/topic-discovery-test.js.es6 b/test/javascripts/acceptance/topic-discovery-test.js.es6 index e060c94d66f..b29891853f8 100644 --- a/test/javascripts/acceptance/topic-discovery-test.js.es6 +++ b/test/javascripts/acceptance/topic-discovery-test.js.es6 @@ -76,3 +76,32 @@ QUnit.test("Clearing state after leaving a category", async assert => { "it doesn't expand all pinned in the latest category" ); }); + +QUnit.test("Live update unread state", async assert => { + await visit("/"); + assert.ok( + exists(".topic-list-item:not(.visited) a[data-topic-id='11995']"), + "shows the topic unread" + ); + + // Mimic a messagebus message + window.MessageBus.callbacks.filterBy("channel", "/latest").map(c => + c.func({ + message_type: "read", + topic_id: 11995, + payload: { + highest_post_number: 1, + last_read_post_number: 2, + notification_level: 1, + topic_id: 11995 + } + }) + ); + + await visit("/"); // We're already there, but use this to wait for re-render + + assert.ok( + exists(".topic-list-item.visited a[data-topic-id='11995']"), + "shows the topic read" + ); +});