From 9d0e185d1ccaa0f4e2cadff7bdb5a1edfae6656d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 27 Sep 2023 10:48:31 +0200 Subject: [PATCH] Ensure `getEventTimelineItemByEventId` is called when we enter in reply mode. --- .../MessageComposerPresenter.kt | 21 ++++++++++++++++-- .../libraries/matrix/api/room/MatrixRoom.kt | 7 +++--- .../matrix/impl/room/RustMatrixRoom.kt | 22 ++++++++++++++++++- .../matrix/test/room/FakeMatrixRoom.kt | 10 ++++++++- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 6898d7796f..9a6849023f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -20,6 +20,7 @@ import android.Manifest import android.annotation.SuppressLint import android.net.Uri import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue @@ -151,15 +152,24 @@ class MessageComposerPresenter @Inject constructor( } } + DisposableEffect(Unit) { + onDispose { + appCoroutineScope.launch { + room.exitReplyMode() + } + } + } + fun handleEvents(event: MessageComposerEvents) { when (event) { MessageComposerEvents.ToggleFullScreenState -> isFullScreen.value = !isFullScreen.value - MessageComposerEvents.CloseSpecialMode -> { richTextEditorState.setHtml("") messageComposerContext.composerMode = MessageComposerMode.Normal("") + appCoroutineScope.launch { + room.exitReplyMode() + } } - is MessageComposerEvents.SendMessage -> appCoroutineScope.sendMessage( message = event.message, updateComposerMode = { messageComposerContext.composerMode = it }, @@ -167,6 +177,13 @@ class MessageComposerPresenter @Inject constructor( ) is MessageComposerEvents.SetMode -> { messageComposerContext.composerMode = event.composerMode + appCoroutineScope.launch { + if (event.composerMode is MessageComposerMode.Reply) { + room.enterReplyMode(event.composerMode.eventId) + } else { + room.exitReplyMode() + } + } } MessageComposerEvents.AddAttachment -> localCoroutineScope.launch { showAttachmentSourcePicker = true diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 1dd6101354..465c0fe365 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -89,6 +89,10 @@ interface MatrixRoom : Closeable { suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?): Result + suspend fun enterReplyMode(eventId: EventId): Result + + suspend fun exitReplyMode(): Result + suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?): Result suspend fun redactEvent(eventId: EventId, reason: String? = null): Result @@ -184,7 +188,4 @@ interface MatrixRoom : Closeable { suspend fun endPoll(pollStartId: EventId, text: String): Result override fun close() = destroy() - } - - diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index d879bcc53d..a4cedfee91 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -60,6 +60,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.RequiredState import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListItem @@ -261,11 +262,30 @@ class RustMatrixRoom( } } + private var inReplyToEventTimelineItem: EventTimelineItem? = null + + override suspend fun enterReplyMode(eventId: EventId): Result = withContext(roomDispatcher) { + runCatching { + inReplyToEventTimelineItem?.destroy() + inReplyToEventTimelineItem = null + inReplyToEventTimelineItem = innerRoom.getEventTimelineItemByEventId(eventId.value) + } + } + + override suspend fun exitReplyMode(): Result = withContext(roomDispatcher) { + runCatching { + inReplyToEventTimelineItem?.destroy() + inReplyToEventTimelineItem = null + } + } + override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?): Result = withContext(roomDispatcher) { runCatching { - innerRoom.getEventTimelineItemByEventId(eventId.value).use { eventTimelineItem -> + val inReplyTo = inReplyToEventTimelineItem ?: innerRoom.getEventTimelineItemByEventId(eventId.value) + inReplyTo.use { eventTimelineItem -> innerRoom.sendReply(messageEventContentFromParts(body, htmlBody), eventTimelineItem) } + inReplyToEventTimelineItem = null } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 0e8916e87e..7771548d01 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -31,8 +31,8 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState -import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState +import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline @@ -208,6 +208,14 @@ class FakeMatrixRoom( var replyMessageParameter: Pair? = null private set + override suspend fun enterReplyMode(eventId: EventId): Result { + return Result.success(Unit) + } + + override suspend fun exitReplyMode(): Result { + return Result.success(Unit) + } + override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?): Result { replyMessageParameter = body to htmlBody return Result.success(Unit)