Merge pull request #887 from vector-im/feature/bma/fixComposerState

Fix composer state
This commit is contained in:
Benoit Marty 2023-07-17 17:58:53 +02:00 committed by GitHub
commit 9f6b68f204
10 changed files with 40 additions and 77 deletions

View file

@ -25,7 +25,6 @@ import io.element.android.features.messages.impl.timeline.components.customreact
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
@ -48,7 +47,7 @@ fun aMessagesState() = MessagesState(
roomAvatar = AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom), roomAvatar = AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom),
userHasPermissionToSendMessage = true, userHasPermissionToSendMessage = true,
composerState = aMessageComposerState().copy( composerState = aMessageComposerState().copy(
text = StableCharSequence("Hello"), text = "Hello",
isFullScreen = false, isFullScreen = false,
mode = MessageComposerMode.Normal("Hello"), mode = MessageComposerMode.Normal("Hello"),
), ),

View file

@ -26,7 +26,7 @@ sealed interface MessageComposerEvents {
data class SendMessage(val message: String) : MessageComposerEvents data class SendMessage(val message: String) : MessageComposerEvents
object CloseSpecialMode : MessageComposerEvents object CloseSpecialMode : MessageComposerEvents
data class SetMode(val composerMode: MessageComposerMode) : MessageComposerEvents data class SetMode(val composerMode: MessageComposerMode) : MessageComposerEvents
data class UpdateText(val text: CharSequence) : MessageComposerEvents data class UpdateText(val text: String) : MessageComposerEvents
object AddAttachment : MessageComposerEvents object AddAttachment : MessageComposerEvents
object DismissAttachmentMenu : MessageComposerEvents object DismissAttachmentMenu : MessageComposerEvents
sealed interface PickAttachmentSource : MessageComposerEvents { sealed interface PickAttachmentSource : MessageComposerEvents {

View file

@ -34,8 +34,6 @@ import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
import io.element.android.features.messages.impl.media.local.LocalMediaFactory import io.element.android.features.messages.impl.media.local.LocalMediaFactory
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.core.data.toStableCharSequence
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.SnackbarMessage import io.element.android.libraries.designsystem.utils.SnackbarMessage
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
@ -94,15 +92,15 @@ class MessageComposerPresenter @Inject constructor(
val hasFocus = remember { val hasFocus = remember {
mutableStateOf(false) mutableStateOf(false)
} }
val text: MutableState<StableCharSequence> = remember { val text: MutableState<String> = rememberSaveable {
mutableStateOf(StableCharSequence("")) mutableStateOf("")
} }
var showAttachmentSourcePicker: Boolean by remember { mutableStateOf(false) } var showAttachmentSourcePicker: Boolean by remember { mutableStateOf(false) }
LaunchedEffect(messageComposerContext.composerMode) { LaunchedEffect(messageComposerContext.composerMode) {
when (val modeValue = messageComposerContext.composerMode) { when (val modeValue = messageComposerContext.composerMode) {
is MessageComposerMode.Edit -> text.value = modeValue.defaultContent.toStableCharSequence() is MessageComposerMode.Edit -> text.value = modeValue.defaultContent
else -> Unit else -> Unit
} }
} }
@ -120,9 +118,9 @@ class MessageComposerPresenter @Inject constructor(
is MessageComposerEvents.FocusChanged -> hasFocus.value = event.hasFocus is MessageComposerEvents.FocusChanged -> hasFocus.value = event.hasFocus
is MessageComposerEvents.UpdateText -> text.value = event.text.toStableCharSequence() is MessageComposerEvents.UpdateText -> text.value = event.text
MessageComposerEvents.CloseSpecialMode -> { MessageComposerEvents.CloseSpecialMode -> {
text.value = "".toStableCharSequence() text.value = ""
messageComposerContext.composerMode = MessageComposerMode.Normal("") messageComposerContext.composerMode = MessageComposerMode.Normal("")
} }
@ -189,11 +187,11 @@ class MessageComposerPresenter @Inject constructor(
private fun CoroutineScope.sendMessage( private fun CoroutineScope.sendMessage(
text: String, text: String,
updateComposerMode: (newComposerMode: MessageComposerMode) -> Unit, updateComposerMode: (newComposerMode: MessageComposerMode) -> Unit,
textState: MutableState<StableCharSequence> textState: MutableState<String>
) = launch { ) = launch {
val capturedMode = messageComposerContext.composerMode val capturedMode = messageComposerContext.composerMode
// Reset composer right away // Reset composer right away
textState.value = "".toStableCharSequence() textState.value = ""
updateComposerMode(MessageComposerMode.Normal("")) updateComposerMode(MessageComposerMode.Normal(""))
when (capturedMode) { when (capturedMode) {
is MessageComposerMode.Normal -> room.sendMessage(text) is MessageComposerMode.Normal -> room.sendMessage(text)

View file

@ -18,13 +18,12 @@ package io.element.android.features.messages.impl.messagecomposer
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.libraries.textcomposer.MessageComposerMode
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@Immutable @Immutable
data class MessageComposerState( data class MessageComposerState(
val text: StableCharSequence?, val text: String?,
val isFullScreen: Boolean, val isFullScreen: Boolean,
val hasFocus: Boolean, val hasFocus: Boolean,
val mode: MessageComposerMode, val mode: MessageComposerMode,
@ -32,7 +31,7 @@ data class MessageComposerState(
val attachmentsState: AttachmentsState, val attachmentsState: AttachmentsState,
val eventSink: (MessageComposerEvents) -> Unit val eventSink: (MessageComposerEvents) -> Unit
) { ) {
val isSendButtonVisible: Boolean = text?.charSequence.isNullOrEmpty().not() val isSendButtonVisible: Boolean = text.isNullOrEmpty().not()
} }
@Immutable @Immutable

View file

@ -17,7 +17,6 @@
package io.element.android.features.messages.impl.messagecomposer package io.element.android.features.messages.impl.messagecomposer
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.libraries.textcomposer.MessageComposerMode
open class MessageComposerStateProvider : PreviewParameterProvider<MessageComposerState> { open class MessageComposerStateProvider : PreviewParameterProvider<MessageComposerState> {
@ -28,7 +27,7 @@ open class MessageComposerStateProvider : PreviewParameterProvider<MessageCompos
} }
fun aMessageComposerState() = MessageComposerState( fun aMessageComposerState() = MessageComposerState(
text = StableCharSequence(""), text = "",
isFullScreen = false, isFullScreen = false,
hasFocus = false, hasFocus = false,
mode = MessageComposerMode.Normal(content = ""), mode = MessageComposerMode.Normal(content = ""),

View file

@ -47,7 +47,7 @@ fun MessageComposerView(
state.eventSink(MessageComposerEvents.CloseSpecialMode) state.eventSink(MessageComposerEvents.CloseSpecialMode)
} }
fun onComposerTextChange(text: CharSequence) { fun onComposerTextChange(text: String) {
state.eventSink(MessageComposerEvents.UpdateText(text)) state.eventSink(MessageComposerEvents.UpdateText(text))
} }
@ -69,7 +69,7 @@ fun MessageComposerView(
onAddAttachment = ::onAddAttachment, onAddAttachment = ::onAddAttachment,
onFocusChanged = ::onFocusChanged, onFocusChanged = ::onFocusChanged,
composerCanSendMessage = state.isSendButtonVisible, composerCanSendMessage = state.isSendButtonVisible,
composerText = state.text?.charSequence?.toString(), composerText = state.text,
modifier = modifier modifier = modifier
) )
} }

View file

@ -31,7 +31,6 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
import io.element.android.features.messages.media.FakeLocalMediaFactory import io.element.android.features.messages.media.FakeLocalMediaFactory
import io.element.android.libraries.core.data.StableCharSequence
import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
@ -84,7 +83,7 @@ class MessageComposerPresenterTest {
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.isFullScreen).isFalse() assertThat(initialState.isFullScreen).isFalse()
assertThat(initialState.text).isEqualTo(StableCharSequence("")) assertThat(initialState.text).isEqualTo("")
assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal("")) assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal(""))
assertThat(initialState.showAttachmentSourcePicker).isFalse() assertThat(initialState.showAttachmentSourcePicker).isFalse()
assertThat(initialState.attachmentsState).isEqualTo(AttachmentsState.None) assertThat(initialState.attachmentsState).isEqualTo(AttachmentsState.None)
@ -117,11 +116,11 @@ class MessageComposerPresenterTest {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE)) initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE))
val withMessageState = awaitItem() val withMessageState = awaitItem()
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE)) assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
assertThat(withMessageState.isSendButtonVisible).isTrue() assertThat(withMessageState.isSendButtonVisible).isTrue()
withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText("")) withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(""))
val withEmptyMessageState = awaitItem() val withEmptyMessageState = awaitItem()
assertThat(withEmptyMessageState.text).isEqualTo(StableCharSequence("")) assertThat(withEmptyMessageState.text).isEqualTo("")
assertThat(withEmptyMessageState.isSendButtonVisible).isFalse() assertThat(withEmptyMessageState.isSendButtonVisible).isFalse()
} }
} }
@ -138,7 +137,7 @@ class MessageComposerPresenterTest {
state = awaitItem() state = awaitItem()
assertThat(state.mode).isEqualTo(mode) assertThat(state.mode).isEqualTo(mode)
state = awaitItem() state = awaitItem()
assertThat(state.text).isEqualTo(StableCharSequence(A_MESSAGE)) assertThat(state.text).isEqualTo(A_MESSAGE)
assertThat(state.isSendButtonVisible).isTrue() assertThat(state.isSendButtonVisible).isTrue()
backToNormalMode(state, skipCount = 1) backToNormalMode(state, skipCount = 1)
} }
@ -155,7 +154,7 @@ class MessageComposerPresenterTest {
state.eventSink.invoke(MessageComposerEvents.SetMode(mode)) state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
state = awaitItem() state = awaitItem()
assertThat(state.mode).isEqualTo(mode) assertThat(state.mode).isEqualTo(mode)
assertThat(state.text).isEqualTo(StableCharSequence("")) assertThat(state.text).isEqualTo("")
assertThat(state.isSendButtonVisible).isFalse() assertThat(state.isSendButtonVisible).isFalse()
backToNormalMode(state) backToNormalMode(state)
} }
@ -172,7 +171,7 @@ class MessageComposerPresenterTest {
state.eventSink.invoke(MessageComposerEvents.SetMode(mode)) state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
state = awaitItem() state = awaitItem()
assertThat(state.mode).isEqualTo(mode) assertThat(state.mode).isEqualTo(mode)
assertThat(state.text).isEqualTo(StableCharSequence("")) assertThat(state.text).isEqualTo("")
assertThat(state.isSendButtonVisible).isFalse() assertThat(state.isSendButtonVisible).isFalse()
backToNormalMode(state) backToNormalMode(state)
} }
@ -187,11 +186,11 @@ class MessageComposerPresenterTest {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE)) initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE))
val withMessageState = awaitItem() val withMessageState = awaitItem()
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE)) assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
assertThat(withMessageState.isSendButtonVisible).isTrue() assertThat(withMessageState.isSendButtonVisible).isTrue()
withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_MESSAGE)) withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_MESSAGE))
val messageSentState = awaitItem() val messageSentState = awaitItem()
assertThat(messageSentState.text).isEqualTo(StableCharSequence("")) assertThat(messageSentState.text).isEqualTo("")
assertThat(messageSentState.isSendButtonVisible).isFalse() assertThat(messageSentState.isSendButtonVisible).isFalse()
} }
} }
@ -207,21 +206,21 @@ class MessageComposerPresenterTest {
presenter.present() presenter.present()
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.text).isEqualTo(StableCharSequence("")) assertThat(initialState.text).isEqualTo("")
val mode = anEditMode() val mode = anEditMode()
initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode))
skipItems(1) skipItems(1)
val withMessageState = awaitItem() val withMessageState = awaitItem()
assertThat(withMessageState.mode).isEqualTo(mode) assertThat(withMessageState.mode).isEqualTo(mode)
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE)) assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
assertThat(withMessageState.isSendButtonVisible).isTrue() assertThat(withMessageState.isSendButtonVisible).isTrue()
withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE)) withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE))
val withEditedMessageState = awaitItem() val withEditedMessageState = awaitItem()
assertThat(withEditedMessageState.text).isEqualTo(StableCharSequence(ANOTHER_MESSAGE)) assertThat(withEditedMessageState.text).isEqualTo(ANOTHER_MESSAGE)
withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE)) withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE))
skipItems(1) skipItems(1)
val messageSentState = awaitItem() val messageSentState = awaitItem()
assertThat(messageSentState.text).isEqualTo(StableCharSequence("")) assertThat(messageSentState.text).isEqualTo("")
assertThat(messageSentState.isSendButtonVisible).isFalse() assertThat(messageSentState.isSendButtonVisible).isFalse()
assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE) assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE)
} }
@ -238,21 +237,21 @@ class MessageComposerPresenterTest {
presenter.present() presenter.present()
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.text).isEqualTo(StableCharSequence("")) assertThat(initialState.text).isEqualTo("")
val mode = anEditMode(eventId = null, transactionId = A_TRANSACTION_ID) val mode = anEditMode(eventId = null, transactionId = A_TRANSACTION_ID)
initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode))
skipItems(1) skipItems(1)
val withMessageState = awaitItem() val withMessageState = awaitItem()
assertThat(withMessageState.mode).isEqualTo(mode) assertThat(withMessageState.mode).isEqualTo(mode)
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE)) assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
assertThat(withMessageState.isSendButtonVisible).isTrue() assertThat(withMessageState.isSendButtonVisible).isTrue()
withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE)) withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE))
val withEditedMessageState = awaitItem() val withEditedMessageState = awaitItem()
assertThat(withEditedMessageState.text).isEqualTo(StableCharSequence(ANOTHER_MESSAGE)) assertThat(withEditedMessageState.text).isEqualTo(ANOTHER_MESSAGE)
withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE)) withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE))
skipItems(1) skipItems(1)
val messageSentState = awaitItem() val messageSentState = awaitItem()
assertThat(messageSentState.text).isEqualTo(StableCharSequence("")) assertThat(messageSentState.text).isEqualTo("")
assertThat(messageSentState.isSendButtonVisible).isFalse() assertThat(messageSentState.isSendButtonVisible).isFalse()
assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE) assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE)
} }
@ -269,21 +268,21 @@ class MessageComposerPresenterTest {
presenter.present() presenter.present()
}.test { }.test {
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.text).isEqualTo(StableCharSequence("")) assertThat(initialState.text).isEqualTo("")
val mode = aReplyMode() val mode = aReplyMode()
initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode))
val state = awaitItem() val state = awaitItem()
assertThat(state.mode).isEqualTo(mode) assertThat(state.mode).isEqualTo(mode)
assertThat(state.text).isEqualTo(StableCharSequence("")) assertThat(state.text).isEqualTo("")
assertThat(state.isSendButtonVisible).isFalse() assertThat(state.isSendButtonVisible).isFalse()
initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_REPLY)) initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_REPLY))
val withMessageState = awaitItem() val withMessageState = awaitItem()
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_REPLY)) assertThat(withMessageState.text).isEqualTo(A_REPLY)
assertThat(withMessageState.isSendButtonVisible).isTrue() assertThat(withMessageState.isSendButtonVisible).isTrue()
withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_REPLY)) withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_REPLY))
skipItems(1) skipItems(1)
val messageSentState = awaitItem() val messageSentState = awaitItem()
assertThat(messageSentState.text).isEqualTo(StableCharSequence("")) assertThat(messageSentState.text).isEqualTo("")
assertThat(messageSentState.isSendButtonVisible).isFalse() assertThat(messageSentState.isSendButtonVisible).isFalse()
assertThat(fakeMatrixRoom.replyMessageParameter).isEqualTo(A_REPLY) assertThat(fakeMatrixRoom.replyMessageParameter).isEqualTo(A_REPLY)
} }
@ -486,7 +485,7 @@ class MessageComposerPresenterTest {
skipItems(skipCount) skipItems(skipCount)
val normalState = awaitItem() val normalState = awaitItem()
assertThat(normalState.mode).isEqualTo(MessageComposerMode.Normal("")) assertThat(normalState.mode).isEqualTo(MessageComposerMode.Normal(""))
assertThat(normalState.text).isEqualTo(StableCharSequence("")) assertThat(normalState.text).isEqualTo("")
assertThat(normalState.isSendButtonVisible).isFalse() assertThat(normalState.isSendButtonVisible).isFalse()
} }

View file

@ -1,31 +0,0 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.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
override fun toString(): String = "StableCharSequence(\"$charSequence\")"
}
fun CharSequence.toStableCharSequence() = StableCharSequence(this)

View file

@ -26,15 +26,15 @@ sealed interface MessageComposerMode : Parcelable {
@Parcelize @Parcelize
data class Normal(val content: CharSequence?) : MessageComposerMode data class Normal(val content: CharSequence?) : MessageComposerMode
sealed class Special(open val eventId: EventId?, open val defaultContent: CharSequence) : sealed class Special(open val eventId: EventId?, open val defaultContent: String) :
MessageComposerMode MessageComposerMode
@Parcelize @Parcelize
data class Edit(override val eventId: EventId?, override val defaultContent: CharSequence, val transactionId: TransactionId?) : data class Edit(override val eventId: EventId?, override val defaultContent: String, val transactionId: TransactionId?) :
Special(eventId, defaultContent) Special(eventId, defaultContent)
@Parcelize @Parcelize
class Quote(override val eventId: EventId, override val defaultContent: CharSequence) : class Quote(override val eventId: EventId, override val defaultContent: String) :
Special(eventId, defaultContent) Special(eventId, defaultContent)
@Parcelize @Parcelize
@ -42,7 +42,7 @@ sealed interface MessageComposerMode : Parcelable {
val senderName: String, val senderName: String,
val attachmentThumbnailInfo: AttachmentThumbnailInfo?, val attachmentThumbnailInfo: AttachmentThumbnailInfo?,
override val eventId: EventId, override val eventId: EventId,
override val defaultContent: CharSequence override val defaultContent: String
) : Special(eventId, defaultContent) ) : Special(eventId, defaultContent)
val relatedEventId: EventId? val relatedEventId: EventId?

View file

@ -96,7 +96,7 @@ fun TextComposer(
focusRequester: FocusRequester = FocusRequester(), focusRequester: FocusRequester = FocusRequester(),
onSendMessage: (String) -> Unit = {}, onSendMessage: (String) -> Unit = {},
onResetComposerMode: () -> Unit = {}, onResetComposerMode: () -> Unit = {},
onComposerTextChange: (CharSequence) -> Unit = {}, onComposerTextChange: (String) -> Unit = {},
onAddAttachment: () -> Unit = {}, onAddAttachment: () -> Unit = {},
onFocusChanged: (Boolean) -> Unit = {}, onFocusChanged: (Boolean) -> Unit = {},
) { ) {