Improve handling of DM layout

Previously, it could happen that DM-layout and non-DM-layout were mixed
in the same chat for following reasons:
- on purpose, when it is a DM, but in the past had messages by a third
  party
- not on purpose, when the room member information wasn't loaded in time
  for some messages, and thus the fallback assumed showing DM layout
  wasn't safe

However, this leads to an inconsistent layout, which looks bad.
Accordingly, this patch changes the behaviour as following:
- always use the DM layout for chats marked as DM
- if it is not clear if the message was sent by the actual DM partner,
  show the name (as opposed to previously: show name and avatar).

While this makes it more difficult to tell apart messages from the DM
partner and a third person, it is still possible, since the third person
has a name shown, and the DM partner's messages start with a bubble with
tail but without name. This is prefered to the previous solution, which
looked rather buggy than anything else.

Change-Id: I7c3e5ca7b04acec6eede345a9abde833ce0714d3
This commit is contained in:
SpiritCroc 2021-05-10 10:25:28 +02:00
parent ed8aada390
commit 1481a3edd3
2 changed files with 23 additions and 9 deletions

View File

@ -46,6 +46,7 @@ import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
import org.matrix.android.sdk.api.session.room.timeline.hasBeenEdited
import org.matrix.android.sdk.api.session.room.timeline.isEdition
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
import timber.log.Timber
import javax.inject.Inject
/**
@ -81,24 +82,32 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
val time = dateFormatter.format(event.root.originServerTs, DateFormatKind.MESSAGE_SIMPLE)
val e2eDecoration = getE2EDecoration(event)
var isEffectivelyDirect = false
// Sometimes, member information is not available at this point yet, so let's completely rely on the DM flag for now.
// Since this can change while processing multiple messages in the same chat, we want to stick to information that is always available,
// instead of mixing different layouts in the same chat.
val roomSummary = roomSummariesHolder.get(event.roomId)
if (roomSummary == null) {
Timber.e("Room summary not available for determining DM status")
}
val isEffectivelyDirect = roomSummary?.isDirect ?: false
//var isEffectivelyDirect = false
var dmOtherMemberId: String? = null
if ((roomSummariesHolder.get(event.roomId)?.isDirect == true) && event.root.roomId != null) {
if ((roomSummary?.isDirect == true) && event.root.roomId != null) {
val members = session.getRoom(event.root.roomId!!)
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
?.map { it.userId }
.orEmpty()
.toSet()
if (members.size == 2) {
var foundSelf = false
//var foundSelf = false
for (member in members) {
if (member == session.myUserId) {
foundSelf = true
//foundSelf = true
} else {
dmOtherMemberId = member
}
}
isEffectivelyDirect = foundSelf && (dmOtherMemberId != null)
//isEffectivelyDirect = foundSelf && (dmOtherMemberId != null)
}
}

View File

@ -74,7 +74,8 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
val hiddenViews = ArrayList<View>()
val invisibleViews = ArrayList<View>()
val avatarUnnecessary = canHideAvatars()
val canHideAvatar = canHideAvatars()
val canHideSender = canHideSender()
// Select which views are visible, based on bubble style and other criteria
if (attributes.informationData.showInformation) {
@ -124,7 +125,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
if (BubbleThemeUtils.getBubbleTimeLocation(holder.bubbleTimeView.context) == BubbleThemeUtils.BUBBLE_TIME_BOTTOM) {
timeView = holder.bubbleFooterTimeView
if (attributes.informationData.showInformation) {
if (avatarUnnecessary) {
if (canHideSender) {
// In the case of footer time, we can also hide the names without making it look awkward
hiddenViews.add(holder.bubbleMemberNameView)
memberNameView = null
@ -147,7 +148,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
// Dual-side bubbles: hide own avatar, and all in direct chats
if ((!attributes.informationData.showInformation) ||
(contentInBubble && avatarUnnecessary)) {
(contentInBubble && canHideAvatar)) {
avatarImageView = null
hiddenViews.add(holder.avatarImageView)
} else {
@ -277,7 +278,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
val time = attributes.informationData.time.toString()
return if (contentInBubble) {
if (BubbleThemeUtils.getBubbleTimeLocation(holder.bubbleTimeView.context) == BubbleThemeUtils.BUBBLE_TIME_BOTTOM) {
if (attributes.informationData.showInformation && !canHideAvatars()) {
if (attributes.informationData.showInformation && !canHideSender()) {
// Since timeView automatically gets enough space, either within or outside the viewStub, we just need to ensure the member name view has enough space
// Somehow not enough without extra space...
ceil(BubbleThemeUtils.guessTextWidth(holder.bubbleMemberNameView, "$memberName ")).toInt()
@ -354,6 +355,10 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
}
private fun canHideAvatars(): Boolean {
return attributes.informationData.sentByMe || attributes.informationData.isDirect
}
private fun canHideSender(): Boolean {
return attributes.informationData.sentByMe ||
(attributes.informationData.isDirect && attributes.informationData.senderId == attributes.informationData.dmChatPartnerId)
}