diff --git a/app/assets/javascripts/discourse/helpers/i18n_helpers.js b/app/assets/javascripts/discourse/helpers/i18n_helpers.js
index eea353f03..92bb0f316 100644
--- a/app/assets/javascripts/discourse/helpers/i18n_helpers.js
+++ b/app/assets/javascripts/discourse/helpers/i18n_helpers.js
@@ -54,7 +54,7 @@ Ember.Handlebars.registerHelper('countI18n', function(key, options) {
shouldRerender: Discourse.View.renderIfChanged('count'),
render: function(buffer) {
- buffer.push(I18n.t(key, { count: this.get('count') }));
+ buffer.push(I18n.t(key + (this.get('suffix') || ""), { count: this.get('count') }));
}
});
diff --git a/app/assets/javascripts/discourse/models/topic_tracking_state.js b/app/assets/javascripts/discourse/models/topic_tracking_state.js
index 94d009cfe..e77476a7b 100644
--- a/app/assets/javascripts/discourse/models/topic_tracking_state.js
+++ b/app/assets/javascripts/discourse/models/topic_tracking_state.js
@@ -17,13 +17,17 @@ Discourse.TopicTrackingState = Discourse.Model.extend({
tracker.incrementMessageCount();
}
- if (data.message_type === "new_topic"){
+ if (data.message_type === "new_topic" || data.message_type === "latest") {
var ignored_categories = Discourse.User.currentProp("muted_category_ids");
if(_.include(ignored_categories, data.payload.category_id)){
return;
}
}
+ if (data.message_type === "latest"){
+ tracker.notify(data);
+ }
+
if (data.message_type === "new_topic" || data.message_type === "unread" || data.message_type === "read") {
tracker.notify(data);
var old = tracker.states["t" + data.topic_id];
@@ -36,6 +40,7 @@ Discourse.TopicTrackingState = Discourse.Model.extend({
};
Discourse.MessageBus.subscribe("/new", process);
+ Discourse.MessageBus.subscribe("/latest", process);
var currentUser = Discourse.User.current();
if(currentUser) {
Discourse.MessageBus.subscribe("/unread/" + currentUser.id, process);
@@ -55,17 +60,29 @@ Discourse.TopicTrackingState = Discourse.Model.extend({
if (!this.newIncoming) { return; }
if ((this.filter === "all" ||this.filter === "latest" || this.filter === "new") && data.message_type === "new_topic" ) {
- this.newIncoming.push(data.topic_id);
+ this.addIncoming(data.topic_id);
}
- if ((this.filter === "all" ||this.filter === "latest" || this.filter === "unread") && data.message_type === "unread") {
+
+ if ((this.filter === "all" || this.filter === "unread") && data.message_type === "unread") {
var old = this.states["t" + data.topic_id];
- if(!old) {
- this.newIncoming.push(data.topic_id);
+ if(!old || old.highest_post_number === old.last_read_post_number) {
+ this.addIncoming(data.topic_id);
}
}
+
+ if(this.filter === "latest" && data.message_type === "latest") {
+ this.addIncoming(data.topic_id);
+ }
+
this.set("incomingCount", this.newIncoming.length);
},
+ addIncoming: function(topicId) {
+ if(this.newIncoming.indexOf(topicId) === -1){
+ this.newIncoming.push(topicId);
+ }
+ },
+
resetTracking: function(){
this.newIncoming = [];
this.set("incomingCount", 0);
diff --git a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
index c2b9f86d3..a9314ea7e 100644
--- a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars
@@ -67,8 +67,8 @@
- {{countI18n new_topics_inserted count=topicTrackingState.incomingCount}}
- {{i18n show_new_topics}}
+ {{countI18n topic_count_ suffix=topicTrackingState.filter count=topicTrackingState.incomingCount}}
+ {{i18n click_to_show}}
|
diff --git a/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars
index b59fb3b88..3702817a6 100644
--- a/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars
@@ -12,8 +12,8 @@
- {{countI18n new_topics_inserted countBinding="topicTrackingState.incomingCount"}}
- {{i18n show_new_topics}}
+ {{countI18n topic_count_ suffix=topicTrackingState.filter count=topicTrackingState.incomingCount}}
+ {{i18n click_to_show}}
|
diff --git a/app/assets/javascripts/discourse/views/topic.js.es6 b/app/assets/javascripts/discourse/views/topic.js.es6
index 25e376dfa..a15125343 100644
--- a/app/assets/javascripts/discourse/views/topic.js.es6
+++ b/app/assets/javascripts/discourse/views/topic.js.es6
@@ -117,6 +117,11 @@ export default Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, {
@method scrolled
**/
scrolled: function(){
+
+ if(this.isDestroyed || this.isDestroying) {
+ return;
+ }
+
var offset = window.pageYOffset || $('html').scrollTop();
if (!this.get('docAt')) {
var title = $('#topic-title');
diff --git a/app/models/topic_tracking_state.rb b/app/models/topic_tracking_state.rb
index fbc5325ec..2ed1bf5f0 100644
--- a/app/models/topic_tracking_state.rb
+++ b/app/models/topic_tracking_state.rb
@@ -37,6 +37,23 @@ class TopicTrackingState
publish_read(topic.id, 1, topic.user_id)
end
+ def self.publish_latest(topic)
+ return unless topic.archetype == "regular"
+
+ message = {
+ topic_id: topic.id,
+ message_type: "latest",
+ payload: {
+ bumped_at: topic.bumped_at,
+ topic_id: topic.id,
+ category_id: topic.category_id
+ }
+ }
+
+ group_ids = topic.category && topic.category.secure_group_ids
+ MessageBus.publish("/latest", message.as_json, group_ids: group_ids)
+ end
+
def self.publish_unread(post)
# TODO at high scale we are going to have to defer this,
# perhaps cut down to users that are around in the last 7 days as well
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index b51f5fcf5..8277d4fde 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -150,8 +150,19 @@ en:
last_read: "this is the last post you've read; click to bookmark it"
remove: "Remove Bookmark"
- new_topics_inserted: "{{count}} new posts."
- show_new_topics: "Click to show."
+ topic_count_latest:
+ one: "{{count}} new or updated topic."
+ other: "{{count}} new or updated topics."
+
+ topic_count_unread:
+ one: "{{count}} unread topic."
+ other: "{{count}} unread topics."
+
+ topic_count_new:
+ one: "{{count}} new topic."
+ other: "{{count}} new topics."
+
+ click_to_show: "Click to show."
preview: "preview"
cancel: "cancel"
diff --git a/lib/post_jobs_enqueuer.rb b/lib/post_jobs_enqueuer.rb
index fcb2f13e8..207780e26 100644
--- a/lib/post_jobs_enqueuer.rb
+++ b/lib/post_jobs_enqueuer.rb
@@ -30,6 +30,7 @@ class PostJobsEnqueuer
def after_post_create
TopicTrackingState.publish_unread(@post) if @post.post_number > 1
+ TopicTrackingState.publish_latest(@topic)
Jobs.enqueue_in(
SiteSetting.email_time_window_mins.minutes,
diff --git a/lib/post_revisor.rb b/lib/post_revisor.rb
index cf6d353d4..d1d84d661 100644
--- a/lib/post_revisor.rb
+++ b/lib/post_revisor.rb
@@ -82,6 +82,7 @@ class PostRevisor
def bump_topic
unless Post.where('post_number > ? and topic_id = ?', @post.post_number, @post.topic_id).exists?
@post.topic.update_column(:bumped_at, Time.now)
+ TopicTrackingState.publish_latest(@post.topic)
end
end