diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 0a35ad6c394192f60be65549c22d42d526445d86..8364967f428a972f289bea9e19a4e1862250b245 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -83,7 +83,9 @@ en: reshare: "Reshare" comment: "Comment" original_post_deleted: "Original post deleted by author." - show_post: "Show post" + show_nsfw_post: "Show post" + show_nsfw_posts: "Show all" + hide_nsfw_posts: "Hide #nsfw posts" follow: "Follow" unfollow: "Unfollow" diff --git a/features/not_safe_for_work.feature b/features/not_safe_for_work.feature index 3c34c78f183dea684b85319b02a3fc2979b1b6f1..7f7604d74d7895249780c6aac67c50270047ceb4 100644 --- a/features/not_safe_for_work.feature +++ b/features/not_safe_for_work.feature @@ -14,14 +14,30 @@ Scenario: Setting not safe for work And I submit the form Then I should see the "you are safe for work" message -Scenario: NSFWs users posts are nsfw +Scenario: Toggling nsfw state + #Nsfw users posts are marked nsfw Given a nsfw user with email "tommy@pr0nking.com" - And I sign in as "tommy@pr0nking.com" + And a user with email "laura@officeworkers.com" + And a user with email "laura@officeworkers.com" is connected with "tommy@pr0nking.com" + When I sign in as "tommy@pr0nking.com" + And I post "I love 0bj3ction4bl3 c0nt3nt!" + And I post "Sexy Senators Gone Wild!" + Then I should have 2 nsfw posts + + #toggling global nsfw state + When I log out + And I sign in as "laura@officeworkers.com" Then I should not see "I love 0bj3ction4bl3 c0nt3nt!" - #And I post "I love 0bj3ction4bl3 c0nt3nt!" - #Then the post "I love 0bj3ction4bl3 c0nt3nt!" should be marked nsfw + When I toggle nsfw posts + Then I should see "I love 0bj3ction4bl3 c0nt3nt!" + And I should see "Sexy Senators Gone Wild!" + + #cookies + #When I refresh the page + #Then I should see "I love 0bj3ction4bl3 c0nt3nt!" + #And I should see "Sexy Senators Gone Wild!" -# And I log out -# And I log in as an office worker -# And I am folllowing "tommy@pr0n.xxx" -# Then I should not see "I love 0bj3ction4bl3 c0nt3nt!" in my stream + #hiding + When I toggle nsfw posts + Then I should not see "I love 0bj3ction4bl3 c0nt3nt!" + And I should not see "Sexy Senators Gone Wild!" diff --git a/features/step_definitions/session_steps.rb b/features/step_definitions/session_steps.rb index 360d2637c13fec43c55b1c64e2c65fad6a4008fd..5d5e16ac49a4cff5776893f2e6fbb15ad1143d8c 100644 --- a/features/step_definitions/session_steps.rb +++ b/features/step_definitions/session_steps.rb @@ -21,13 +21,13 @@ When /^I try to sign in manually$/ do step %(I press "Sign in") end -When /^I sign in as "([^"]*)"$/ do |email| +When /^I (?:sign|log) in as "([^"]*)"$/ do |email| @me = User.find_by_email(email) @me.password ||= 'password' step 'I am signed in' end -When /^I sign in with password "([^"]*)"$/ do |password| +When /^I (?:sign|log) in with password "([^"]*)"$/ do |password| @me.password = password step 'I am signed in' end diff --git a/features/step_definitions/stream_steps.rb b/features/step_definitions/stream_steps.rb index f26aa922fdd3eb9efdcca03e4aab38300da2f821..d508ebc58ccd9d773a6c5fec4100a95ed5a4259e 100644 --- a/features/step_definitions/stream_steps.rb +++ b/features/step_definitions/stream_steps.rb @@ -9,3 +9,11 @@ end Then /^"([^"]*)" should be post (\d+)$/ do |post_text, position| find(".stream_element:nth-child(#{position}) .post-content").text.should == post_text end + +When /^I toggle nsfw posts$/ do + find(".toggle_nsfw_state").click +end + +Then /^I should have (\d+) nsfw posts$/ do |num_posts| + all(".nsfw-shield").size.should == num_posts.to_i +end \ No newline at end of file diff --git a/public/javascripts/app/app.js b/public/javascripts/app/app.js index fdb4bf0c5e49d4c86b535285a72a0d72641790a4..ef0e1d13df57bf886630eb7685499d5365a3eae0 100644 --- a/public/javascripts/app/app.js +++ b/public/javascripts/app/app.js @@ -4,8 +4,8 @@ var app = { helpers: {}, views: {}, - user: function(user) { - if(user) { return this._user = user } + user: function(userAttrs) { + if(userAttrs) { return this._user = new app.models.User(userAttrs) } return this._user || false }, diff --git a/public/javascripts/app/models/user.js b/public/javascripts/app/models/user.js new file mode 100644 index 0000000000000000000000000000000000000000..247346b08068514820cb92a7b78bbff917cfbc65 --- /dev/null +++ b/public/javascripts/app/models/user.js @@ -0,0 +1,6 @@ +app.models.User = Backbone.Model.extend({ + toggleNsfwState : function() { + this.set({showNsfw : !this.get("showNsfw")}); + this.trigger("nsfwChanged"); + } +}); diff --git a/public/javascripts/app/templates/stream-element.handlebars b/public/javascripts/app/templates/stream-element.handlebars index 7af3c8872a89ec3d346e0898bd90a5dca52fd5e6..47b59963d3bfc9b3bbe90dd7605bcff3d7211b15 100644 --- a/public/javascripts/app/templates/stream-element.handlebars +++ b/public/javascripts/app/templates/stream-element.handlebars @@ -44,24 +44,37 @@ </span> </div> - {{#if nsfw}} + {{#if showPost}} + {{#if nsfw}} + <div class="nsfw_off"> + <strong> + #NSFW + </strong> + | + <a href="#" class="toggle_nsfw_state"> + {{t "stream.hide_nsfw_posts"}} + </a> + </div> + {{/if}} + <div class="post-content"> </div> + + <div class="feedback"> </div> + <div class="likes"> </div> + <div class="comments"> </div> + {{else}} <div class="nsfw-shield"> <strong> - NSFW + #NSFW </strong> | - <a href="#"> - {{t "stream.show_post"}} + <a href="#" class="show_nsfw_post"> + {{t "stream.show_nsfw_post"}} + </a> + | + <a href="#" class="toggle_nsfw_state"> + {{t "stream.show_nsfw_posts"}} </a> </div> - - {{else}} - - <div class="post-content"> </div> - - <div class="feedback"> </div> - <div class="likes"> </div> - <div class="comments"> </div> {{/if}} </div> diff --git a/public/javascripts/app/views.js b/public/javascripts/app/views.js index b55c6a04152e80755a5462c6b2575bfce611b593..9b15044c164a4c48c65b2d44c8f6de13ce0ba742 100644 --- a/public/javascripts/app/views.js +++ b/public/javascripts/app/views.js @@ -11,7 +11,7 @@ app.views.Base = Backbone.View.extend({ defaultPresenter : function(){ var modelJson = this.model ? this.model.toJSON() : {} - return _.extend(modelJson, {current_user: app.user()}); + return _.extend(modelJson, {current_user: app.user().attributes}); }, render : function() { diff --git a/public/javascripts/app/views/comment_view.js b/public/javascripts/app/views/comment_view.js index 9ef1307a46efb4456f63d7f2be47e03e72a56da8..8c36dfa1c83c176e039dc01e5c16acae3f65ed4c 100644 --- a/public/javascripts/app/views/comment_view.js +++ b/public/javascripts/app/views/comment_view.js @@ -16,11 +16,11 @@ app.views.Comment = app.views.Content.extend({ }, ownComment : function() { - return this.model.get("author").diaspora_id == app.user().diaspora_id + return this.model.get("author").diaspora_id == app.user().get("diaspora_id") }, postOwner : function() { - return this.model.get("parent").author.diaspora_id == app.user().diaspora_id + return this.model.get("parent").author.diaspora_id == app.user().get("diaspora_id") }, canRemove : function() { diff --git a/public/javascripts/app/views/feedback_view.js b/public/javascripts/app/views/feedback_view.js index 4543680bb0b8c6126e2e27a9cd08c919ca541e64..ab967961940c69f3f05ffb6596de460b39a67d64 100644 --- a/public/javascripts/app/views/feedback_view.js +++ b/public/javascripts/app/views/feedback_view.js @@ -43,8 +43,8 @@ app.views.Feedback = app.views.StreamObject.extend({ var rootExists = (isReshare ? this.model.get("root") : true) var publicPost = this.model.get("public"); - var userIsNotAuthor = this.model.get("author").diaspora_id != app.user().diaspora_id; - var userIsNotRootAuthor = rootExists && (isReshare ? this.model.get("root").author.diaspora_id != app.user().diaspora_id : true) + var userIsNotAuthor = this.model.get("author").diaspora_id != app.user().get("diaspora_id"); + var userIsNotRootAuthor = rootExists && (isReshare ? this.model.get("root").author.diaspora_id != app.user().get("diaspora_id") : true) return publicPost && userIsNotAuthor && userIsNotRootAuthor; } diff --git a/public/javascripts/app/views/post_view.js b/public/javascripts/app/views/post_view.js index 9d93b28ba45e41e39c31f6b38858a3d31c5a48cd..31307e79ba617179154271365f3b94f16cd52e8c 100644 --- a/public/javascripts/app/views/post_view.js +++ b/public/javascripts/app/views/post_view.js @@ -6,7 +6,9 @@ app.views.Post = app.views.StreamObject.extend({ events: { "click .focus_comment_textarea": "focusCommentTextarea", - "click .nsfw-shield a": "removeNsfwShield", + "click .show_nsfw_post": "removeNsfwShield", + "click .toggle_nsfw_state": "toggleNsfwState", + "click .remove_post": "destroyModel", "click .hide_post": "hidePost", "click .block_user": "blockUser" @@ -49,15 +51,24 @@ app.views.Post = app.views.StreamObject.extend({ presenter : function() { return _.extend(this.defaultPresenter(), { - authorIsCurrentUser : this.authorIsCurrentUser() + authorIsCurrentUser : this.authorIsCurrentUser(), + showPost : this.showPost() }) }, + showPost : function() { + return (app.user() && app.user().get("showNsfw")) || !this.model.get("nsfw") + }, + removeNsfwShield: function(evt){ if(evt){ evt.preventDefault(); } this.model.set({nsfw : false}) this.render(); - return this; + }, + + toggleNsfwState: function(evt){ + if(evt){ evt.preventDefault(); } + app.user().toggleNsfwState(); }, blockUser: function(evt){ diff --git a/public/javascripts/app/views/stream_view.js b/public/javascripts/app/views/stream_view.js index 20e9566aced7d981b8b7e5616804b425aa8b88c7..be37cd134da7260bf7528aed9ba1543bfeba0e4f 100644 --- a/public/javascripts/app/views/stream_view.js +++ b/public/javascripts/app/views/stream_view.js @@ -11,12 +11,16 @@ app.views.Stream = Backbone.View.extend({ this.setupEvents() this.setupInfiniteScroll() this.setupLightbox() + this.postViews = [] }, setupEvents : function(){ this.stream.bind("fetched", this.removeLoader, this) this.stream.bind("allPostsLoaded", this.unbindInfScroll, this) this.collection.bind("add", this.addPost, this); + app.user().bind("nsfwChanged", function() { + _.map(this.postViews, function(view){ view.render() }) + }, this) }, addPost : function(post) { @@ -28,6 +32,7 @@ app.views.Stream = Backbone.View.extend({ : "append" ](postView.render().el); + this.postViews.push(postView) return this; }, diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index d6a425d807d3a8f22f935d9f8181c299c17f27cf..1ee9621e978a83bd95d1582e3c3332032e1807ce 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -2815,3 +2815,9 @@ a.toggle_selector .float-right :float right :margin-top 5px + +.nsfw_off + :font-size smaller + :color #999 + a + :color #666 \ No newline at end of file diff --git a/spec/javascripts/app/app_spec.js b/spec/javascripts/app/app_spec.js index 0be9ee9753d9a5bb381c17f0c847525f6071bec8..eaf1a90a7e0f917401ce8ae72f727568930ba8c6 100644 --- a/spec/javascripts/app/app_spec.js +++ b/spec/javascripts/app/app_spec.js @@ -5,7 +5,7 @@ describe("app", function() { app.user({name: "alice"}); - expect(app.user()).toEqual({name: "alice"}); + expect(app.user().get("name")).toEqual("alice"); }); it("returns false if the current_user isn't set", function() { diff --git a/spec/javascripts/app/views/post_view_spec.js b/spec/javascripts/app/views/post_view_spec.js index 2f52e44a62465b9486f719ce707e86398cafd98d..4ecb335691591c55f006bde4f962d3dcea02b4ae 100644 --- a/spec/javascripts/app/views/post_view_spec.js +++ b/spec/javascripts/app/views/post_view_spec.js @@ -61,23 +61,40 @@ describe("app.views.Post", function(){ }) context("NSFW", function(){ - it("contains a shield element", function(){ + beforeEach(function(){ this.statusMessage.set({nsfw: true}); + this.view = new app.views.Post({model : this.statusMessage}).render(); - var view = new app.views.Post({model : this.statusMessage}).render(); - var statusElement = $(view.el) + this.hiddenPosts = function(){ + return this.view.$(".nsfw-shield") + } + }); - expect(statusElement.find(".nsfw-shield").length).toBe(1) - }) + it("contains a shield element", function(){ + expect(this.hiddenPosts().length).toBe(1) + }); - it("does not contain a shield element", function(){ + it("does not contain a shield element when nsfw is false", function(){ this.statusMessage.set({nsfw: false}); + this.view.render(); + expect(this.hiddenPosts()).not.toExist(); + }) - var view = new app.views.Post({model : this.statusMessage}).render(); - var statusElement = $(view.el) - - expect(statusElement.find(".shield").html()).toBe(null); + context("showing a single post", function(){ + it("removes the shields when the post is clicked", function(){ + expect(this.hiddenPosts()).toExist(); + this.view.$(".nsfw-shield .show_nsfw_post").click(); + expect(this.hiddenPosts()).not.toExist(); + }); + }); + + context("clicking the toggle nsfw link toggles it on the user", function(){ + it("calls toggleNsfw on the user", function(){ + spyOn(app.user(), "toggleNsfwState") + this.view.$(".toggle_nsfw_state").first().click(); + expect(app.user().toggleNsfwState).toHaveBeenCalled(); + }); }) }) }) -}) +}); diff --git a/spec/javascripts/helpers/factory.js b/spec/javascripts/helpers/factory.js index b0e871911384e3c843b484459fb6336f2bb70a97..c5c0520cde202877c06fc753b85dfa5638a3f4f0 100644 --- a/spec/javascripts/helpers/factory.js +++ b/spec/javascripts/helpers/factory.js @@ -35,15 +35,15 @@ factory = { userAttrs : function(overrides){ var id = this.id.next() - var defaultAttrs = { - "name":"Awesome User" + id, - "id": id, - "diaspora_id": "bob@bob.com", - "avatar":{ - "large":"http://localhost:3000/images/user/uma.jpg", - "medium":"http://localhost:3000/images/user/uma.jpg", - "small":"http://localhost:3000/images/user/uma.jpg"} - } + var defaultAttrs = { + "name":"Awesome User" + id, + "id": id, + "diaspora_id": "bob@bob.com", + "avatar":{ + "large":"http://localhost:3000/images/user/uma.jpg", + "medium":"http://localhost:3000/images/user/uma.jpg", + "small":"http://localhost:3000/images/user/uma.jpg"} + } return _.extend(defaultAttrs, overrides) },