Skip to content

Commit b42343f

Browse files
authored
Merge pull request #887 from vector-im/feature/bma/fixComposerState
Fix composer state
2 parents 9247cd7 + 8b73abe commit b42343f

File tree

10 files changed

+40
-77
lines changed

10 files changed

+40
-77
lines changed

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import io.element.android.features.messages.impl.timeline.components.customreact
2525
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
2626
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
2727
import io.element.android.libraries.architecture.Async
28-
import io.element.android.libraries.core.data.StableCharSequence
2928
import io.element.android.libraries.designsystem.components.avatar.AvatarData
3029
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
3130
import io.element.android.libraries.matrix.api.core.RoomId
@@ -48,7 +47,7 @@ fun aMessagesState() = MessagesState(
4847
roomAvatar = AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom),
4948
userHasPermissionToSendMessage = true,
5049
composerState = aMessageComposerState().copy(
51-
text = StableCharSequence("Hello"),
50+
text = "Hello",
5251
isFullScreen = false,
5352
mode = MessageComposerMode.Normal("Hello"),
5453
),

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ sealed interface MessageComposerEvents {
2626
data class SendMessage(val message: String) : MessageComposerEvents
2727
object CloseSpecialMode : MessageComposerEvents
2828
data class SetMode(val composerMode: MessageComposerMode) : MessageComposerEvents
29-
data class UpdateText(val text: CharSequence) : MessageComposerEvents
29+
data class UpdateText(val text: String) : MessageComposerEvents
3030
object AddAttachment : MessageComposerEvents
3131
object DismissAttachmentMenu : MessageComposerEvents
3232
sealed interface PickAttachmentSource : MessageComposerEvents {

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ import io.element.android.features.messages.impl.attachments.Attachment
3434
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
3535
import io.element.android.features.messages.impl.media.local.LocalMediaFactory
3636
import io.element.android.libraries.architecture.Presenter
37-
import io.element.android.libraries.core.data.StableCharSequence
38-
import io.element.android.libraries.core.data.toStableCharSequence
3937
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
4038
import io.element.android.libraries.designsystem.utils.SnackbarMessage
4139
import io.element.android.libraries.di.RoomScope
@@ -94,15 +92,15 @@ class MessageComposerPresenter @Inject constructor(
9492
val hasFocus = remember {
9593
mutableStateOf(false)
9694
}
97-
val text: MutableState<StableCharSequence> = remember {
98-
mutableStateOf(StableCharSequence(""))
95+
val text: MutableState<String> = rememberSaveable {
96+
mutableStateOf("")
9997
}
10098

10199
var showAttachmentSourcePicker: Boolean by remember { mutableStateOf(false) }
102100

103101
LaunchedEffect(messageComposerContext.composerMode) {
104102
when (val modeValue = messageComposerContext.composerMode) {
105-
is MessageComposerMode.Edit -> text.value = modeValue.defaultContent.toStableCharSequence()
103+
is MessageComposerMode.Edit -> text.value = modeValue.defaultContent
106104
else -> Unit
107105
}
108106
}
@@ -120,9 +118,9 @@ class MessageComposerPresenter @Inject constructor(
120118

121119
is MessageComposerEvents.FocusChanged -> hasFocus.value = event.hasFocus
122120

123-
is MessageComposerEvents.UpdateText -> text.value = event.text.toStableCharSequence()
121+
is MessageComposerEvents.UpdateText -> text.value = event.text
124122
MessageComposerEvents.CloseSpecialMode -> {
125-
text.value = "".toStableCharSequence()
123+
text.value = ""
126124
messageComposerContext.composerMode = MessageComposerMode.Normal("")
127125
}
128126

@@ -189,11 +187,11 @@ class MessageComposerPresenter @Inject constructor(
189187
private fun CoroutineScope.sendMessage(
190188
text: String,
191189
updateComposerMode: (newComposerMode: MessageComposerMode) -> Unit,
192-
textState: MutableState<StableCharSequence>
190+
textState: MutableState<String>
193191
) = launch {
194192
val capturedMode = messageComposerContext.composerMode
195193
// Reset composer right away
196-
textState.value = "".toStableCharSequence()
194+
textState.value = ""
197195
updateComposerMode(MessageComposerMode.Normal(""))
198196
when (capturedMode) {
199197
is MessageComposerMode.Normal -> room.sendMessage(text)

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@ package io.element.android.features.messages.impl.messagecomposer
1818

1919
import androidx.compose.runtime.Immutable
2020
import io.element.android.features.messages.impl.attachments.Attachment
21-
import io.element.android.libraries.core.data.StableCharSequence
2221
import io.element.android.libraries.textcomposer.MessageComposerMode
2322
import kotlinx.collections.immutable.ImmutableList
2423

2524
@Immutable
2625
data class MessageComposerState(
27-
val text: StableCharSequence?,
26+
val text: String?,
2827
val isFullScreen: Boolean,
2928
val hasFocus: Boolean,
3029
val mode: MessageComposerMode,
3130
val showAttachmentSourcePicker: Boolean,
3231
val attachmentsState: AttachmentsState,
3332
val eventSink: (MessageComposerEvents) -> Unit
3433
) {
35-
val isSendButtonVisible: Boolean = text?.charSequence.isNullOrEmpty().not()
34+
val isSendButtonVisible: Boolean = text.isNullOrEmpty().not()
3635
}
3736

3837
@Immutable

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package io.element.android.features.messages.impl.messagecomposer
1818

1919
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
20-
import io.element.android.libraries.core.data.StableCharSequence
2120
import io.element.android.libraries.textcomposer.MessageComposerMode
2221

2322
open class MessageComposerStateProvider : PreviewParameterProvider<MessageComposerState> {
@@ -28,7 +27,7 @@ open class MessageComposerStateProvider : PreviewParameterProvider<MessageCompos
2827
}
2928

3029
fun aMessageComposerState() = MessageComposerState(
31-
text = StableCharSequence(""),
30+
text = "",
3231
isFullScreen = false,
3332
hasFocus = false,
3433
mode = MessageComposerMode.Normal(content = ""),

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fun MessageComposerView(
4747
state.eventSink(MessageComposerEvents.CloseSpecialMode)
4848
}
4949

50-
fun onComposerTextChange(text: CharSequence) {
50+
fun onComposerTextChange(text: String) {
5151
state.eventSink(MessageComposerEvents.UpdateText(text))
5252
}
5353

@@ -69,7 +69,7 @@ fun MessageComposerView(
6969
onAddAttachment = ::onAddAttachment,
7070
onFocusChanged = ::onFocusChanged,
7171
composerCanSendMessage = state.isSendButtonVisible,
72-
composerText = state.text?.charSequence?.toString(),
72+
composerText = state.text,
7373
modifier = modifier
7474
)
7575
}

features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
3131
import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter
3232
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
3333
import io.element.android.features.messages.media.FakeLocalMediaFactory
34-
import io.element.android.libraries.core.data.StableCharSequence
3534
import io.element.android.libraries.core.mimetype.MimeTypes
3635
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
3736
import io.element.android.libraries.featureflag.api.FeatureFlagService
@@ -84,7 +83,7 @@ class MessageComposerPresenterTest {
8483
}.test {
8584
val initialState = awaitItem()
8685
assertThat(initialState.isFullScreen).isFalse()
87-
assertThat(initialState.text).isEqualTo(StableCharSequence(""))
86+
assertThat(initialState.text).isEqualTo("")
8887
assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal(""))
8988
assertThat(initialState.showAttachmentSourcePicker).isFalse()
9089
assertThat(initialState.attachmentsState).isEqualTo(AttachmentsState.None)
@@ -117,11 +116,11 @@ class MessageComposerPresenterTest {
117116
val initialState = awaitItem()
118117
initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE))
119118
val withMessageState = awaitItem()
120-
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE))
119+
assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
121120
assertThat(withMessageState.isSendButtonVisible).isTrue()
122121
withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(""))
123122
val withEmptyMessageState = awaitItem()
124-
assertThat(withEmptyMessageState.text).isEqualTo(StableCharSequence(""))
123+
assertThat(withEmptyMessageState.text).isEqualTo("")
125124
assertThat(withEmptyMessageState.isSendButtonVisible).isFalse()
126125
}
127126
}
@@ -138,7 +137,7 @@ class MessageComposerPresenterTest {
138137
state = awaitItem()
139138
assertThat(state.mode).isEqualTo(mode)
140139
state = awaitItem()
141-
assertThat(state.text).isEqualTo(StableCharSequence(A_MESSAGE))
140+
assertThat(state.text).isEqualTo(A_MESSAGE)
142141
assertThat(state.isSendButtonVisible).isTrue()
143142
backToNormalMode(state, skipCount = 1)
144143
}
@@ -155,7 +154,7 @@ class MessageComposerPresenterTest {
155154
state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
156155
state = awaitItem()
157156
assertThat(state.mode).isEqualTo(mode)
158-
assertThat(state.text).isEqualTo(StableCharSequence(""))
157+
assertThat(state.text).isEqualTo("")
159158
assertThat(state.isSendButtonVisible).isFalse()
160159
backToNormalMode(state)
161160
}
@@ -172,7 +171,7 @@ class MessageComposerPresenterTest {
172171
state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
173172
state = awaitItem()
174173
assertThat(state.mode).isEqualTo(mode)
175-
assertThat(state.text).isEqualTo(StableCharSequence(""))
174+
assertThat(state.text).isEqualTo("")
176175
assertThat(state.isSendButtonVisible).isFalse()
177176
backToNormalMode(state)
178177
}
@@ -187,11 +186,11 @@ class MessageComposerPresenterTest {
187186
val initialState = awaitItem()
188187
initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE))
189188
val withMessageState = awaitItem()
190-
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE))
189+
assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
191190
assertThat(withMessageState.isSendButtonVisible).isTrue()
192191
withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_MESSAGE))
193192
val messageSentState = awaitItem()
194-
assertThat(messageSentState.text).isEqualTo(StableCharSequence(""))
193+
assertThat(messageSentState.text).isEqualTo("")
195194
assertThat(messageSentState.isSendButtonVisible).isFalse()
196195
}
197196
}
@@ -207,21 +206,21 @@ class MessageComposerPresenterTest {
207206
presenter.present()
208207
}.test {
209208
val initialState = awaitItem()
210-
assertThat(initialState.text).isEqualTo(StableCharSequence(""))
209+
assertThat(initialState.text).isEqualTo("")
211210
val mode = anEditMode()
212211
initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode))
213212
skipItems(1)
214213
val withMessageState = awaitItem()
215214
assertThat(withMessageState.mode).isEqualTo(mode)
216-
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE))
215+
assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
217216
assertThat(withMessageState.isSendButtonVisible).isTrue()
218217
withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE))
219218
val withEditedMessageState = awaitItem()
220-
assertThat(withEditedMessageState.text).isEqualTo(StableCharSequence(ANOTHER_MESSAGE))
219+
assertThat(withEditedMessageState.text).isEqualTo(ANOTHER_MESSAGE)
221220
withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE))
222221
skipItems(1)
223222
val messageSentState = awaitItem()
224-
assertThat(messageSentState.text).isEqualTo(StableCharSequence(""))
223+
assertThat(messageSentState.text).isEqualTo("")
225224
assertThat(messageSentState.isSendButtonVisible).isFalse()
226225
assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE)
227226
}
@@ -238,21 +237,21 @@ class MessageComposerPresenterTest {
238237
presenter.present()
239238
}.test {
240239
val initialState = awaitItem()
241-
assertThat(initialState.text).isEqualTo(StableCharSequence(""))
240+
assertThat(initialState.text).isEqualTo("")
242241
val mode = anEditMode(eventId = null, transactionId = A_TRANSACTION_ID)
243242
initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode))
244243
skipItems(1)
245244
val withMessageState = awaitItem()
246245
assertThat(withMessageState.mode).isEqualTo(mode)
247-
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_MESSAGE))
246+
assertThat(withMessageState.text).isEqualTo(A_MESSAGE)
248247
assertThat(withMessageState.isSendButtonVisible).isTrue()
249248
withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE))
250249
val withEditedMessageState = awaitItem()
251-
assertThat(withEditedMessageState.text).isEqualTo(StableCharSequence(ANOTHER_MESSAGE))
250+
assertThat(withEditedMessageState.text).isEqualTo(ANOTHER_MESSAGE)
252251
withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE))
253252
skipItems(1)
254253
val messageSentState = awaitItem()
255-
assertThat(messageSentState.text).isEqualTo(StableCharSequence(""))
254+
assertThat(messageSentState.text).isEqualTo("")
256255
assertThat(messageSentState.isSendButtonVisible).isFalse()
257256
assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE)
258257
}
@@ -269,21 +268,21 @@ class MessageComposerPresenterTest {
269268
presenter.present()
270269
}.test {
271270
val initialState = awaitItem()
272-
assertThat(initialState.text).isEqualTo(StableCharSequence(""))
271+
assertThat(initialState.text).isEqualTo("")
273272
val mode = aReplyMode()
274273
initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode))
275274
val state = awaitItem()
276275
assertThat(state.mode).isEqualTo(mode)
277-
assertThat(state.text).isEqualTo(StableCharSequence(""))
276+
assertThat(state.text).isEqualTo("")
278277
assertThat(state.isSendButtonVisible).isFalse()
279278
initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_REPLY))
280279
val withMessageState = awaitItem()
281-
assertThat(withMessageState.text).isEqualTo(StableCharSequence(A_REPLY))
280+
assertThat(withMessageState.text).isEqualTo(A_REPLY)
282281
assertThat(withMessageState.isSendButtonVisible).isTrue()
283282
withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_REPLY))
284283
skipItems(1)
285284
val messageSentState = awaitItem()
286-
assertThat(messageSentState.text).isEqualTo(StableCharSequence(""))
285+
assertThat(messageSentState.text).isEqualTo("")
287286
assertThat(messageSentState.isSendButtonVisible).isFalse()
288287
assertThat(fakeMatrixRoom.replyMessageParameter).isEqualTo(A_REPLY)
289288
}
@@ -486,7 +485,7 @@ class MessageComposerPresenterTest {
486485
skipItems(skipCount)
487486
val normalState = awaitItem()
488487
assertThat(normalState.mode).isEqualTo(MessageComposerMode.Normal(""))
489-
assertThat(normalState.text).isEqualTo(StableCharSequence(""))
488+
assertThat(normalState.text).isEqualTo("")
490489
assertThat(normalState.isSendButtonVisible).isFalse()
491490
}
492491

libraries/core/src/main/kotlin/io/element/android/libraries/core/data/StableCharSequence.kt

Lines changed: 0 additions & 31 deletions
This file was deleted.

libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,23 @@ sealed interface MessageComposerMode : Parcelable {
2626
@Parcelize
2727
data class Normal(val content: CharSequence?) : MessageComposerMode
2828

29-
sealed class Special(open val eventId: EventId?, open val defaultContent: CharSequence) :
29+
sealed class Special(open val eventId: EventId?, open val defaultContent: String) :
3030
MessageComposerMode
3131

3232
@Parcelize
33-
data class Edit(override val eventId: EventId?, override val defaultContent: CharSequence, val transactionId: TransactionId?) :
33+
data class Edit(override val eventId: EventId?, override val defaultContent: String, val transactionId: TransactionId?) :
3434
Special(eventId, defaultContent)
3535

3636
@Parcelize
37-
class Quote(override val eventId: EventId, override val defaultContent: CharSequence) :
37+
class Quote(override val eventId: EventId, override val defaultContent: String) :
3838
Special(eventId, defaultContent)
3939

4040
@Parcelize
4141
class Reply(
4242
val senderName: String,
4343
val attachmentThumbnailInfo: AttachmentThumbnailInfo?,
4444
override val eventId: EventId,
45-
override val defaultContent: CharSequence
45+
override val defaultContent: String
4646
) : Special(eventId, defaultContent)
4747

4848
val relatedEventId: EventId?

libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fun TextComposer(
9696
focusRequester: FocusRequester = FocusRequester(),
9797
onSendMessage: (String) -> Unit = {},
9898
onResetComposerMode: () -> Unit = {},
99-
onComposerTextChange: (CharSequence) -> Unit = {},
99+
onComposerTextChange: (String) -> Unit = {},
100100
onAddAttachment: () -> Unit = {},
101101
onFocusChanged: (Boolean) -> Unit = {},
102102
) {

0 commit comments

Comments
 (0)