diff --git a/app/src/main/java/im/vector/riotredesign/core/extensions/Iterable.kt b/app/src/main/java/im/vector/riotredesign/core/extensions/Iterable.kt new file mode 100644 index 00000000..092a94ac --- /dev/null +++ b/app/src/main/java/im/vector/riotredesign/core/extensions/Iterable.kt @@ -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 > Iterable.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 +} \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt index abdf1a1c..3d1d4cf1 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt @@ -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.events.model.Event import im.vector.matrix.rx.rx +import im.vector.riotredesign.core.extensions.lastMinBy import im.vector.riotredesign.core.platform.RiotViewModel import im.vector.riotredesign.features.home.room.VisibleRoomHolder import io.reactivex.rxkotlin.subscribeBy @@ -86,12 +87,12 @@ class RoomDetailViewModel(initialState: RoomDetailViewState, displayedEventsObservable.hide() .buffer(1, TimeUnit.SECONDS) .filter { it.isNotEmpty() } - .subscribeBy { actions -> - val mostRecentEvent = actions.minBy { it.index } + .subscribeBy(onNext = { actions -> + val mostRecentEvent = actions.lastMinBy { it.index } mostRecentEvent?.event?.root?.eventId?.let { eventId -> room.setReadReceipt(eventId, callback = object : MatrixCallback {}) } - } + }) .disposeOnClear() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt index 92e44155..f127966d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/read/SetReadMarkersTask.kt @@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.room.read import arrow.core.Try 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.internal.database.model.ChunkEntity 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 { val markers = HashMap() - if (params.fullyReadEventId?.isNotEmpty() == true) { + if (params.fullyReadEventId != null && MatrixPatterns.isEventId(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) markers[READ_RECEIPT] = params.readReceiptEventId } @@ -72,7 +76,7 @@ internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI, val isLatestReceived = EventEntity.latestEvent(realm, eventId)?.eventId == eventId if (isLatestReceived) { val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst() - ?: return@tryTransactionAsync + ?: return@tryTransactionAsync roomSummary.notificationCount = 0 roomSummary.highlightCount = 0 } @@ -83,11 +87,11 @@ internal class DefaultSetReadMarkersTask(private val roomAPI: RoomAPI, var isEventRead = false monarchy.doWithRealm { val readReceipt = ReadReceiptEntity.where(it, roomId, credentials.userId).findFirst() - ?: return@doWithRealm + ?: return@doWithRealm val liveChunk = ChunkEntity.findLastLiveChunkFromRoom(it, roomId) - ?: return@doWithRealm + ?: return@doWithRealm val readReceiptIndex = liveChunk.events.find(readReceipt.eventId)?.displayIndex - ?: -1 + ?: -1 val eventToCheckIndex = liveChunk.events.find(eventId)?.displayIndex ?: -1 isEventRead = eventToCheckIndex >= readReceiptIndex }