diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.kt index 0500872c3f..3734617c7e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.kt @@ -19,6 +19,7 @@ import com.google.android.flexbox.JustifyContent import network.loki.messenger.R import network.loki.messenger.databinding.ViewEmojiReactionsBinding import org.session.libsession.utilities.ThemeUtil +import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.components.emoji.EmojiImageView import org.thoughtcrime.securesms.components.emoji.EmojiUtil @@ -68,7 +69,11 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { binding.layoutEmojiContainer.removeAllViews() } - fun setReactions(messageId: MessageId, records: List, outgoing: Boolean, delegate: VisibleMessageViewDelegate?) { + fun setReactions(messageId: MessageId, + threadRecipient: Recipient, + records: List, + outgoing: Boolean, + delegate: VisibleMessageViewDelegate?) { this.delegate = delegate if (records == this.records) { return @@ -81,7 +86,7 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { extended = false } this.messageId = messageId - displayReactions(messageId, if (extended) Int.MAX_VALUE else DEFAULT_THRESHOLD) + displayReactions(messageId, threadRecipient, if (extended) Int.MAX_VALUE else DEFAULT_THRESHOLD) } override fun onTouch(v: View, event: MotionEvent): Boolean { @@ -94,12 +99,18 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { return true } - private fun displayReactions(messageId: MessageId, threshold: Int) { + private fun displayReactions(messageId: MessageId, threadRecipient: Recipient, threshold: Int) { val userPublicKey = (context.applicationContext as ApplicationContext).loginStateRepository .get() .getLocalNumber() - val reactions = buildSortedReactionsList(messageId, records!!, userPublicKey, threshold) + val reactions = buildSortedReactionsList( + messageId = messageId, + threadRecipient = threadRecipient, + records = records!!, + userPublicKey = userPublicKey, + threshold = threshold + ) binding.layoutEmojiContainer.removeAllViews() val overflowContainer = LinearLayout(context) overflowContainer.orientation = LinearLayout.HORIZONTAL @@ -116,7 +127,7 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { val pill = buildPill(context, this, reaction, true) pill.setOnClickListener { v: View? -> extended = true - displayReactions(messageId, Int.MAX_VALUE) + displayReactions(messageId, threadRecipient, Int.MAX_VALUE) } pill.findViewById(R.id.reactions_pill_count).visibility = GONE pill.findViewById(R.id.reactions_pill_spacer).visibility = GONE @@ -148,7 +159,7 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { for (id in binding.groupShowLess.referencedIds) { findViewById(id).setOnClickListener { view: View? -> extended = false - displayReactions(messageId, DEFAULT_THRESHOLD) + displayReactions(messageId, threadRecipient, DEFAULT_THRESHOLD) } } } else { @@ -158,12 +169,15 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { private fun buildSortedReactionsList( messageId: MessageId, + threadRecipient: Recipient, records: List, userPublicKey: String?, threshold: Int ): List { val reactions = arrayListOf() + val accumulateReactionCount = !threadRecipient.isCommunityRecipient + // First go through reaction records and create a sorted list of reaction data based on emoji for (record in records) { val baseEmoji = EmojiUtil.getCanonicalRepresentation(record.emoji) @@ -171,6 +185,7 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { if (index >= 0) { reactions[index].update( count = record.count, + accumulateCount = accumulateReactionCount, lastSeen = record.dateReceived, userWasSender = record.author == userPublicKey ) @@ -275,8 +290,13 @@ class EmojiReactionsView : ConstraintLayout, OnTouchListener { var lastSeen: Long, var userWasSender: Boolean, ) : Comparable { - fun update(count: Long, lastSeen: Long, userWasSender: Boolean) { - this.count = this.count.coerceAtLeast(count) + fun update(count: Long, accumulateCount: Boolean, lastSeen: Long, userWasSender: Boolean) { + if (accumulateCount) { + this.count += count + } else { + this.count = this.count.coerceAtLeast(count) + } + this.lastSeen = this.lastSeen.coerceAtLeast(lastSeen) this.userWasSender = this.userWasSender || userWasSender } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt index 5bd7220209..4fc3638845 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt @@ -275,7 +275,13 @@ class VisibleMessageView : FrameLayout { val capabilities = (threadRecipient.address as? Address.Community)?.serverUrl?.let { lokiApiDb.getServerCapabilities(it) } if (capabilities.isNullOrEmpty() || capabilities.contains(OpenGroupApi.Capability.REACTIONS.name.lowercase())) { emojiReactionsBinding.value.root.let { root -> - root.setReactions(message.messageId, message.reactions, message.isOutgoing, delegate) + root.setReactions( + messageId = message.messageId, + threadRecipient = threadRecipient, + records = message.reactions, + outgoing = message.isOutgoing, + delegate = delegate + ) root.layoutParams = (root.layoutParams as ConstraintLayout.LayoutParams).apply { horizontalBias = if (message.isOutgoing) 1f else 0f } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.kt index 18b02032ca..13fd9ce9d5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ReactionRecord.kt @@ -7,10 +7,11 @@ data class ReactionRecord( val emoji: String, val serverId: String = "", /** - * Count of this emoji per message. Note that this means that multiple rows with the same - * messageId and emoji will have the same count value (due to having different author). - * - * So you MUST NOT sum these counts across rows for one message. + * The meaning of count depends on the context: + * - When the message is from community, this count represents the total number of reactions of this type and + * it is the same across all ReactionRecords for the same emoji/messageId. + * - When the message is from a private chat, this count should be added up across all ReactionRecords for the + * same emoji/messageId to get the total number of reactions of this type. */ val count: Long = 0, val sortId: Long = 0,