2018-11-13 18:17:59 +00:00
|
|
|
package im.vector.matrix.android.internal.database.helper
|
|
|
|
|
|
|
|
import im.vector.matrix.android.api.session.events.model.Event
|
2018-11-22 10:20:50 +00:00
|
|
|
import im.vector.matrix.android.api.session.events.model.EventType
|
2019-01-07 18:38:49 +00:00
|
|
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
2019-01-03 16:10:02 +00:00
|
|
|
import im.vector.matrix.android.internal.database.mapper.toEntity
|
|
|
|
import im.vector.matrix.android.internal.database.mapper.updateWith
|
2018-11-13 18:17:59 +00:00
|
|
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
2018-11-27 21:42:46 +00:00
|
|
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
2018-11-22 10:20:50 +00:00
|
|
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
2018-11-13 18:17:59 +00:00
|
|
|
import im.vector.matrix.android.internal.database.query.fastContains
|
|
|
|
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
2018-11-22 10:20:50 +00:00
|
|
|
import io.realm.Sort
|
2018-11-28 17:28:35 +00:00
|
|
|
|
|
|
|
internal fun ChunkEntity.deleteOnCascade() {
|
2019-01-07 18:38:49 +00:00
|
|
|
assertIsManaged()
|
2018-11-28 17:28:35 +00:00
|
|
|
this.events.deleteAllFromRealm()
|
|
|
|
this.deleteFromRealm()
|
|
|
|
}
|
2018-11-13 18:17:59 +00:00
|
|
|
|
2018-11-29 17:35:24 +00:00
|
|
|
// By default if a chunk is empty we consider it unlinked
|
2018-11-27 21:42:46 +00:00
|
|
|
internal fun ChunkEntity.isUnlinked(): Boolean {
|
2019-01-07 18:38:49 +00:00
|
|
|
assertIsManaged()
|
2018-11-29 17:35:24 +00:00
|
|
|
return events.where().equalTo(EventEntityFields.IS_UNLINKED, false).findAll().isEmpty()
|
2018-11-27 21:42:46 +00:00
|
|
|
}
|
2018-11-15 17:32:39 +00:00
|
|
|
|
2019-01-07 18:38:49 +00:00
|
|
|
internal fun ChunkEntity.merge(roomId: String,
|
|
|
|
chunkToMerge: ChunkEntity,
|
2018-11-15 17:32:39 +00:00
|
|
|
direction: PaginationDirection) {
|
2019-01-07 18:38:49 +00:00
|
|
|
assertIsManaged()
|
2018-11-27 21:42:46 +00:00
|
|
|
val isChunkToMergeUnlinked = chunkToMerge.isUnlinked()
|
|
|
|
val isCurrentChunkUnlinked = this.isUnlinked()
|
|
|
|
val isUnlinked = isCurrentChunkUnlinked && isChunkToMergeUnlinked
|
2018-11-19 14:47:54 +00:00
|
|
|
|
2018-11-27 21:42:46 +00:00
|
|
|
if (isCurrentChunkUnlinked && !isChunkToMergeUnlinked) {
|
|
|
|
this.events.forEach { it.isUnlinked = false }
|
2018-11-19 14:47:54 +00:00
|
|
|
}
|
2018-11-27 21:42:46 +00:00
|
|
|
val eventsToMerge: List<EventEntity>
|
2018-11-15 17:32:39 +00:00
|
|
|
if (direction == PaginationDirection.FORWARDS) {
|
2018-11-27 21:42:46 +00:00
|
|
|
this.nextToken = chunkToMerge.nextToken
|
|
|
|
this.isLast = chunkToMerge.isLast
|
|
|
|
eventsToMerge = chunkToMerge.events.reversed()
|
2018-11-15 17:32:39 +00:00
|
|
|
} else {
|
2018-11-27 21:42:46 +00:00
|
|
|
this.prevToken = chunkToMerge.prevToken
|
|
|
|
eventsToMerge = chunkToMerge.events
|
|
|
|
}
|
|
|
|
eventsToMerge.forEach {
|
2019-01-07 18:38:49 +00:00
|
|
|
add(roomId, it.asDomain(), direction, isUnlinked = isUnlinked)
|
2018-11-15 17:32:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-03 16:10:02 +00:00
|
|
|
internal fun ChunkEntity.addAll(roomId: String,
|
|
|
|
events: List<Event>,
|
2018-11-15 17:32:39 +00:00
|
|
|
direction: PaginationDirection,
|
2018-11-27 21:42:46 +00:00
|
|
|
stateIndexOffset: Int = 0,
|
|
|
|
isUnlinked: Boolean = false) {
|
2019-01-07 18:38:49 +00:00
|
|
|
assertIsManaged()
|
2018-11-15 17:32:39 +00:00
|
|
|
events.forEach { event ->
|
2019-01-03 16:10:02 +00:00
|
|
|
add(roomId, event, direction, stateIndexOffset, isUnlinked)
|
2018-11-15 17:32:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-25 15:17:47 +00:00
|
|
|
internal fun ChunkEntity.updateDisplayIndexes() {
|
|
|
|
events.forEachIndexed { index, eventEntity -> eventEntity.displayIndex = index }
|
|
|
|
}
|
|
|
|
|
2019-01-03 16:10:02 +00:00
|
|
|
internal fun ChunkEntity.add(roomId: String,
|
|
|
|
event: Event,
|
2018-11-28 17:28:35 +00:00
|
|
|
direction: PaginationDirection,
|
|
|
|
stateIndexOffset: Int = 0,
|
|
|
|
isUnlinked: Boolean = false) {
|
2019-01-03 16:10:02 +00:00
|
|
|
|
2019-01-07 18:38:49 +00:00
|
|
|
assertIsManaged()
|
|
|
|
if (event.eventId.isNullOrEmpty() || events.fastContains(event.eventId)) {
|
2018-11-14 18:32:42 +00:00
|
|
|
return
|
|
|
|
}
|
2018-11-22 10:20:50 +00:00
|
|
|
var currentStateIndex = lastStateIndex(direction, defaultValue = stateIndexOffset)
|
2019-01-07 18:38:49 +00:00
|
|
|
if (direction == PaginationDirection.FORWARDS && EventType.isStateEvent(event.type)) {
|
2018-11-22 10:20:50 +00:00
|
|
|
currentStateIndex += 1
|
|
|
|
} else if (direction == PaginationDirection.BACKWARDS && events.isNotEmpty()) {
|
|
|
|
val lastEventType = events.last()?.type ?: ""
|
|
|
|
if (EventType.isStateEvent(lastEventType)) {
|
|
|
|
currentStateIndex -= 1
|
|
|
|
}
|
2018-11-19 14:47:54 +00:00
|
|
|
}
|
2019-01-07 18:38:49 +00:00
|
|
|
val eventEntity = event.toEntity(roomId)
|
2019-01-03 16:10:02 +00:00
|
|
|
eventEntity.updateWith(currentStateIndex, isUnlinked)
|
2018-11-28 17:28:35 +00:00
|
|
|
val position = if (direction == PaginationDirection.FORWARDS) 0 else this.events.size
|
|
|
|
events.add(position, eventEntity)
|
2018-11-22 10:20:50 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 18:38:49 +00:00
|
|
|
private fun ChunkEntity.assertIsManaged() {
|
|
|
|
if (!isManaged) {
|
|
|
|
throw IllegalStateException("Chunk entity should be managed to use this function")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-22 10:20:50 +00:00
|
|
|
internal fun ChunkEntity.lastStateIndex(direction: PaginationDirection, defaultValue: Int = 0): Int {
|
|
|
|
return when (direction) {
|
2019-01-07 18:38:49 +00:00
|
|
|
PaginationDirection.FORWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING).findFirst()?.stateIndex
|
|
|
|
PaginationDirection.BACKWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING).findFirst()?.stateIndex
|
|
|
|
} ?: defaultValue
|
2018-11-13 18:17:59 +00:00
|
|
|
}
|