FEATURE: collapse replies to topics

when you get two replies to a topic they are now collapsed as opposed to getting two notificatons.
This commit is contained in:
Sam 2014-02-03 13:57:44 +11:00
parent 854fdae7cd
commit 60c5eb63ce
2 changed files with 52 additions and 25 deletions

View File

@ -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])

View File

@ -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?