diff --git a/feature/media-send/src/main/java/org/signal/mediasend/MediaSendFlowViewModel.kt b/feature/media-send/src/main/java/org/signal/mediasend/MediaSendFlowViewModel.kt index a3faf34722..2526dda914 100644 --- a/feature/media-send/src/main/java/org/signal/mediasend/MediaSendFlowViewModel.kt +++ b/feature/media-send/src/main/java/org/signal/mediasend/MediaSendFlowViewModel.kt @@ -100,7 +100,7 @@ class MediaSendFlowViewModel( isReply = args.isReply, isAddToGroupStoryFlow = args.isAddToGroupStoryFlow, maxSelection = args.maxSelection, - message = if (args.asTextStory) null else args.initialMessage, + message = if (args.asTextStory) null else normalizeMessageBody(args.initialMessage), isContactSelectionRequired = args.mode == MediaSendFlowActivityContract.Mode.ChooseAfterMediaSelection, sendType = args.sendType ) @@ -1077,11 +1077,7 @@ class MediaSendFlowViewModel( //region Message fun setMessage(text: CharSequence?) { - updateState { copy(message = text) } - } - - private fun onMessageChange(message: String) { - setMessage(message) + updateState { copy(message = normalizeMessageBody(text)) } } //endregion @@ -1321,6 +1317,14 @@ class MediaSendFlowViewModel( private const val KEY_STATE = "media_send_vm_state" private const val KEY_EDITED_VIDEO_URIS = "media_send_vm_edited_video_uris" private const val KEY_BACK_STACK = "media_send_vm_back_stack" + + /** + * Trims a body the way the chat compose field does before a send, preserving spans like mentions and styling, and + * collapses a whitespace-only body to null so it is indistinguishable from a body the user never typed. + */ + private fun normalizeMessageBody(text: CharSequence?): CharSequence? { + return text?.let { StringUtil.trimSequence(it) }?.takeIf { it.isNotEmpty() } + } } /** diff --git a/feature/media-send/src/main/java/org/signal/mediasend/screens/edit/AddAMessageRow.kt b/feature/media-send/src/main/java/org/signal/mediasend/screens/edit/AddAMessageRow.kt index a6cc979c75..29f8551c43 100644 --- a/feature/media-send/src/main/java/org/signal/mediasend/screens/edit/AddAMessageRow.kt +++ b/feature/media-send/src/main/java/org/signal/mediasend/screens/edit/AddAMessageRow.kt @@ -113,7 +113,7 @@ fun AddAMessageRow( } LocalAddAMessageRowTextField.current( - message ?: stringResource(R.string.AddAMessageRow__message), + message?.takeIf { it.isNotBlank() } ?: stringResource(R.string.AddAMessageRow__message), Modifier .weight(1f) .padding(end = if (viewOnceAvailable) 0.dp else 16.dp) diff --git a/feature/media-send/src/test/java/org/signal/mediasend/screens/edit/AddAMessageRowTest.kt b/feature/media-send/src/test/java/org/signal/mediasend/screens/edit/AddAMessageRowTest.kt index f663084760..4675466d71 100644 --- a/feature/media-send/src/test/java/org/signal/mediasend/screens/edit/AddAMessageRowTest.kt +++ b/feature/media-send/src/test/java/org/signal/mediasend/screens/edit/AddAMessageRowTest.kt @@ -9,6 +9,7 @@ import android.app.Application import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.longClick import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.test.core.app.ApplicationProvider @@ -25,7 +26,7 @@ import org.signal.mediasend.test.TestTags /** * Covers the send affordance's two gestures: a tap advances the flow, while a long press offers the schedule menu when - * the flow allows scheduling. + * the flow allows scheduling. Also covers when the row falls back to its placeholder. */ @RunWith(RobolectricTestRunner::class) @Config(application = Application::class) @@ -74,11 +75,25 @@ class AddAMessageRowTest { assertEquals(emptyList(), events) } - private fun setContent(canScheduleSend: Boolean) { + @Test + fun `Given a blank message, when the row is displayed, then the placeholder is shown`() { + setContent(message = " ") + + composeTestRule.onNodeWithText("Message").assertExists() + } + + @Test + fun `Given a message, when the row is displayed, then the message is shown`() { + setContent(message = "Check this out") + + composeTestRule.onNodeWithText("Check this out").assertExists() + } + + private fun setContent(canScheduleSend: Boolean = false, message: CharSequence? = null) { composeTestRule.setContent { SignalTheme { AddAMessageRow( - message = null, + message = message, onEvent = { events += it }, onNextClick = { nextClicks++ }, canScheduleSend = canScheduleSend