Add thread decoration with latest event details (#5355)

* Add thread decoration with latest event details
* Update screenshots

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa 2025-09-23 16:57:50 +02:00 committed by GitHub
parent 5cadd37fa6
commit 0a5c178fe8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
106 changed files with 554 additions and 282 deletions

View file

@ -7,8 +7,19 @@
package io.element.android.libraries.eventformatter.api
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName
interface TimelineEventFormatter {
fun format(event: EventTimelineItem): CharSequence?
fun format(event: EventTimelineItem): CharSequence? {
return format(
content = event.content,
isOutgoing = event.isOwn,
sender = event.sender,
senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender),
)
}
fun format(content: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): CharSequence?
}

View file

@ -13,7 +13,9 @@ import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.eventformatter.api.TimelineEventFormatter
import io.element.android.libraries.eventformatter.impl.mode.RenderingMode
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
@ -43,12 +45,16 @@ class DefaultTimelineEventFormatter(
override fun format(event: EventTimelineItem): CharSequence? {
val isOutgoing = event.isOwn
val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender)
return when (val content = event.content) {
return format(event.content, isOutgoing, event.sender, senderDisambiguatedDisplayName)
}
override fun format(content: EventContent, isOutgoing: Boolean, sender: UserId, senderDisambiguatedDisplayName: String): CharSequence? {
return when (content) {
is RoomMembershipContent -> {
roomMembershipContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing)
}
is ProfileChangeContent -> {
profileChangeContentFormatter.format(content, event.sender, senderDisambiguatedDisplayName, isOutgoing)
profileChangeContentFormatter.format(content, sender, senderDisambiguatedDisplayName, isOutgoing)
}
is StateContent -> {
stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.Timeline)
@ -66,7 +72,7 @@ class DefaultTimelineEventFormatter(
is FailedToParseStateContent,
is UnknownContent -> {
if (buildMeta.isDebuggable) {
error("You should not use this formatter for this event: $event")
error("You should not use this formatter for this event content: $content")
}
sp.getString(CommonStrings.common_unsupported_event)
}

View file

@ -14,7 +14,6 @@ import com.google.common.truth.Truth.assertWithMessage
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
@ -175,7 +174,7 @@ class DefaultBaseRoomLastMessageFormatterTest {
) {
val body = "Shared body"
fun createMessageContent(type: MessageType): MessageContent {
return MessageContent(body, null, false, EventThreadInfo(null, null), type)
return MessageContent(body, null, false, null, type)
}
val sharedContentMessagesTypes = arrayOf(

View file

@ -14,7 +14,6 @@ import com.google.common.truth.Truth.assertWithMessage
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.timeline.item.EventThreadInfo
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
@ -130,7 +129,7 @@ class DefaultPinnedMessagesBannerFormatterTest {
fun `Message contents`() {
val body = "Shared body"
fun createMessageContent(type: MessageType): MessageContent {
return MessageContent(body, null, false, EventThreadInfo(null, null), type)
return MessageContent(body, null, false, null, type)
}
val sharedContentMessagesTypes = arrayOf(