diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationAdapter.kt index 9866c852c0..77f0d7ca24 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationAdapter.kt @@ -67,7 +67,8 @@ class ConversationAdapter(context: Context, cursor: Cursor, private val onItemPr } else { null } - view.bind(message) + val position = viewHolder.adapterPosition + view.bind(message, getMessageBefore(position, cursor), getMessageAfter(position, cursor)) view.setOnClickListener { onItemPress(message, viewHolder.adapterPosition) } view.setOnLongClickListener { onItemLongPress(message, viewHolder.adapterPosition) @@ -90,6 +91,16 @@ class ConversationAdapter(context: Context, cursor: Cursor, private val onItemPr return messageDB.readerFor(cursor).current } + private fun getMessageBefore(position: Int, cursor: Cursor): MessageRecord? { + if (!cursor.moveToPosition(position - 1)) { return null } + return messageDB.readerFor(cursor).current + } + + private fun getMessageAfter(position: Int, cursor: Cursor): MessageRecord? { + if (!cursor.moveToPosition(position + 1)) { return null } + return messageDB.readerFor(cursor).current + } + fun toggleSelection(message: MessageRecord, position: Int) { if (selectedItems.contains(message)) selectedItems.remove(message) else selectedItems.add(message) notifyItemChanged(position) 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 bf9a7e04d5..4c4cd0409d 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 @@ -10,8 +10,12 @@ import android.widget.LinearLayout import kotlinx.android.synthetic.main.view_visible_message.view.* import network.loki.messenger.R import org.session.libsession.messaging.contacts.Contact.ContactContext +import org.session.libsession.utilities.ViewUtil +import org.session.libsignal.utilities.guava.Optional import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.MessageRecord +import org.thoughtcrime.securesms.util.DateUtils +import kotlin.math.roundToInt class VisibleMessageView : LinearLayout { @@ -35,7 +39,7 @@ class VisibleMessageView : LinearLayout { // endregion // region Updating - fun bind(message: MessageRecord) { + fun bind(message: MessageRecord, previous: MessageRecord?, next: MessageRecord?) { val sender = message.individualRecipient val senderSessionID = sender.address.serialize() val threadID = message.threadId @@ -71,7 +75,8 @@ class VisibleMessageView : LinearLayout { messageContentViewLayoutParams.rightMargin = if (message.isOutgoing) resources.getDimension(R.dimen.medium_spacing).toInt() else resources.getDimension(R.dimen.very_large_spacing).toInt() messageContentView.layoutParams = messageContentViewLayoutParams - // TODO: Inter-message spacing + // Set inter-message spacing + setMessageSpacing(message, previous, next, isGroupThread) // Gravity val gravity = if (message.isOutgoing) Gravity.RIGHT else Gravity.LEFT mainContainer.gravity = gravity or Gravity.BOTTOM @@ -79,6 +84,37 @@ class VisibleMessageView : LinearLayout { messageContentView.bind(message) } + private fun setMessageSpacing(current: MessageRecord, previous: MessageRecord?, next: MessageRecord?, isGroupThread: Boolean) { + val isStartOfMessageCluster = (isStartOfMessageCluster(current, previous, isGroupThread)) + val topPadding = if (isStartOfMessageCluster) R.dimen.conversation_vertical_message_spacing_default + else R.dimen.conversation_vertical_message_spacing_collapse + ViewUtil.setPaddingTop(this, resources.getDimension(topPadding).roundToInt()) + val isEndOfMessageCluster = (isEndOfMessageCluster(current, previous, isGroupThread)) + val bottomPadding = if (isEndOfMessageCluster) R.dimen.conversation_vertical_message_spacing_default + else R.dimen.conversation_vertical_message_spacing_collapse + ViewUtil.setPaddingBottom(this, resources.getDimension(bottomPadding).roundToInt()) + } + + private fun isStartOfMessageCluster(current: MessageRecord, previous: MessageRecord?, isGroupThread: Boolean): Boolean { + return if (isGroupThread) { + previous == null || previous.isUpdate || !DateUtils.isSameDay(current.timestamp, previous.timestamp) + || current.recipient.address != previous.recipient.address + } else { + previous == null || previous.isUpdate || !DateUtils.isSameDay(current.timestamp, previous.timestamp) + || current.isOutgoing != previous.isOutgoing + } + } + + private fun isEndOfMessageCluster(current: MessageRecord, next: MessageRecord?, isGroupThread: Boolean): Boolean { + return if (isGroupThread) { + next == null || next.isUpdate || !DateUtils.isSameDay(current.timestamp, next.timestamp) + || current.recipient.address != next.recipient.address + } else { + next == null || next.isUpdate || !DateUtils.isSameDay(current.timestamp, next.timestamp) + || current.isOutgoing != next.isOutgoing + } + } + fun recycle() { profilePictureView.recycle() messageContentView.recycle()