discourse/plugins/chat/app/serializers/chat_message_serializer.rb
Gerhard Schlager 7ef482a292
REFACTOR: Fix pluralized strings in chat plugin (#20357)
* FIX: Use pluralized string

* REFACTOR: Fix misuse of pluralized string

* REFACTOR: Fix misuse of pluralized string

* DEV: Remove linting of `one` key in MessageFormat string, it doesn't work

* REFACTOR: Fix misuse of pluralized string

This also ensures that the URL works on subfolder and shows the site setting link only for admins instead of staff. The string is quite complicated, so the best option was to switch to MessageFormat.

* REFACTOR: Fix misuse of pluralized string

* FIX: Use pluralized string

This also ensures that the URL works on subfolder and shows the site setting link only for admins instead of staff.

* REFACTOR: Correctly pluralize reaction tooltips in chat

This also ensures that maximum 5 usernames are shown and fixes the number of "others" which was off by 1 if the current user reacted on a message.

* REFACTOR: Use translatable string as comma separator

* DEV: Add comment to translation to clarify the meaning of `%{identifier}`

* REFACTOR: Use translatable comma separator and use explicit interpolation keys

* REFACTOR: Don't interpolate lowercase channel status

* REFACTOR: Fix misuse of pluralized string

* REFACTOR: Don't interpolate channel status

* REFACTOR: Use %{count} interpolation key

* REFACTOR: Fix misuse of pluralized string

* REFACTOR: Correctly pluralize DM chat channel titles
2023-02-20 10:31:02 +01:00

154 lines
3.8 KiB
Ruby

# frozen_string_literal: true
class ChatMessageSerializer < ApplicationSerializer
attributes :id,
:message,
:cooked,
:created_at,
:excerpt,
:deleted_at,
:deleted_by_id,
:reviewable_id,
:user_flag_status,
:edited,
:reactions,
:bookmark,
:available_flags,
:thread_id,
:chat_channel_id
has_one :user, serializer: ChatMessageUserSerializer, embed: :objects
has_one :chat_webhook_event, serializer: ChatWebhookEventSerializer, embed: :objects
has_one :in_reply_to, serializer: ChatInReplyToSerializer, embed: :objects
has_many :uploads, serializer: UploadSerializer, embed: :objects
def channel
@channel ||= @options.dig(:chat_channel) || object.chat_channel
end
def user
object.user || DeletedChatUser.new
end
def excerpt
WordWatcher.censor(object.excerpt)
end
def reactions
reactions_hash = {}
object
.reactions
.group_by(&:emoji)
.each do |emoji, reactions|
users = reactions[0..5].map(&:user).filter { |user| user.id != scope&.user&.id }[0..4]
next unless Emoji.exists?(emoji)
reactions_hash[emoji] = {
count: reactions.count,
users:
ActiveModel::ArraySerializer.new(users, each_serializer: BasicUserSerializer).as_json,
reacted: users_reactions.include?(emoji),
}
end
reactions_hash
end
def include_reactions?
object.reactions.any?
end
def users_reactions
@users_reactions ||=
object.reactions.select { |reaction| reaction.user_id == scope&.user&.id }.map(&:emoji)
end
def users_bookmark
@user_bookmark ||= object.bookmarks.find { |bookmark| bookmark.user_id == scope&.user&.id }
end
def include_bookmark?
users_bookmark.present?
end
def bookmark
{
id: users_bookmark.id,
reminder_at: users_bookmark.reminder_at,
name: users_bookmark.name,
auto_delete_preference: users_bookmark.auto_delete_preference,
bookmarkable_id: users_bookmark.bookmarkable_id,
bookmarkable_type: users_bookmark.bookmarkable_type,
}
end
def edited
true
end
def include_edited?
object.revisions.any?
end
def deleted_at
object.user ? object.deleted_at : Time.zone.now
end
def deleted_by_id
object.user ? object.deleted_by_id : Discourse.system_user.id
end
def include_deleted_at?
object.user ? !object.deleted_at.nil? : true
end
def include_deleted_by_id?
object.user ? !object.deleted_at.nil? : true
end
def include_in_reply_to?
object.in_reply_to_id.presence
end
def reviewable_id
return @reviewable_id if defined?(@reviewable_id)
return @reviewable_id = nil unless @options && @options[:reviewable_ids]
@reviewable_id = @options[:reviewable_ids][object.id]
end
def include_reviewable_id?
reviewable_id.present?
end
def user_flag_status
return @user_flag_status if defined?(@user_flag_status)
return @user_flag_status = nil unless @options&.dig(:user_flag_statuses)
@user_flag_status = @options[:user_flag_statuses][object.id]
end
def include_user_flag_status?
user_flag_status.present?
end
def available_flags
return [] if !scope.can_flag_chat_message?(object)
return [] if reviewable_id.present? && user_flag_status == ReviewableScore.statuses[:pending]
PostActionType.flag_types.map do |sym, id|
next if channel.direct_message_channel? && %i[notify_moderators notify_user].include?(sym)
if sym == :notify_user &&
(
scope.current_user == user || user.bot? ||
!scope.current_user.in_any_groups?(SiteSetting.personal_message_enabled_groups_map)
)
next
end
sym
end
end
end