FEATURE: Publish read state on group messages. (#7989)

* Enable or disable read state based on group attribute

* When read state needs to be published, the minimum unread count is calculated in the topic query. This way, we can know if someone reads the last post

* The option can be enabled/disabled from the UI

* The read indicator will live-updated using message bus

* Show read indicator on every post

* The read indicator now shows read count and can be expanded to see user avatars

* Read count gets updated everytime someone reads a message

* Simplify topic-list read indicator logic

* Unsubscribe from message bus on willDestroyElement, removed unnecesarry values from post-menu, and added a comment to explain where does minimum_unread_count comes from
This commit is contained in:
Roman Rizzi
2019-08-20 09:46:57 -03:00
committed by GitHub
parent 15e70cc4b4
commit 1630dae2db
35 changed files with 524 additions and 21 deletions

View File

@ -344,11 +344,13 @@ class TopicQuery
def list_private_messages_group(user)
list = private_messages_for(user, :group)
group_id = Group.where('name ilike ?', @options[:group_name]).pluck(:id).first
group = Group.where('name ilike ?', @options[:group_name]).select(:id, :publish_read_state).first
publish_read_state = !!group&.publish_read_state
list = list.joins("LEFT JOIN group_archived_messages gm ON gm.topic_id = topics.id AND
gm.group_id = #{group_id.to_i}")
gm.group_id = #{group&.id&.to_i}")
list = list.where("gm.id IS NULL")
create_list(:private_messages, {}, list)
list = append_read_state(list, group) if publish_read_state
create_list(:private_messages, { publish_read_state: publish_read_state }, list)
end
def list_private_messages_group_archive(user)
@ -1057,4 +1059,23 @@ class TopicQuery
def sanitize_sql_array(input)
ActiveRecord::Base.public_send(:sanitize_sql_array, input.join(','))
end
def append_read_state(list, group)
group_id = group&.id
return list if group_id.nil?
selected_values = list.select_values.empty? ? ['topics.*'] : list.select_values
selected_values << "tuig.minimum_unread_count"
# The calculation was borrowed from lib/unread.rb
minimum_unread_count = TopicUser
.joins(:topic)
.joins("INNER JOIN group_users ON group_users.user_id = topic_users.user_id")
.where(group_users: { group_id: group_id })
.select(
"MIN(COALESCE(topics.highest_post_number, 0) - COALESCE(highest_seen_post_number, 0)) AS minimum_unread_count, topic_id"
).group(:topic_id).to_sql
list.joins("LEFT OUTER JOIN (#{minimum_unread_count}) tuig ON topics.id = tuig.topic_id").select(*selected_values)
end
end