mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-29 14:38:45 +03:00
Improve room preview generation
- Also look into past chunks for previewable events - Better timestamp guesses if not enough history loaded yet - Update missing previews when more chunks loaded Change-Id: I27a420b9564e091db0e322751c798e205e26fd47
This commit is contained in:
parent
bc368070c9
commit
a95e41056d
4 changed files with 124 additions and 50 deletions
|
@ -80,6 +80,63 @@ internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm,
|
|||
?.findFirst()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <Event, Boolean>, with:
|
||||
* - Event: best event we could find to generate room timestamps
|
||||
* - Boolean: true if Event is previewable, else false
|
||||
*/
|
||||
internal fun TimelineEventEntity.Companion.bestTimestampPreviewEvent(realm: Realm,
|
||||
roomId: String,
|
||||
filters: TimelineEventFilters = TimelineEventFilters(),
|
||||
chunk: ChunkEntity? = null,
|
||||
maxChunksToVisit: Int = 10): Pair<TimelineEventEntity, Boolean>? {
|
||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: return null
|
||||
|
||||
// First try currently sending events, later recurse and try chunks
|
||||
val query = if (chunk == null) {
|
||||
roomEntity.sendingTimelineEvents.where().filterEvents(filters)
|
||||
} else {
|
||||
chunk.timelineEvents.where()?.filterEvents(filters)
|
||||
}
|
||||
val filteredResult = query
|
||||
?.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
|
||||
?.findFirst()
|
||||
if (filteredResult != null) {
|
||||
return Pair(filteredResult, true)
|
||||
}
|
||||
var recursiveResult: Pair<TimelineEventEntity, Boolean>? = null
|
||||
// One recursion step more than maxChunksToVisit, since in first step, we don't visit any chunk, but only sendingTimelineEvents
|
||||
if (maxChunksToVisit > 0 || chunk == null) {
|
||||
if (chunk == null) {
|
||||
// Initial chunk recursion
|
||||
val latestChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId)
|
||||
if (latestChunk != null) {
|
||||
recursiveResult = bestTimestampPreviewEvent(realm, roomId, filters, latestChunk, maxChunksToVisit - 1)
|
||||
}
|
||||
} else {
|
||||
val prevChunk = chunk.prevChunk
|
||||
if (prevChunk != null) {
|
||||
recursiveResult = bestTimestampPreviewEvent(realm, roomId, filters, prevChunk, maxChunksToVisit - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (recursiveResult != null) {
|
||||
return recursiveResult
|
||||
}
|
||||
// If we haven't found any previewable event by now, fall back to the oldest non-previewable event we found
|
||||
return chunk?.timelineEvents?.where()?.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.ASCENDING)?.findFirst()?.let {
|
||||
Pair(it, false)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Pair<TimelineEventEntity, Boolean>?.previewable(): TimelineEventEntity? {
|
||||
return if (this == null || !second) {
|
||||
null
|
||||
} else {
|
||||
first
|
||||
}
|
||||
}
|
||||
|
||||
internal fun RealmQuery<TimelineEventEntity>.filterEvents(filters: TimelineEventFilters): RealmQuery<TimelineEventEntity> {
|
||||
if (filters.filterTypes && filters.allowedTypes.isNotEmpty()) {
|
||||
beginGroup()
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.session.room.summary.RoomSummaryConstants
|
|||
import org.matrix.android.sdk.api.session.room.timeline.EventTypeFilter
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEventFilters
|
||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||
import org.matrix.android.sdk.internal.database.query.bestTimestampPreviewEvent
|
||||
import org.matrix.android.sdk.internal.database.query.latestEvent
|
||||
|
||||
internal object RoomSummaryEventsHelper {
|
||||
|
@ -51,31 +52,32 @@ internal object RoomSummaryEventsHelper {
|
|||
filterEdits = true
|
||||
)
|
||||
|
||||
fun getLatestPreviewableEvent(realm: Realm, roomId: String): TimelineEventEntity? {
|
||||
return TimelineEventEntity.latestEvent(
|
||||
// SC-modified
|
||||
fun getLatestPreviewableEvent(realm: Realm, roomId: String): Pair<TimelineEventEntity, Boolean>? {
|
||||
return TimelineEventEntity.bestTimestampPreviewEvent(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
includesSending = true,
|
||||
//includesSending = true,
|
||||
filters = previewFilters
|
||||
)
|
||||
}
|
||||
|
||||
// SC addition
|
||||
fun getLatestPreviewableEventScAll(realm: Realm, roomId: String): TimelineEventEntity? {
|
||||
return TimelineEventEntity.latestEvent(
|
||||
fun getLatestPreviewableEventScAll(realm: Realm, roomId: String): Pair<TimelineEventEntity, Boolean>? {
|
||||
return TimelineEventEntity.bestTimestampPreviewEvent(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
includesSending = true,
|
||||
//includesSending = true,
|
||||
filters = previewFiltersScAll
|
||||
)
|
||||
}
|
||||
|
||||
// SC addition
|
||||
fun getLatestPreviewableEventScOriginalContent(realm: Realm, roomId: String): TimelineEventEntity? {
|
||||
return TimelineEventEntity.latestEvent(
|
||||
fun getLatestPreviewableEventScOriginalContent(realm: Realm, roomId: String): Pair<TimelineEventEntity, Boolean>? {
|
||||
return TimelineEventEntity.bestTimestampPreviewEvent(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
includesSending = true,
|
||||
//includesSending = true,
|
||||
filters = previewFiltersScOriginalContent
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room.summary
|
|||
|
||||
import de.spiritcroc.matrixsdk.StaticScSdkHelper
|
||||
import io.realm.Realm
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.createObject
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
|
@ -52,11 +53,13 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
|||
import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.SpaceParentSummaryEntity
|
||||
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.findAllInRoomWithSendStates
|
||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||
import org.matrix.android.sdk.internal.database.query.getOrNull
|
||||
import org.matrix.android.sdk.internal.database.query.isEventRead
|
||||
import org.matrix.android.sdk.internal.database.query.latestEvent
|
||||
import org.matrix.android.sdk.internal.database.query.previewable
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.extensions.clearWith
|
||||
|
@ -80,13 +83,49 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
private val roomAccountDataDataSource: RoomAccountDataDataSource
|
||||
) {
|
||||
|
||||
fun refreshLatestPreviewContent(realm: Realm, roomId: String) {
|
||||
fun refreshLatestPreviewContent(realm: Realm, roomId: String, attemptDecrypt: Boolean = true) {
|
||||
val roomSummaryEntity = RoomSummaryEntity.getOrNull(realm, roomId)
|
||||
if (roomSummaryEntity != null) {
|
||||
val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScAll(realm, roomId)
|
||||
val latestPreviewableContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||
val latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScOriginalContent(realm, roomId)
|
||||
attemptToDecryptLatestPreviewables(latestPreviewableEvent, latestPreviewableContentEvent, latestPreviewableOriginalContentEvent)
|
||||
//roomSummaryEntity.latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScAll(realm, roomId)?.first
|
||||
//roomSummaryEntity.latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)?.first
|
||||
//val latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScOriginalContent(realm, roomId)?.first
|
||||
//attemptToDecryptLatestPreviewables(latestPreviewableEvent, latestPreviewableContentEvent, latestPreviewableOriginalContentEvent)
|
||||
refreshLatestPreviewContent(roomSummaryEntity, realm, roomId, attemptDecrypt)
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshLatestPreviewContentIfNull(realm: Realm, roomId: String) {
|
||||
val roomSummaryEntity = RoomSummaryEntity.getOrNull(realm, roomId) ?: return
|
||||
if (roomSummaryEntity.latestPreviewableOriginalContentEvent == null) {
|
||||
refreshLatestPreviewContent(roomSummaryEntity, realm, roomId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshLatestPreviewContent(roomSummaryEntity: RoomSummaryEntity, realm: Realm, roomId: String, attemptDecrypt: Boolean = true) {
|
||||
val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScAll(realm, roomId)
|
||||
val latestPreviewableContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||
val latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScOriginalContent(realm, roomId)
|
||||
|
||||
roomSummaryEntity.latestPreviewableEvent = latestPreviewableEvent.previewable()
|
||||
roomSummaryEntity.latestPreviewableContentEvent = latestPreviewableContentEvent.previewable()
|
||||
roomSummaryEntity.latestPreviewableOriginalContentEvent = latestPreviewableOriginalContentEvent.previewable()
|
||||
val scLatestPreviewableEvent = roomSummaryEntity.scLatestPreviewableEvent()
|
||||
|
||||
val lastActivityFromEvent = scLatestPreviewableEvent?.root?.originServerTs
|
||||
if (lastActivityFromEvent != null) {
|
||||
roomSummaryEntity.lastActivityTime = lastActivityFromEvent
|
||||
}
|
||||
// If we still did not find a timestamp for the last activity:
|
||||
// Any (non-previewable) event is still better for sorting than just dropping the room to the bottom in the list
|
||||
if (roomSummaryEntity.lastActivityTime == null) {
|
||||
roomSummaryEntity.lastActivityTime = latestPreviewableOriginalContentEvent?.first?.root?.originServerTs
|
||||
}
|
||||
if (attemptDecrypt) {
|
||||
attemptToDecryptLatestPreviewables(
|
||||
roomSummaryEntity.latestPreviewableEvent,
|
||||
roomSummaryEntity.latestPreviewableContentEvent,
|
||||
roomSummaryEntity.latestPreviewableOriginalContentEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,36 +181,7 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
val encryptionEvent = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_ENCRYPTION, stateKey = "")?.root
|
||||
Timber.d("## CRYPTO: currentEncryptionEvent is $encryptionEvent")
|
||||
|
||||
val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScAll(realm, roomId)
|
||||
val latestPreviewableContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||
val latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScOriginalContent(realm, roomId)
|
||||
|
||||
roomSummaryEntity.latestPreviewableEvent = latestPreviewableEvent
|
||||
roomSummaryEntity.latestPreviewableContentEvent = latestPreviewableContentEvent
|
||||
roomSummaryEntity.latestPreviewableOriginalContentEvent = latestPreviewableOriginalContentEvent
|
||||
val scLatestPreviewableEvent = roomSummaryEntity.scLatestPreviewableEvent()
|
||||
|
||||
val lastActivityFromEvent = scLatestPreviewableEvent?.root?.originServerTs
|
||||
if (lastActivityFromEvent != null) {
|
||||
roomSummaryEntity.lastActivityTime = lastActivityFromEvent
|
||||
} else if (latestPreviewableEvent != scLatestPreviewableEvent) {
|
||||
// Try using a less aggressive previewable filter for last activity, so we avoid null timestamps, which would just drop the room to the bottom
|
||||
roomSummaryEntity.lastActivityTime = latestPreviewableEvent?.root?.originServerTs
|
||||
}
|
||||
// If we still did not find a timestamp for the last activity:
|
||||
// Any (non-previewable) event is still better for sorting than just dropping the room to the bottom in the list
|
||||
if (roomSummaryEntity.lastActivityTime == null) {
|
||||
roomSummaryEntity.lastActivityTime = TimelineEventEntity.latestEvent(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
includesSending = true
|
||||
)?.root?.originServerTs
|
||||
}
|
||||
attemptToDecryptLatestPreviewables(
|
||||
roomSummaryEntity.latestPreviewableEvent,
|
||||
roomSummaryEntity.latestPreviewableContentEvent,
|
||||
roomSummaryEntity.latestPreviewableOriginalContentEvent
|
||||
)
|
||||
refreshLatestPreviewContent(roomSummaryEntity, realm, roomId)
|
||||
|
||||
val roomSummaryUnreadCount = roomSummaryEntity.unreadCount
|
||||
if (roomSummaryUnreadCount != null /* && preferences.prioritizeUnreadCountsOverRoomPreviewsForUnreadCalculation() */) {
|
||||
|
@ -188,15 +198,15 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0 ||
|
||||
//(roomSummaryEntity.unreadCount?.let { it > 0 } ?: false) ||
|
||||
// avoid this call if we are sure there are unread events
|
||||
latestPreviewableEvent?.let { !isEventRead(realm.configuration, userId, roomId, it.eventId) } ?: false
|
||||
roomSummaryEntity.latestPreviewableEvent?.let { !isEventRead(realm.configuration, userId, roomId, it.eventId) } ?: false
|
||||
roomSummaryEntity.hasUnreadContentMessages = roomSummaryEntity.notificationCount > 0 ||
|
||||
//(roomSummaryEntity.unreadCount?.let { it > 0 } ?: false) ||
|
||||
// avoid this call if we are sure there are unread events
|
||||
latestPreviewableContentEvent?.let { !isEventRead(realm.configuration, userId, roomId, it.eventId) } ?: false
|
||||
roomSummaryEntity.latestPreviewableContentEvent?.let { !isEventRead(realm.configuration, userId, roomId, it.eventId) } ?: false
|
||||
roomSummaryEntity.hasUnreadOriginalContentMessages = roomSummaryEntity.notificationCount > 0 ||
|
||||
//(roomSummaryEntity.unreadCount?.let { it > 0 } ?: false) ||
|
||||
// avoid this call if we are sure there are unread events
|
||||
latestPreviewableOriginalContentEvent?.let { !isEventRead(realm.configuration, userId, roomId, it.eventId) } ?: false
|
||||
roomSummaryEntity.latestPreviewableOriginalContentEvent?.let { !isEventRead(realm.configuration, userId, roomId, it.eventId) } ?: false
|
||||
}
|
||||
|
||||
roomSummaryEntity.setDisplayName(roomDisplayNameResolver.resolve(realm, roomId))
|
||||
|
@ -274,9 +284,10 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
fun updateSendingInformation(realm: Realm, roomId: String) {
|
||||
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
|
||||
roomSummaryEntity.updateHasFailedSending()
|
||||
roomSummaryEntity.latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||
roomSummaryEntity.latestPreviewableContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
|
||||
roomSummaryEntity.latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScOriginalContent(realm, roomId)
|
||||
refreshLatestPreviewContent(realm, roomId, attemptDecrypt = false)
|
||||
//roomSummaryEntity.latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId).previewable()
|
||||
//roomSummaryEntity.latestPreviewableContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId).previewable()
|
||||
//roomSummaryEntity.latestPreviewableOriginalContentEvent = RoomSummaryEventsHelper.getLatestPreviewableEventScOriginalContent(realm, roomId).previewable()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.matrix.android.sdk.internal.database.query.where
|
|||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.StreamEventsManager
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater
|
||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import timber.log.Timber
|
||||
|
@ -56,6 +57,7 @@ import javax.inject.Inject
|
|||
internal class TokenChunkEventPersistor @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
@UserId private val userId: String,
|
||||
private val roomSummaryUpdater: RoomSummaryUpdater,
|
||||
private val lightweightSettingsStorage: LightweightSettingsStorage,
|
||||
private val liveEventManager: Lazy<StreamEventsManager>,
|
||||
private val clock: Clock,
|
||||
|
@ -318,6 +320,8 @@ internal class TokenChunkEventPersistor @Inject constructor(
|
|||
}
|
||||
if (currentChunk.isValid) {
|
||||
RoomEntity.where(realm, roomId).findFirst()?.addIfNecessary(currentChunk)
|
||||
// After linking chunks, we may have a new room summary preview
|
||||
roomSummaryUpdater.refreshLatestPreviewContentIfNull(realm, roomId)
|
||||
}
|
||||
|
||||
if (lightweightSettingsStorage.areThreadMessagesEnabled()) {
|
||||
|
|
Loading…
Reference in a new issue