diff --git a/app/components/application_component.rb b/app/components/application_component.rb index 3db4d0451..98d567fbd 100644 --- a/app/components/application_component.rb +++ b/app/components/application_component.rb @@ -1,2 +1,5 @@ class ApplicationComponent < ViewComponent::Base + def policy(subject) + Pundit.policy!(current_user, subject) + end end diff --git a/app/components/comment_component.rb b/app/components/comment_component.rb index 537bf654f..8dfede7f3 100644 --- a/app/components/comment_component.rb +++ b/app/components/comment_component.rb @@ -2,17 +2,8 @@ class CommentComponent < ApplicationComponent attr_reader :comment, :context, :dtext_data, :show_deleted, :current_user - delegate :link_to_user, :time_ago_in_words_tagged, :format_text, :policy, to: :helpers + delegate :link_to_user, :time_ago_in_words_tagged, :format_text, to: :helpers - def self.with_collection(comments, current_user:, **options) - dtext_data = DText.preprocess(comments.map(&:body)) - # XXX - #comments = comments.includes(:moderation_reports) if Pundit.policy!(current_user, ModerationReport).show? - - super(comments, current_user: current_user, dtext_data: dtext_data, **options) - end - - # XXX calls to pundit policy don't respect current_user. def initialize(comment:, current_user:, context: nil, dtext_data: nil, show_deleted: false) @comment = comment @context = context @@ -25,6 +16,14 @@ class CommentComponent < ApplicationComponent !comment.is_deleted? || show_deleted || current_user.is_moderator? end + def dimmed? + !comment.is_sticky? && comment.score < current_user.comment_threshold/2.0 + end + + def thresholded? + !comment.is_sticky? && comment.score < current_user.comment_threshold + end + def has_moderation_reports? policy(ModerationReport).show? && comment.moderation_reports.present? end diff --git a/app/components/comment_component/comment_component.html.erb b/app/components/comment_component/comment_component.html.erb index 8f5ef5e88..45cb60574 100644 --- a/app/components/comment_component/comment_component.html.erb +++ b/app/components/comment_component/comment_component.html.erb @@ -8,7 +8,8 @@ data-do-not-bump-post="<%= comment.do_not_bump_post? %>" data-is-deleted="<%= comment.is_deleted? %>" data-is-sticky="<%= comment.is_sticky? %>" - data-below-threshold="<%= comment.score < current_user.comment_threshold %>" + data-is-dimmed="<%= dimmed? %>" + data-is-thresholded="<%= thresholded? %>" data-is-reported="<%= has_moderation_reports? %>" data-is-voted="<%= comment.voted_by?(current_user) %>">
@@ -21,10 +22,14 @@ <%= link_to time_ago_in_words_tagged(comment.created_at), post_path(comment.post, anchor: "comment_#{comment.id}"), class: "message-timestamp" %>
-
+ <% if thresholded? %> + <%= link_to "[hidden]", "javascript:void(0)", class: "unhide-comment-link" %> + <% end %> + + <%= tag.div class: "body prose", style: ("display: none;" if thresholded?) do %> <%= format_text(comment.body, data: dtext_data) %> -
- <%= render "application/update_notice", record: comment %> + <%= render "application/update_notice", record: comment %> + <% end %> <% if policy(comment).create? %> diff --git a/app/components/comment_component/comment_component.scss b/app/components/comment_component/comment_component.scss index 442c0f343..edb5ce61f 100644 --- a/app/components/comment_component/comment_component.scss +++ b/app/components/comment_component/comment_component.scss @@ -21,7 +21,7 @@ article.comment { } } - &[data-below-threshold="true"][data-is-sticky="false"] { + &[data-is-dimmed="true"] { opacity: 0.3; &:hover { @@ -29,6 +29,11 @@ article.comment { } } + .unhide-comment-link { + margin-bottom: 1em; + display: block; + } + .moderation-report-notice { font-weight: bold; color: var(--moderation-report-text-color); diff --git a/app/components/comment_section_component.rb b/app/components/comment_section_component.rb new file mode 100644 index 000000000..341ea6c8e --- /dev/null +++ b/app/components/comment_section_component.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CommentSectionComponent < ApplicationComponent + attr_reader :post, :comments, :current_user, :limit, :dtext_data + + def initialize(post:, current_user:, limit: nil) + @post = post + @current_user = current_user + @limit = limit + + @comments = @post.comments.order(id: :asc) + @comments = @comments.includes(:creator) + @comments = @comments.includes(:votes) if !current_user.is_anonymous? + @comments = @comments.includes(:moderation_reports) if policy(ModerationReport).show? + @comments = @comments.last(limit) if limit.present? + + @dtext_data = DText.preprocess(@comments.map(&:body)) + end + + def has_unloaded_comments? + unloaded_comment_count > 0 + end + + def unloaded_comment_count + return 0 if limit.nil? + [post.comments.size - limit, 0].max + end +end diff --git a/app/components/comment_section_component/comment_section_component.html.erb b/app/components/comment_section_component/comment_section_component.html.erb new file mode 100644 index 000000000..882ab186c --- /dev/null +++ b/app/components/comment_section_component/comment_section_component.html.erb @@ -0,0 +1,20 @@ +
+ <% if has_unloaded_comments? %> + <%= link_to "Show #{pluralize unloaded_comment_count, "more comment"}", comments_path(post_id: post.id), class: "show-all-comments-link", remote: true %> + <% end %> + +
+ <% if comments.present? %> + <%= render CommentComponent.with_collection(comments, current_user: current_user, context: :index_by_post, dtext_data: dtext_data) %> + <% else %> +

There are no comments.

+ <% end %> +
+ + <% if policy(Comment).create? %> +
+

<%= link_to "Post comment", new_comment_path(comment: { post_id: post.id }), class: "expand-comment-response" %>

+ <%= render "comments/form", comment: post.comments.new, hidden: true %> +
+ <% end %> +
diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index ff51ce9bc..891cf061a 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -23,11 +23,6 @@ class PostsController < ApplicationController @post = authorize Post.find(params[:id]) if request.format.html? - @comments = @post.comments - @comments = @comments.includes(:creator) - @comments = @comments.includes(:votes) if CurrentUser.is_member? - @comments = @comments.unhidden(CurrentUser.user) - include_deleted = @post.is_deleted? || (@post.parent_id.present? && @post.parent.is_deleted?) || CurrentUser.user.show_deleted_children? @sibling_posts = @post.parent.present? ? @post.parent.children : Post.none @sibling_posts = @sibling_posts.undeleted unless include_deleted diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb deleted file mode 100644 index be2d52e4e..000000000 --- a/app/helpers/comments_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -module CommentsHelper - def render_comment(comment, **options) - render CommentComponent.new(comment: comment, **options) - end - - def render_comment_list(comments, **options) - render CommentComponent.with_collection(comments, current_user: CurrentUser.user, **options) - end -end diff --git a/app/helpers/components_helper.rb b/app/helpers/components_helper.rb new file mode 100644 index 000000000..48443a217 --- /dev/null +++ b/app/helpers/components_helper.rb @@ -0,0 +1,17 @@ +module ComponentsHelper + def post_preview(post, **options) + render PostPreviewComponent.new(post: post, **options) + end + + def post_previews_html(posts, **options) + render PostPreviewComponent.with_collection(posts, **options) + end + + def render_comment(comment, **options) + render CommentComponent.new(comment: comment, **options) + end + + def render_comment_section(post, **options) + render CommentSectionComponent.new(post: post, **options) + end +end diff --git a/app/helpers/posts_helper.rb b/app/helpers/posts_helper.rb index 12f4c23aa..d43948dd8 100644 --- a/app/helpers/posts_helper.rb +++ b/app/helpers/posts_helper.rb @@ -1,12 +1,4 @@ module PostsHelper - def post_preview(post, **options) - render PostPreviewComponent.new(post: post, **options) - end - - def post_previews_html(posts, **options) - render PostPreviewComponent.with_collection(posts, **options) - end - def reportbooru_enabled? Danbooru.config.reportbooru_server.present? && Danbooru.config.reportbooru_key.present? end diff --git a/app/javascript/src/javascripts/comments.js b/app/javascript/src/javascripts/comments.js index aad19b7ca..968c7888e 100644 --- a/app/javascript/src/javascripts/comments.js +++ b/app/javascript/src/javascripts/comments.js @@ -4,6 +4,7 @@ Comment.initialize_all = function() { if ($("#c-posts").length || $("#c-comments").length) { $(document).on("click.danbooru.comment", ".edit_comment_link", Comment.show_edit_form); $(document).on("click.danbooru.comment", ".expand-comment-response", Comment.show_new_comment_form); + $(document).on("click.danbooru.comment", ".unhide-comment-link", Comment.unhide_comment); } } @@ -20,6 +21,13 @@ Comment.show_edit_form = function(e) { e.preventDefault(); } +Comment.unhide_comment = function(e) { + let $comment = $(this).closest(".comment"); + $comment.find(".unhide-comment-link").hide(); + $comment.find(".body").show(); + e.preventDefault(); +} + $(document).ready(function() { Comment.initialize_all(); }); diff --git a/app/javascript/src/styles/specific/comments.scss b/app/javascript/src/styles/specific/comments.scss index 47f01878f..6dd2745bd 100644 --- a/app/javascript/src/styles/specific/comments.scss +++ b/app/javascript/src/styles/specific/comments.scss @@ -1,20 +1,10 @@ @import "../base/000_vars.scss"; -div.comments-for-post { - div.moderation-comments-notice { - margin: 1em 0; - font-weight: bold; - color: var(--moderation-report-text-color); - } - - div.hidden-comments-notice { - margin: 1em 0; - } -} - div#c-comments { - div#a-index, div#a-show { + div#a-index { div.header { + margin-bottom: 1em; + span.info { margin-right: 1.5em; } @@ -58,7 +48,7 @@ div#c-comments { text-align: center; } - div.comments-for-post { + div.comment-section { flex: 1; } } @@ -89,12 +79,6 @@ form.edit_comment div.input.boolean { width: auto; height: auto; } - - div.comments-for-post { - div.header div.row span.info { - display: block; - } - } } } } diff --git a/app/models/comment.rb b/app/models/comment.rb index e18f27276..041b47ee5 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -118,21 +118,6 @@ class Comment < ApplicationRecord user.id.in?(votes.map(&:user_id)) end - def visibility(user) - return :invisible if is_deleted? && !user.is_moderator? - return :hidden if is_deleted? && user.is_moderator? - return :hidden if score < user.comment_threshold && !is_sticky? - return :visible - end - - def self.hidden(user) - select { |comment| comment.visibility(user) == :hidden } - end - - def self.unhidden(user) - select { |comment| comment.visibility(user) == :visible } - end - def quoted_response DText.quote(body, creator.name) end diff --git a/app/models/post.rb b/app/models/post.rb index 53092b64f..0640bad28 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -49,7 +49,7 @@ class Post < ApplicationRecord has_many :appeals, :class_name => "PostAppeal", :dependent => :destroy has_many :votes, :class_name => "PostVote", :dependent => :destroy has_many :notes, :dependent => :destroy - has_many :comments, -> {order("comments.id")}, :dependent => :destroy + has_many :comments, :dependent => :destroy has_many :children, -> {order("posts.id")}, :class_name => "Post", :foreign_key => "parent_id" has_many :approvals, :class_name => "PostApproval", :dependent => :destroy has_many :disapprovals, :class_name => "PostDisapproval", :dependent => :destroy diff --git a/app/views/comments/_index_by_post.html.erb b/app/views/comments/_index_by_post.html.erb index d04d9c175..1e976ab28 100644 --- a/app/views/comments/_index_by_post.html.erb +++ b/app/views/comments/_index_by_post.html.erb @@ -4,13 +4,15 @@ <% end %> <% @posts.select(&:visible?).each do |post| %> - <% if post.comments.unhidden(CurrentUser.user).any? || post.comments.hidden(CurrentUser.user).any? %> - <%= tag.div id: "post_#{post.id}", **PostPreviewComponent.new(post: post).article_attrs("post") do %> -
- <%= link_to(image_tag(post.preview_file_url), post_path(post)) %> -
- <%= render "comments/partials/index/list", post: post, comments: post.comments.unhidden(CurrentUser.user).last(6), page: :comments %> - <% end %> + <%= tag.div id: "post_#{post.id}", **PostPreviewComponent.new(post: post).article_attrs("post") do %> +
+ <%= link_to(image_tag(post.preview_file_url), post_path(post)) %> +
+ +
+ <%= render "comments/partials/index/header", post: post %> + <%= render_comment_section(post, limit: 6, current_user: CurrentUser.user) %> +
<% end %> <% end %>
diff --git a/app/views/comments/index_for_post.js.erb b/app/views/comments/index_for_post.js.erb index e3fbbf04b..6f6a80c1a 100644 --- a/app/views/comments/index_for_post.js.erb +++ b/app/views/comments/index_for_post.js.erb @@ -1,5 +1,3 @@ -$("#threshold-comments-notice-for-<%= @post.id %>").hide(); - -var current_comment_section = $("div.comments-for-post[data-post-id=<%= @post.id %>] div.list-of-comments"); -current_comment_section.html("<%= j render_comment_list(@comments, context: :index_by_post) %>"); +var current_comment_section = $("div.comments-for-post[data-post-id=<%= @post.id %>]"); +current_comment_section.replaceWith("<%= j render_comment_section(@post, limit: nil, current_user: CurrentUser.user) %>"); $(window).trigger("danbooru:index_for_post", [<%= @post.id %>]); diff --git a/app/views/comments/partials/index/_list.html.erb b/app/views/comments/partials/index/_list.html.erb deleted file mode 100644 index 8b0311e3d..000000000 --- a/app/views/comments/partials/index/_list.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -
- <% if page == :comments %> - <%= render "comments/partials/index/header", :post => post %> - <% end %> - - <% if post.comments.hidden(CurrentUser.user).any? || (page == :comments && post.comments.size > 6) %> -
- - <%= link_to "Show #{pluralize post.comments.hidden(CurrentUser.user).size, "hidden comment"}", comments_path(post_id: post.id), id: "show-all-comments-link", remote: true %> - -
- <% end %> - -
- <% if comments.present? %> - <%= render_comment_list(comments, context: :index_by_post) %> - <% elsif post.last_commented_at.present? %> -

There are no visible comments.

- <% else %> -

There are no comments.

- <% end %> -
- - <% if policy(Comment).create? %> -
-

<%= link_to "Post comment", new_comment_path(comment: { post_id: post.id }), :class => "expand-comment-response" %>

- <%= render "comments/form", comment: post.comments.new, hidden: true %> -
- <% end %> -
diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index 7e7edfb14..0a6d50aae 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -105,7 +105,7 @@ <% end %>
- <%= render "comments/partials/index/list", comments: @comments, post: @post, page: :post %> + <%= render_comment_section(@post, current_user: CurrentUser.user) %>