diff --git a/app/helpers/sockets_helper.rb b/app/helpers/sockets_helper.rb index c42a0defd..491c7cc3c 100644 --- a/app/helpers/sockets_helper.rb +++ b/app/helpers/sockets_helper.rb @@ -63,18 +63,19 @@ module SocketsHelper Rails.logger.error("event=socket_render status=fail user=#{user.diaspora_handle} object=#{object.id.to_s}") raise e end - action_hash = {:class =>object.class.to_s.underscore.pluralize, :html => v, :post_id => obj_id(object)} + action_hash = { + :class =>object.class.to_s.underscore.pluralize, + :html => v, + :post_id => obj_id(object) + } action_hash.merge! opts + if object.is_a? Photo action_hash[:photo_hash] = object.thumb_hash end if object.is_a? Comment - post = object.post action_hash[:comment_id] = object.id - action_hash[:my_post?] = (post.author.owner_id == uid) - action_hash[:post_guid] = post.guid - end if object.is_a? Like diff --git a/app/views/comments/create.js.erb b/app/views/comments/create.js.erb index bc4bba110..dca796b3b 100644 --- a/app/views/comments/create.js.erb +++ b/app/views/comments/create.js.erb @@ -1,5 +1,7 @@ -WebSocketReceiver.processComment(<%= @comment.post_id %>, - <%= @comment.id %>, - "<%= escape_javascript(render(:partial => 'comments/comment', :locals => { :comment => @comment, :person => current_user.person}))%>", - false); +WebSocketReceiver.processComment({ + post_id: <%= @comment.post_id %>, + comment_id: <%= @comment.id %>, + html: "<%= escape_javascript(render(:partial => 'comments/comment', :locals => { :comment => @comment, :person => current_user.person}))%>", + options: false +}); diff --git a/public/javascripts/content-updater.js b/public/javascripts/content-updater.js index 7cb24d308..03b083b35 100644 --- a/public/javascripts/content-updater.js +++ b/public/javascripts/content-updater.js @@ -1,19 +1,29 @@ /* Copyright (c) 2010, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ - + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ var ContentUpdater = { - addPostToStream: function(html) { - var streamElement = $(html); - var postId = streamElement.attr("data-guid"); + elementWithGuid: function(selector, guid) { + return $(selector + "[data-guid='" + guid + "']"); + }, - if($(".stream_element[data-guid='" + postId + "']").length === 0) { - if($("#no_posts").length) { + commentDoesNotExist: function(commentId) { + return (ContentUpdater.elementWithGuid(".comment", commentId).length === 0); + }, + + postDoesNotExist: function(postId) { + return (ContentUpdater.elementWithGuid(".stream_element", postId).length === 0); + }, + + addPostToStream: function(postId, html) { + var streamElement = $(html); + + if (ContentUpdater.postDoesNotExist(postId)) { + if ($("#no_posts").length) { $("#no_posts").detach(); } - streamElement.prependTo("#main_stream:not('.show')").fadeIn("fast", function() { + streamElement.prependTo("#main_stream").fadeIn("fast", function() { streamElement.find("label").inFieldLabels(); }); @@ -21,5 +31,48 @@ var ContentUpdater = { Diaspora.widgets.timeago.updateTimeAgo(); Diaspora.widgets.directionDetector.updateBinds(); } + }, + + addCommentToPost: function(commentId, postId, html) { + if (ContentUpdater.commentDoesNotExist(commentId)) { + var post = ContentUpdater.elementWithGuid(".stream_element", postId), + newComment = $(html), + commentsContainer = $(".comments", post), + comments = commentsContainer.find(".comment.posted"), + showCommentsToggle = $(".show_post_comments", post); + + if(comments.length === 0) { + comments + .last() + .after( + newComment.fadeIn("fast") + ); + } + else { + commentsContainer + .find("li") + .last() + .before( + newComment.fadeIn("fast") + ); + } + + + if (showCommentsToggle.length > 0) { + showCommentsToggle.html( + showCommentsToggle.html().replace(/\d+/, comments.length) + ); + + if (comments.is(":not(:visible)")) { + showCommentsToggle.click(); + } + + $(".show_comments", post).removeClass('hidden'); + + Diaspora.widgets.publish("stream/commentAdded", [postId, commentId]); + Diaspora.widgets.timeago.updateTimeAgo(); + Diaspora.widgets.directionDetector.updateBinds(); + } + } } }; \ No newline at end of file diff --git a/public/javascripts/web-socket-receiver.js b/public/javascripts/web-socket-receiver.js index c244ea05a..d7eec350f 100644 --- a/public/javascripts/web-socket-receiver.js +++ b/public/javascripts/web-socket-receiver.js @@ -1,11 +1,11 @@ var WebSocketReceiver = { initialize: function(url) { - var ws = new WebSocket(url); - WSR.socket = ws; + this.debuggable = true; + this.url = url; + this.socket = new WebSocket(url); - //Attach onmessage to websocket - ws.onmessage = WSR.onMessage; - ws.onclose = function() { + this.socket.onmessage = WSR.onMessage; + this.socket.onclose = function() { Diaspora.widgets.notifications.showNotification({ html: '
' + Diaspora.widgets.i18n.t("web_sockets.disconnected") + @@ -13,43 +13,38 @@ var WebSocketReceiver = { incrementCount: false }); - WSR.debug("socket closed"); - }; - ws.onopen = function() { - ws.send(location.pathname); - WSR.debug("connected..."); + WSR.debug("Socket closed"); }; + + this.socket.onopen = $.proxy(function() { + this.socket.send(location.pathname); + WSR.debug("Connected to " + this.url + "..."); + }, this); }, onMessage: function(evt) { - var obj = jQuery.parseJSON(evt.data); + var message = jQuery.parseJSON(evt.data);WSR.debug("WebSocket received " + message.class, message) - if(obj['class'].match(/^notifications/)) { - WebSocketReceiver.processNotification(obj); - } else if (obj['class'] == 'people') { - WSR.debug("got a " + obj['class']); - WebSocketReceiver.processPerson(obj); - - } else { - WSR.debug("got a " + obj['class'] + " for aspects " + obj.aspect_ids); - - if (obj['class']=="retractions") { - WebSocketReceiver.processRetraction(obj.post_id); - - } else if (obj['class']=="comments") { - WebSocketReceiver.processComment(obj.post_id, obj.comment_id, obj.html, { - 'notification': obj.notification, - 'mine?': obj['mine?'], - 'my_post?': obj['my_post?'] - }); - - } else if (obj['class']=="likes") { - WebSocketReceiver.processLike(obj.post_id, obj.html); - - } else { - WebSocketReceiver.processPost(obj['class'], obj.post_id, obj.html, obj.aspect_ids); - } + if(message.class.match(/^notifications/)) { + WebSocketReceiver.processNotification(message); + } + else if(message.class === "people") { + WebSocketReceiver.processPerson(message); + } + else { + if(message.class === "retractions") { + WebSocketReceiver.processRetraction(message.post_id); } + else if(message.class === "comments") { + WebSocketReceiver.processComment(message); + } + else if(message.class === "likes") { + WebSocketReceiver.processLike(message.post_id, message.html); + } + else { + WebSocketReceiver.processPost(message.post_id, message.html, message.aspect_ids); + } + } }, processPerson: function(response) { @@ -74,8 +69,8 @@ var WebSocketReceiver = { Diaspora.widgets.notifications.showNotification(notification); }, - processRetraction: function(post_id){ - $("*[data-guid='" + post_id + "']").fadeOut(400, function() { + processRetraction: function(postId){ + $("*[data-guid='" + postId + "']").fadeOut(400, function() { $(this).remove(); }); if($("#main_stream")[0].childElementCount === 0) { @@ -83,42 +78,8 @@ var WebSocketReceiver = { } }, - processComment: function(postId, commentId, html, opts) { - - if( $(".comment[data-guid='"+commentId+"']").length === 0 ) { - - var post = $("*[data-guid='"+postId+"']'"), - prevComments = $('.comment.posted', post); - - if(prevComments.length > 0) { - prevComments.last().after( - $(html).fadeIn("fast", function(){}) - ); - } else { - $('.comments li:last', post).before( - $(html).fadeIn("fast", function(){}) - ); - } - - var toggler = $('.show_post_comments', post); - - if(toggler.length > 0){ - toggler.html( - toggler.html().replace(/\d+/,$('.comments', post).find('li').length -1) - ); - - if( !$(".comments", post).is(':visible') ) { - toggler.click(); - } - - if( $(".show_comments", post).hasClass('hidden') ){ - $(".show_comments", post).removeClass('hidden'); - } - } - } - - Diaspora.widgets.timeago.updateTimeAgo(); - Diaspora.widgets.directionDetector.updateBinds(); + processComment: function(comment) { + ContentUpdater.addCommentToPost(comment.comment_id, comment.post_id, comment.html); }, processLike: function(postId, html) { @@ -126,7 +87,7 @@ var WebSocketReceiver = { $(".likes_container", post).fadeOut('fast').html(html).fadeIn('fast'); }, - processPost: function(className, postId, html, aspectIds) { + processPost: function(postId, html, aspectIds) { if(WebSocketReceiver.onPageForAspects(aspectIds)) { ContentUpdater.addPostToStream(postId, html); } @@ -138,14 +99,14 @@ var WebSocketReceiver = { onPageForAspects: function(aspectIds) { var streamIds = $('#main_stream').attr('data-guids'), - found = false; + found = false; $.each(aspectIds, function(index, value) { if(WebSocketReceiver.onStreamForAspect(value, streamIds)) { found = true; - return false; } }); + return found; }, @@ -153,12 +114,10 @@ var WebSocketReceiver = { return (streamIds.search(aspectId) != -1); }, - onPageOne: function() { - var c = document.location.search.charAt(document.location.search.length-1); - return ((c === '') || (c === '1')); - }, - debug: function(str) { - $("#debug").append("

" + str); + debug: function() { + if(this.debuggable && typeof console !== "undefined") { + console.log.apply(console, arguments); + } } }; var WSR = WebSocketReceiver; diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb index 95d65af7a..2017c561f 100644 --- a/spec/controllers/aspects_controller_spec.rb +++ b/spec/controllers/aspects_controller_spec.rb @@ -70,6 +70,7 @@ describe AspectsController do save_fixture(html_for("body"), "aspects_index_with_posts") save_fixture(html_for(".stream_element:first"), "status_message_in_stream") + save_fixture(html_for(".comment.posted:first"), "comment_on_status_message") end context 'with getting_started = true' do diff --git a/spec/javascripts/content-updater-spec.js b/spec/javascripts/content-updater-spec.js index df0bc5ae0..c6235e347 100644 --- a/spec/javascripts/content-updater-spec.js +++ b/spec/javascripts/content-updater-spec.js @@ -5,30 +5,56 @@ describe("ContentUpdater", function() { describe("addPostToStream", function() { - + var $post; beforeEach(function() { $("#jasmine_content").empty(); spec.loadFixture("aspects_index"); + $post = $(spec.fixtureHtml("status_message_in_stream")); }); - it("adds a post to the stream", function() { var originalPostCount = $(".stream_element").length; - ContentUpdater.addPostToStream(spec.fixtureHtml("status_message_in_stream")); + ContentUpdater.addPostToStream($post.data("guid"), spec.fixtureHtml("status_message_in_stream")); expect($(".stream_element").length).toEqual(originalPostCount + 1); }); it("does not add duplicate posts", function() { var originalPostCount = $(".stream_element").length; - ContentUpdater.addPostToStream(spec.fixtureHtml("status_message_in_stream")); + ContentUpdater.addPostToStream($post.data("guid"), spec.fixtureHtml("status_message_in_stream")); expect($(".stream_element").length).toEqual(originalPostCount + 1); - ContentUpdater.addPostToStream(spec.fixtureHtml("status_message_in_stream")); + ContentUpdater.addPostToStream($post.data("guid"), spec.fixtureHtml("status_message_in_stream")); expect($(".stream_element").length).toEqual(originalPostCount + 1); }); it("removes the div that says you have no posts if it exists", function() { expect($("#no_posts").length).toEqual(1); - ContentUpdater.addPostToStream(spec.fixtureHtml("status_message_in_stream")); + ContentUpdater.addPostToStream($post.data("guid"), spec.fixtureHtml("status_message_in_stream")); expect($("#no_posts").length).toEqual(0); }); + + it("fires a custom event (stream/postAdded)", function() { + var spy = jasmine.createSpy("stub"); + Diaspora.widgets.subscribe("stream/postAdded", spy); + ContentUpdater.addPostToStream($post.data("guid"), spec.fixtureHtml("status_message_in_stream")); + expect(spy).toHaveBeenCalled(); + }); + }); + + describe("addCommentToPost", function() { + var $comment, $post; + + beforeEach(function() { + spec.loadFixture("aspects_index"); + $comment = $(spec.fixtureHtml("comment_on_status_message")), + $post = $(spec.fixtureHtml("status_message_in_stream")); + }); + + it("adds a comment to a post only if it doesnt exist", function() { + ContentUpdater.addPostToStream($post.data("guid"), spec.fixtureHtml("status_message_in_stream")) + var originalCommentCount = $(".comment.posted").length; + ContentUpdater.addCommentToPost($comment.data("guid"), $post.data("guid"), spec.fixtureHtml("comment_on_status_message")); + expect($(".comment.posted").length).toEqual(originalCommentCount); + ContentUpdater.addCommentToPost("9000786", $post.data("guid"), spec.fixtureHtml("comment_on_status_message")); + expect($(".comment.posted").length).toBeGreaterThan(originalCommentCount); + }); }); });