From abe8b9c07137a563a2b210df9c80551d540052ff Mon Sep 17 00:00:00 2001 From: evazion Date: Wed, 8 Aug 2018 23:44:35 -0500 Subject: [PATCH 01/11] Fix "Show all comments" link. The second argument to `trigger` is supposed to be an array. ref: https://danbooru.donmai.us/forum_topics/9127?page=250#forum_post_149379 --- app/javascript/src/javascripts/comments.js | 2 +- app/views/comments/index_for_post.js.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/src/javascripts/comments.js b/app/javascript/src/javascripts/comments.js index 544eaad91..7131d8393 100644 --- a/app/javascript/src/javascripts/comments.js +++ b/app/javascript/src/javascripts/comments.js @@ -19,7 +19,7 @@ Comment.initialize_all = function() { Comment.highlight_threshold_comments(Utility.meta("post-id")); } - $(window).on("danbooru:index_for_post", (post_id, current_comment_section, include_below_threshold) => { + $(window).on("danbooru:index_for_post", (_event, post_id, current_comment_section, include_below_threshold) => { if (include_below_threshold) { $("#threshold-comments-notice-for-" + post_id).hide(); } else { diff --git a/app/views/comments/index_for_post.js.erb b/app/views/comments/index_for_post.js.erb index 37bb6f687..a58fd7168 100644 --- a/app/views/comments/index_for_post.js.erb +++ b/app/views/comments/index_for_post.js.erb @@ -2,4 +2,4 @@ $("#hidden-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(:partial => 'comments/partials/show/comment', :collection => @comments))%>"); -$(window).trigger("danbooru:index_for_post", <%= @post.id %>, current_comment_section, <%= ActiveModel::Type::Boolean.new.cast(params[:include_below_threshold]) %>); +$(window).trigger("danbooru:index_for_post", [<%= @post.id %>, current_comment_section, <%= ActiveModel::Type::Boolean.new.cast(params[:include_below_threshold]) %>]); From c615b53a7e929e2d3f47b2184aa41ffa31c8a680 Mon Sep 17 00:00:00 2001 From: evazion Date: Thu, 9 Aug 2018 12:49:40 -0500 Subject: [PATCH 02/11] Fix broken "Link to alias" / "Link to implication" forum links. /tag_implications was changed to filter out inactive implications by default when the `status` param wasn't given. This broke "Link to implication":/tag_implications?search[id]=NNN links inside pending implication requests in forum posts. These links now return an empty search instead of the pending implication. Hiding inactive aliases/implications by default also changed the API behavior. --- app/models/tag_relationship.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/models/tag_relationship.rb b/app/models/tag_relationship.rb index b7824fb4d..649f2bbad 100644 --- a/app/models/tag_relationship.rb +++ b/app/models/tag_relationship.rb @@ -104,8 +104,6 @@ class TagRelationship < ApplicationRecord if params[:status].present? q = q.status_matches(params[:status]) - else - q = q.active end if params[:category].present? From 8e8a39af43b96d31dc451795f95ead20f73b1845 Mon Sep 17 00:00:00 2001 From: evazion Date: Thu, 9 Aug 2018 00:24:08 -0500 Subject: [PATCH 03/11] comments.js: fix forms flickering on page load. Mark the edit form, new comment form, and unvote links as hidden in html, instead of showing them by default then hiding them later in Javascript. This eliminates flickering on page load. --- app/javascript/src/javascripts/comments.js | 10 ---------- app/views/comments/_form.html.erb | 2 +- app/views/comments/edit.html.erb | 2 +- app/views/comments/partials/index/_list.html.erb | 2 +- app/views/comments/partials/show/_comment.html.erb | 4 ++-- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/app/javascript/src/javascripts/comments.js b/app/javascript/src/javascripts/comments.js index 7131d8393..63ad45bc6 100644 --- a/app/javascript/src/javascripts/comments.js +++ b/app/javascript/src/javascripts/comments.js @@ -8,7 +8,6 @@ Comment.initialize_all = function() { this.initialize_response_link(); this.initialize_reply_links(); this.initialize_expand_links(); - this.initialize_vote_links(); if (!$("#a-edit").length) { this.initialize_edit_links(); @@ -27,7 +26,6 @@ Comment.initialize_all = function() { } Comment.initialize_reply_links(current_comment_section); Comment.initialize_edit_links(current_comment_section); - Comment.initialize_vote_links(current_comment_section); Dtext.initialize_expandables(current_comment_section); }); } @@ -74,13 +72,10 @@ Comment.initialize_response_link = function() { Utility.scroll_to($form); e.preventDefault(); }); - - $("div.new-comment form").hide(); } Comment.initialize_edit_links = function($parent) { $parent = $parent || $(document); - $parent.find(".edit_comment").hide(); $parent.find(".edit_comment_link").click(function(e) { var link_id = $(this).attr("id"); var comment_id = link_id.match(/^edit_comment_link_(\d+)$/)[1]; @@ -111,11 +106,6 @@ Comment.hide_threshold_comments = function(post_id) { }); } -Comment.initialize_vote_links = function($parent) { - $parent = $parent || $(document); - $parent.find(".unvote-comment-link").hide(); -} - $(document).ready(function() { Comment.initialize_all(); }); diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb index 645385043..e64ee90f1 100644 --- a/app/views/comments/_form.html.erb +++ b/app/views/comments/_form.html.erb @@ -1,6 +1,6 @@ <%= error_messages_for :comment %> -<%= simple_form_for(comment, :html => {:class => "edit_comment"}) do |f| %> +<%= simple_form_for(comment, :html => {:style => ("display: none;" if local_assigns[:hidden]), :class => "edit_comment"}) do |f| %> <%= f.hidden_field :post_id %> <%= dtext_field "comment", "body", :classes => "autocomplete-mentions", :value => comment.body, :input_id => "comment_body_for_#{comment.id}", :preview_id => "dtext-preview-for-#{comment.id}" %> <%= f.button :submit, "Submit" %> diff --git a/app/views/comments/edit.html.erb b/app/views/comments/edit.html.erb index 6914b6f77..b163f50a7 100644 --- a/app/views/comments/edit.html.erb +++ b/app/views/comments/edit.html.erb @@ -2,7 +2,7 @@

Edit Comment

- <%= render "comments/form", :post => @comment.post, :comment => @comment %> + <%= render "comments/form", comment: @comment %>
diff --git a/app/views/comments/partials/index/_list.html.erb b/app/views/comments/partials/index/_list.html.erb index 6cf957800..10c092ed6 100644 --- a/app/views/comments/partials/index/_list.html.erb +++ b/app/views/comments/partials/index/_list.html.erb @@ -28,7 +28,7 @@ <% if CurrentUser.is_member? %>

<%= link_to "Post comment", new_comment_path, :class => "expand-comment-response" %>

- <%= render "comments/form", :post => post, :comment => post.comments.new %> + <%= render "comments/form", comment: post.comments.new, hidden: true %>
<% end %> diff --git a/app/views/comments/partials/show/_comment.html.erb b/app/views/comments/partials/show/_comment.html.erb index a490a7b2d..5d9f9a306 100644 --- a/app/views/comments/partials/show/_comment.html.erb +++ b/app/views/comments/partials/show/_comment.html.erb @@ -35,7 +35,7 @@ <% end %> - + <% if CurrentUser.is_moderator? %>
  • |
  • @@ -46,7 +46,7 @@ <% end %> <% if comment.editable_by?(CurrentUser.user) %> - <%= render "comments/form", :post => comment.post, :comment => comment %> + <%= render "comments/form", comment: comment, hidden: true %> <% end %> <% end %> From 031cb6b8cff9007214c2675a707af0fa8d88f182 Mon Sep 17 00:00:00 2001 From: evazion Date: Thu, 9 Aug 2018 00:57:36 -0500 Subject: [PATCH 04/11] comments.js: use event delegation to bind click handlers. Use event delegation to bind click handlers so that they don't have to be rebound when comments are dynamically loaded with "Show all comments". --- app/javascript/src/javascripts/comments.js | 41 +++++++--------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/app/javascript/src/javascripts/comments.js b/app/javascript/src/javascripts/comments.js index 63ad45bc6..82c137e85 100644 --- a/app/javascript/src/javascripts/comments.js +++ b/app/javascript/src/javascripts/comments.js @@ -5,13 +5,10 @@ let Comment = {}; Comment.initialize_all = function() { if ($("#c-posts").length || $("#c-comments").length) { - this.initialize_response_link(); - this.initialize_reply_links(); + $(document).on("click", ".reply-link", Comment.quote); + $(document).on("click", ".edit_comment_link", Comment.show_edit_form); + $(document).on("click", ".expand-comment-response", Comment.show_new_comment_form); this.initialize_expand_links(); - - if (!$("#a-edit").length) { - this.initialize_edit_links(); - } } if ($("#c-posts").length && $("#a-show").length) { @@ -24,8 +21,6 @@ Comment.initialize_all = function() { } else { Comment.highlight_threshold_comments(post_id); } - Comment.initialize_reply_links(current_comment_section); - Comment.initialize_edit_links(current_comment_section); Dtext.initialize_expandables(current_comment_section); }); } @@ -49,11 +44,6 @@ Comment.quote = function(e) { e.preventDefault(); } -Comment.initialize_reply_links = function($parent) { - $parent = $parent || $(document); - $parent.find(".reply-link").click(Comment.quote); -} - Comment.initialize_expand_links = function() { $(".comment-section form").hide(); $(".comment-section input.expand-comment-response").click(function(e) { @@ -64,24 +54,17 @@ Comment.initialize_expand_links = function() { }); } -Comment.initialize_response_link = function() { - $("a.expand-comment-response").click(function(e) { - $(e.target).hide(); - var $form = $(e.target).closest("div.new-comment").find("form"); - $form.show(); - Utility.scroll_to($form); - e.preventDefault(); - }); +Comment.show_new_comment_form = function(e) { + $(e.target).hide(); + var $form = $(e.target).closest("div.new-comment").find("form"); + $form.show(); + Utility.scroll_to($form); + e.preventDefault(); } -Comment.initialize_edit_links = function($parent) { - $parent = $parent || $(document); - $parent.find(".edit_comment_link").click(function(e) { - var link_id = $(this).attr("id"); - var comment_id = link_id.match(/^edit_comment_link_(\d+)$/)[1]; - $("#edit_comment_" + comment_id).fadeToggle("fast"); - e.preventDefault(); - }); +Comment.show_edit_form = function(e) { + $(this).closest(".comment").find(".edit_comment").show(); + e.preventDefault(); } Comment.highlight_threshold_comments = function(post_id) { From 130570aa33fadb1d6b2df196274aeaa6f12de83a Mon Sep 17 00:00:00 2001 From: evazion Date: Thu, 9 Aug 2018 12:41:15 -0500 Subject: [PATCH 05/11] comments.js: fix thresholded comments. * Restore behavior of thresholded comments being greyed out (lost in 6fa0ae2cf). * Set the `below-threshold` class for thresholded comments in the html instead of in javascript. * Remove `include_below_threshold` param; it was always true when clicking "Show all comments". --- app/controllers/comments_controller.rb | 1 - app/javascript/src/javascripts/comments.js | 23 ++----------------- app/models/comment.rb | 4 ++++ app/views/comments/index_for_post.js.erb | 2 +- .../comments/partials/index/_list.html.erb | 2 +- .../comments/partials/show/_comment.html.erb | 2 +- 6 files changed, 9 insertions(+), 25 deletions(-) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 3c47bf13b..92a39c61e 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -70,7 +70,6 @@ private def index_for_post @post = Post.find(params[:post_id]) @comments = @post.comments - @comments = @comments.visible(CurrentUser.user) unless params[:include_below_threshold] render :action => "index_for_post" end diff --git a/app/javascript/src/javascripts/comments.js b/app/javascript/src/javascripts/comments.js index 82c137e85..2637b6f03 100644 --- a/app/javascript/src/javascripts/comments.js +++ b/app/javascript/src/javascripts/comments.js @@ -11,16 +11,8 @@ Comment.initialize_all = function() { this.initialize_expand_links(); } - if ($("#c-posts").length && $("#a-show").length) { - Comment.highlight_threshold_comments(Utility.meta("post-id")); - } - - $(window).on("danbooru:index_for_post", (_event, post_id, current_comment_section, include_below_threshold) => { - if (include_below_threshold) { - $("#threshold-comments-notice-for-" + post_id).hide(); - } else { - Comment.highlight_threshold_comments(post_id); - } + $(window).on("danbooru:index_for_post", (_event, post_id, current_comment_section) => { + $("#threshold-comments-notice-for-" + post_id).hide(); Dtext.initialize_expandables(current_comment_section); }); } @@ -67,17 +59,6 @@ Comment.show_edit_form = function(e) { e.preventDefault(); } -Comment.highlight_threshold_comments = function(post_id) { - var threshold = parseInt(Utility.meta("user-comment-threshold")); - var articles = $("article.comment[data-post-id=" + post_id + "]"); - articles.each(function(i, v) { - var $comment = $(v); - if (parseInt($comment.data("score")) < threshold) { - $comment.addClass("below-threshold"); - } - }); -} - Comment.hide_threshold_comments = function(post_id) { var threshold = parseInt(Utility.meta("user-comment-threshold")); var articles = $("article.comment[data-post-id=" + post_id + "]"); diff --git a/app/models/comment.rb b/app/models/comment.rb index a252d0233..0a7fcbfb6 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -189,6 +189,10 @@ class Comment < ApplicationRecord true end + def below_threshold?(user = CurrentUser.user) + score < user.comment_threshold + end + def editable_by?(user) creator_id == user.id || user.is_moderator? end diff --git a/app/views/comments/index_for_post.js.erb b/app/views/comments/index_for_post.js.erb index a58fd7168..7cea35603 100644 --- a/app/views/comments/index_for_post.js.erb +++ b/app/views/comments/index_for_post.js.erb @@ -2,4 +2,4 @@ $("#hidden-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(:partial => 'comments/partials/show/comment', :collection => @comments))%>"); -$(window).trigger("danbooru:index_for_post", [<%= @post.id %>, current_comment_section, <%= ActiveModel::Type::Boolean.new.cast(params[:include_below_threshold]) %>]); +$(window).trigger("danbooru:index_for_post", [<%= @post.id %>, current_comment_section]); diff --git a/app/views/comments/partials/index/_list.html.erb b/app/views/comments/partials/index/_list.html.erb index 10c092ed6..5c3d7193f 100644 --- a/app/views/comments/partials/index/_list.html.erb +++ b/app/views/comments/partials/index/_list.html.erb @@ -6,7 +6,7 @@
    <% if post.comments.hidden(CurrentUser.user).count > 0 || (params[:controller] == "comments" && post.comments.count > 6) %> - <%= link_to "Show all comments", comments_path(:post_id => post.id, :include_below_threshold => true), :remote => true %> + <%= link_to "Show all comments", comments_path(:post_id => post.id), :remote => true %> <% end %>
    diff --git a/app/views/comments/partials/show/_comment.html.erb b/app/views/comments/partials/show/_comment.html.erb index 5d9f9a306..d8f014098 100644 --- a/app/views/comments/partials/show/_comment.html.erb +++ b/app/views/comments/partials/show/_comment.html.erb @@ -1,6 +1,6 @@ <% if CurrentUser.is_moderator? || (params[:search] && params[:search][:is_deleted] =~ /t/) || !comment.is_deleted? %> -
    +
    " data-post-id="<%= comment.post_id %>" data-comment-id="<%= comment.id %>" data-score="<%= comment.score %>" data-creator="<%= comment.creator_name %>" data-is-sticky="<%= comment.is_sticky %>">

    <%= link_to_user comment.creator %> From 755397e6c9a81ab25e9df1b9f3c4c7b0842a1160 Mon Sep 17 00:00:00 2001 From: evazion Date: Thu, 9 Aug 2018 03:46:17 -0500 Subject: [PATCH 06/11] comments.js: remove dead code. Remove dead and hide_threshold_comments and initialize_expand_links methods. initialize_expand_links is dead because `.comment-section` doesn't exist. --- app/javascript/src/javascripts/comments.js | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/app/javascript/src/javascripts/comments.js b/app/javascript/src/javascripts/comments.js index 2637b6f03..9347e24b7 100644 --- a/app/javascript/src/javascripts/comments.js +++ b/app/javascript/src/javascripts/comments.js @@ -8,7 +8,6 @@ Comment.initialize_all = function() { $(document).on("click", ".reply-link", Comment.quote); $(document).on("click", ".edit_comment_link", Comment.show_edit_form); $(document).on("click", ".expand-comment-response", Comment.show_new_comment_form); - this.initialize_expand_links(); } $(window).on("danbooru:index_for_post", (_event, post_id, current_comment_section) => { @@ -36,16 +35,6 @@ Comment.quote = function(e) { e.preventDefault(); } -Comment.initialize_expand_links = function() { - $(".comment-section form").hide(); - $(".comment-section input.expand-comment-response").click(function(e) { - var post_id = $(this).closest(".comment-section").data("post-id"); - $(this).hide(); - $(".comment-section[data-post-id=" + post_id + "] form").slideDown("fast"); - e.preventDefault(); - }); -} - Comment.show_new_comment_form = function(e) { $(e.target).hide(); var $form = $(e.target).closest("div.new-comment").find("form"); @@ -59,17 +48,6 @@ Comment.show_edit_form = function(e) { e.preventDefault(); } -Comment.hide_threshold_comments = function(post_id) { - var threshold = parseInt(Utility.meta("user-comment-threshold")); - var articles = $("article.comment[data-post-id=" + post_id + "]"); - articles.each(function(i, v) { - var $comment = $(v); - if (parseInt($comment.data("score")) < threshold) { - $comment.hide(); - } - }); -} - $(document).ready(function() { Comment.initialize_all(); }); From d369d384190cb55da0cf959b0b4ad6e9205171b6 Mon Sep 17 00:00:00 2001 From: evazion Date: Sat, 11 Aug 2018 16:36:25 -0500 Subject: [PATCH 07/11] shortcuts.js: Add declarative `data-shortcut` keyboard shortcuts. --- app/javascript/packs/application.js | 1 + app/javascript/src/javascripts/shortcuts.js | 35 +++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 395020c6d..f0eeef6f0 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -38,4 +38,5 @@ export { default as Note } from '../src/javascripts/notes.js'; export { default as PostModeMenu } from '../src/javascripts/post_mode_menu.js'; export { default as Utility } from '../src/javascripts/utility.js'; export { default as Ugoira } from '../src/javascripts/ugoira.js'; +export { default as Shortcuts } from '../src/javascripts/shortcuts.js'; export { default as TagScript } from '../src/javascripts/tag_script.js'; diff --git a/app/javascript/src/javascripts/shortcuts.js b/app/javascript/src/javascripts/shortcuts.js index 5cdc09666..444854ca5 100644 --- a/app/javascript/src/javascripts/shortcuts.js +++ b/app/javascript/src/javascripts/shortcuts.js @@ -6,6 +6,7 @@ let Shortcuts = {}; Shortcuts.initialize = function() { Utility.keydown("s", "scroll_down", Shortcuts.nav_scroll_down); Utility.keydown("w", "scroll_up", Shortcuts.nav_scroll_up); + Shortcuts.initialize_data_shortcuts(); Utility.keydown("q", "focus_search", function(e) { $("#tags, #search_name, #search_name_matches, #query").trigger("focus").selectEnd(); @@ -39,6 +40,40 @@ Shortcuts.initialize = function() { } } +// Bind keyboard shortcuts to links that have a `data-shortcut="..."` attribute. If multiple links have the +// same shortcut, then only the first link will be triggered by the shortcut. +// +// Add `data-shortcut-when="$selector"`, where `selector` is any valid jQuery selector, to make the shortcut +// active only when the link matches the selector. For example, `data-shortcut-when=":visible"` makes the +// shortcut apply only when the link is visible. +Shortcuts.initialize_data_shortcuts = function() { + $(document).off("keydown.danbooru.shortcut"); + + $("[data-shortcut]").each((_i, element) => { + const id = $(element).attr("id"); + const keys = $(element).attr("data-shortcut"); + const namespace = `shortcut.${id}`; + + const title = `Shortcut is ${keys.split(/\s+/).join(" or ")}`; + $(element).attr("title", title); + + Utility.keydown(keys, namespace, event => { + const e = $(`[data-shortcut="${keys}"]`).get(0); + const condition = $(e).attr("data-shortcut-when") || "*"; + + if ($(e).is(condition)) { + if ($(e).is("input, textarea")) { + e.focus(); + } else { + e.click(); + } + + event.preventDefault(); + } + }); + }); +}; + Shortcuts.nav_scroll_down = function() { var scroll_top = $(window).scrollTop() + ($(window).height() * 0.15); $(window).scrollTop(scroll_top); From bbaadda1e3af61179d2fdebe390dbe660ac82b1e Mon Sep 17 00:00:00 2001 From: evazion Date: Sat, 11 Aug 2018 16:39:45 -0500 Subject: [PATCH 08/11] Convert keyboard shortcuts to use `data-shortcut`. --- app/helpers/pagination_helper.rb | 8 ++-- app/javascript/src/javascripts/artists.js | 15 ------- .../src/javascripts/favorite_groups.js | 16 -------- app/javascript/src/javascripts/forum_posts.js | 16 -------- app/javascript/src/javascripts/notes.js | 6 +-- app/javascript/src/javascripts/paginator.js | 26 ------------ app/javascript/src/javascripts/pools.js | 18 -------- .../src/javascripts/post_popular.js | 38 ----------------- app/javascript/src/javascripts/posts.js.erb | 41 +++++-------------- app/javascript/src/javascripts/shortcuts.js | 32 --------------- app/javascript/src/javascripts/uploads.js | 9 ---- app/javascript/src/javascripts/wiki_pages.js | 25 ----------- app/presenters/post_set_presenters/popular.rb | 6 ++- app/views/artists/_secondary_links.html.erb | 4 +- .../_add_to_favgroup_dialog.html.erb | 3 +- app/views/favorites/index.html.erb | 2 +- .../forum_topics/_secondary_links.html.erb | 6 +-- app/views/pools/_secondary_links.html.erb | 4 +- .../posts/partials/common/_search.html.erb | 4 +- .../posts/partials/index/_related.html.erb | 2 +- app/views/posts/partials/show/_edit.html.erb | 2 +- .../posts/partials/show/_options.html.erb | 10 ++--- app/views/posts/show.html.erb | 2 +- app/views/uploads/new.html.erb | 4 +- .../wiki_pages/_secondary_links.html.erb | 4 +- 25 files changed, 44 insertions(+), 259 deletions(-) delete mode 100644 app/javascript/src/javascripts/paginator.js delete mode 100644 app/javascript/src/javascripts/post_popular.js delete mode 100644 app/javascript/src/javascripts/wiki_pages.js diff --git a/app/helpers/pagination_helper.rb b/app/helpers/pagination_helper.rb index 855b507f6..a0e71a619 100644 --- a/app/helpers/pagination_helper.rb +++ b/app/helpers/pagination_helper.rb @@ -4,11 +4,11 @@ module PaginationHelper if records.any? if params[:page] =~ /[ab]/ && !records.is_first_page? - html << '
  • ' + link_to("< Previous", nav_params_for("a#{records[0].id}"), :rel => "prev") + '
  • ' + html << '
  • ' + link_to("< Previous", nav_params_for("a#{records[0].id}"), rel: "prev", "data-shortcut": "a left") + '
  • ' end unless records.is_last_page? - html << '
  • ' + link_to("Next >", nav_params_for("b#{records[-1].id}"), :rel => "next") + '
  • ' + html << '
  • ' + link_to("Next >", nav_params_for("b#{records[-1].id}"), rel: "next", "data-shortcut": "d right") + '
  • ' end end @@ -29,7 +29,7 @@ module PaginationHelper window = 4 if records.current_page >= 2 - html << "
  • " + link_to(content_tag(:i, nil, class: "fas fa-chevron-left"), nav_params_for(records.current_page - 1), :rel => "prev") + "
  • " + html << "
  • " + link_to(content_tag(:i, nil, class: "fas fa-chevron-left"), nav_params_for(records.current_page - 1), rel: "prev", "data-shortcut": "a left") + "
  • " else html << "
  • " + content_tag(:i, nil, class: "fas fa-chevron-left") + "
  • " end @@ -69,7 +69,7 @@ module PaginationHelper end if records.current_page < records.total_pages && records.size > 0 - html << "
  • " + link_to(content_tag(:i, nil, class: "fas fa-chevron-right"), nav_params_for(records.current_page + 1), :rel => "next") + "
  • " + html << "
  • " + link_to(content_tag(:i, nil, class: "fas fa-chevron-right"), nav_params_for(records.current_page + 1), rel: "next", "data-shortcut": "d right") + "
  • " else html << "
  • " + content_tag(:i, nil, class: "fas fa-chevron-right") + "
  • " end diff --git a/app/javascript/src/javascripts/artists.js b/app/javascript/src/javascripts/artists.js index 83a8784df..8024cf9bf 100644 --- a/app/javascript/src/javascripts/artists.js +++ b/app/javascript/src/javascripts/artists.js @@ -1,11 +1,8 @@ -import Utility from "./utility"; - let Artist = {}; Artist.initialize_all = function() { if ($("#c-artists").length) { Artist.initialize_check_name(); - Artist.initialize_shortcuts(); } } @@ -29,18 +26,6 @@ Artist.initialize_check_name = function() { }); } -Artist.initialize_shortcuts = function() { - if ($("#c-artists #a-show").length) { - Utility.keydown("e", "edit", function(e) { - $("#artist-edit a")[0].click(); - }); - - Utility.keydown("shift+d", "delete", function(e) { - $("#artist-delete a")[0].click(); - }); - } -}; - $(document).ready(function() { Artist.initialize_all(); }); diff --git a/app/javascript/src/javascripts/favorite_groups.js b/app/javascript/src/javascripts/favorite_groups.js index 5445ed1e8..3aa7b6153 100644 --- a/app/javascript/src/javascripts/favorite_groups.js +++ b/app/javascript/src/javascripts/favorite_groups.js @@ -1,11 +1,8 @@ -import Utility from './utility' - let FavoriteGroup = {}; FavoriteGroup.initialize_all = function() { if ($("#c-posts").length && $("#a-show").length) { this.initialize_add_to_favgroup_dialog(); - Utility.keydown("1 2 3 4 5 6 7 8 9 0", "add_to_favgroup", FavoriteGroup.add_to_favgroup); } } @@ -21,10 +18,6 @@ FavoriteGroup.initialize_add_to_favgroup_dialog = function() { }); var open_favgroup_dialog = function(e) { - if (Utility.meta("current-user-id") === "") { // anonymous - return; - } - if ($(".add-to-favgroup").length === 1) { // If the user only has one favorite group we don't need to ask which group to add the post to. $(".add-to-favgroup").click(); @@ -34,18 +27,9 @@ FavoriteGroup.initialize_add_to_favgroup_dialog = function() { e.preventDefault(); } - Utility.keydown("g", "open_favgroup_dialog", open_favgroup_dialog); $("#open-favgroup-dialog-link").click(open_favgroup_dialog); } -FavoriteGroup.add_to_favgroup = function(e) { - var favgroup_index = (e.key === "0") ? "10" : e.key; - var link = $("#add-to-favgroup-" + favgroup_index + ":visible"); - if (link.length) { - link.click(); - } -} - $(function() { FavoriteGroup.initialize_all(); }); diff --git a/app/javascript/src/javascripts/forum_posts.js b/app/javascript/src/javascripts/forum_posts.js index ec855934d..d63d11f98 100644 --- a/app/javascript/src/javascripts/forum_posts.js +++ b/app/javascript/src/javascripts/forum_posts.js @@ -1,24 +1,8 @@ -import Utility from './utility' - let ForumPost = {}; ForumPost.initialize_all = function() { if ($("#c-forum-topics #a-show,#c-forum-posts #a-show").length) { this.initialize_edit_links(); - - Utility.keydown("e", "edit", function(e) { - $(".edit_forum_topic_link")[0].click(); - }); - - Utility.keydown("shift+d", "delete", function(e) { - $("#forum-topic-delete a")[0].click(); - }); - } - - if ($("#c-forum-topics").length) { - Utility.keydown("shift+r", "mark_all_as_read", function(e) { - $("#forum-topic-mark-all-as-read a")[0].click(); - }); } } diff --git a/app/javascript/src/javascripts/notes.js b/app/javascript/src/javascripts/notes.js index f4ce1d95d..43f4a6586 100644 --- a/app/javascript/src/javascripts/notes.js +++ b/app/javascript/src/javascripts/notes.js @@ -806,11 +806,7 @@ let Note = { }, initialize_shortcuts: function() { - if ($("#note-locked-notice").length === 0) { - $("#translate").click(Note.TranslationMode.toggle); - Utility.keydown("n", "translation_mode", Note.TranslationMode.toggle); - } - + $("#translate").click(Note.TranslationMode.toggle); $("#image").click(Note.Box.toggle_all); }, diff --git a/app/javascript/src/javascripts/paginator.js b/app/javascript/src/javascripts/paginator.js deleted file mode 100644 index 5a00e6726..000000000 --- a/app/javascript/src/javascripts/paginator.js +++ /dev/null @@ -1,26 +0,0 @@ -import Utility from './utility' - -let Paginator = {}; - -Paginator.next_page = function() { - var href = $(".paginator a[rel=next]").attr("href"); - if (href) { - window.location = href; - } -} - -Paginator.prev_page = function() { - var href = $(".paginator a[rel=prev]").attr("href"); - if (href) { - window.location = href; - } -} - -$(function() { - if ($(".paginator").length) { - Utility.keydown("d right", "next_page", Paginator.next_page); - Utility.keydown("a left", "prev_page", Paginator.prev_page); - } -}); - -export default Paginator diff --git a/app/javascript/src/javascripts/pools.js b/app/javascript/src/javascripts/pools.js index 67fe3986a..8e9cd5209 100644 --- a/app/javascript/src/javascripts/pools.js +++ b/app/javascript/src/javascripts/pools.js @@ -1,12 +1,6 @@ -import Utility from './utility' - let Pool = {}; Pool.initialize_all = function() { - if ($("#c-pools").length) { - this.initialize_shortcuts(); - } - if ($("#c-posts").length && $("#a-show").length) { this.initialize_add_to_pool_link(); } @@ -30,18 +24,6 @@ Pool.initialize_add_to_pool_link = function() { }); } -Pool.initialize_shortcuts = function() { - if ($("#c-pools #a-show").length) { - Utility.keydown("e", "edit", function(e) { - $("#pool-edit a")[0].click(); - }); - - Utility.keydown("shift+d", "delete", function(e) { - $("#pool-delete a")[0].click(); - }); - } -}; - Pool.initialize_simple_edit = function() { $("#sortable").sortable({ placeholder: "ui-state-placeholder" diff --git a/app/javascript/src/javascripts/post_popular.js b/app/javascript/src/javascripts/post_popular.js deleted file mode 100644 index a783adb3b..000000000 --- a/app/javascript/src/javascripts/post_popular.js +++ /dev/null @@ -1,38 +0,0 @@ -import Utility from './utility' - -let PostPopular = {}; - -PostPopular.nav_prev = function(e) { - if ($("#popular-nav-links").length) { - var href = $("#popular-nav-links a[rel=prev]").attr("href"); - if (href) { - location.href = href; - } - } - - e.preventDefault(); -} - -PostPopular.nav_next = function(e) { - if ($("#popular-nav-links").length) { - var href = $("#popular-nav-links a[rel=next]").attr("href"); - if (href) { - location.href = href; - } - } - - e.preventDefault(); -} - -PostPopular.initialize_all = function() { - if ($("#c-explore-posts").length) { - Utility.keydown("a left", "prev_page", PostPopular.nav_prev); - Utility.keydown("d right", "next_page", PostPopular.nav_next); - } -} - -$(document).ready(function() { - PostPopular.initialize_all(); -}); - -export default PostPopular diff --git a/app/javascript/src/javascripts/posts.js.erb b/app/javascript/src/javascripts/posts.js.erb index 8c8f409f8..18ecb592c 100644 --- a/app/javascript/src/javascripts/posts.js.erb +++ b/app/javascript/src/javascripts/posts.js.erb @@ -95,6 +95,17 @@ Post.initialize_edit_dialog = function() { } Post.open_edit_dialog = function() { + if ($("#edit-dialog").length === 1) { + return; + } + + $("#edit").show(); + $("#comments").hide(); + $("#share").hide(); + $("#post-sections li").removeClass("active"); + $("#post-edit-link").parent("li").addClass("active"); + $("#related-tags-container").show(); + var $tag_string = $("#post_tag_string,#upload_tag_string"); $("div.input").has($tag_string).prevAll().hide(); $("#open-edit-dialog").hide(); @@ -230,22 +241,8 @@ Post.swipe_next = function(e) { Post.initialize_shortcuts = function() { if ($("#a-show").length) { - Utility.keydown("e", "edit", function(e) { - $("#post-edit-link").trigger("click"); - $("#post_tag_string").focus(); - e.preventDefault(); - }); - - if (Utility.meta("current-user-can-approve-posts") === "true") { - Utility.keydown("shift+o", "approve", function(e) { - $(".approve-link").click(); - }); - } - Utility.keydown("a", "prev_page", Post.nav_prev); Utility.keydown("d", "next_page", Post.nav_next); - Utility.keydown("f", "favorite", Post.favorite); - Utility.keydown("shift+f", "unfavorite", Post.unfavorite); } } @@ -586,22 +583,6 @@ Post.approve = function(post_id) { }); } -Post.favorite = function (e) { - if ($("#add-to-favorites").is(":visible")) { - $("#add-to-favorites")[0].click(); - } else if (Utility.meta("current-user-id") === "") { - $(window).trigger("danbooru:notice", "You must be logged in to favorite posts"); - } else { - $(window).trigger("danbooru:notice", "You have already favorited this post"); - } -}; - -Post.unfavorite = function (e) { - $.ajax("/favorites/" + Utility.meta("post-id") + ".js", { - type: "DELETE" - }); -}; - Post.initialize_saved_searches = function() { $("#new_saved_search #saved_search_label_string").autocomplete({ search: function() { diff --git a/app/javascript/src/javascripts/shortcuts.js b/app/javascript/src/javascripts/shortcuts.js index 444854ca5..476ed6be7 100644 --- a/app/javascript/src/javascripts/shortcuts.js +++ b/app/javascript/src/javascripts/shortcuts.js @@ -1,5 +1,4 @@ import Utility from './utility' -import Post from './posts.js.erb' let Shortcuts = {}; @@ -7,37 +6,6 @@ Shortcuts.initialize = function() { Utility.keydown("s", "scroll_down", Shortcuts.nav_scroll_down); Utility.keydown("w", "scroll_up", Shortcuts.nav_scroll_up); Shortcuts.initialize_data_shortcuts(); - - Utility.keydown("q", "focus_search", function(e) { - $("#tags, #search_name, #search_name_matches, #query").trigger("focus").selectEnd(); - e.preventDefault(); - }); - - if ($("#image").length) { // post page or bookmarklet upload page - Utility.keydown("shift+e", "edit_dialog", function(e) { - if (Utility.meta("current-user-id") === "") { // anonymous - return; - } - - if (!$("#edit-dialog").length) { - $("#edit").show(); - $("#comments").hide(); - $("#share").hide(); - $("#post-sections li").removeClass("active"); - $("#post-edit-link").parent("li").addClass("active"); - $("#related-tags-container").show(); - - Post.open_edit_dialog(); - } - e.preventDefault(); - }); - } - - if ($("#c-posts #a-index, #c-favorites #a-index").length) { - Utility.keydown("r", "random", function(e) { - $("#random-post")[0].click(); - }); - } } // Bind keyboard shortcuts to links that have a `data-shortcut="..."` attribute. If multiple links have the diff --git a/app/javascript/src/javascripts/uploads.js b/app/javascript/src/javascripts/uploads.js index 99ef33de8..3a8649d41 100644 --- a/app/javascript/src/javascripts/uploads.js +++ b/app/javascript/src/javascripts/uploads.js @@ -1,4 +1,3 @@ -import Utility from './utility' import Post from './posts.js.erb' import RelatedTag from './related_tag.js.erb' @@ -18,7 +17,6 @@ Upload.initialize_all = function() { } this.initialize_info_bookmarklet(); this.initialize_similar(); - this.initialize_shortcuts(); this.initialize_submit(); $("#related-tags-button").trigger("click"); @@ -55,13 +53,6 @@ Upload.initialize_submit = function() { }); } -Upload.initialize_shortcuts = function() { - Utility.keydown("e", "edit", function(e) { - $("#upload_tag_string").focus(); - e.preventDefault(); - }); -}; - Upload.initialize_iqdb_source = function() { if (/^https?:\/\//.test($("#normalized_url").val())) { $.get("/iqdb_queries", {"url": $("#normalized_url").val()}).done(function(html) {$("#iqdb-similar").html(html)}); diff --git a/app/javascript/src/javascripts/wiki_pages.js b/app/javascript/src/javascripts/wiki_pages.js deleted file mode 100644 index 637d9929e..000000000 --- a/app/javascript/src/javascripts/wiki_pages.js +++ /dev/null @@ -1,25 +0,0 @@ -import Utility from './utility' - -let WikiPage = {}; - -WikiPage.initialize_all = function() { - if ($("#c-wiki-pages,#c-wiki-page-versions").length) { - this.initialize_shortcuts(); - } -} - -WikiPage.initialize_shortcuts = function() { - if ($("#a-show").length) { - Utility.keydown("e", "edit", function(e) { - $("#wiki-page-edit a")[0].click(); - }); - - Utility.keydown("shift+d", "delete", function(e) { - $("#wiki-page-delete a")[0].click(); - }); - } -} - -$(document).ready(function() { - WikiPage.initialize_all(); -}); diff --git a/app/presenters/post_set_presenters/popular.rb b/app/presenters/post_set_presenters/popular.rb index db95f8c7a..6d7012fa3 100644 --- a/app/presenters/post_set_presenters/popular.rb +++ b/app/presenters/post_set_presenters/popular.rb @@ -76,7 +76,8 @@ module PostSetPresenters :date => prev_date_for_scale(scale), :scale => scale.downcase ), - :rel => (link_rel_for_scale?(template, scale.downcase) ? "prev" : nil) + :rel => (link_rel_for_scale?(template, scale.downcase) ? "prev" : nil), + :"data-shortcut" => (link_rel_for_scale?(template, scale.downcase) ? "a left" : nil) ) html << template.link_to( scale, @@ -92,7 +93,8 @@ module PostSetPresenters :date => next_date_for_scale(scale), :scale => scale.downcase ), - :rel => (link_rel_for_scale?(template, scale.downcase) ? "next" : nil) + :rel => (link_rel_for_scale?(template, scale.downcase) ? "next" : nil), + :"data-shortcut" => (link_rel_for_scale?(template, scale.downcase) ? "d right" : nil) ) html << '' html.join("\n").html_safe diff --git a/app/views/artists/_secondary_links.html.erb b/app/views/artists/_secondary_links.html.erb index 496fb339d..f375ff65d 100644 --- a/app/views/artists/_secondary_links.html.erb +++ b/app/views/artists/_secondary_links.html.erb @@ -10,12 +10,12 @@
  • <%= link_to "Posts (#{Post.fast_count(@artist.name)})", posts_path(:tags => @artist.name) %>
  • <%= link_to "Show", artist_path(@artist) %>
  • <% if CurrentUser.is_member? %> -
  • <%= link_to "Edit", edit_artist_path(@artist) %>
  • +
  • <%= link_to "Edit", edit_artist_path(@artist), :"data-shortcut" => "e" %>
  • <% end %>
  • <%= link_to "History", artist_versions_path(:search => {:artist_id => @artist.id}) %>
  • <% if @artist.deletable_by?(CurrentUser.user) %> <% if @artist.is_active? %> -
  • <%= link_to "Delete", artist_path(@artist), method: :delete, data: {confirm: "Are you sure you want to delete this artist?"} %>
  • +
  • <%= link_to "Delete", artist_path(@artist), method: :delete, "data-shortcut": "shift+d", "data-confirm": "Are you sure you want to delete this artist?" %>
  • <% else %>
  • <%= link_to "Undelete", artist_path(@artist, format: "js"), method: :put, data: {confirm: "Are you sure you want to undelete this artist?", params: "artist[is_active]=true"}, remote: true %>
  • <% end %> diff --git a/app/views/favorite_groups/_add_to_favgroup_dialog.html.erb b/app/views/favorite_groups/_add_to_favgroup_dialog.html.erb index 428c9a7fe..48b35c55e 100644 --- a/app/views/favorite_groups/_add_to_favgroup_dialog.html.erb +++ b/app/views/favorite_groups/_add_to_favgroup_dialog.html.erb @@ -6,6 +6,7 @@ <%= link_to favgroup.name, add_post_favorite_group_path(favgroup, :post_id => post.id, :format => :js), :id => "add-to-favgroup-#{i + 1}", :class => "add-to-favgroup", - :method => :put, :remote => true %> + :method => :put, :remote => true, + :"data-shortcut" => (i + 1) % 10, :"data-shortcut-when" => ":visible" %>

    <% end %> diff --git a/app/views/favorites/index.html.erb b/app/views/favorites/index.html.erb index 57d41aa46..630e0fcbe 100644 --- a/app/views/favorites/index.html.erb +++ b/app/views/favorites/index.html.erb @@ -17,7 +17,7 @@ diff --git a/app/views/forum_topics/_secondary_links.html.erb b/app/views/forum_topics/_secondary_links.html.erb index 1e1c0d846..4d727ba64 100644 --- a/app/views/forum_topics/_secondary_links.html.erb +++ b/app/views/forum_topics/_secondary_links.html.erb @@ -7,7 +7,7 @@
  • <%= link_to "New", new_forum_topic_path %>
  • <%= link_to "Request alias", new_tag_alias_request_path %>
  • <%= link_to "Request implication", new_tag_implication_request_path %>
  • -
  • <%= link_to "Mark all as read", mark_all_as_read_forum_topics_path, :method => :post %>
  • +
  • <%= link_to "Mark all as read", mark_all_as_read_forum_topics_path, :method => :post, :"data-shortcut" => "shift+r" %>
  • <% end %>
  • <%= link_to "Search", search_forum_posts_path %>
  • @@ -21,12 +21,12 @@
  • <%= link_to "Subscribe", subscribe_forum_topic_path(@forum_topic), :method => :post, :data => {:confirm => "Are you sure you want to receive email notifications for this forum topic?"} %>
  • <% end %> <% if !@forum_topic.new_record? && @forum_topic.editable_by?(CurrentUser.user) %> -
  • <%= link_to "Edit", edit_forum_topic_path(@forum_topic) %>
  • +
  • <%= link_to "Edit", edit_forum_topic_path(@forum_topic), "data-shortcut": "e" %>
  • <% if CurrentUser.is_moderator? %> <% if @forum_topic.is_deleted? %>
  • <%= link_to "Undelete", undelete_forum_topic_path(@forum_topic), :method => :post %>
  • <% else %> -
  • <%= link_to "Delete", forum_topic_path(@forum_topic), :method => :delete, :data => {:confirm => "Are you sure you want to delete this forum topic?"} %>
  • +
  • <%= link_to "Delete", forum_topic_path(@forum_topic), :method => :delete, :"data-shortcut" => "shift+d", :"data-confirm" => "Are you sure you want to delete this forum topic?" %>
  • <% end %> <% if @forum_topic.is_locked? %>
  • <%= link_to "Unlock", forum_topic_path(@forum_topic, :forum_topic => {:is_locked => false}), :method => :put %>
  • diff --git a/app/views/pools/_secondary_links.html.erb b/app/views/pools/_secondary_links.html.erb index 39e5c4d2e..ac2272b4c 100644 --- a/app/views/pools/_secondary_links.html.erb +++ b/app/views/pools/_secondary_links.html.erb @@ -10,13 +10,13 @@
  • <%= link_to "Show", pool_path(@pool) %>
  • <%= link_to "Posts", posts_path(:tags => "pool:#{@pool.id}") %>
  • <% if CurrentUser.is_member? %> -
  • <%= link_to "Edit", edit_pool_path(@pool) %>
  • +
  • <%= link_to "Edit", edit_pool_path(@pool), "data-shortcut": "e" %>
  • <% end %> <% if @pool.deletable_by?(CurrentUser.user) %> <% if @pool.is_deleted? %>
  • <%= link_to "Undelete", undelete_pool_path(@pool), :method => :post, :remote => true %>
  • <% else %> -
  • <%= link_to "Delete", pool_path(@pool), :method => :delete, :data => {:confirm => "Are you sure you want to delete this pool?"}, :remote => true %>
  • +
  • <%= link_to "Delete", pool_path(@pool), :method => :delete, :"data-shortcut" => "shift+d", :"data-confirm" => "Are you sure you want to delete this pool?", :remote => true %>
  • <% end %> <% end %> <% if PoolArchive.enabled? %> diff --git a/app/views/posts/partials/common/_search.html.erb b/app/views/posts/partials/common/_search.html.erb index 7229bc50f..aa2f80fd7 100644 --- a/app/views/posts/partials/common/_search.html.erb +++ b/app/views/posts/partials/common/_search.html.erb @@ -12,7 +12,7 @@ <% if params[:random] %> <%= hidden_field_tag :random, params[:random] %> <% end %> - <%= text_field_tag("tags", tags, :id => tags_dom_id, :data => { :autocomplete => "tag-query" }) %><%= content_tag "button", content_tag("i", nil, class: "fas fa-search"), type: "submit" %> + <%= text_field_tag("tags", tags, :id => tags_dom_id, :"data-shortcut" => "q", :"data-autocomplete" => "tag-query") %><%= content_tag "button", content_tag("i", nil, class: "fas fa-search"), type: "submit" %> <%= hidden_field_tag "ms", "1" %> <% end %> @@ -31,4 +31,4 @@ }); });*/ -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/posts/partials/index/_related.html.erb b/app/views/posts/partials/index/_related.html.erb index 8d69bfdd9..13a9021eb 100644 --- a/app/views/posts/partials/index/_related.html.erb +++ b/app/views/posts/partials/index/_related.html.erb @@ -14,7 +14,7 @@
  • <%= link_to "Deleted", posts_path(:tags => "#{params[:tags]} status:deleted"), :rel => "nofollow" %>
  • -
  • <%= link_to "Random", random_posts_path(:tags => params[:tags]), :id => "random-post", :rel => "nofollow" %>
  • +
  • <%= link_to "Random", random_posts_path(:tags => params[:tags]), :id => "random-post", :rel => "nofollow", :"data-shortcut" => "r" %>
  • <%= link_to "Count", posts_counts_path(:tags => params[:tags]) %>
  • diff --git a/app/views/posts/partials/show/_edit.html.erb b/app/views/posts/partials/show/_edit.html.erb index 1bbed2490..f70a07af4 100644 --- a/app/views/posts/partials/show/_edit.html.erb +++ b/app/views/posts/partials/show/_edit.html.erb @@ -80,7 +80,7 @@
    <%= f.label :tag_string, "Tags" %> <%= f.text_area :tag_string, :size => "50x5", :value => post.presenter.categorized_tag_string + " ", :data => { :autocomplete => "tag-edit" } %> -
    <%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> diff --git a/app/views/posts/partials/show/_options.html.erb b/app/views/posts/partials/show/_options.html.erb index 80c227a4f..d2230acc5 100644 --- a/app/views/posts/partials/show/_options.html.erb +++ b/app/views/posts/partials/show/_options.html.erb @@ -2,20 +2,20 @@
  • <%= link_to "Resize to window", "#", :id => "image-resize-to-window-link" %>
  • <% if CurrentUser.is_member? %> -
  • <%= link_to "Favorite", favorites_path(:post_id => post.id), :remote => true, :method => :post, :id => "add-to-favorites", :title => "Shortcut is F" %>
  • -
  • <%= link_to "Unfavorite", favorite_path(post), :remote => true, :method => :delete, :id => "remove-from-favorites" %>
  • +
  • <%= link_to "Favorite", favorites_path(:post_id => post.id), :remote => true, :method => :post, :id => "add-to-favorites", :"data-shortcut" => "f" %>
  • +
  • <%= link_to "Unfavorite", favorite_path(post), :remote => true, :method => :delete, :id => "remove-from-favorites", :"data-shortcut" => "shift+f" %>
  • <%= link_to_if post.visible?, "Download", post.tagged_file_url + "?download=1", download: post.presenter.filename_for_download %>
  • <%= link_to "Add to pool", "#", :id => "pool" %>
  • <% if post.is_note_locked? %>
  • Note locked
  • <% else %> -
  • <%= link_to "Add note", "#", :id => "translate", :title => "Shortcut is N" %>
  • +
  • <%= link_to "Add note", "#", :id => "translate", :"data-shortcut" => "n" %>
  • <% end %> <% if CurrentUser.is_builder? && post.has_notes? %>
  • <%= link_to "Copy notes", "#", :id => "copy-notes" %>
  • <% end %>
  • <%= link_to "Add commentary", "#", :id => "add-commentary" %>
  • -
  • <%= link_to "Add to favorite group", "#", :id => "open-favgroup-dialog-link" %>
  • +
  • <%= link_to "Add to favorite group", "#", :id => "open-favgroup-dialog-link", :"data-shortcut" => "g" %>
  • <%= link_to "Find similar", iqdb_queries_path(:post_id => post.id) %>
  • <% if post.is_status_locked? %> @@ -40,7 +40,7 @@ <% end %> <% if post.is_flagged? || post.is_pending? %> -
  • <%= link_to "Approve", moderator_post_approval_path(:post_id => post.id), :remote => true, :method => :post, :id => "approve", :data => { :confirm => "Are you sure you want to approve this post?" } %>
  • +
  • <%= link_to "Approve", moderator_post_approval_path(:post_id => post.id), :remote => true, :method => :post, :id => "approve", :"data-shortcut" => "shift+o", :"data-confirm" => "Are you sure you want to approve this post?" %>
  • <% else %>
  • <%= link_to "Hide from queue", moderator_post_disapproval_path(post_disapproval: { post_id: post.id, reason: "disinterest" }), remote: true, method: :post, id: "disapprove" %>
  • <% end %> diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index 069f7a343..b6c02c7c8 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -94,7 +94,7 @@ <% end %> <% if CurrentUser.is_member? && @post.visible? %> -
  • Edit
  • +
  • Edit
  • <% end %>
  • Share
  • diff --git a/app/views/uploads/new.html.erb b/app/views/uploads/new.html.erb index e17750c55..78a0b90be 100644 --- a/app/views/uploads/new.html.erb +++ b/app/views/uploads/new.html.erb @@ -111,8 +111,8 @@
    <%= f.label :tag_string, "Tags" %> - <%= f.text_area :tag_string, :size => "60x5", :spellcheck => false, :data => { :autocomplete => "tag-edit" } %> -
    <%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> diff --git a/app/views/wiki_pages/_secondary_links.html.erb b/app/views/wiki_pages/_secondary_links.html.erb index a95eb10d0..5cefde78f 100644 --- a/app/views/wiki_pages/_secondary_links.html.erb +++ b/app/views/wiki_pages/_secondary_links.html.erb @@ -18,10 +18,10 @@
  • <%= link_to "Posts (#{@wiki_page.tag.try(:post_count) || 0})", posts_path(:tags => @wiki_page.title) %>
  • <%= link_to "History", wiki_page_versions_path(:search => {:wiki_page_id => @wiki_page.id}) %>
  • <% if CurrentUser.is_member? %> -
  • <%= link_to "Edit", edit_wiki_page_path(@wiki_page) %>
  • +
  • <%= link_to "Edit", edit_wiki_page_path(@wiki_page), "data-shortcut": "e" %>
  • <% end %> <% if CurrentUser.is_builder? && !@wiki_page.is_deleted? %> -
  • <%= link_to "Delete", wiki_page_path(@wiki_page), :remote => true, :method => :delete, :data => {:confirm => "Are you sure you want to delete this wiki page?"} %>
  • +
  • <%= link_to "Delete", wiki_page_path(@wiki_page), :remote => true, :method => :delete, :"data-shortcut" => "shift+d", :"data-confirm" => "Are you sure you want to delete this wiki page?" %>
  • <% end %> <% elsif @wiki_page_version %>
  • |
  • From 202527008f49309c207d775e40a7da81bdb58d39 Mon Sep 17 00:00:00 2001 From: evazion Date: Sun, 12 Aug 2018 12:35:15 -0500 Subject: [PATCH 09/11] user.rb: drop unused add_favorite!, delete_favorite! methods. These methods were incorrect anyway, didn't upvote/downvote the post. --- app/models/user.rb | 16 +--------------- test/unit/favorite_test.rb | 12 ++++++------ 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 6eb6937d5..85aef23bd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -108,6 +108,7 @@ class User < ApplicationRecord has_many :forum_posts, -> {order("forum_posts.created_at, forum_posts.id")}, :foreign_key => "creator_id" has_many :user_name_change_requests, -> {visible.order("user_name_change_requests.created_at desc")} has_many :favorite_groups, -> {order(name: :asc)}, foreign_key: :creator_id + has_many :favorites, ->(rec) {where("user_id % 100 = #{rec.id % 100} and user_id = #{rec.id}").order("id desc")} belongs_to :inviter, class_name: "User", optional: true after_update :create_mod_action accepts_nested_attributes_for :dmail_filter @@ -297,20 +298,6 @@ class User < ApplicationRecord end end - module FavoriteMethods - def favorites - Favorite.where("user_id % 100 = #{id % 100} and user_id = #{id}").order("id desc") - end - - def add_favorite!(post) - Favorite.add(post: post, user: self) - end - - def remove_favorite!(post) - Favorite.remove(post: post, user: self) - end - end - module LevelMethods extend ActiveSupport::Concern @@ -917,7 +904,6 @@ class User < ApplicationRecord include NameMethods include PasswordMethods include AuthenticationMethods - include FavoriteMethods include LevelMethods include EmailMethods include BlacklistMethods diff --git a/test/unit/favorite_test.rb b/test/unit/favorite_test.rb index 0d52f0db4..6bbdb4d10 100644 --- a/test/unit/favorite_test.rb +++ b/test/unit/favorite_test.rb @@ -18,7 +18,7 @@ class FavoriteTest < ActiveSupport::TestCase user1 = FactoryBot.create(:user) p1 = FactoryBot.create(:post) - user1.add_favorite!(p1) + p1.add_favorite!(user1) assert_equal(1, Favorite.count) Favorite.where(:user_id => user1.id, :post_id => p1.id).delete_all @@ -31,9 +31,9 @@ class FavoriteTest < ActiveSupport::TestCase p1 = FactoryBot.create(:post) p2 = FactoryBot.create(:post) - user1.add_favorite!(p1) - user1.add_favorite!(p2) - user2.add_favorite!(p1) + p1.add_favorite!(user1) + p2.add_favorite!(user1) + p1.add_favorite!(user2) favorites = user1.favorites.order("id desc") assert_equal(2, favorites.count) @@ -49,8 +49,8 @@ class FavoriteTest < ActiveSupport::TestCase user1 = FactoryBot.create(:user) p1 = FactoryBot.create(:post) p2 = FactoryBot.create(:post) - user1.add_favorite!(p1) - user1.add_favorite!(p1) + p1.add_favorite!(user1) + p1.add_favorite!(user1) assert_equal(1, user1.favorites.count) end From fb91bbc6c5489370da06ad527eace9aacad53154 Mon Sep 17 00:00:00 2001 From: evazion Date: Sun, 12 Aug 2018 14:22:08 -0500 Subject: [PATCH 10/11] Fix #3813: Favorite limit can be bypassed. --- app/controllers/favorites_controller.rb | 28 +++---------- app/models/favorite.rb | 9 +++- app/models/user.rb | 2 +- app/views/favorites/create.js.erb | 28 ++++++------- app/views/static/error.js.erb | 2 + test/unit/favorite_test.rb | 56 ++++++++++++------------- 6 files changed, 56 insertions(+), 69 deletions(-) create mode 100644 app/views/static/error.js.erb diff --git a/app/controllers/favorites_controller.rb b/app/controllers/favorites_controller.rb index 75e481e14..82c99ac86 100644 --- a/app/controllers/favorites_controller.rb +++ b/app/controllers/favorites_controller.rb @@ -1,6 +1,6 @@ class FavoritesController < ApplicationController before_action :member_only, except: [:index] - respond_to :html, :xml, :json + respond_to :html, :xml, :json, :js skip_before_action :api_check def index @@ -24,23 +24,10 @@ class FavoritesController < ApplicationController end def create - if CurrentUser.favorite_limit.nil? || CurrentUser.favorite_count < CurrentUser.favorite_limit - @post = Post.find(params[:post_id]) - @post.add_favorite!(CurrentUser.user) - else - @error_msg = "You can only keep up to #{CurrentUser.favorite_limit} favorites. Upgrade your account to save more." - end + @post = Post.find(params[:post_id]) + @post.add_favorite!(CurrentUser.user) - respond_with(@post) do |format| - format.js - format.json do - if @post - render :json => {:success => true}.to_json - else - render :json => {:success => false, :reason => @error_msg}.to_json, :status => 422 - end - end - end + respond_with(@post) end def destroy @@ -52,11 +39,6 @@ class FavoritesController < ApplicationController Favorite.remove(post_id: params[:id], user: CurrentUser.user) end - respond_with(@post) do |format| - format.js - format.json do - render :json => {:success => true}.to_json - end - end + respond_with(@post) end end diff --git a/app/models/favorite.rb b/app/models/favorite.rb index ed1ac6828..d751cee07 100644 --- a/app/models/favorite.rb +++ b/app/models/favorite.rb @@ -1,4 +1,6 @@ class Favorite < ApplicationRecord + class Error < Exception ; end + belongs_to :post belongs_to :user scope :for_user, ->(user_id) {where("user_id % 100 = #{user_id.to_i % 100} and user_id = #{user_id.to_i}")} @@ -7,7 +9,12 @@ class Favorite < ApplicationRecord Favorite.transaction do User.where(:id => user.id).select("id").lock("FOR UPDATE NOWAIT").first - return if Favorite.for_user(user.id).where(:user_id => user.id, :post_id => post.id).exists? + if user.favorite_count >= user.favorite_limit + raise Error, "You can only keep up to #{user.favorite_limit} favorites. Upgrade your account to save more." + elsif Favorite.for_user(user.id).where(:user_id => user.id, :post_id => post.id).exists? + raise Error, "You have already favorited this post" + end + Favorite.create!(:user_id => user.id, :post_id => post.id) Post.where(:id => post.id).update_all("fav_count = fav_count + 1") post.append_user_to_fav_string(user.id) diff --git a/app/models/user.rb b/app/models/user.rb index 85aef23bd..1a7117d16 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -605,7 +605,7 @@ class User < ApplicationRecord def favorite_limit if is_platinum? - nil + Float::INFINITY elsif is_gold? 20_000 else diff --git a/app/views/favorites/create.js.erb b/app/views/favorites/create.js.erb index 4439d2c53..2b66837a8 100644 --- a/app/views/favorites/create.js.erb +++ b/app/views/favorites/create.js.erb @@ -1,17 +1,13 @@ -<% if @error_msg %> - $(window).trigger("danbooru:error", "<%= @error_msg %>"); -<% else %> - $("#add-to-favorites").hide(); - $("#add-fav-button").hide(); - $("#remove-from-favorites").show(); - $("#remove-fav-button").show(); - $("#score-for-post-<%= @post.id %>").html(<%= @post.score %>); - $("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>); - <% if CurrentUser.is_gold? %> - $("#favlist").html("<%= escape_javascript(post_favlist(@post)) %>"); - if (!$("#favlist").is(":visible")) { - $("#show-favlist-link").show(); - } - <% end %> - $(window).trigger("danbooru:notice", "You have favorited this post"); +$("#add-to-favorites").hide(); +$("#add-fav-button").hide(); +$("#remove-from-favorites").show(); +$("#remove-fav-button").show(); +$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>); +$("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>); +<% if CurrentUser.is_gold? %> + $("#favlist").html("<%= escape_javascript(post_favlist(@post)) %>"); + if (!$("#favlist").is(":visible")) { + $("#show-favlist-link").show(); + } <% end %> +$(window).trigger("danbooru:notice", "You have favorited this post"); diff --git a/app/views/static/error.js.erb b/app/views/static/error.js.erb new file mode 100644 index 000000000..dff1e527a --- /dev/null +++ b/app/views/static/error.js.erb @@ -0,0 +1,2 @@ +var message = <%= raw @error_message.try(:to_json) || @exception.message.to_json %>; +Danbooru.Utility.error(message); diff --git a/test/unit/favorite_test.rb b/test/unit/favorite_test.rb index 6bbdb4d10..c4536442f 100644 --- a/test/unit/favorite_test.rb +++ b/test/unit/favorite_test.rb @@ -2,10 +2,13 @@ require 'test_helper' class FavoriteTest < ActiveSupport::TestCase setup do - user = FactoryBot.create(:user) - CurrentUser.user = user + @user1 = FactoryBot.create(:user) + @user2 = FactoryBot.create(:user) + @p1 = FactoryBot.create(:post) + @p2 = FactoryBot.create(:post) + + CurrentUser.user = @user1 CurrentUser.ip_addr = "127.0.0.1" - Favorite # need to force loading the favorite model end teardown do @@ -15,44 +18,41 @@ class FavoriteTest < ActiveSupport::TestCase context "A favorite" do should "delete from all tables" do - user1 = FactoryBot.create(:user) - p1 = FactoryBot.create(:post) + @p1.add_favorite!(@user1) + assert_equal(1, @user1.favorite_count) - p1.add_favorite!(user1) - assert_equal(1, Favorite.count) - - Favorite.where(:user_id => user1.id, :post_id => p1.id).delete_all + Favorite.where(:user_id => @user1.id, :post_id => @p1.id).delete_all assert_equal(0, Favorite.count) end should "know which table it belongs to" do - user1 = FactoryBot.create(:user) - user2 = FactoryBot.create(:user) - p1 = FactoryBot.create(:post) - p2 = FactoryBot.create(:post) + @p1.add_favorite!(@user1) + @p2.add_favorite!(@user1) + @p1.add_favorite!(@user2) - p1.add_favorite!(user1) - p2.add_favorite!(user1) - p1.add_favorite!(user2) - - favorites = user1.favorites.order("id desc") + favorites = @user1.favorites.order("id desc") assert_equal(2, favorites.count) - assert_equal(p2.id, favorites[0].post_id) - assert_equal(p1.id, favorites[1].post_id) + assert_equal(@p2.id, favorites[0].post_id) + assert_equal(@p1.id, favorites[1].post_id) - favorites = user2.favorites.order("id desc") + favorites = @user2.favorites.order("id desc") assert_equal(1, favorites.count) - assert_equal(p1.id, favorites[0].post_id) + assert_equal(@p1.id, favorites[0].post_id) end should "not allow duplicates" do - user1 = FactoryBot.create(:user) - p1 = FactoryBot.create(:post) - p2 = FactoryBot.create(:post) - p1.add_favorite!(user1) - p1.add_favorite!(user1) + @p1.add_favorite!(@user1) + error = assert_raises(Favorite::Error) { @p1.add_favorite!(@user1) } - assert_equal(1, user1.favorites.count) + assert_equal("You have already favorited this post", error.message) + assert_equal(1, @user1.favorite_count) + end + + should "not allow exceeding the user's favorite limit" do + @user1.stubs(:favorite_limit).returns(0) + error = assert_raises(Favorite::Error) { @p1.add_favorite!(@user1) } + + assert_equal("You can only keep up to 0 favorites. Upgrade your account to save more.", error.message) end end end From bcaee199f5f447bc4148800fe52f8a8f6bb2ee73 Mon Sep 17 00:00:00 2001 From: evazion Date: Sun, 12 Aug 2018 15:49:13 -0500 Subject: [PATCH 11/11] favorites: unify create.js.erb & destory.js.erb code paths. --- app/controllers/favorites_controller.rb | 2 ++ app/views/favorites/_update.js.erb | 16 ++++++++++++++++ app/views/favorites/create.js.erb | 14 +------------- app/views/favorites/destroy.js.erb | 14 +------------- 4 files changed, 20 insertions(+), 26 deletions(-) create mode 100644 app/views/favorites/_update.js.erb mode change 100644 => 120000 app/views/favorites/create.js.erb mode change 100644 => 120000 app/views/favorites/destroy.js.erb diff --git a/app/controllers/favorites_controller.rb b/app/controllers/favorites_controller.rb index 82c99ac86..6456a11d1 100644 --- a/app/controllers/favorites_controller.rb +++ b/app/controllers/favorites_controller.rb @@ -26,6 +26,7 @@ class FavoritesController < ApplicationController def create @post = Post.find(params[:post_id]) @post.add_favorite!(CurrentUser.user) + flash[:notice] = "You have favorited this post" respond_with(@post) end @@ -39,6 +40,7 @@ class FavoritesController < ApplicationController Favorite.remove(post_id: params[:id], user: CurrentUser.user) end + flash[:notice] = "You have unfavorited this post" respond_with(@post) end end diff --git a/app/views/favorites/_update.js.erb b/app/views/favorites/_update.js.erb new file mode 100644 index 000000000..5d608b019 --- /dev/null +++ b/app/views/favorites/_update.js.erb @@ -0,0 +1,16 @@ +$("#add-to-favorites, #add-fav-button, #remove-from-favorites, #remove-fav-button").toggle(); +$("#score-for-post-<%= @post.id %>").text(<%= @post.score %>); +$("#favcount-for-post-<%= @post.id %>").text(<%= @post.fav_count %>); + +<% if CurrentUser.is_gold? %> + var fav_count = <%= @post.fav_count %>; + $("#favlist").html("<%= j post_favlist(@post) %>"); + + if (fav_count === 0) { + $("#show-favlist-link, #hide-favlist-link, #favlist").hide(); + } else if (!$("#favlist").is(":visible")) { + $("#show-favlist-link").show(); + } +<% end %> + +Danbooru.Utility.notice("<%= j flash[:notice] %>"); diff --git a/app/views/favorites/create.js.erb b/app/views/favorites/create.js.erb deleted file mode 100644 index 2b66837a8..000000000 --- a/app/views/favorites/create.js.erb +++ /dev/null @@ -1,13 +0,0 @@ -$("#add-to-favorites").hide(); -$("#add-fav-button").hide(); -$("#remove-from-favorites").show(); -$("#remove-fav-button").show(); -$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>); -$("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>); -<% if CurrentUser.is_gold? %> - $("#favlist").html("<%= escape_javascript(post_favlist(@post)) %>"); - if (!$("#favlist").is(":visible")) { - $("#show-favlist-link").show(); - } -<% end %> -$(window).trigger("danbooru:notice", "You have favorited this post"); diff --git a/app/views/favorites/create.js.erb b/app/views/favorites/create.js.erb new file mode 120000 index 000000000..348ee6954 --- /dev/null +++ b/app/views/favorites/create.js.erb @@ -0,0 +1 @@ +_update.js.erb \ No newline at end of file diff --git a/app/views/favorites/destroy.js.erb b/app/views/favorites/destroy.js.erb deleted file mode 100644 index bd69dfc52..000000000 --- a/app/views/favorites/destroy.js.erb +++ /dev/null @@ -1,13 +0,0 @@ -$("#add-to-favorites").show(); -$("#add-fav-button").show(); -$("#remove-from-favorites").hide(); -$("#remove-fav-button").hide(); -$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>); -$("#favcount-for-post-<%= @post.id %>").html(<%= @post.fav_count %>); -<% if CurrentUser.is_gold? %> - $("#favlist").html("<%= escape_javascript(post_favlist(@post)) %>"); - <% if @post.fav_count == 0 %> - $("#show-favlist-link, #hide-favlist-link, #favlist").hide(); - <% end %> -<% end %> -$(window).trigger("danbooru:notice", "You have unfavorited this post"); diff --git a/app/views/favorites/destroy.js.erb b/app/views/favorites/destroy.js.erb new file mode 120000 index 000000000..348ee6954 --- /dev/null +++ b/app/views/favorites/destroy.js.erb @@ -0,0 +1 @@ +_update.js.erb \ No newline at end of file