Enhance thread summary
Fix deleted root thread messages when show deleted messages are enabled/disabled
This commit is contained in:
parent
b1b27bdd0e
commit
c19b52cded
@ -28,5 +28,6 @@ data class ThreadDetails(
|
|||||||
val threadSummarySenderInfo: SenderInfo? = null,
|
val threadSummarySenderInfo: SenderInfo? = null,
|
||||||
val threadSummaryLatestTextMessage: String? = null,
|
val threadSummaryLatestTextMessage: String? = null,
|
||||||
val lastMessageTimestamp: Long? = null,
|
val lastMessageTimestamp: Long? = null,
|
||||||
var threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE
|
var threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE,
|
||||||
|
val isThread: Boolean = false
|
||||||
)
|
)
|
||||||
|
@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.database.helper
|
|||||||
|
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.RealmResults
|
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import org.matrix.android.sdk.api.session.threads.ThreadNotificationState
|
import org.matrix.android.sdk.api.session.threads.ThreadNotificationState
|
||||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
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.ReadReceiptEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
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.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.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.where
|
||||||
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
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
|
* 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
|
* 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,
|
roomId: String,
|
||||||
realm: Realm, currentUserId: String,
|
realm: Realm, currentUserId: String,
|
||||||
shouldUpdateNotifications: Boolean = true) {
|
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
|
// If this is a thread message, find its root event if exists
|
||||||
val rootThreadEvent = if (eventEntity.isThread()) eventEntity.findRootThreadEvent() else eventEntity
|
val rootThreadEvent = if (eventEntity.isThread()) eventEntity.findRootThreadEvent() else eventEntity
|
||||||
|
|
||||||
rootThreadEvent?.markEventAsRoot(
|
rootThreadEvent?.markEventAsRoot(
|
||||||
threadsCounted = it.size,
|
threadsCounted = numberOfMessages,
|
||||||
latestMessageTimelineEventEntity = latestMessage
|
latestMessageTimelineEventEntity = latestEventInThread
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,16 +87,49 @@ internal fun EventEntity.markEventAsRoot(
|
|||||||
threadSummaryLatestMessage = latestMessageTimelineEventEntity
|
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
|
* Count the number of threads for the provided root thread eventId, and finds the latest event message
|
||||||
* @param rootThreadEventId The root eventId that will try to find bind threads
|
* @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> =
|
internal fun EventEntity.threadSummaryInThread(realm: Realm, rootThreadEventId: String): ThreadSummary {
|
||||||
TimelineEventEntity
|
|
||||||
.whereRoomId(realm, roomId = roomId)
|
// Number of messages
|
||||||
.equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, rootThreadEventId)
|
val messages = TimelineEventEntity
|
||||||
.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
|
.whereRoomId(realm, roomId = roomId)
|
||||||
.findAll()
|
.equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, rootThreadEventId)
|
||||||
|
.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
|
* Find all TimelineEventEntity that are root threads for the specified room
|
||||||
|
@ -103,6 +103,7 @@ internal object EventMapper {
|
|||||||
it.mCryptoErrorReason = eventEntity.decryptionErrorReason
|
it.mCryptoErrorReason = eventEntity.decryptionErrorReason
|
||||||
it.threadDetails = ThreadDetails(
|
it.threadDetails = ThreadDetails(
|
||||||
isRootThread = eventEntity.isRootThread,
|
isRootThread = eventEntity.isRootThread,
|
||||||
|
isThread = if (it.threadDetails?.isThread == true) true else eventEntity.isThread(),
|
||||||
numberOfThreads = eventEntity.numberOfThreads,
|
numberOfThreads = eventEntity.numberOfThreads,
|
||||||
threadSummarySenderInfo = eventEntity.threadSummaryLatestMessage?.let { timelineEventEntity ->
|
threadSummarySenderInfo = eventEntity.threadSummaryLatestMessage?.let { timelineEventEntity ->
|
||||||
SenderInfo(
|
SenderInfo(
|
||||||
|
@ -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.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
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.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.ContentMapper
|
||||||
import org.matrix.android.sdk.internal.database.mapper.EventMapper
|
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.EventEntity
|
||||||
|
@ -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.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TimelineEventVisibilityHelper @Inject constructor(private val userPreferencesProvider: UserPreferencesProvider) {
|
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 {
|
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
|
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) {
|
if (root.getRelationContent()?.type == RelationType.REPLACE) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -155,6 +166,7 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow only the the threads within the rootThreadEventId along with the root event
|
||||||
if (userPreferencesProvider.areThreadMessagesEnabled() && isFromThreadTimeline) {
|
if (userPreferencesProvider.areThreadMessagesEnabled() && isFromThreadTimeline) {
|
||||||
return if (root.getRootThreadEventId() == rootThreadEventId) {
|
return if (root.getRootThreadEventId() == rootThreadEventId) {
|
||||||
false
|
false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user