mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 03:06:14 +00:00
Merge pull request #7539 from hayaksi1/fix/5356-sender-name-fallback
Name a sender the timeline has no profile for from the room member list
This commit is contained in:
+24
-1
@@ -28,10 +28,12 @@ import io.element.android.libraries.dateformatter.api.DateFormatterMode
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName
|
||||
import io.element.android.libraries.matrix.ui.messages.reply.map
|
||||
@@ -64,7 +66,7 @@ class TimelineItemEventFactory(
|
||||
val currentSender = currentTimelineItem.event.sender
|
||||
val groupPosition =
|
||||
computeGroupPosition(currentTimelineItem, timelineItems, index)
|
||||
val senderProfile = currentTimelineItem.event.senderProfile
|
||||
val senderProfile = currentTimelineItem.event.senderProfile.orFallbackTo(roomMembers, currentSender)
|
||||
val sentTime = dateFormatter.format(
|
||||
timestamp = currentTimelineItem.event.timestamp,
|
||||
mode = DateFormatterMode.TimeOnly,
|
||||
@@ -138,11 +140,32 @@ class TimelineItemEventFactory(
|
||||
roomMembers: List<RoomMember>,
|
||||
renderReadReceipts: Boolean,
|
||||
): TimelineItem.Event {
|
||||
val senderProfile = receivedMatrixTimelineItem.event.senderProfile.orFallbackTo(roomMembers, timelineItem.senderId)
|
||||
return timelineItem.copy(
|
||||
senderProfile = senderProfile,
|
||||
senderAvatar = timelineItem.senderAvatar.copy(
|
||||
name = senderProfile.getDisambiguatedDisplayName(timelineItem.senderId),
|
||||
url = senderProfile.getAvatarUrl(),
|
||||
),
|
||||
readReceiptState = receivedMatrixTimelineItem.computeReadReceiptState(roomMembers, renderReadReceipts)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The timeline only knows the profiles the SDK has resolved, so a sender it has nothing for is rendered as a raw
|
||||
* user ID. The room member list usually knows that user, so use it rather than showing the ID.
|
||||
*/
|
||||
private fun ProfileDetails.orFallbackTo(roomMembers: List<RoomMember>, senderId: UserId): ProfileDetails {
|
||||
if (this is ProfileDetails.Ready) return this
|
||||
val member = roomMembers.find { it.userId == senderId } ?: return this
|
||||
return ProfileDetails.Ready(
|
||||
displayName = member.displayName,
|
||||
displayNameAmbiguous = member.isNameAmbiguous,
|
||||
avatarUrl = member.avatarUrl,
|
||||
displayedStatus = member.displayedStatus,
|
||||
)
|
||||
}
|
||||
|
||||
private fun MatrixTimelineItem.Event.computeReactionsState(): TimelineItemReactions {
|
||||
if (!config.computeReactions) {
|
||||
return TimelineItemReactions(reactions = persistentListOf())
|
||||
|
||||
+71
@@ -20,8 +20,11 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.OtherMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails
|
||||
import io.element.android.libraries.matrix.test.A_THREAD_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.room.aRoomMember
|
||||
import io.element.android.libraries.matrix.test.timeline.aMessageContent
|
||||
import io.element.android.libraries.matrix.test.timeline.aRedactedContent
|
||||
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
|
||||
@@ -207,6 +210,74 @@ class TimelineItemsFactoryTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a sender the timeline knows nothing about is named from the room member list`() = runTest {
|
||||
val factory = aTimelineItemsFactory(
|
||||
config = TimelineItemsFactoryConfig(
|
||||
computeReadReceipts = false,
|
||||
computeReactions = false,
|
||||
)
|
||||
)
|
||||
val items = listOf(
|
||||
MatrixTimelineItem.Event(
|
||||
uniqueId = UniqueId("event-0"),
|
||||
event = anEventTimelineItem(
|
||||
sender = A_USER_ID,
|
||||
senderProfile = ProfileDetails.Unavailable,
|
||||
content = aMessageContent(body = "A regular message"),
|
||||
),
|
||||
),
|
||||
)
|
||||
factory.timelineItems.test {
|
||||
factory.replaceWith(
|
||||
timelineItems = items,
|
||||
roomMembers = listOf(aRoomMember(userId = A_USER_ID, displayName = "Alice")),
|
||||
renderReadReceipts = false,
|
||||
)
|
||||
val event = awaitItem().filterIsInstance<TimelineItem.Event>().single()
|
||||
assertThat(event.senderProfile).isEqualTo(
|
||||
ProfileDetails.Ready(
|
||||
displayName = "Alice",
|
||||
displayNameAmbiguous = false,
|
||||
avatarUrl = null,
|
||||
displayedStatus = null,
|
||||
)
|
||||
)
|
||||
assertThat(event.senderAvatar.name).isEqualTo("Alice")
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a sender the room member list knows nothing about keeps the profile the timeline gave`() = runTest {
|
||||
val factory = aTimelineItemsFactory(
|
||||
config = TimelineItemsFactoryConfig(
|
||||
computeReadReceipts = false,
|
||||
computeReactions = false,
|
||||
)
|
||||
)
|
||||
val items = listOf(
|
||||
MatrixTimelineItem.Event(
|
||||
uniqueId = UniqueId("event-0"),
|
||||
event = anEventTimelineItem(
|
||||
sender = A_USER_ID,
|
||||
senderProfile = ProfileDetails.Unavailable,
|
||||
content = aMessageContent(body = "A regular message"),
|
||||
),
|
||||
),
|
||||
)
|
||||
factory.timelineItems.test {
|
||||
factory.replaceWith(
|
||||
timelineItems = items,
|
||||
roomMembers = listOf(aRoomMember(userId = A_USER_ID_2, displayName = "Bob")),
|
||||
renderReadReceipts = false,
|
||||
)
|
||||
val event = awaitItem().filterIsInstance<TimelineItem.Event>().single()
|
||||
assertThat(event.senderProfile).isEqualTo(ProfileDetails.Unavailable)
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun TestScope.groupPositionsOf(timestamps: List<Long>): List<TimelineItemGroupPosition> {
|
||||
val factory = aTimelineItemsFactory(
|
||||
config = TimelineItemsFactoryConfig(
|
||||
|
||||
Reference in New Issue
Block a user