From dccb83fe7612d533f78331d3fe527541012a74b9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 9 Nov 2022 10:26:39 +0100 Subject: [PATCH] Empty composer when message is sent --- .../x/features/messages/MessagesScreen.kt | 17 ++++++++++++++++- .../textcomposer/MessageComposerViewModel.kt | 10 ++++++++++ .../textcomposer/MessageComposerViewState.kt | 5 ++++- .../android/x/core/data/StableCharSequence.kt | 11 +++++++++++ .../android/x/textcomposer/TextComposer.kt | 8 +++++++- 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 libraries/core/src/main/java/io/element/android/x/core/data/StableCharSequence.kt diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt b/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt index 373f044158..17b1127f7a 100644 --- a/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt +++ b/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.zIndex import com.airbnb.mvrx.compose.collectAsState import com.airbnb.mvrx.compose.mavericksViewModel import io.element.android.x.core.data.LogCompositions +import io.element.android.x.core.data.StableCharSequence import io.element.android.x.designsystem.components.avatar.AvatarData import io.element.android.x.features.messages.model.MessagesItemGroupPosition import io.element.android.x.features.messages.model.MessagesTimelineItemState @@ -58,6 +59,8 @@ fun MessagesScreen( val timelineItems by viewModel.collectAsState(MessagesViewState::timelineItems) val hasMoreToLoad by viewModel.collectAsState(MessagesViewState::hasMoreToLoad) val composerFullScreen by composerViewModel.collectAsState(MessageComposerViewState::isFullScreen) + val composerCanSendMessage by composerViewModel.collectAsState(MessageComposerViewState::isSendButtonVisible) + val composerText by composerViewModel.collectAsState(MessageComposerViewState::text) MessagesContent( roomTitle = roomTitle, roomAvatar = roomAvatar, @@ -65,9 +68,15 @@ fun MessagesScreen( hasMoreToLoad = hasMoreToLoad, onReachedLoadMore = viewModel::loadMore, onBackPressed = onBackPressed, - onSendMessage = viewModel::sendMessage, + onSendMessage = { + viewModel.sendMessage(it) + composerViewModel.updateText("") + }, composerFullScreen = composerFullScreen, onComposerFullScreenChange = composerViewModel::onComposerFullScreenChange, + onComposerTextChange = composerViewModel::updateText, + composerCanSendMessage = composerCanSendMessage, + composerText = composerText, ) } @@ -82,6 +91,9 @@ fun MessagesContent( onSendMessage: (CharSequence) -> Unit, composerFullScreen: Boolean, onComposerFullScreenChange: () -> Unit, + onComposerTextChange: (CharSequence) -> Unit, + composerCanSendMessage: Boolean, + composerText: StableCharSequence?, ) { LogCompositions(tag = "MessagesScreen", msg = "Content") val lazyListState = rememberLazyListState() @@ -133,6 +145,9 @@ fun MessagesContent( onSendMessage = onSendMessage, fullscreen = composerFullScreen, onFullscreenToggle = onComposerFullScreenChange, + onComposerTextChange = onComposerTextChange, + composerCanSendMessage = composerCanSendMessage, + composerText = composerText?.charSequence, modifier = Modifier .fillMaxWidth() .let { diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewModel.kt b/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewModel.kt index 0383de64d3..1c4611f97d 100644 --- a/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewModel.kt +++ b/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewModel.kt @@ -3,6 +3,7 @@ package io.element.android.x.features.messages.textcomposer import com.airbnb.mvrx.MavericksViewModel import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.ViewModelContext +import io.element.android.x.core.data.StableCharSequence import io.element.android.x.matrix.MatrixClient import io.element.android.x.matrix.MatrixInstance @@ -35,4 +36,13 @@ class MessageComposerViewModel( ) } } + + fun updateText(newText: CharSequence) { + setState { + copy( + text = StableCharSequence(newText), + isSendButtonVisible = newText.isNotEmpty(), + ) + } + } } \ No newline at end of file diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewState.kt b/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewState.kt index a6cd890437..c34ed56029 100644 --- a/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewState.kt +++ b/features/messages/src/main/java/io/element/android/x/features/messages/textcomposer/MessageComposerViewState.kt @@ -1,7 +1,10 @@ package io.element.android.x.features.messages.textcomposer +import androidx.compose.runtime.Stable import com.airbnb.mvrx.MavericksState +import io.element.android.x.core.data.StableCharSequence +@Stable data class MessageComposerViewState( // val roomId: String, // val canSendMessage: CanSendStatus = CanSendStatus.Allowed, @@ -11,6 +14,6 @@ data class MessageComposerViewState( // val sendMode: SendMode = SendMode.Regular("", false), // val voiceRecordingUiState: VoiceMessageRecorderView.RecordingUiState = VoiceMessageRecorderView.RecordingUiState.Idle, // val voiceBroadcastState: VoiceBroadcastState? = null, - val text: CharSequence? = null, + val text: StableCharSequence? = null, val isFullScreen: Boolean = false, ) : MavericksState \ No newline at end of file diff --git a/libraries/core/src/main/java/io/element/android/x/core/data/StableCharSequence.kt b/libraries/core/src/main/java/io/element/android/x/core/data/StableCharSequence.kt new file mode 100644 index 0000000000..29e72c95f1 --- /dev/null +++ b/libraries/core/src/main/java/io/element/android/x/core/data/StableCharSequence.kt @@ -0,0 +1,11 @@ +package io.element.android.x.core.data + +/** + * Wrapper for a CharSequence, which support mutation of the CharSequence. + */ +class StableCharSequence(val charSequence: CharSequence) { + private val hash = charSequence.toString().hashCode() + + override fun hashCode() = hash + override fun equals(other: Any?) = other is StableCharSequence && other.hash == hash +} diff --git a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt index e13b09ba74..336a3446d3 100644 --- a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt @@ -4,6 +4,7 @@ import android.net.Uri import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.view.isInvisible import androidx.core.view.isVisible import io.element.android.x.element.resources.R as ElementR @@ -13,6 +14,9 @@ fun TextComposer( modifier: Modifier = Modifier, fullscreen: Boolean, onFullscreenToggle: () -> Unit, + onComposerTextChange: (CharSequence) -> Unit, + composerCanSendMessage: Boolean, + composerText: CharSequence?, ) { AndroidView( modifier = modifier, @@ -25,6 +29,7 @@ fun TextComposer( } override fun onTextChanged(text: CharSequence) { + onComposerTextChange(text) } override fun onCloseRelatedMessage() { @@ -59,7 +64,8 @@ fun TextComposer( // Example of Compose -> View communication val messageComposerView = (view as MessageComposerView) messageComposerView.toggleFullScreen(fullscreen) - messageComposerView.sendButton.isVisible = true + messageComposerView.sendButton.isInvisible = !composerCanSendMessage + messageComposerView.setTextIfDifferent(composerText ?: "") } ) }