diff --git a/app/models/post_alert_observer.rb b/app/models/post_alert_observer.rb index d33c443f323..290fcd8f3b1 100644 --- a/app/models/post_alert_observer.rb +++ b/app/models/post_alert_observer.rb @@ -68,9 +68,7 @@ class PostAlertObserver < ActiveRecord::Observer next unless post.reply_to_post.user_id == user.id end - destroy_notifications(user, Notification.types[:private_message], post.topic) - unread_post = first_unread_post(user,post.topic) || post - create_notification(user, Notification.types[:private_message], unread_post) + create_notification(user, Notification.types[:private_message], post) end elsif post.post_type != Post.types[:moderator_action] # If it's not a private message and it's not an automatic post caused by a moderator action, notify the users @@ -84,13 +82,26 @@ class PostAlertObserver < ActiveRecord::Observer "#{action}_#{model.class.name.underscore.gsub(/.+\//, '')}" end - def first_unread_post(user, topic) + def unread_posts(user, topic) Post.where('post_number > COALESCE(( SELECT last_read_post_number FROM topic_users tu WHERE tu.user_id = ? AND tu.topic_id = ? ),0)', user.id, topic.id) + .where('reply_to_user_id = ? OR exists( + SELECT 1 from topic_users tu + WHERE tu.user_id = ? AND + tu.topic_id = ? AND + notification_level = ? + )', user.id, user.id, topic.id, TopicUser.notification_levels[:watching]) .where(topic_id: topic.id) - .order('post_number').first + end + + def first_unread_post(user, topic) + unread_posts(user, topic).order('post_number').first + end + + def unread_count(user, topic) + unread_posts(user, topic).count end def destroy_notifications(user, type, topic) @@ -113,6 +124,31 @@ class PostAlertObserver < ActiveRecord::Observer # Don't notify the same user about the same notification on the same post return if user.notifications.exists?(notification_type: type, topic_id: post.topic_id, post_number: post.post_number) + collapsed = false + + if type == Notification.types[:replied] || + type == Notification.types[:posted] + + destroy_notifications(user, Notification.types[:replied] , post.topic) + destroy_notifications(user, Notification.types[:posted] , post.topic) + collapsed = true + end + + if type == Notification.types[:private_message] + destroy_notifications(user, type, post.topic) + collapsed = true + end + + original_post = post + + if collapsed + post = first_unread_post(user,post.topic) || post + count = unread_count(user, post.topic) + opts[:display_username] = I18n.t('embed.replies', count: count) if count > 1 + end + + UserActionObserver.log_notification(original_post, user, type) + # Create the notification user.notifications.create(notification_type: type, topic_id: post.topic_id, @@ -150,11 +186,12 @@ class PostAlertObserver < ActiveRecord::Observer reply_to_user = post.reply_notification_target notify_users(reply_to_user, :replied, post) - exclude_user_ids = [] - exclude_user_ids << post.user_id + exclude_user_ids = [] << + post.user_id << + extract_mentioned_users(post).map(&:id) << + extract_quoted_users(post).map(&:id) + exclude_user_ids << reply_to_user.id if reply_to_user.present? - exclude_user_ids << extract_mentioned_users(post).map(&:id) - exclude_user_ids << extract_quoted_users(post).map(&:id) exclude_user_ids.flatten! TopicUser .where(topic_id: post.topic_id, notification_level: TopicUser.notification_levels[:watching]) diff --git a/app/models/user_action_observer.rb b/app/models/user_action_observer.rb index a4315840d37..76ea7b8b3c6 100644 --- a/app/models/user_action_observer.rb +++ b/app/models/user_action_observer.rb @@ -9,15 +9,11 @@ class UserActionObserver < ActiveRecord::Observer log_topic(model) when (model.is_a?(Post)) log_post(model) - when (model.is_a?(Notification)) - log_notification(model) when (model.is_a?(TopicUser)) log_topic_user(model) end end - protected - def log_topic_user(model) action = UserAction::STAR @@ -37,9 +33,9 @@ class UserActionObserver < ActiveRecord::Observer end end - def log_notification(model) + def self.log_notification(post, user, notification_type) action = - case model.notification_type + case notification_type when Notification.types[:quoted] UserAction::QUOTE when Notification.types[:replied] @@ -51,20 +47,14 @@ class UserActionObserver < ActiveRecord::Observer end # like is skipped - return unless action - - post = Post.where(post_number: model.post_number, topic_id: model.topic_id).first - - # stray data - return unless post + return unless action && post && user row = { action_type: action, - user_id: model.user_id, + user_id: user.id, acting_user_id: (action == UserAction::EDIT) ? post.last_editor_id : post.user_id, - target_topic_id: model.topic_id, - target_post_id: post.id, - created_at: model.created_at + target_topic_id: post.topic_id, + target_post_id: post.id } if post.deleted_at.nil?