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