Fix formatting inconsistencies in latest event summaries (#6855)

* Fix message type prefixes formatting inconsistencies

* Use new string for the poll summary prefix instead of the A11y text. Also add tests check for the bold spans.

---------

Co-authored-by: Jorge Martín <jorgem@element.io>
This commit is contained in:
bxdxnn 2026-05-25 12:40:25 +03:00 committed by GitHub
parent b31dad4b26
commit 3df85017af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 38 additions and 8 deletions

View file

@ -93,8 +93,8 @@ class DefaultRoomLatestEventFormatter(
message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
}
is StickerContent -> {
val message = sp.getString(CommonStrings.common_sticker) + " (" + content.bestDescription + ")"
message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
content.bestDescription.prefixWith(sp.getString(CommonStrings.common_sticker))
.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
}
is UnableToDecryptContent -> {
val message = sp.getString(CommonStrings.common_waiting_for_decryption_key)
@ -110,8 +110,8 @@ class DefaultRoomLatestEventFormatter(
stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.RoomList)
}
is PollContent -> {
val message = sp.getString(CommonStrings.common_poll_summary, content.question)
message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
content.question.prefixWith(sp.getString(CommonStrings.common_poll_summary_prefix))
.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
}
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
val message = sp.getString(CommonStrings.common_unsupported_event)

View file

@ -20,6 +20,10 @@ internal fun CharSequence.prefixWith(prefix: String): AnnotatedString {
append(prefix)
}
append(": ")
append(this@prefixWith)
if (this@prefixWith is AnnotatedString) {
append(this@prefixWith)
} else {
append(this@prefixWith.toString())
}
}
}

View file

@ -10,6 +10,7 @@ package io.element.android.libraries.eventformatter.impl
import android.content.Context
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import io.element.android.libraries.matrix.api.core.UserId
@ -103,7 +104,14 @@ class DefaultRoomLatestEventFormatterTest {
val info = ImageInfo(null, null, null, null, null, null, null)
val message = createLatestEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url")))
val result = formatter.format(message, false)
val expectedBody = someoneElseId.value + ": Sticker (a sticker body)"
val expectedBody = someoneElseId.value + ": Sticker: a sticker body"
// Check we have formatting
assertThat(result is AnnotatedString).isTrue()
// And there is a bold span for the 'Sticker' part
val boldSpanStyle = (result as AnnotatedString).spanStyles.lastOrNull { it.item.fontWeight == FontWeight.Bold }
assertThat(boldSpanStyle).isNotNull()
val spanStart = someoneElseId.value.length + 2
assertThat(boldSpanStyle!!.start..boldSpanStyle.end).isEqualTo(spanStart..spanStart + 7)
assertThat(result.toString()).isEqualTo(expectedBody)
}
@ -909,10 +917,18 @@ class DefaultRoomLatestEventFormatterTest {
val pollContent = aPollContent()
val mineContentEvent = createLatestEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent)
assertThat(formatter.format(mineContentEvent, true)).isEqualTo("Poll: Do you like polls?")
assertThat(formatter.format(mineContentEvent, true).toString()).isEqualTo("Poll: Do you like polls?")
val contentEvent = createLatestEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent)
assertThat(formatter.format(contentEvent, true)).isEqualTo("Poll: Do you like polls?")
assertThat(formatter.format(contentEvent, true).toString()).isEqualTo("Poll: Do you like polls?")
val result = formatter.format(contentEvent, true)
// Check we have formatting
assertThat(result is AnnotatedString).isTrue()
// And there is a bold span for the 'Poll' part
val boldSpanStyle = (result as AnnotatedString).spanStyles.lastOrNull { it.item.fontWeight == FontWeight.Bold }
assertThat(boldSpanStyle).isNotNull()
assertThat(boldSpanStyle!!.start..boldSpanStyle.end).isEqualTo(0..4)
}
@Test
@ -925,6 +941,15 @@ class DefaultRoomLatestEventFormatterTest {
val contentEvent = createLatestEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent)
assertThat(formatter.format(contentEvent, false).toString()).isEqualTo("Bob: Poll: Do you like polls?")
val result = formatter.format(contentEvent, false)
// Check we have formatting
assertThat(result is AnnotatedString).isTrue()
// And there is a bold span for the 'Poll' part
val boldSpanStyle = (result as AnnotatedString).spanStyles.lastOrNull { it.item.fontWeight == FontWeight.Bold }
assertThat(boldSpanStyle).isNotNull()
val spanStart = "Bob".length + 2
assertThat(boldSpanStyle!!.start..boldSpanStyle.end).isEqualTo(spanStart..spanStart + 4)
}
// endregion

View file

@ -303,6 +303,7 @@ Reason: %1$s."</string>
<string name="common_please_wait">"Please wait…"</string>
<string name="common_poll_end_confirmation">"Are you sure you want to end this poll?"</string>
<string name="common_poll_summary">"Poll: %1$s"</string>
<string name="common_poll_summary_prefix">"Poll"</string>
<string name="common_poll_total_votes">"Total votes: %1$s"</string>
<string name="common_poll_undisclosed_text">"Results will show after the poll has ended"</string>
<plurals name="common_poll_votes_count">