Format state Event: use disambiguated Display name #2722.

- Rename some parameter and val from `senderDisplayName` (and consort) to `senderDisambiguatedDisplayName`.
- In `InReplyToDetails`, replace `senderDisplayName` and `senderAvatarUrl` by `senderProfile`.
This commit is contained in:
Benoit Marty 2024-04-22 11:52:53 +02:00 committed by Benoit Marty
parent e0d40ec0a4
commit 03abfcaadb
29 changed files with 157 additions and 140 deletions

View file

@ -41,7 +41,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessage
import io.element.android.libraries.matrix.api.timeline.item.event.OtherMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
@ -52,6 +51,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecry
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName
import io.element.android.libraries.matrix.ui.messages.toPlainText
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.toolbox.api.strings.StringProvider
@ -72,15 +72,13 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
override fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? {
val isOutgoing = event.isOwn
// Note: we do not use disambiguated display name here, see
// https://github.com/element-hq/element-x-ios/issues/1845#issuecomment-1888707428
val senderDisplayName = (event.senderProfile as? ProfileTimelineDetails.Ready)?.displayName ?: event.sender.value
val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender)
return when (val content = event.content) {
is MessageContent -> processMessageContents(content, senderDisplayName, isDmRoom)
is MessageContent -> processMessageContents(content, senderDisambiguatedDisplayName, isDmRoom)
RedactedContent -> {
val message = sp.getString(CommonStrings.common_message_removed)
if (!isDmRoom) {
prefix(message, senderDisplayName)
prefix(message, senderDisambiguatedDisplayName)
} else {
message
}
@ -91,36 +89,40 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
is UnableToDecryptContent -> {
val message = sp.getString(CommonStrings.common_waiting_for_decryption_key)
if (!isDmRoom) {
prefix(message, senderDisplayName)
prefix(message, senderDisambiguatedDisplayName)
} else {
message
}
}
is RoomMembershipContent -> {
roomMembershipContentFormatter.format(content, senderDisplayName, isOutgoing)
roomMembershipContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing)
}
is ProfileChangeContent -> {
profileChangeContentFormatter.format(content, event.sender, senderDisplayName, isOutgoing)
profileChangeContentFormatter.format(content, event.sender, senderDisambiguatedDisplayName, isOutgoing)
}
is StateContent -> {
stateContentFormatter.format(content, senderDisplayName, isOutgoing, RenderingMode.RoomList)
stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.RoomList)
}
is PollContent -> {
val message = sp.getString(CommonStrings.common_poll_summary, content.question)
prefixIfNeeded(message, senderDisplayName, isDmRoom)
prefixIfNeeded(message, senderDisambiguatedDisplayName, isDmRoom)
}
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
prefixIfNeeded(sp.getString(CommonStrings.common_unsupported_event), senderDisplayName, isDmRoom)
prefixIfNeeded(sp.getString(CommonStrings.common_unsupported_event), senderDisambiguatedDisplayName, isDmRoom)
}
is LegacyCallInviteContent -> sp.getString(CommonStrings.common_call_invite)
}?.take(MAX_SAFE_LENGTH)
}
private fun processMessageContents(messageContent: MessageContent, senderDisplayName: String, isDmRoom: Boolean): CharSequence? {
private fun processMessageContents(
messageContent: MessageContent,
senderDisambiguatedDisplayName: String,
isDmRoom: Boolean,
): CharSequence {
val internalMessage = when (val messageType: MessageType = messageContent.type) {
// Doesn't need a prefix
is EmoteMessageType -> {
return "* $senderDisplayName ${messageType.body}"
return "* $senderDisambiguatedDisplayName ${messageType.body}"
}
is TextMessageType -> {
messageType.toPlainText(permalinkParser)
@ -153,19 +155,23 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
messageType.body
}
}
return prefixIfNeeded(internalMessage, senderDisplayName, isDmRoom)
return prefixIfNeeded(internalMessage, senderDisambiguatedDisplayName, isDmRoom)
}
private fun prefixIfNeeded(message: String, senderDisplayName: String, isDmRoom: Boolean): CharSequence = if (isDmRoom) {
private fun prefixIfNeeded(
message: String,
senderDisambiguatedDisplayName: String,
isDmRoom: Boolean,
): CharSequence = if (isDmRoom) {
message
} else {
prefix(message, senderDisplayName)
prefix(message, senderDisambiguatedDisplayName)
}
private fun prefix(message: String, senderDisplayName: String): AnnotatedString {
private fun prefix(message: String, senderDisambiguatedDisplayName: String): AnnotatedString {
return buildAnnotatedString {
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(senderDisplayName)
append(senderDisambiguatedDisplayName)
}
append(": ")
append(message)

View file

@ -49,16 +49,16 @@ class DefaultTimelineEventFormatter @Inject constructor(
) : TimelineEventFormatter {
override fun format(event: EventTimelineItem): CharSequence? {
val isOutgoing = event.isOwn
val senderDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender)
val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender)
return when (val content = event.content) {
is RoomMembershipContent -> {
roomMembershipContentFormatter.format(content, senderDisplayName, isOutgoing)
roomMembershipContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing)
}
is ProfileChangeContent -> {
profileChangeContentFormatter.format(content, event.sender, senderDisplayName, isOutgoing)
profileChangeContentFormatter.format(content, event.sender, senderDisambiguatedDisplayName, isOutgoing)
}
is StateContent -> {
stateContentFormatter.format(content, senderDisplayName, isOutgoing, RenderingMode.Timeline)
stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.Timeline)
}
is LegacyCallInviteContent -> {
sp.getString(CommonStrings.common_call_invite)

View file

@ -27,14 +27,19 @@ class ProfileChangeContentFormatter @Inject constructor(
fun format(
profileChangeContent: ProfileChangeContent,
senderId: UserId,
senderDisplayName: String,
senderDisambiguatedDisplayName: String,
senderIsYou: Boolean,
): String? = profileChangeContent.run {
val displayNameChanged = displayName != prevDisplayName
val avatarChanged = avatarUrl != prevAvatarUrl
return when {
avatarChanged && displayNameChanged -> {
val message = format(profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null), senderId, senderDisplayName, senderIsYou)
val message = format(
profileChangeContent = profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null),
senderId = senderId,
senderDisambiguatedDisplayName = senderDisambiguatedDisplayName,
senderIsYou = senderIsYou,
)
val avatarChangedToo = sp.getString(R.string.state_event_avatar_changed_too)
"$message\n$avatarChangedToo"
}
@ -63,7 +68,7 @@ class ProfileChangeContentFormatter @Inject constructor(
if (senderIsYou) {
sp.getString(R.string.state_event_avatar_url_changed_by_you)
} else {
sp.getString(R.string.state_event_avatar_url_changed, senderDisplayName)
sp.getString(R.string.state_event_avatar_url_changed, senderDisambiguatedDisplayName)
}
}
else -> null

View file

@ -29,7 +29,7 @@ class RoomMembershipContentFormatter @Inject constructor(
) {
fun format(
membershipContent: RoomMembershipContent,
senderDisplayName: String,
senderDisambiguatedDisplayName: String,
senderIsYou: Boolean,
): CharSequence? {
val userId = membershipContent.userId
@ -48,24 +48,24 @@ class RoomMembershipContentFormatter @Inject constructor(
MembershipChange.BANNED, MembershipChange.KICKED_AND_BANNED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_ban_by_you, userId.value)
} else {
sp.getString(R.string.state_event_room_ban, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_ban, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.UNBANNED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_unban_by_you, userId.value)
} else {
sp.getString(R.string.state_event_room_unban, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_unban, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.KICKED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_remove_by_you, userId.value)
} else {
sp.getString(R.string.state_event_room_remove, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_remove, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.INVITED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_invite_by_you, userId.value)
} else if (memberIsYou) {
sp.getString(R.string.state_event_room_invite_you, senderDisplayName)
sp.getString(R.string.state_event_room_invite_you, senderDisambiguatedDisplayName)
} else {
sp.getString(R.string.state_event_room_invite, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_invite, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.INVITATION_ACCEPTED -> if (memberIsYou) {
sp.getString(R.string.state_event_room_invite_accepted_by_you)
@ -80,7 +80,7 @@ class RoomMembershipContentFormatter @Inject constructor(
MembershipChange.INVITATION_REVOKED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_third_party_revoked_invite_by_you, userId.value)
} else {
sp.getString(R.string.state_event_room_third_party_revoked_invite, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_third_party_revoked_invite, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.KNOCKED -> if (memberIsYou) {
sp.getString(R.string.state_event_room_knock_by_you)
@ -90,7 +90,7 @@ class RoomMembershipContentFormatter @Inject constructor(
MembershipChange.KNOCK_ACCEPTED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_knock_accepted_by_you, userId.value)
} else {
sp.getString(R.string.state_event_room_knock_accepted, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_knock_accepted, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.KNOCK_RETRACTED -> if (memberIsYou) {
sp.getString(R.string.state_event_room_knock_retracted_by_you)
@ -100,14 +100,14 @@ class RoomMembershipContentFormatter @Inject constructor(
MembershipChange.KNOCK_DENIED -> if (senderIsYou) {
sp.getString(R.string.state_event_room_knock_denied_by_you, userId.value)
} else if (memberIsYou) {
sp.getString(R.string.state_event_room_knock_denied_you, senderDisplayName)
sp.getString(R.string.state_event_room_knock_denied_you, senderDisambiguatedDisplayName)
} else {
sp.getString(R.string.state_event_room_knock_denied, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_knock_denied, senderDisambiguatedDisplayName, userId.value)
}
MembershipChange.NONE -> if (senderIsYou) {
sp.getString(R.string.state_event_room_none_by_you)
} else {
sp.getString(R.string.state_event_room_none, senderDisplayName)
sp.getString(R.string.state_event_room_none, senderDisambiguatedDisplayName)
}
MembershipChange.ERROR -> {
Timber.v("Filtering timeline item for room membership: $membershipContent")

View file

@ -29,7 +29,7 @@ class StateContentFormatter @Inject constructor(
) {
fun format(
stateContent: StateContent,
senderDisplayName: String,
senderDisambiguatedDisplayName: String,
senderIsYou: Boolean,
renderingMode: RenderingMode,
): CharSequence? {
@ -39,15 +39,15 @@ class StateContentFormatter @Inject constructor(
when {
senderIsYou && hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_changed_by_you)
senderIsYou && !hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_removed_by_you)
!senderIsYou && hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_changed, senderDisplayName)
else -> sp.getString(R.string.state_event_room_avatar_removed, senderDisplayName)
!senderIsYou && hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_changed, senderDisambiguatedDisplayName)
else -> sp.getString(R.string.state_event_room_avatar_removed, senderDisambiguatedDisplayName)
}
}
is OtherState.RoomCreate -> {
if (senderIsYou) {
sp.getString(R.string.state_event_room_created_by_you)
} else {
sp.getString(R.string.state_event_room_created, senderDisplayName)
sp.getString(R.string.state_event_room_created, senderDisambiguatedDisplayName)
}
}
is OtherState.RoomEncryption -> sp.getString(CommonStrings.common_encryption_enabled)
@ -56,8 +56,8 @@ class StateContentFormatter @Inject constructor(
when {
senderIsYou && hasRoomName -> sp.getString(R.string.state_event_room_name_changed_by_you, content.name)
senderIsYou && !hasRoomName -> sp.getString(R.string.state_event_room_name_removed_by_you)
!senderIsYou && hasRoomName -> sp.getString(R.string.state_event_room_name_changed, senderDisplayName, content.name)
else -> sp.getString(R.string.state_event_room_name_removed, senderDisplayName)
!senderIsYou && hasRoomName -> sp.getString(R.string.state_event_room_name_changed, senderDisambiguatedDisplayName, content.name)
else -> sp.getString(R.string.state_event_room_name_removed, senderDisambiguatedDisplayName)
}
}
is OtherState.RoomThirdPartyInvite -> {
@ -68,7 +68,7 @@ class StateContentFormatter @Inject constructor(
if (senderIsYou) {
sp.getString(R.string.state_event_room_third_party_invite_by_you, content.displayName)
} else {
sp.getString(R.string.state_event_room_third_party_invite, senderDisplayName, content.displayName)
sp.getString(R.string.state_event_room_third_party_invite, senderDisambiguatedDisplayName, content.displayName)
}
}
is OtherState.RoomTopic -> {
@ -76,8 +76,8 @@ class StateContentFormatter @Inject constructor(
when {
senderIsYou && hasRoomTopic -> sp.getString(R.string.state_event_room_topic_changed_by_you, content.topic)
senderIsYou && !hasRoomTopic -> sp.getString(R.string.state_event_room_topic_removed_by_you)
!senderIsYou && hasRoomTopic -> sp.getString(R.string.state_event_room_topic_changed, senderDisplayName, content.topic)
else -> sp.getString(R.string.state_event_room_topic_removed, senderDisplayName)
!senderIsYou && hasRoomTopic -> sp.getString(R.string.state_event_room_topic_changed, senderDisambiguatedDisplayName, content.topic)
else -> sp.getString(R.string.state_event_room_topic_removed, senderDisambiguatedDisplayName)
}
}
is OtherState.Custom -> when (renderingMode) {