From b2a61f2ed3482f104b3c26c0369e5b665dd9ed07 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Fri, 27 Oct 2023 11:30:57 +0200 Subject: [PATCH] Show correct UI when replying to a voice message (#1658) Shows voice messages in the room summary. Shows voice messages in the reply context menu and composer. Show replies to voice messages in the timeline. (before this PR voice messages were shown the same as audio messages) Story: https://github.com/vector-im/element-meta/issues/2106 --- .../messages/impl/MessagesPresenter.kt | 5 ++++- .../actionlist/ActionListStateProvider.kt | 18 +++++++++++++++ .../impl/actionlist/ActionListView.kt | 13 ++++++++++- .../components/TimelineItemEventRow.kt | 16 ++++++++++---- .../main/res/drawable/ic_voice_attachment.xml | 9 ++++++++ .../impl/DefaultRoomLastMessageFormatter.kt | 6 ++++- .../DefaultRoomLastMessageFormatterTest.kt | 22 ++++++++++++++++--- .../ui/components/AttachmentThumbnail.kt | 8 ++++++- ...tContent-D-1_1_null_10,NEXUS_5,1.0,en].png | 3 +++ ...etContent-D-1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...etContent-D-1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...etContent-D-1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...etContent-D-1_1_null_9,NEXUS_5,1.0,en].png | 3 +++ ...tContent-N-1_2_null_10,NEXUS_5,1.0,en].png | 3 +++ ...etContent-N-1_2_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...etContent-N-1_2_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...etContent-N-1_2_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...etContent-N-1_2_null_9,NEXUS_5,1.0,en].png | 3 +++ 18 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 libraries/designsystem/src/main/res/drawable/ic_voice_attachment.xml create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_10,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_9,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_10,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_9,NEXUS_5,1.0,en].png diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index ea9eade4b3..f924e7f716 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -331,11 +331,14 @@ class MessagesPresenter @AssistedInject constructor( textContent = targetEvent.content.body, type = AttachmentThumbnailType.Audio, ) + is TimelineItemVoiceContent -> AttachmentThumbnailInfo( + textContent = targetEvent.content.body, + type = AttachmentThumbnailType.Voice, + ) is TimelineItemLocationContent -> AttachmentThumbnailInfo( type = AttachmentThumbnailType.Location, ) is TimelineItemPollContent, // TODO Polls: handle reply to - is TimelineItemVoiceContent, // TODO Voice messages: handle reply to is TimelineItemTextBasedContent, is TimelineItemRedactedContent, is TimelineItemStateContent, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index 44736bc076..3ea99aaede 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -20,11 +20,13 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVideoContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -67,6 +69,22 @@ open class ActionListStateProvider : PreviewParameterProvider { actions = aTimelineItemActionList(), ) ), + anActionListState().copy( + target = ActionListState.Target.Success( + event = aTimelineItemEvent(content = aTimelineItemAudioContent()).copy( + reactionsState = reactionsState + ), + actions = aTimelineItemActionList(), + ) + ), + anActionListState().copy( + target = ActionListState.Target.Success( + event = aTimelineItemEvent(content = aTimelineItemVoiceContent()).copy( + reactionsState = reactionsState + ), + actions = aTimelineItemActionList(), + ) + ), anActionListState().copy( target = ActionListState.Target.Success( event = aTimelineItemEvent(content = aTimelineItemLocationContent()).copy( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index c5e6e5facd..bed3af59bd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -238,7 +238,6 @@ private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modif when (event.content) { is TimelineItemPollContent, // TODO Polls: handle summary - is TimelineItemVoiceContent, // TODO Voice messages: handle reply summary is TimelineItemTextBasedContent, is TimelineItemStateContent, is TimelineItemEncryptedContent, @@ -309,6 +308,18 @@ private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modif } content = { ContentForBody(event.content.body) } } + is TimelineItemVoiceContent -> { + icon = { + AttachmentThumbnail( + modifier = imageModifier, + info = AttachmentThumbnailInfo( + textContent = textContent, + type = AttachmentThumbnailType.Voice, + ) + ) + } + content = { ContentForBody(event.content.body) } + } } Row(modifier = modifier) { icon() diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 0ef1c9bc67..304ff88662 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -612,10 +612,18 @@ private fun attachmentThumbnailInfoForInReplyTo(inReplyTo: InReplyTo.Ready): Att textContent = messageContent.body, type = AttachmentThumbnailType.Location, ) - is AudioMessageType -> AttachmentThumbnailInfo( - textContent = messageContent.body, - type = AttachmentThumbnailType.Audio, - ) + is AudioMessageType -> { + when (type.isVoiceMessage) { + true -> AttachmentThumbnailInfo( + textContent = messageContent.body, + type = AttachmentThumbnailType.Voice, + ) + false -> AttachmentThumbnailInfo( + textContent = messageContent.body, + type = AttachmentThumbnailType.Audio, + ) + } + } else -> null } } diff --git a/libraries/designsystem/src/main/res/drawable/ic_voice_attachment.xml b/libraries/designsystem/src/main/res/drawable/ic_voice_attachment.xml new file mode 100644 index 0000000000..d8986e206d --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_voice_attachment.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt index 80e7a7155b..99b06401d9 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt @@ -128,7 +128,11 @@ class DefaultRoomLastMessageFormatter @Inject constructor( sp.getString(CommonStrings.common_file) } is AudioMessageType -> { - sp.getString(CommonStrings.common_audio) + if (messageType.isVoiceMessage) { + sp.getString(CommonStrings.common_voice_message) + } else { + sp.getString(CommonStrings.common_audio) + } } is OtherMessageType -> { messageType.body diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt index bc58aa1d48..48c498c3d8 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt @@ -163,6 +163,7 @@ class DefaultRoomLastMessageFormatterTest { TextMessageType(body, null), VideoMessageType(body, MediaSource("url"), null), AudioMessageType(body, MediaSource("url"), null, null, false), + AudioMessageType(body, MediaSource("url"), null, null, true), ImageMessageType(body, MediaSource("url"), null), FileMessageType(body, MediaSource("url"), null), LocationMessageType(body, "geo:1,2", null), @@ -198,7 +199,12 @@ class DefaultRoomLastMessageFormatterTest { for ((type, result) in resultsInDm) { val expectedResult = when (type) { is VideoMessageType -> "Video" - is AudioMessageType -> "Audio" + is AudioMessageType -> { + when (type.isVoiceMessage) { + true -> "Voice message" + false -> "Audio" + } + } is ImageMessageType -> "Image" is FileMessageType -> "File" is LocationMessageType -> "Shared location" @@ -216,7 +222,12 @@ class DefaultRoomLastMessageFormatterTest { val string = result.toString() val expectedResult = when (type) { is VideoMessageType -> "$senderName: Video" - is AudioMessageType -> "$senderName: Audio" + is AudioMessageType -> { + when (type.isVoiceMessage) { + true -> "$senderName: Voice message" + false -> "$senderName: Audio" + } + } is ImageMessageType -> "$senderName: Image" is FileMessageType -> "$senderName: File" is LocationMessageType -> "$senderName: Shared location" @@ -228,7 +239,12 @@ class DefaultRoomLastMessageFormatterTest { } val shouldCreateAnnotatedString = when (type) { is VideoMessageType -> true - is AudioMessageType -> true + is AudioMessageType -> { + when (type.isVoiceMessage) { + true -> true + false -> true + } + } is ImageMessageType -> true is FileMessageType -> true is LocationMessageType -> false diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AttachmentThumbnail.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AttachmentThumbnail.kt index cafbdd04c0..c1fa34a764 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AttachmentThumbnail.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AttachmentThumbnail.kt @@ -75,6 +75,12 @@ fun AttachmentThumbnail( contentDescription = info.textContent, ) } + AttachmentThumbnailType.Voice -> { + Icon( + resourceId = CommonDrawables.ic_voice_attachment, + contentDescription = info.textContent, + ) + } AttachmentThumbnailType.File -> { Icon( resourceId = CommonDrawables.ic_september_attachment, @@ -95,7 +101,7 @@ fun AttachmentThumbnail( @Parcelize enum class AttachmentThumbnailType : Parcelable { - Image, Video, File, Audio, Location + Image, Video, File, Audio, Location, Voice } @Parcelize diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_10,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..af7782f5d7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_10,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85692ea3847fe5a79f955bb71153ccb6e5b24cf451292c7b9d56f26e2eff95b7 +size 28840 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_6,NEXUS_5,1.0,en].png index 74448d6967..c458b9a7b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:979138753000ada021a67f4bc14a89b912430c4331ac69aa702b2e50c050d7cb -size 41200 +oid sha256:d32becec465a3f01e35aac9ebbeb8f48507cc2146f35b8e6c6393bbd410cca3e +size 39370 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_7,NEXUS_5,1.0,en].png index 3cb12c4c94..0ed5c052a6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e06e1a32d8c9d06a307a5116a396a03308d5e5486f911d34002139485e7d9ffe -size 28176 +oid sha256:a1f8750e66aa2a60198fe68d2e3185bcf5a8708df81502f33c394d72f7b20a30 +size 42765 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_8,NEXUS_5,1.0,en].png index af7782f5d7..74448d6967 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85692ea3847fe5a79f955bb71153ccb6e5b24cf451292c7b9d56f26e2eff95b7 -size 28840 +oid sha256:979138753000ada021a67f4bc14a89b912430c4331ac69aa702b2e50c050d7cb +size 41200 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_9,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..3cb12c4c94 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-1_1_null_9,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e06e1a32d8c9d06a307a5116a396a03308d5e5486f911d34002139485e7d9ffe +size 28176 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_10,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..ee2fa7b46f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_10,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5df2d3b6e4698867277712214fa526e08a9bf790140cd000cfe2bf94c70e77f4 +size 27525 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_6,NEXUS_5,1.0,en].png index 8d45efac8c..dbe1f4d267 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:752abe37a810cc8e4b36ae5f4c4aa38c9f22757b6458f272ba991050c69aee53 -size 39409 +oid sha256:a99566280864e66ec327d2d6d8016c74b12f1c62ff27fd0d2d4ba0109ae9756a +size 37747 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_7,NEXUS_5,1.0,en].png index 811cb7e4cd..8ee1838413 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c53fdbe427ddb7088d9bd8f9b46a1281d145fd6f9ccc3a7de339750e3079075 -size 26498 +oid sha256:fbb1233cf288e6ffc1aaa7136b56c412699897d7edd20bef82784562e302bf40 +size 41215 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_8,NEXUS_5,1.0,en].png index ee2fa7b46f..8d45efac8c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5df2d3b6e4698867277712214fa526e08a9bf790140cd000cfe2bf94c70e77f4 -size 27525 +oid sha256:752abe37a810cc8e4b36ae5f4c4aa38c9f22757b6458f272ba991050c69aee53 +size 39409 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_9,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..811cb7e4cd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-1_2_null_9,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c53fdbe427ddb7088d9bd8f9b46a1281d145fd6f9ccc3a7de339750e3079075 +size 26498