Add missing withRelations fields

This commit is contained in:
Florian Renaud 2023-01-24 11:37:31 +01:00
parent 9c3cacc2da
commit 0704fc5e15
11 changed files with 88 additions and 21 deletions

View File

@ -156,11 +156,12 @@ interface SendService {
/** /**
* Redact (delete) the given event. * Redact (delete) the given event.
* @param event The event to redact * @param event the event to redact
* @param reason Optional reason string * @param reason optional reason string
* @param withRelations the list of relation types to redact with this event
* @param additionalContent additional content to put in the event content * @param additionalContent additional content to put in the event content
*/ */
fun redactEvent(event: Event, reason: String?, additionalContent: Content? = null): Cancelable fun redactEvent(event: Event, reason: String?, withRelations: List<String>? = null, additionalContent: Content? = null): Cancelable
/** /**
* Schedule this message to be resent. * Schedule this message to be resent.

View File

@ -52,7 +52,7 @@ internal class DefaultRedactEventTask @Inject constructor(
txId = params.txID, txId = params.txID,
roomId = params.roomId, roomId = params.roomId,
eventId = params.eventId, eventId = params.eventId,
body = EventRedactBody(params.reason, withRelations) body = EventRedactBody(params.reason, withRelations, withRelations)
) )
} }
return response.eventId return response.eventId

View File

@ -65,6 +65,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo045
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo046 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo046
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo047 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo047
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo048 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo048
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo049
import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.Normalizer
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
import javax.inject.Inject import javax.inject.Inject
@ -73,7 +74,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
private val normalizer: Normalizer private val normalizer: Normalizer
) : MatrixRealmMigration( ) : MatrixRealmMigration(
dbName = "Session", dbName = "Session",
schemaVersion = 48L, schemaVersion = 49L,
) { ) {
/** /**
* Forces all RealmSessionStoreMigration instances to be equal. * Forces all RealmSessionStoreMigration instances to be equal.
@ -131,5 +132,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
if (oldVersion < 46) MigrateSessionTo046(realm).perform() if (oldVersion < 46) MigrateSessionTo046(realm).perform()
if (oldVersion < 47) MigrateSessionTo047(realm).perform() if (oldVersion < 47) MigrateSessionTo047(realm).perform()
if (oldVersion < 48) MigrateSessionTo048(realm).perform() if (oldVersion < 48) MigrateSessionTo048(realm).perform()
if (oldVersion < 49) MigrateSessionTo049(realm).perform()
} }
} }

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 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.database.migration
import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities
import org.matrix.android.sdk.internal.util.database.RealmMigrator
internal class MigrateSessionTo049(realm: DynamicRealm) : RealmMigrator(realm, 49) {
override fun doMigrate(realm: DynamicRealm) {
realm.schema.get("HomeServerCapabilitiesEntity")
?.addField(HomeServerCapabilitiesEntityFields.CAN_REDACT_EVENT_WITH_RELATIONS, Boolean::class.java)
?.transform { obj ->
obj.set(HomeServerCapabilitiesEntityFields.CAN_REDACT_EVENT_WITH_RELATIONS, false)
}
?.forceRefreshOfHomeServerCapabilities()
}
}

View File

@ -25,5 +25,8 @@ internal data class EventRedactBody(
val reason: String? = null, val reason: String? = null,
@Json(name = "with_relations") @Json(name = "with_relations")
val withRelations: List<String>? = null val withRelations: List<String>? = null,
@Json(name = "org.matrix.msc3912.with_relations")
val withRelationsUnstable: List<String>? = null,
) )

View File

@ -140,11 +140,11 @@ internal class DefaultSendService @AssistedInject constructor(
.let { sendEvent(it) } .let { sendEvent(it) }
} }
override fun redactEvent(event: Event, reason: String?, additionalContent: Content?): Cancelable { override fun redactEvent(event: Event, reason: String?, withRelations: List<String>?, additionalContent: Content?): Cancelable {
// TODO manage media/attachements? // TODO manage media/attachements?
val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason, additionalContent) val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason, withRelations, additionalContent)
.also { createLocalEcho(it) } .also { createLocalEcho(it) }
return eventSenderProcessor.postRedaction(redactionEcho, reason) return eventSenderProcessor.postRedaction(redactionEcho, reason, withRelations)
} }
override fun resendTextMessage(localEcho: TimelineEvent): Cancelable { override fun resendTextMessage(localEcho: TimelineEvent): Cancelable {

View File

@ -70,6 +70,7 @@ import org.matrix.android.sdk.api.util.TextContent
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor
import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory
import org.matrix.android.sdk.internal.session.room.EventRedactBody
import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils
import org.matrix.android.sdk.internal.util.time.Clock import org.matrix.android.sdk.internal.util.time.Clock
import java.util.UUID import java.util.UUID
@ -795,8 +796,13 @@ internal class LocalEchoEventFactory @Inject constructor(
} }
} }
*/ */
fun createRedactEvent(roomId: String, eventId: String, reason: String?, additionalContent: Content? = null): Event { fun createRedactEvent(roomId: String, eventId: String, reason: String?, withRelations: List<String>? = null, additionalContent: Content? = null): Event {
val localId = LocalEcho.createLocalEchoId() val localId = LocalEcho.createLocalEchoId()
val content = if (reason != null || withRelations != null) {
EventRedactBody(reason, withRelations, withRelations).toContent().plus(additionalContent.orEmpty())
} else {
additionalContent
}
return Event( return Event(
roomId = roomId, roomId = roomId,
originServerTs = dummyOriginServerTs(), originServerTs = dummyOriginServerTs(),
@ -804,7 +810,7 @@ internal class LocalEchoEventFactory @Inject constructor(
eventId = localId, eventId = localId,
type = EventType.REDACTION, type = EventType.REDACTION,
redacts = eventId, redacts = eventId,
content = reason?.let { mapOf("reason" to it).toContent().plus(additionalContent.orEmpty()) } ?: additionalContent, content = content,
unsignedData = UnsignedData(age = null, transactionId = localId) unsignedData = UnsignedData(age = null, transactionId = localId)
) )
} }
@ -830,10 +836,10 @@ internal class LocalEchoEventFactory @Inject constructor(
createMessageEvent( createMessageEvent(
roomId, roomId,
textContent.toThreadTextContent( textContent.toThreadTextContent(
rootThreadEventId = rootThreadEventId, rootThreadEventId = rootThreadEventId,
latestThreadEventId = localEchoRepository.getLatestThreadEvent(rootThreadEventId), latestThreadEventId = localEchoRepository.getLatestThreadEvent(rootThreadEventId),
msgType = MessageType.MSGTYPE_TEXT msgType = MessageType.MSGTYPE_TEXT
), ),
additionalContent, additionalContent,
) )
} else { } else {

View File

@ -19,10 +19,12 @@ import android.content.Context
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.SessionComponent import org.matrix.android.sdk.internal.session.SessionComponent
import org.matrix.android.sdk.internal.session.room.EventRedactBody
import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.RoomAPI
import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
import org.matrix.android.sdk.internal.worker.SessionWorkerParams import org.matrix.android.sdk.internal.worker.SessionWorkerParams
@ -43,11 +45,13 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters, ses
val roomId: String, val roomId: String,
val eventId: String, val eventId: String,
val reason: String?, val reason: String?,
val withRelations: List<String>? = null,
override val lastFailureMessage: String? = null override val lastFailureMessage: String? = null
) : SessionWorkerParams ) : SessionWorkerParams
@Inject lateinit var roomAPI: RoomAPI @Inject lateinit var roomAPI: RoomAPI
@Inject lateinit var globalErrorReceiver: GlobalErrorReceiver @Inject lateinit var globalErrorReceiver: GlobalErrorReceiver
@Inject lateinit var homeServerCapabilitiesService: HomeServerCapabilitiesService
override fun injectWith(injector: SessionComponent) { override fun injectWith(injector: SessionComponent) {
injector.inject(this) injector.inject(this)
@ -55,13 +59,20 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters, ses
override suspend fun doSafeWork(params: Params): Result { override suspend fun doSafeWork(params: Params): Result {
val eventId = params.eventId val eventId = params.eventId
val withRelations = if (homeServerCapabilitiesService.getHomeServerCapabilities().canRedactEventWithRelations &&
!params.withRelations.isNullOrEmpty()) {
params.withRelations
} else {
null
}
return runCatching { return runCatching {
executeRequest(globalErrorReceiver) { executeRequest(globalErrorReceiver) {
roomAPI.redactEvent( roomAPI.redactEvent(
params.txID, params.txID,
params.roomId, params.roomId,
eventId, eventId,
if (params.reason == null) emptyMap() else mapOf("reason" to params.reason) EventRedactBody(params.reason, withRelations, withRelations)
) )
} }
}.fold( }.fold(

View File

@ -26,9 +26,9 @@ internal interface EventSenderProcessor : SessionLifecycleObserver {
fun postEvent(event: Event, encrypt: Boolean): Cancelable fun postEvent(event: Event, encrypt: Boolean): Cancelable
fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List<String>?): Cancelable fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List<String>? = null): Cancelable
fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelations: List<String>?): Cancelable fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelations: List<String>? = null): Cancelable
fun postTask(task: QueuedTask): Cancelable fun postTask(task: QueuedTask): Cancelable

View File

@ -19,8 +19,10 @@ package org.matrix.android.sdk.internal.session.room.send.queue
import android.content.Context import android.content.Context
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.session.room.EventRedactBody
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -107,10 +109,18 @@ internal class QueueMemento @Inject constructor(
info.redactionLocalEcho?.let { localEchoRepository.getUpToDateEcho(it) }?.let { info.redactionLocalEcho?.let { localEchoRepository.getUpToDateEcho(it) }?.let {
localEchoRepository.updateSendState(it.eventId!!, it.roomId, SendState.UNSENT) localEchoRepository.updateSendState(it.eventId!!, it.roomId, SendState.UNSENT)
// try to get reason // try to get reason
val reason = it.content?.get("reason") as? String val body = it.content.toModel<EventRedactBody>()
if (it.redacts != null && it.roomId != null) { if (it.redacts != null && it.roomId != null) {
Timber.d("## Send -Reschedule redact $info") Timber.d("## Send -Reschedule redact $info")
eventProcessor.postTask(queuedTaskFactory.createRedactTask(it.eventId, it.redacts, it.roomId, reason)) eventProcessor.postTask(
queuedTaskFactory.createRedactTask(
redactionLocalEcho = it.eventId,
eventId = it.redacts,
roomId = it.roomId,
reason = body?.reason,
withRelations = body?.withRelations ?: body?.withRelationsUnstable
)
)
} }
} }
// postTask(queuedTaskFactory.createRedactTask(info.eventToRedactId, info.) // postTask(queuedTaskFactory.createRedactTask(info.eventToRedactId, info.)

View File

@ -43,7 +43,7 @@ internal class QueuedTaskFactory @Inject constructor(
) )
} }
fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?, withRelations: List<String>?): QueuedTask { fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?, withRelations: List<String>? = null): QueuedTask {
return RedactQueuedTask( return RedactQueuedTask(
redactionLocalEchoId = redactionLocalEcho, redactionLocalEchoId = redactionLocalEcho,
toRedactEventId = eventId, toRedactEventId = eventId,