mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Thread redaction will now update the thread summary counter
Root threads with 0 threads replies will become normal messages and removed from thread summaries
This commit is contained in:
parent
84b34f75de
commit
3c7495bd60
3 changed files with 82 additions and 9 deletions
|
@ -46,3 +46,5 @@ data class UnsignedData(
|
|||
@Json(name = "replaces_state") val replacesState: String? = null
|
||||
|
||||
)
|
||||
|
||||
fun UnsignedData?.isRedacted() = this?.redactedEvent != null
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.database.helper
|
||||
|
||||
import com.squareup.moshi.JsonDataException
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmQuery
|
||||
import io.realm.Sort
|
||||
import org.matrix.android.sdk.api.session.events.model.UnsignedData
|
||||
import org.matrix.android.sdk.api.session.events.model.isRedacted
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.session.threads.ThreadNotificationState
|
||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||
|
@ -33,6 +36,8 @@ import org.matrix.android.sdk.internal.database.query.findIncludingEvent
|
|||
import org.matrix.android.sdk.internal.database.query.findLastForwardChunkOfRoom
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
import timber.log.Timber
|
||||
|
||||
private typealias Summary = Pair<Int, TimelineEventEntity>?
|
||||
|
||||
|
@ -90,19 +95,18 @@ internal fun EventEntity.markEventAsRoot(
|
|||
|
||||
/**
|
||||
* Count the number of threads for the provided root thread eventId, and finds the latest event message
|
||||
* note: Redactions are handled by RedactionEventProcessor
|
||||
* @param rootThreadEventId The root eventId that will find the number of threads
|
||||
* @return A ThreadSummary containing the counted threads and the latest event message
|
||||
*/
|
||||
internal fun EventEntity.threadSummaryInThread(realm: Realm, rootThreadEventId: String, chunkEntity: ChunkEntity?): Summary {
|
||||
// Number of messages
|
||||
val messages = TimelineEventEntity
|
||||
.whereRoomId(realm, roomId = roomId)
|
||||
.equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, rootThreadEventId)
|
||||
.distinct(TimelineEventEntityFields.ROOT.EVENT_ID)
|
||||
.count()
|
||||
.toInt()
|
||||
val numberOfThread = countThreads(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
rootThreadEventId = rootThreadEventId
|
||||
) ?: return null
|
||||
|
||||
if (messages <= 0) return null
|
||||
if (numberOfThread <= 0) return null
|
||||
|
||||
// Find latest thread event, we know it exists
|
||||
var chunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: chunkEntity ?: return null
|
||||
|
@ -124,7 +128,36 @@ internal fun EventEntity.threadSummaryInThread(realm: Realm, rootThreadEventId:
|
|||
|
||||
result ?: return null
|
||||
|
||||
return Summary(messages, result)
|
||||
return Summary(numberOfThread, result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of threads in the main timeline thread summary,
|
||||
* with respect to redactions.
|
||||
*/
|
||||
internal fun countThreads(realm: Realm, roomId: String, rootThreadEventId: String): Int? =
|
||||
TimelineEventEntity
|
||||
.whereRoomId(realm, roomId = roomId)
|
||||
.equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, rootThreadEventId)
|
||||
.distinct(TimelineEventEntityFields.ROOT.EVENT_ID)
|
||||
.findAll()
|
||||
?.filterNot { timelineEvent ->
|
||||
timelineEvent.root
|
||||
?.unsignedData
|
||||
?.takeIf { it.isNotBlank() }
|
||||
?.toUnsignedData()
|
||||
.isRedacted()
|
||||
}?.size
|
||||
|
||||
/**
|
||||
* Mapping string to UnsignedData using Moshi
|
||||
*/
|
||||
private fun String.toUnsignedData(): UnsignedData? =
|
||||
try {
|
||||
MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).fromJson(this)
|
||||
} catch (ex: JsonDataException) {
|
||||
Timber.e(ex, "Failed to parse UnsignedData")
|
||||
null
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,11 +21,14 @@ import org.matrix.android.sdk.api.session.events.model.Event
|
|||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||
import org.matrix.android.sdk.api.session.events.model.UnsignedData
|
||||
import org.matrix.android.sdk.internal.database.helper.countThreads
|
||||
import org.matrix.android.sdk.internal.database.helper.findRootThreadEvent
|
||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
||||
import org.matrix.android.sdk.internal.database.mapper.EventMapper
|
||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.query.findWithSenderMembershipEvent
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.di.MoshiProvider
|
||||
|
@ -89,6 +92,8 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr
|
|||
eventToPrune.unsignedData = MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(modified)
|
||||
eventToPrune.decryptionResultJson = null
|
||||
eventToPrune.decryptionErrorCode = null
|
||||
|
||||
handleTimelineThreadSummaryIfNeeded(realm, eventToPrune, isLocalEcho)
|
||||
}
|
||||
// EventType.REACTION -> {
|
||||
// eventRelationsAggregationUpdater.handleReactionRedact(eventToPrune, realm, userId)
|
||||
|
@ -104,6 +109,39 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the number of threads in the main timeline thread summary,
|
||||
* with respect to redactions.
|
||||
*/
|
||||
private fun handleTimelineThreadSummaryIfNeeded(
|
||||
realm: Realm,
|
||||
eventToPrune: EventEntity,
|
||||
isLocalEcho: Boolean,
|
||||
) {
|
||||
if (eventToPrune.isThread() && !isLocalEcho) {
|
||||
val roomId = eventToPrune.roomId
|
||||
val rootThreadEvent = eventToPrune.findRootThreadEvent() ?: return
|
||||
val rootThreadEventId = eventToPrune.rootThreadEventId ?: return
|
||||
|
||||
val numberOfThreads = countThreads(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
rootThreadEventId = rootThreadEventId
|
||||
) ?: return
|
||||
|
||||
rootThreadEvent.numberOfThreads = numberOfThreads
|
||||
if (numberOfThreads == 0) {
|
||||
// We should also clear the thread summary list
|
||||
rootThreadEvent.isRootThread = false
|
||||
rootThreadEvent.threadSummaryLatestMessage = null
|
||||
ThreadSummaryEntity
|
||||
.where(realm, roomId = roomId, rootThreadEventId)
|
||||
.findFirst()
|
||||
?.deleteFromRealm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeAllowedKeys(type: String): List<String> {
|
||||
// Add filtered content, allowed keys in content depends on the event type
|
||||
return when (type) {
|
||||
|
|
Loading…
Reference in a new issue