mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 21:32:34 +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.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
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.permalink.PermalinkParser
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
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.MatrixTimelineItem
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo
|
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.getAvatarUrl
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName
|
import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName
|
||||||
import io.element.android.libraries.matrix.ui.messages.reply.map
|
import io.element.android.libraries.matrix.ui.messages.reply.map
|
||||||
@@ -64,7 +66,7 @@ class TimelineItemEventFactory(
|
|||||||
val currentSender = currentTimelineItem.event.sender
|
val currentSender = currentTimelineItem.event.sender
|
||||||
val groupPosition =
|
val groupPosition =
|
||||||
computeGroupPosition(currentTimelineItem, timelineItems, index)
|
computeGroupPosition(currentTimelineItem, timelineItems, index)
|
||||||
val senderProfile = currentTimelineItem.event.senderProfile
|
val senderProfile = currentTimelineItem.event.senderProfile.orFallbackTo(roomMembers, currentSender)
|
||||||
val sentTime = dateFormatter.format(
|
val sentTime = dateFormatter.format(
|
||||||
timestamp = currentTimelineItem.event.timestamp,
|
timestamp = currentTimelineItem.event.timestamp,
|
||||||
mode = DateFormatterMode.TimeOnly,
|
mode = DateFormatterMode.TimeOnly,
|
||||||
@@ -138,11 +140,32 @@ class TimelineItemEventFactory(
|
|||||||
roomMembers: List<RoomMember>,
|
roomMembers: List<RoomMember>,
|
||||||
renderReadReceipts: Boolean,
|
renderReadReceipts: Boolean,
|
||||||
): TimelineItem.Event {
|
): TimelineItem.Event {
|
||||||
|
val senderProfile = receivedMatrixTimelineItem.event.senderProfile.orFallbackTo(roomMembers, timelineItem.senderId)
|
||||||
return timelineItem.copy(
|
return timelineItem.copy(
|
||||||
|
senderProfile = senderProfile,
|
||||||
|
senderAvatar = timelineItem.senderAvatar.copy(
|
||||||
|
name = senderProfile.getDisambiguatedDisplayName(timelineItem.senderId),
|
||||||
|
url = senderProfile.getAvatarUrl(),
|
||||||
|
),
|
||||||
readReceiptState = receivedMatrixTimelineItem.computeReadReceiptState(roomMembers, renderReadReceipts)
|
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 {
|
private fun MatrixTimelineItem.Event.computeReactionsState(): TimelineItemReactions {
|
||||||
if (!config.computeReactions) {
|
if (!config.computeReactions) {
|
||||||
return TimelineItemReactions(reactions = persistentListOf())
|
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.EventThreadInfo
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary
|
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.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_THREAD_ID
|
||||||
import io.element.android.libraries.matrix.test.A_USER_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.aMessageContent
|
||||||
import io.element.android.libraries.matrix.test.timeline.aRedactedContent
|
import io.element.android.libraries.matrix.test.timeline.aRedactedContent
|
||||||
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
|
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> {
|
private suspend fun TestScope.groupPositionsOf(timestamps: List<Long>): List<TimelineItemGroupPosition> {
|
||||||
val factory = aTimelineItemsFactory(
|
val factory = aTimelineItemsFactory(
|
||||||
config = TimelineItemsFactoryConfig(
|
config = TimelineItemsFactoryConfig(
|
||||||
|
|||||||
Reference in New Issue
Block a user