diff --git a/app/controllers/dmails_controller.rb b/app/controllers/dmails_controller.rb index 87421bd02..32f347476 100644 --- a/app/controllers/dmails_controller.rb +++ b/app/controllers/dmails_controller.rb @@ -22,7 +22,7 @@ class DmailsController < ApplicationController def show @dmail = Dmail.find(params[:id]) check_privilege(@dmail) - @dmail.mark_as_read! + @dmail.update!(is_read: true) if request.format.html? respond_with(@dmail) end @@ -41,10 +41,8 @@ class DmailsController < ApplicationController end def mark_all_as_read - Dmail.visible.unread.each do |x| - x.update_column(:is_read, true) - end - CurrentUser.user.update(has_mail: false, unread_dmail_count: 0) + @dmails = CurrentUser.user.dmails.mark_all_as_read + respond_with(@dmails) end private diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 5ba80cbf3..8b17b7efc 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,4 +1,16 @@ module UsersHelper + def unread_dmail_indicator(user) + "(#{user.unread_dmail_count})" if user.unread_dmail_count > 0 + end + + def has_unread_dmails?(user) + user.unread_dmail_count > 0 && (cookies[:hide_dmail_notice].to_i < latest_unread_dmail(user).id) + end + + def latest_unread_dmail(user) + user.dmails.active.unread.first + end + def email_sig(user) verifier = ActiveSupport::MessageVerifier.new(Danbooru.config.email_key, serializer: JSON, digest: "SHA256") verifier.generate(user.id.to_s) diff --git a/app/models/dmail.rb b/app/models/dmail.rb index 8c19b8fa4..956fc022e 100644 --- a/app/models/dmail.rb +++ b/app/models/dmail.rb @@ -14,7 +14,7 @@ class Dmail < ApplicationRecord belongs_to :from, :class_name => "User" after_initialize :initialize_attributes, if: :new_record? - after_create :update_recipient + after_save :update_unread_dmail_count after_commit :send_email, on: :create api_attributes including: [:key] @@ -152,6 +152,10 @@ class Dmail < ApplicationRecord include FactoryMethods extend SearchMethods + def self.mark_all_as_read + unread.update(is_read: true) + end + def validate_sender_is_not_banned if from.try(:is_banned?) errors[:base] << "Sender is banned and cannot send messages" @@ -168,13 +172,6 @@ class Dmail < ApplicationRecord end end - def mark_as_read! - update_column(:is_read, true) - owner.dmails.unread.count.tap do |unread_count| - owner.update(has_mail: (unread_count > 0), unread_dmail_count: unread_count) - end - end - def is_automated? from == User.system end @@ -187,9 +184,12 @@ class Dmail < ApplicationRecord owner == to end - def update_recipient - if is_recipient? && !is_deleted? && !is_read? - to.update(has_mail: true, unread_dmail_count: to.dmails.unread.count) + def update_unread_dmail_count + return unless saved_change_to_id? || saved_change_to_is_read? || saved_change_to_is_deleted? + + owner.with_lock do + unread_count = owner.dmails.active.unread.count + owner.update!(unread_dmail_count: unread_count) end end diff --git a/app/models/user.rb b/app/models/user.rb index 4e1c96c40..aa179ff28 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -35,6 +35,7 @@ class User < ApplicationRecord # - has_saved_searches # - opt_out_tracking # - enable_recommended_posts + # - has_mail BOOLEAN_ATTRIBUTES = %w( is_banned has_mail @@ -798,14 +799,6 @@ class User < ApplicationRecord CurrentUser.as(self, &block) end - def dmail_count - if has_mail? - "(#{unread_dmail_count})" - else - "" - end - end - def reportable_by?(user) ModerationReport.enabled? && user.is_builder? && id != user.id && !is_moderator? end diff --git a/app/views/dmails/index.html.erb b/app/views/dmails/index.html.erb index 8f8e14a7b..02c582b2f 100644 --- a/app/views/dmails/index.html.erb +++ b/app/views/dmails/index.html.erb @@ -25,11 +25,18 @@ <%= link_to dmail.title, dmail_path(dmail) %> <% end %> <% t.column do |dmail| %> + <% if dmail.is_read? %> + <%= link_to "Unread", dmail_path(dmail, format: :js), remote: true, method: :put, "data-params": "dmail[is_read]=false" %> + <% else %> + <%= link_to "Read", dmail_path(dmail, format: :js), remote: true, method: :put, "data-params": "dmail[is_read]=true" %> + <% end %> + | <% if dmail.is_deleted? %> <%= link_to "Undelete", dmail_path(dmail, format: :js), remote: true, method: :put, "data-params": "dmail[is_deleted]=false" %> <% else %> <%= link_to "Delete", dmail_path(dmail, format: :js), remote: true, method: :put, "data-params": "dmail[is_deleted]=true", "data-confirm": "Are you sure you want to delete this dmail?" %> <% end %> + <% if dmail.reportable_by?(CurrentUser.user) %> | <%= link_to "Report", new_moderation_report_path(moderation_report: { model_type: "Dmail", model_id: dmail.id }), remote: true, title: "Report this dmail to the moderators" %> <% end %> diff --git a/app/views/layouts/_main_links.html.erb b/app/views/layouts/_main_links.html.erb index 42f8a6492..32ebfd521 100644 --- a/app/views/layouts/_main_links.html.erb +++ b/app/views/layouts/_main_links.html.erb @@ -2,7 +2,7 @@ <% if CurrentUser.is_anonymous? %> <%= nav_link_to("Login", login_path) %> <% else %> - <%= nav_link_to("My Account #{CurrentUser.dmail_count}", profile_path) %> + <%= nav_link_to("My Account #{unread_dmail_indicator(CurrentUser.user)}", profile_path) %> <% end %> <%= nav_link_to("Posts", posts_path) %> <%= nav_link_to("Comments", comments_path(:group_by => "post")) %> diff --git a/app/views/layouts/default.html.erb b/app/views/layouts/default.html.erb index 13de838a3..f0abf5cee 100644 --- a/app/views/layouts/default.html.erb +++ b/app/views/layouts/default.html.erb @@ -118,7 +118,7 @@ <%= render "users/ban_notice" %> <% end %> - <% if CurrentUser.has_mail? && CurrentUser.dmails.unread.first.present? && (cookies[:hide_dmail_notice].blank? || cookies[:hide_dmail_notice].to_i < CurrentUser.dmails.unread.first.id) %> + <% if params[:controller] != "dmails" && has_unread_dmails?(CurrentUser.user) %> <%= render "users/dmail_notice" %> <% end %> diff --git a/app/views/static/site_map.html.erb b/app/views/static/site_map.html.erb index 8927ab60b..6cd8af1fc 100644 --- a/app/views/static/site_map.html.erb +++ b/app/views/static/site_map.html.erb @@ -127,7 +127,7 @@