Message state: allow edit and copy when failed
This commit is contained in:
parent
bbb5dd06a2
commit
6c8e2f1fd6
@ -66,11 +66,11 @@ interface RelationService {
|
||||
|
||||
/**
|
||||
* Edit a text message body. Limited to "m.text" contentType
|
||||
* @param targetEventId The event to edit
|
||||
* @param targetEvent The event to edit
|
||||
* @param newBodyText The edited body
|
||||
* @param compatibilityBodyText The text that will appear on clients that don't support yet edition
|
||||
*/
|
||||
fun editTextMessage(targetEventId: String,
|
||||
fun editTextMessage(targetEvent: TimelineEvent,
|
||||
msgType: String,
|
||||
newBodyText: CharSequence,
|
||||
newBodyAutoMarkdown: Boolean,
|
||||
|
@ -15,10 +15,7 @@
|
||||
*/
|
||||
package org.matrix.android.sdk.internal.crypto.tasks
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||
import org.matrix.android.sdk.internal.network.executeRequest
|
||||
@ -27,7 +24,6 @@ import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTa
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
||||
import org.matrix.android.sdk.internal.session.room.send.SendResponse
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import java.lang.IllegalStateException
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface SendEventTask : Task<SendEventTask.Params, String> {
|
||||
@ -55,9 +51,6 @@ internal class DefaultSendEventTask @Inject constructor(
|
||||
|
||||
val event = handleEncryption(params)
|
||||
val localId = event.eventId!!
|
||||
if((event.content?.get("body") as? String)?.contains("Fail").orFalse()){
|
||||
throw IllegalStateException()
|
||||
}
|
||||
localEchoRepository.updateSendState(localId, params.event.roomId, SendState.SENDING)
|
||||
val executeRequest = executeRequest<SendResponse>(globalErrorReceiver) {
|
||||
apiCall = roomAPI.send(
|
||||
|
@ -17,14 +17,13 @@ package org.matrix.android.sdk.internal.session.room.relation
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.assisted.AssistedFactory
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
@ -39,6 +38,7 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
||||
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
|
||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||
import org.matrix.android.sdk.internal.task.configureWith
|
||||
@ -47,6 +47,7 @@ import timber.log.Timber
|
||||
|
||||
internal class DefaultRelationService @AssistedInject constructor(
|
||||
@Assisted private val roomId: String,
|
||||
private val eventEditor: EventEditor,
|
||||
private val eventSenderProcessor: EventSenderProcessor,
|
||||
private val eventFactory: LocalEchoEventFactory,
|
||||
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
|
||||
@ -112,32 +113,19 @@ internal class DefaultRelationService @AssistedInject constructor(
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun editTextMessage(targetEventId: String,
|
||||
override fun editTextMessage(targetEvent: TimelineEvent,
|
||||
msgType: String,
|
||||
newBodyText: CharSequence,
|
||||
newBodyAutoMarkdown: Boolean,
|
||||
compatibilityBodyText: String): Cancelable {
|
||||
val event = eventFactory
|
||||
.createReplaceTextEvent(roomId, targetEventId, newBodyText, newBodyAutoMarkdown, msgType, compatibilityBodyText)
|
||||
.also { saveLocalEcho(it) }
|
||||
return eventSenderProcessor.postEvent(event, cryptoSessionInfoProvider.isRoomEncrypted(roomId))
|
||||
return eventEditor.editTextMessage(targetEvent, msgType, newBodyText, newBodyAutoMarkdown, compatibilityBodyText)
|
||||
}
|
||||
|
||||
override fun editReply(replyToEdit: TimelineEvent,
|
||||
originalTimelineEvent: TimelineEvent,
|
||||
newBodyText: String,
|
||||
compatibilityBodyText: String): Cancelable {
|
||||
val event = eventFactory.createReplaceTextOfReply(
|
||||
roomId,
|
||||
replyToEdit,
|
||||
originalTimelineEvent,
|
||||
newBodyText,
|
||||
true,
|
||||
MessageType.MSGTYPE_TEXT,
|
||||
compatibilityBodyText
|
||||
)
|
||||
.also { saveLocalEcho(it) }
|
||||
return eventSenderProcessor.postEvent(event, cryptoSessionInfoProvider.isRoomEncrypted(roomId))
|
||||
return eventEditor.editReply(replyToEdit, originalTimelineEvent, newBodyText, compatibilityBodyText)
|
||||
}
|
||||
|
||||
override suspend fun fetchEditHistory(eventId: String): List<Event> {
|
||||
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* 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 org.matrix.android.sdk.internal.session.room.relation
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.util.Cancelable
|
||||
import org.matrix.android.sdk.api.util.NoOpCancellable
|
||||
import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider
|
||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
|
||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
||||
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class EventEditor @Inject constructor(private val eventSenderProcessor: EventSenderProcessor,
|
||||
private val eventFactory: LocalEchoEventFactory,
|
||||
private val cryptoSessionInfoProvider: CryptoSessionInfoProvider,
|
||||
private val localEchoRepository: LocalEchoRepository) {
|
||||
|
||||
fun editTextMessage(targetEvent: TimelineEvent,
|
||||
msgType: String,
|
||||
newBodyText: CharSequence,
|
||||
newBodyAutoMarkdown: Boolean,
|
||||
compatibilityBodyText: String): Cancelable {
|
||||
val roomId = targetEvent.roomId
|
||||
if (targetEvent.root.sendState.hasFailed()) {
|
||||
// We create a new in memory event for the EventSenderProcessor but we keep the eventId of the failed event.
|
||||
val editedEvent = eventFactory.createTextEvent(roomId, msgType, newBodyText, newBodyAutoMarkdown).copy(
|
||||
eventId = targetEvent.eventId
|
||||
)
|
||||
updateFailedEchoWithEvent(roomId, targetEvent.eventId, editedEvent)
|
||||
return eventSenderProcessor.postEvent(editedEvent, cryptoSessionInfoProvider.isRoomEncrypted(roomId))
|
||||
} else if (targetEvent.root.sendState.isSent()) {
|
||||
val event = eventFactory
|
||||
.createReplaceTextEvent(roomId, targetEvent.eventId, newBodyText, newBodyAutoMarkdown, msgType, compatibilityBodyText)
|
||||
.also { localEchoRepository.createLocalEcho(it) }
|
||||
return eventSenderProcessor.postEvent(event, cryptoSessionInfoProvider.isRoomEncrypted(roomId))
|
||||
} else {
|
||||
// Should we throw?
|
||||
Timber.w("Can't edit a sending event")
|
||||
return NoOpCancellable
|
||||
}
|
||||
}
|
||||
|
||||
fun editReply(replyToEdit: TimelineEvent,
|
||||
originalTimelineEvent: TimelineEvent,
|
||||
newBodyText: String,
|
||||
compatibilityBodyText: String): Cancelable {
|
||||
val roomId = replyToEdit.roomId
|
||||
if (replyToEdit.root.sendState.hasFailed()) {
|
||||
// We create a new in memory event for the EventSenderProcessor but we keep the eventId of the failed event.
|
||||
val editedEvent = eventFactory.createReplyTextEvent(roomId, originalTimelineEvent, newBodyText, false)?.copy(
|
||||
eventId = replyToEdit.eventId
|
||||
) ?: return NoOpCancellable
|
||||
updateFailedEchoWithEvent(roomId, replyToEdit.eventId, editedEvent)
|
||||
return eventSenderProcessor.postEvent(editedEvent, cryptoSessionInfoProvider.isRoomEncrypted(roomId))
|
||||
} else if (replyToEdit.root.sendState.isSent()) {
|
||||
val event = eventFactory.createReplaceTextOfReply(
|
||||
roomId,
|
||||
replyToEdit,
|
||||
originalTimelineEvent,
|
||||
newBodyText,
|
||||
true,
|
||||
MessageType.MSGTYPE_TEXT,
|
||||
compatibilityBodyText
|
||||
)
|
||||
.also { localEchoRepository.createLocalEcho(it) }
|
||||
return eventSenderProcessor.postEvent(event, cryptoSessionInfoProvider.isRoomEncrypted(roomId))
|
||||
} else {
|
||||
// Should we throw?
|
||||
Timber.w("Can't edit a sending event")
|
||||
return NoOpCancellable
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFailedEchoWithEvent(roomId: String, failedEchoEventId: String, editedEvent: Event) {
|
||||
val editedEventEntity = editedEvent.toEntity(roomId, SendState.UNSENT, System.currentTimeMillis())
|
||||
localEchoRepository.updateEchoAsync(failedEchoEventId) { _, entity ->
|
||||
entity.content = editedEventEntity.content
|
||||
entity.ageLocalTs = editedEventEntity.ageLocalTs
|
||||
entity.age = editedEventEntity.age
|
||||
entity.originServerTs = editedEventEntity.originServerTs
|
||||
entity.sendState = editedEventEntity.sendState
|
||||
}
|
||||
}
|
||||
}
|
@ -828,7 +828,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
val messageContent = state.sendMode.timelineEvent.getLastMessageContent()
|
||||
val existingBody = messageContent?.body ?: ""
|
||||
if (existingBody != action.text) {
|
||||
room.editTextMessage(state.sendMode.timelineEvent.root.eventId ?: "",
|
||||
room.editTextMessage(state.sendMode.timelineEvent,
|
||||
messageContent?.msgType ?: MessageType.MSGTYPE_TEXT,
|
||||
action.text,
|
||||
action.autoMarkdown)
|
||||
|
@ -59,5 +59,4 @@ data class MessageActionState(
|
||||
fun canReact() = timelineEvent()?.canReact() == true && actionPermissions.canReact
|
||||
|
||||
fun sendState(): SendState? = timelineEvent()?.root?.sendState
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user