From c362bca5270f88d8d64b55c914ae6be849c7e404 Mon Sep 17 00:00:00 2001 From: hayyaksi <193020925+hayaksi1@users.noreply.github.com> Date: Thu, 20 Aug 2026 09:55:50 +0300 Subject: [PATCH] Keep the send button when the composer is emptied while editing a message (#7456) * Keep the send button when the composer is emptied while editing rememberEndButtonParams checked whether the composer had sendable text before it checked whether the user was editing a message, so clearing the text of a message being edited replaced the send button with the voice recorder button. Starting a recording from there abandons the edit. Check the editing branch first, as the formatting composer already does, and let it render a disabled send button when there is nothing to send. * Update screenshots --- .../libraries/textcomposer/TextComposer.kt | 26 +++--- .../textcomposer/TextComposerEndButtonTest.kt | 85 +++++++++++++++++++ ...oser_MarkdownTextComposerEdit_Day_0_en.png | 4 +- ...er_MarkdownTextComposerEdit_Night_0_en.png | 4 +- ...mposer_TextComposerAddCaption_Day_0_en.png | 4 +- ...oser_TextComposerAddCaption_Night_0_en.png | 4 +- ...poser_TextComposerEditCaption_Day_0_en.png | 4 +- ...ser_TextComposerEditCaption_Night_0_en.png | 4 +- ..._TextComposerEditNotEncrypted_Day_0_en.png | 4 +- ...extComposerEditNotEncrypted_Night_0_en.png | 4 +- ...textcomposer_TextComposerEdit_Day_0_en.png | 4 +- ...xtcomposer_TextComposerEdit_Night_0_en.png | 4 +- 12 files changed, 119 insertions(+), 32 deletions(-) create mode 100644 libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/TextComposerEndButtonTest.kt diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 66c9dcba03..980443621c 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -245,6 +245,20 @@ fun TextComposer( canSendTextMessage, ) { when { + composerMode.isEditing -> EndButtonParams( + endButtonContentDescriptionResId = CommonStrings.action_send_edited_message, + endButtonClick = { + if (canSendTextMessage) { + onSendMessage() + } + }, + endButtonContent = @Composable { + SendButtonIcon( + canSendMessage = canSendTextMessage, + isEditing = true, + ) + }, + ) !canSendTextMessage -> when (voiceMessageState) { VoiceMessageState.Idle -> EndButtonParams( @@ -296,18 +310,6 @@ fun TextComposer( ) } } - composerMode.isEditing -> EndButtonParams( - endButtonContentDescriptionResId = CommonStrings.action_send_edited_message, - endButtonClick = { - onSendMessage() - }, - endButtonContent = @Composable { - SendButtonIcon( - canSendMessage = true, - isEditing = true, - ) - }, - ) else -> EndButtonParams( endButtonContentDescriptionResId = CommonStrings.action_send_message, endButtonClick = { diff --git a/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/TextComposerEndButtonTest.kt b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/TextComposerEndButtonTest.kt new file mode 100644 index 0000000000..c979e8c909 --- /dev/null +++ b/libraries/textcomposer/impl/src/test/kotlin/io/element/android/libraries/textcomposer/TextComposerEndButtonTest.kt @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * Copyright 2026 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +@file:OptIn(ExperimentalTestApi::class) + +package io.element.android.libraries.textcomposer + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.v2.runAndroidComposeUiTest +import io.element.android.libraries.textcomposer.model.MessageComposerMode +import io.element.android.libraries.textcomposer.model.VoiceMessageState +import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.robolectric.RobolectricTest +import io.element.android.wysiwyg.display.TextDisplay +import org.junit.Test + +class TextComposerEndButtonTest : RobolectricTest() { + @Test + fun `editing a message with text shows the send edited message button`() = runAndroidComposeUiTest { + setTextComposer(text = "Some text", composerMode = aMessageComposerModeEdit()) + onNodeWithContentDescription(getString(CommonStrings.action_send_edited_message)).assertIsDisplayed() + } + + @Test + fun `emptying the composer while editing keeps the send edited message button`() = runAndroidComposeUiTest { + setTextComposer(text = "", composerMode = aMessageComposerModeEdit()) + onNodeWithContentDescription(getString(CommonStrings.action_send_edited_message)).assertIsDisplayed() + onNodeWithContentDescription(getString(CommonStrings.a11y_voice_message_record)).assertDoesNotExist() + } + + @Test + fun `emptying the composer while editing a caption keeps the send edited message button`() = runAndroidComposeUiTest { + setTextComposer(text = "", composerMode = aMessageComposerModeEditCaption(content = "An existing caption")) + onNodeWithContentDescription(getString(CommonStrings.action_send_edited_message)).assertIsDisplayed() + onNodeWithContentDescription(getString(CommonStrings.a11y_voice_message_record)).assertDoesNotExist() + } + + @Test + fun `an empty composer outside of edition still offers to record a voice message`() = runAndroidComposeUiTest { + setTextComposer(text = "", composerMode = MessageComposerMode.Normal) + onNodeWithContentDescription(getString(CommonStrings.a11y_voice_message_record)).assertIsDisplayed() + } + + private fun AndroidComposeUiTest.getString(resId: Int): String { + return activity!!.getString(resId) + } + + private fun AndroidComposeUiTest.setTextComposer( + text: String, + composerMode: MessageComposerMode, + ) { + setContent { + TextComposer( + state = aTextEditorStateMarkdown(initialText = text, initialFocus = true), + voiceMessageState = VoiceMessageState.Idle, + composerMode = composerMode, + onRequestFocus = {}, + onSendMessage = {}, + onResetComposerMode = {}, + onAddAttachment = {}, + onDismissTextFormatting = {}, + onVoiceRecorderEvent = {}, + onVoicePlayerEvent = {}, + onSendVoiceMessage = {}, + onDeleteVoiceMessage = {}, + onError = {}, + onTyping = {}, + onReceiveSuggestion = {}, + onSelectRichContent = null, + resolveMentionDisplay = { _, _ -> TextDisplay.Plain }, + resolveAtRoomMentionDisplay = { TextDisplay.Plain }, + ) + } + } +} diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png index 96215547bb..bae0e74d1e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1622f9765fda65985a369d6958f7a5993696dd629c0c1013c0a1647cfb7b562 -size 50109 +oid sha256:25fdfa4b65263c02e10c6ddea16a3210a84722a742a66cd2d91b8b3f61968466 +size 49924 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png index 70d41498a8..389ae383c8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a94de003f65d2fb30ab42e4ac60802707abf1358b0defed7598a3aad69992f40 -size 48136 +oid sha256:dc99c7505aa48b7ccdbae1de6daec75c12b9293172c804ef3cf027f6b46c45ea +size 47883 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png index c17cbfdb66..45f5ce2bde 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdab4bea33337547250355c29991f45c118e8c2c05abdf69b1824475feced5d6 -size 51241 +oid sha256:c446e3b322a1eb8634f2f643819672cfb626ca9e76c7e1fb5a10fc03a1ae7824 +size 51031 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png index ef9c49d6c5..ff238fd979 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerAddCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f92c594febc463911c8418deeff3b94e5a8ce4171461d812a0f4f527ab0cf8e -size 49245 +oid sha256:86260ffd841034c31327df736e0e127271f875a6cf383c688b7ea8c3a9d1dbd4 +size 48943 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png index 9ba3d99527..cebea0c88b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81d8acdb1158c3e5c19b5a602e3b9afe7643f1bb77d43f51d3f5c4327478a76a -size 50282 +oid sha256:9669ba8ab19e7f7f1322e973e6f39855113b45ab5f6b26e7b5230a2fe9ec1d68 +size 50067 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png index 969e5b04bf..50cd50736a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditCaption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c225ad12c5a32e2392606f9afacc6dbc37478a141d5485e4942012c6b22ad052 -size 48046 +oid sha256:f1f66076e3b06df1471f367bed57f81d15272e3600eebc51cd131794e29d5dfb +size 47767 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png index a0192f0890..c4b21b86af 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cfb1d8b7828692d5c318206770f9484822a1749b3e80a618b502811cf512d76 -size 60489 +oid sha256:ffe11074abe52ccd1c34f687f780c5185be370b2b92867ee0b686bad85f28890 +size 60210 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png index c745fa256a..839c4a88ba 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca67409e4af247b43d8594d6351419cd12894485357596aff7b26745e2df009a -size 57687 +oid sha256:e9914f3ffd70dd83013ff6059539bda348ae64fc39a2419d621f8d198f6471cc +size 57380 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png index 635e14be9e..f47016a59f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b3a91d104a5949dde83ac38b3127afa342816c631a1e29d78e2ada1bcc906bb -size 50150 +oid sha256:895ba0487ed933f4c8eddc99fe008032fe01454771ccf2987905aec357f3d9c0 +size 49972 diff --git a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png index 573b6123ed..adfcb6a616 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerEdit_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69c281829fbca15261f196d2134f933b789ff444cd7bebc88d05cdbb7553357f -size 48012 +oid sha256:b5a435c5aa78ffda52d96d611ab869d006e6c95e8aaf4cd005d99128b4f60b1c +size 47736