Fix message edition is not rendered in e2e rooms after pagination (#3887)

This commit is contained in:
ganfra 2021-08-24 19:58:54 +02:00
parent b4979e0bfb
commit 2e2deba3ac
8 changed files with 37 additions and 31 deletions

1
changelog.d/3887.bugfix Normal file
View file

@ -0,0 +1 @@
Message edition is not rendered in e2e rooms after pagination

View file

@ -17,6 +17,9 @@
package org.matrix.android.sdk.internal.database package org.matrix.android.sdk.internal.database
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import io.realm.RealmConfiguration
import io.realm.RealmResults
import kotlinx.coroutines.launch
import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.mapper.asDomain
import org.matrix.android.sdk.internal.database.model.EventEntity import org.matrix.android.sdk.internal.database.model.EventEntity
import org.matrix.android.sdk.internal.database.model.EventInsertEntity import org.matrix.android.sdk.internal.database.model.EventInsertEntity
@ -24,20 +27,15 @@ import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields
import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
import io.realm.RealmConfiguration
import io.realm.RealmResults
import kotlinx.coroutines.launch
import org.matrix.android.sdk.internal.crypto.EventDecryptor
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration, internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration,
private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>, private val processors: Set<@JvmSuppressWildcards EventInsertLiveProcessor>)
private val eventDecryptor: EventDecryptor)
: RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) { : RealmLiveEntityObserver<EventInsertEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventInsertEntity> { override val query = Monarchy.Query {
it.where(EventInsertEntity::class.java) it.where(EventInsertEntity::class.java).equalTo(EventInsertEntityFields.CAN_BE_PROCESSED, true)
} }
override fun onChange(results: RealmResults<EventInsertEntity>) { override fun onChange(results: RealmResults<EventInsertEntity>) {
@ -86,23 +84,6 @@ internal class EventInsertLiveObserver @Inject constructor(@SessionDatabase real
} }
} }
// private fun decryptIfNeeded(event: Event) {
// if (event.isEncrypted() && event.mxDecryptionResult == null) {
// try {
// val result = eventDecryptor.decryptEvent(event, event.roomId ?: "")
// event.mxDecryptionResult = OlmDecryptionResult(
// payload = result.clearEvent,
// senderKey = result.senderCurve25519Key,
// keysClaimed = result.claimedEd25519Key?.let { k -> mapOf("ed25519" to k) },
// forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain
// )
// } catch (e: MXCryptoError) {
// Timber.v("Failed to decrypt event")
// // TODO -> we should keep track of this and retry, or some processing will never be handled
// }
// }
// }
private fun shouldProcess(eventInsertEntity: EventInsertEntity): Boolean { private fun shouldProcess(eventInsertEntity: EventInsertEntity): Boolean {
return processors.any { return processors.any {
it.shouldProcess(eventInsertEntity.eventId, eventInsertEntity.eventType, eventInsertEntity.insertType) it.shouldProcess(eventInsertEntity.eventId, eventInsertEntity.eventType, eventInsertEntity.insertType)

View file

@ -29,6 +29,7 @@ import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFie
import org.matrix.android.sdk.internal.database.model.EditAggregatedSummaryEntityFields import org.matrix.android.sdk.internal.database.model.EditAggregatedSummaryEntityFields
import org.matrix.android.sdk.internal.database.model.EditionOfEventFields import org.matrix.android.sdk.internal.database.model.EditionOfEventFields
import org.matrix.android.sdk.internal.database.model.EventEntityFields import org.matrix.android.sdk.internal.database.model.EventEntityFields
import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields
import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields
import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields
import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields
@ -46,7 +47,7 @@ import timber.log.Timber
internal object RealmSessionStoreMigration : RealmMigration { internal object RealmSessionStoreMigration : RealmMigration {
const val SESSION_STORE_SCHEMA_VERSION = 16L const val SESSION_STORE_SCHEMA_VERSION = 17L
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Timber.v("Migrating Realm Session from $oldVersion to $newVersion") Timber.v("Migrating Realm Session from $oldVersion to $newVersion")
@ -67,6 +68,7 @@ internal object RealmSessionStoreMigration : RealmMigration {
if (oldVersion <= 13) migrateTo14(realm) if (oldVersion <= 13) migrateTo14(realm)
if (oldVersion <= 14) migrateTo15(realm) if (oldVersion <= 14) migrateTo15(realm)
if (oldVersion <= 15) migrateTo16(realm) if (oldVersion <= 15) migrateTo16(realm)
if (oldVersion <= 16) migrateTo17(realm)
} }
private fun migrateTo1(realm: DynamicRealm) { private fun migrateTo1(realm: DynamicRealm) {
@ -330,4 +332,10 @@ internal object RealmSessionStoreMigration : RealmMigration {
obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0) obj.setLong(HomeServerCapabilitiesEntityFields.LAST_UPDATED_TIMESTAMP, 0)
} }
} }
private fun migrateTo17(realm: DynamicRealm) {
Timber.d("Step 16 -> 17")
realm.schema.get("EventInsertEntity")
?.addField(EventInsertEntityFields.CAN_BE_PROCESSED, Boolean::class.java)
}
} }

View file

@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.Index import io.realm.annotations.Index
import org.matrix.android.sdk.internal.extensions.assertIsManaged
internal open class EventEntity(@Index var eventId: String = "", internal open class EventEntity(@Index var eventId: String = "",
@Index var roomId: String = "", @Index var roomId: String = "",
@ -56,15 +57,22 @@ internal open class EventEntity(@Index var eventId: String = "",
companion object companion object
fun setDecryptionResult(result: MXEventDecryptionResult) { fun setDecryptionResult(result: MXEventDecryptionResult) {
assertIsManaged()
val decryptionResult = OlmDecryptionResult( val decryptionResult = OlmDecryptionResult(
payload = result.clearEvent, payload = result.clearEvent,
senderKey = result.senderCurve25519Key, senderKey = result.senderCurve25519Key,
keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) }, keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) },
forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain
) )
val adapter = MoshiProvider.providesMoshi().adapter<OlmDecryptionResult>(OlmDecryptionResult::class.java) val adapter = MoshiProvider.providesMoshi().adapter(OlmDecryptionResult::class.java)
decryptionResultJson = adapter.toJson(decryptionResult) decryptionResultJson = adapter.toJson(decryptionResult)
decryptionErrorCode = null decryptionErrorCode = null
decryptionErrorReason = null decryptionErrorReason = null
// If we have an EventInsertEntity for the eventId we make sures it can be processed now.
realm.where(EventInsertEntity::class.java)
.equalTo(EventInsertEntityFields.EVENT_ID, eventId)
.findFirst()
?.canBeProcessed = true
} }
} }

View file

@ -23,7 +23,12 @@ import io.realm.RealmObject
* in EventEntity table. * in EventEntity table.
*/ */
internal open class EventInsertEntity(var eventId: String = "", internal open class EventInsertEntity(var eventId: String = "",
var eventType: String = "" var eventType: String = "",
/**
* This flag will be used to filter EventInsertEntity in EventInsertLiveObserver.
* Currently it's set to false when the event content is encrypted.
*/
var canBeProcessed: Boolean = true
) : RealmObject() { ) : RealmObject() {
private var insertTypeStr: String = EventInsertType.INCREMENTAL_SYNC.name private var insertTypeStr: String = EventInsertType.INCREMENTAL_SYNC.name

View file

@ -24,6 +24,7 @@ import io.realm.Realm
import io.realm.RealmList import io.realm.RealmList
import io.realm.RealmQuery import io.realm.RealmQuery
import io.realm.kotlin.where import io.realm.kotlin.where
import org.matrix.android.sdk.api.session.events.model.EventType
internal fun EventEntity.copyToRealmOrIgnore(realm: Realm, insertType: EventInsertType): EventEntity { internal fun EventEntity.copyToRealmOrIgnore(realm: Realm, insertType: EventInsertType): EventEntity {
val eventEntity = realm.where<EventEntity>() val eventEntity = realm.where<EventEntity>()
@ -31,7 +32,8 @@ internal fun EventEntity.copyToRealmOrIgnore(realm: Realm, insertType: EventInse
.equalTo(EventEntityFields.ROOM_ID, roomId) .equalTo(EventEntityFields.ROOM_ID, roomId)
.findFirst() .findFirst()
return if (eventEntity == null) { return if (eventEntity == null) {
val insertEntity = EventInsertEntity(eventId = eventId, eventType = type).apply { val canBeProcessed = type != EventType.ENCRYPTED || decryptionResultJson != null
val insertEntity = EventInsertEntity(eventId = eventId, eventType = type, canBeProcessed = canBeProcessed).apply {
this.insertType = insertType this.insertType = insertType
} }
realm.insert(insertEntity) realm.insert(insertEntity)

View file

@ -77,7 +77,7 @@ internal class LocalEchoRepository @Inject constructor(@SessionDatabase private
val timelineEvent = timelineEventMapper.map(timelineEventEntity) val timelineEvent = timelineEventMapper.map(timelineEventEntity)
timelineInput.onLocalEchoCreated(roomId = roomId, timelineEvent = timelineEvent) timelineInput.onLocalEchoCreated(roomId = roomId, timelineEvent = timelineEvent)
taskExecutor.executorScope.asyncTransaction(monarchy) { realm -> taskExecutor.executorScope.asyncTransaction(monarchy) { realm ->
val eventInsertEntity = EventInsertEntity(event.eventId, event.type).apply { val eventInsertEntity = EventInsertEntity(event.eventId, event.type, canBeProcessed = true).apply {
this.insertType = EventInsertType.LOCAL_ECHO this.insertType = EventInsertType.LOCAL_ECHO
} }
realm.insert(eventInsertEntity) realm.insert(eventInsertEntity)

View file

@ -106,7 +106,8 @@ internal class TimelineEventDecryptor @Inject constructor(
val result = cryptoService.decryptEvent(request.event, timelineId) val result = cryptoService.decryptEvent(request.event, timelineId)
Timber.v("Successfully decrypted event ${event.eventId}") Timber.v("Successfully decrypted event ${event.eventId}")
realm.executeTransaction { realm.executeTransaction {
EventEntity.where(it, eventId = event.eventId ?: "") val eventId = event.eventId ?: ""
EventEntity.where(it, eventId = eventId)
.findFirst() .findFirst()
?.setDecryptionResult(result) ?.setDecryptionResult(result)
} }