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/controllers/favorites_controller.rb b/app/controllers/favorites_controller.rb
index 75e481e14..6456a11d1 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,11 @@ 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)
+ flash[:notice] = "You have favorited this post"
- 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 +40,7 @@ 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
+ flash[:notice] = "You have unfavorited this post"
+ respond_with(@post)
end
end
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/packs/application.js b/app/javascript/packs/application.js
index 88093358d..c55e20661 100644
--- a/app/javascript/packs/application.js
+++ b/app/javascript/packs/application.js
@@ -38,3 +38,4 @@ 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';
+
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/comments.js b/app/javascript/src/javascripts/comments.js
index 544eaad91..9347e24b7 100644
--- a/app/javascript/src/javascripts/comments.js
+++ b/app/javascript/src/javascripts/comments.js
@@ -5,29 +5,13 @@ let Comment = {};
Comment.initialize_all = function() {
if ($("#c-posts").length || $("#c-comments").length) {
- this.initialize_response_link();
- this.initialize_reply_links();
- this.initialize_expand_links();
- this.initialize_vote_links();
-
- if (!$("#a-edit").length) {
- this.initialize_edit_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);
}
- if ($("#c-posts").length && $("#a-show").length) {
- Comment.highlight_threshold_comments(Utility.meta("post-id"));
- }
-
- $(window).on("danbooru:index_for_post", (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);
- }
- Comment.initialize_reply_links(current_comment_section);
- Comment.initialize_edit_links(current_comment_section);
- Comment.initialize_vote_links(current_comment_section);
+ $(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);
});
}
@@ -51,69 +35,17 @@ Comment.quote = function(e) {
e.preventDefault();
}
-Comment.initialize_reply_links = function($parent) {
- $parent = $parent || $(document);
- $parent.find(".reply-link").click(Comment.quote);
+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_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.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();
- });
-
- $("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];
- $("#edit_comment_" + comment_id).fadeToggle("fast");
- 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 + "]");
- articles.each(function(i, v) {
- var $comment = $(v);
- if (parseInt($comment.data("score")) < threshold) {
- $comment.hide();
- }
- });
-}
-
-Comment.initialize_vote_links = function($parent) {
- $parent = $parent || $(document);
- $parent.find(".unvote-comment-link").hide();
+Comment.show_edit_form = function(e) {
+ $(this).closest(".comment").find(".edit_comment").show();
+ e.preventDefault();
}
$(document).ready(function() {
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 a00be2fcd..71e853e3b 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);
}
}
@@ -591,22 +588,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 5cdc09666..476ed6be7 100644
--- a/app/javascript/src/javascripts/shortcuts.js
+++ b/app/javascript/src/javascripts/shortcuts.js
@@ -1,44 +1,47 @@
import Utility from './utility'
-import Post from './posts.js.erb'
let Shortcuts = {};
Shortcuts.initialize = function() {
Utility.keydown("s", "scroll_down", Shortcuts.nav_scroll_down);
Utility.keydown("w", "scroll_up", Shortcuts.nav_scroll_up);
-
- 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();
- });
- }
+ Shortcuts.initialize_data_shortcuts();
}
+// 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);
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/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/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/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?
diff --git a/app/models/user.rb b/app/models/user.rb
index 6eb6937d5..1a7117d16 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
@@ -618,7 +605,7 @@ class User < ApplicationRecord
def favorite_limit
if is_platinum?
- nil
+ Float::INFINITY
elsif is_gold?
20_000
else
@@ -917,7 +904,6 @@ class User < ApplicationRecord
include NameMethods
include PasswordMethods
include AuthenticationMethods
- include FavoriteMethods
include LevelMethods
include EmailMethods
include BlacklistMethods
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/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/index_for_post.js.erb b/app/views/comments/index_for_post.js.erb
index 37bb6f687..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 6cf957800..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) %>
<% end %>
@@ -28,7 +28,7 @@
<% if CurrentUser.is_member? %>
<% end %>
diff --git a/app/views/comments/partials/show/_comment.html.erb b/app/views/comments/partials/show/_comment.html.erb
index a490a7b2d..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? %>
-
<%= 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 %>