Enhance thread summary

Fix deleted root thread messages when show deleted messages are enabled/disabled
This commit is contained in:
ariskotsomitopoulos 2022-01-25 18:21:42 +02:00
parent b1b27bdd0e
commit c19b52cded
5 changed files with 70 additions and 17 deletions

View file

@ -28,5 +28,6 @@ data class ThreadDetails(
val threadSummarySenderInfo: SenderInfo? = null,
val threadSummaryLatestTextMessage: String? = null,
val lastMessageTimestamp: Long? = null,
var threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE
var threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE,
val isThread: Boolean = false
)

View file

@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.database.helper
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import org.matrix.android.sdk.api.session.threads.ThreadNotificationState
import org.matrix.android.sdk.internal.database.mapper.asDomain
@ -27,10 +26,14 @@ import org.matrix.android.sdk.internal.database.model.EventEntity
import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
import org.matrix.android.sdk.internal.database.query.find
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
private typealias ThreadSummary = Pair<Int, TimelineEventEntity>?
/**
* Finds the root thread event and update it with the latest message summary along with the number
* of threads included. If there is no root thread event no action is done
@ -39,19 +42,21 @@ internal fun Map<String, EventEntity>.updateThreadSummaryIfNeeded(
roomId: String,
realm: Realm, currentUserId: String,
shouldUpdateNotifications: Boolean = true) {
for ((rootThreadEventId, eventEntity) in this) {
eventEntity.findAllThreadsForRootEventId(eventEntity.realm, rootThreadEventId).let {
if (it.isNullOrEmpty()) return@let
val latestMessage = it.firstOrNull()
for ((rootThreadEventId, eventEntity) in this) {
eventEntity.threadSummaryInThread(eventEntity.realm, rootThreadEventId)?.let { threadSummary ->
val numberOfMessages = threadSummary.first
val latestEventInThread = threadSummary.second
// If this is a thread message, find its root event if exists
val rootThreadEvent = if (eventEntity.isThread()) eventEntity.findRootThreadEvent() else eventEntity
rootThreadEvent?.markEventAsRoot(
threadsCounted = it.size,
latestMessageTimelineEventEntity = latestMessage
threadsCounted = numberOfMessages,
latestMessageTimelineEventEntity = latestEventInThread
)
}
}
@ -82,16 +87,49 @@ internal fun EventEntity.markEventAsRoot(
threadSummaryLatestMessage = latestMessageTimelineEventEntity
}
///**
// * Find all TimelineEventEntity that are threads bind to the Event with rootThreadEventId
// * @param rootThreadEventId The root eventId that will try to find bind threads
// */
//internal fun EventEntity.findAllThreadsForRootEventId(realm: Realm, rootThreadEventId: String): RealmResults<TimelineEventEntity> =
// TimelineEventEntity
// .whereRoomId(realm, roomId = roomId)
// .equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, rootThreadEventId)
// .sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
// .findAll()
/**
* Find all TimelineEventEntity that are threads bind to the Event with rootThreadEventId
* @param rootThreadEventId The root eventId that will try to find bind threads
* Count the number of threads for the provided root thread eventId, and finds the latest event message
* @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.findAllThreadsForRootEventId(realm: Realm, rootThreadEventId: String): RealmResults<TimelineEventEntity> =
TimelineEventEntity
internal fun EventEntity.threadSummaryInThread(realm: Realm, rootThreadEventId: String): ThreadSummary {
// Number of messages
val messages = TimelineEventEntity
.whereRoomId(realm, roomId = roomId)
.equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, rootThreadEventId)
.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
.findAll()
.count()
.toInt()
if (messages <= 0) return null
// Find latest thread event, we know it exists
var chunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return null
var result: TimelineEventEntity? = null
// Iterate the chunk until we find our latest event
while (result == null) {
result = chunk.timelineEvents.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)?.firstOrNull {
it.root?.rootThreadEventId == rootThreadEventId
}
chunk = ChunkEntity.find(realm, roomId, nextToken = chunk.prevToken) ?: break
}
result ?: return null
return ThreadSummary(messages, result)
}
/**
* Find all TimelineEventEntity that are root threads for the specified room

View file

@ -103,6 +103,7 @@ internal object EventMapper {
it.mCryptoErrorReason = eventEntity.decryptionErrorReason
it.threadDetails = ThreadDetails(
isRootThread = eventEntity.isRootThread,
isThread = if (it.threadDetails?.isThread == true) true else eventEntity.isThread(),
numberOfThreads = eventEntity.numberOfThreads,
threadSummarySenderInfo = eventEntity.threadSummaryLatestMessage?.let { timelineEventEntity ->
SenderInfo(

View file

@ -21,6 +21,7 @@ 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.api.session.room.model.relation.RelationContent
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

View file

@ -27,6 +27,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import timber.log.Timber
import javax.inject.Inject
class TimelineEventVisibilityHelper @Inject constructor(private val userPreferencesProvider: UserPreferencesProvider) {
@ -137,9 +138,19 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen
}
private fun TimelineEvent.shouldBeHidden(rootThreadEventId: String?, isFromThreadTimeline: Boolean): Boolean {
if (root.isRedacted() && !userPreferencesProvider.shouldShowRedactedMessages()) {
if (root.isRedacted() && !userPreferencesProvider.shouldShowRedactedMessages() && root.threadDetails?.isRootThread == false ) {
return true
}
// We should not display deleted thread messages within the normal timeline
if (root.isRedacted() &&
userPreferencesProvider.areThreadMessagesEnabled() &&
root.threadDetails?.isThread == true){
return true
}
if (root.getRelationContent()?.type == RelationType.REPLACE) {
return true
}
@ -155,6 +166,7 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen
return true
}
// Allow only the the threads within the rootThreadEventId along with the root event
if (userPreferencesProvider.areThreadMessagesEnabled() && isFromThreadTimeline) {
return if (root.getRootThreadEventId() == rootThreadEventId) {
false