Read receipts : fix read receipt being sent for dummyEvent + scroll appearing index

This commit is contained in:
ganfra 2019-01-31 11:45:11 +01:00
parent 6113bba703
commit 6c653287e1
3 changed files with 52 additions and 9 deletions

View File

@ -0,0 +1,38 @@
/*
*
* * Copyright 2019 New Vector Ltd
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package im.vector.riotredesign.core.extensions
/**
* Returns the last element yielding the smallest value of the given function or `null` if there are no elements.
*/
public inline fun <T, R : Comparable<R>> Iterable<T>.lastMinBy(selector: (T) -> R): T? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var minElem = iterator.next()
var minValue = selector(minElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = selector(e)
if (minValue >= v) {
minElem = e
minValue = v
}
}
return minElem
}

View File

@ -24,6 +24,7 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.rx.rx import im.vector.matrix.rx.rx
import im.vector.riotredesign.core.extensions.lastMinBy
import im.vector.riotredesign.core.platform.RiotViewModel import im.vector.riotredesign.core.platform.RiotViewModel
import im.vector.riotredesign.features.home.room.VisibleRoomHolder import im.vector.riotredesign.features.home.room.VisibleRoomHolder
import io.reactivex.rxkotlin.subscribeBy import io.reactivex.rxkotlin.subscribeBy
@ -86,12 +87,12 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
displayedEventsObservable.hide() displayedEventsObservable.hide()
.buffer(1, TimeUnit.SECONDS) .buffer(1, TimeUnit.SECONDS)
.filter { it.isNotEmpty() } .filter { it.isNotEmpty() }
.subscribeBy { actions -> .subscribeBy(onNext = { actions ->
val mostRecentEvent = actions.minBy { it.index } val mostRecentEvent = actions.lastMinBy { it.index }
mostRecentEvent?.event?.root?.eventId?.let { eventId -> mostRecentEvent?.event?.root?.eventId?.let { eventId ->
room.setReadReceipt(eventId, callback = object : MatrixCallback<Void> {}) room.setReadReceipt(eventId, callback = object : MatrixCallback<Void> {})
} }
} })
.disposeOnClear() .disposeOnClear()
} }

View File

@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.room.read
import arrow.core.Try import arrow.core.Try
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixPatterns
import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity
@ -51,10 +52,13 @@ internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI,
override fun execute(params: SetReadMarkersTask.Params): Try<Unit> { override fun execute(params: SetReadMarkersTask.Params): Try<Unit> {
val markers = HashMap<String, String>() val markers = HashMap<String, String>()
if (params.fullyReadEventId?.isNotEmpty() == true) { if (params.fullyReadEventId != null && MatrixPatterns.isEventId(params.fullyReadEventId)) {
markers[READ_MARKER] = params.fullyReadEventId markers[READ_MARKER] = params.fullyReadEventId
} }
if (params.readReceiptEventId?.isNotEmpty() == true && !isEventRead(params.roomId, params.readReceiptEventId)) { if (params.readReceiptEventId != null
&& MatrixPatterns.isEventId(params.readReceiptEventId)
&& !isEventRead(params.roomId, params.readReceiptEventId)) {
updateNotificationCountIfNecessary(params.roomId, params.readReceiptEventId) updateNotificationCountIfNecessary(params.roomId, params.readReceiptEventId)
markers[READ_RECEIPT] = params.readReceiptEventId markers[READ_RECEIPT] = params.readReceiptEventId
} }
@ -72,7 +76,7 @@ internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI,
val isLatestReceived = EventEntity.latestEvent(realm, eventId)?.eventId == eventId val isLatestReceived = EventEntity.latestEvent(realm, eventId)?.eventId == eventId
if (isLatestReceived) { if (isLatestReceived) {
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst() val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
?: return@tryTransactionAsync ?: return@tryTransactionAsync
roomSummary.notificationCount = 0 roomSummary.notificationCount = 0
roomSummary.highlightCount = 0 roomSummary.highlightCount = 0
} }
@ -83,11 +87,11 @@ internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI,
var isEventRead = false var isEventRead = false
monarchy.doWithRealm { monarchy.doWithRealm {
val readReceipt = ReadReceiptEntity.where(it, roomId, credentials.userId).findFirst() val readReceipt = ReadReceiptEntity.where(it, roomId, credentials.userId).findFirst()
?: return@doWithRealm ?: return@doWithRealm
val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(it, roomId) val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(it, roomId)
?: return@doWithRealm ?: return@doWithRealm
val readReceiptIndex = liveChunk.events.find(readReceipt.eventId)?.displayIndex val readReceiptIndex = liveChunk.events.find(readReceipt.eventId)?.displayIndex
?: -1 ?: -1
val eventToCheckIndex = liveChunk.events.find(eventId)?.displayIndex ?: -1 val eventToCheckIndex = liveChunk.events.find(eventId)?.displayIndex ?: -1
isEventRead = eventToCheckIndex >= readReceiptIndex isEventRead = eventToCheckIndex >= readReceiptIndex
} }