diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js b/app/assets/javascripts/discourse/controllers/topic_controller.js index b629c37727f..893e486c97d 100644 --- a/app/assets/javascripts/discourse/controllers/topic_controller.js +++ b/app/assets/javascripts/discourse/controllers/topic_controller.js @@ -265,6 +265,12 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected return (this.get('progressPosition') < 2); }.property('progressPosition'), + filteredPostCountChanged: function(){ + if(this.get('postStream.filteredPostsCount') < this.get('progressPosition')){ + this.set('progressPosition', this.get('postStream.filteredPostsCount')); + } + }.observes('postStream.filteredPostsCount'), + jumpBottomDisabled: function() { return this.get('progressPosition') >= this.get('postStream.filteredPostsCount') || this.get('progressPosition') >= this.get('highest_post_number'); @@ -410,6 +416,16 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected return; } + if (data.type === "deleted"){ + postStream.triggerDeletedPost(data.id, data.post_number); + return; + } + + if (data.type === "recovered"){ + postStream.triggerRecoveredPost(data.id, data.post_number); + return; + } + // Add the new post into the stream postStream.triggerNewPostInStream(data.id); }); diff --git a/app/assets/javascripts/discourse/models/post_stream.js b/app/assets/javascripts/discourse/models/post_stream.js index 0e7e5292385..9888d5d8f8e 100644 --- a/app/assets/javascripts/discourse/models/post_stream.js +++ b/app/assets/javascripts/discourse/models/post_stream.js @@ -17,14 +17,18 @@ Discourse.PostStream = Em.Object.extend({ notLoading: Em.computed.not('loading'), - filteredPostsCount: Em.computed.alias('stream.length'), + filteredPostsCount: function(){ + return this.get("stream").length; + }.property("stream.@each"), /** Have we loaded any posts? @property hasPosts **/ - hasPosts: Em.computed.gt('posts.length', 0), + hasPosts: function(){ + return this.get('posts.length') > 0; + }.property("posts.@each"), /** Do we have a stream list of post ids? @@ -55,7 +59,7 @@ Discourse.PostStream = Em.Object.extend({ firstPostPresent: function() { if (!this.get('hasLoadedData')) { return false; } return !!this.get('posts').findProperty('id', this.get('firstPostId')); - }.property('hasLoadedData', 'posts.[]', 'firstPostId'), + }.property('hasLoadedData', 'posts.@each', 'firstPostId'), firstPostNotLoaded: Em.computed.not('firstPostPresent'), @@ -480,9 +484,13 @@ Discourse.PostStream = Em.Object.extend({ if (Em.isEmpty(posts)) { return; } var postIds = posts.map(function (p) { return p.get('id'); }); + var identityMap = this.get('postIdentityMap'); this.get('stream').removeObjects(postIds); this.get('posts').removeObjects(posts); + postIds.forEach(function(id){ + identityMap.remove(id); + }); }, /** @@ -518,17 +526,78 @@ Discourse.PostStream = Em.Object.extend({ } }, + triggerRecoveredPost: function(postId){ + var self = this, + postIdentityMap = this.get('postIdentityMap'), + existing = postIdentityMap.get(postId); + + if(existing){ + this.triggerChangedPost(postId, new Date()); + } else { + // need to insert into stream + var url = "/posts/" + postId; + Discourse.ajax(url).then(function(p){ + var post = Discourse.Post.create(p); + var stream = self.get("stream"); + var posts = self.get("posts"); + self.storePost(post); + + // we need to zip this into the stream + var index = 0; + stream.forEach(function(postId){ + if(postId < p.id){ + index+= 1; + } + }); + + stream.insertAt(index, p.id); + + index = 0; + posts.forEach(function(_post){ + if(_post.id < p.id){ + index+= 1; + } + }); + + if(index < posts.length){ + posts.insertAt(index, post); + } else { + if(post.post_number < posts[posts.length-1].post_number + 5){ + self.appendMore(); + } + } + }); + } + }, + + triggerDeletedPost: function(postId){ + var self = this, + postIdentityMap = this.get('postIdentityMap'), + existing = postIdentityMap.get(postId); + + if(existing){ + var url = "/posts/" + postId; + Discourse.ajax(url).then( + function(p){ + self.storePost(Discourse.Post.create(p)); + }, + function(){ + self.removePosts([existing]); + }); + } + }, + triggerChangedPost: function(postId, updatedAt) { if (!postId) { return; } var postIdentityMap = this.get('postIdentityMap'), existing = postIdentityMap.get(postId), - postStream = this; + self = this; if (existing && existing.updated_at !== updatedAt) { var url = "/posts/" + postId; Discourse.ajax(url).then(function(p){ - postStream.storePost(Discourse.Post.create(p)); + self.storePost(Discourse.Post.create(p)); }); } }, diff --git a/app/assets/javascripts/discourse/views/topic_view.js b/app/assets/javascripts/discourse/views/topic_view.js index 1abb09729a2..496b7f91178 100644 --- a/app/assets/javascripts/discourse/views/topic_view.js +++ b/app/assets/javascripts/discourse/views/topic_view.js @@ -25,7 +25,7 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, { updateBar: function() { Em.run.scheduleOnce('afterRender', this, '_updateProgressBar'); - }.observes('controller.streamPercentage'), + }.observes('controller.streamPercentage', 'postStream.stream.@each'), _updateProgressBar: function() { var $topicProgress = this._topicProgress; diff --git a/lib/post_destroyer.rb b/lib/post_destroyer.rb index f8d72e7b43a..4245f6b9cc1 100644 --- a/lib/post_destroyer.rb +++ b/lib/post_destroyer.rb @@ -48,6 +48,7 @@ class PostDestroyer def staff_recovered @post.recover! + publish("recovered") end # When a post is properly deleted. Well, it's still soft deleted, but it will no longer @@ -68,6 +69,21 @@ class PostDestroyer @post.topic.trash!(@user) if @post.topic and @post.post_number == 1 update_associated_category_latest_topic end + publish("deleted") + end + + def publish(message) + # edge case, topic is already destroyed + return unless @post.topic + + MessageBus.publish("/topic/#{@post.topic_id}",{ + id: @post.id, + post_number: @post.post_number, + updated_at: @post.updated_at, + type: message + }, + group_ids: @post.topic.secure_group_ids + ) end # When a user 'deletes' their own post. We just change the text.