From 3c702b723079f97e234cccb96fadc96e6985a27b Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Fri, 6 May 2022 10:26:39 +0200 Subject: [PATCH] Fix read marker update when rm becomes visible last If the read marker becomes visible after all events, the global most recent visible event won't be caught unless the user starts scrolling it out and back in. To fix, immediately look up the most recently displayed event once the read marker becomes visible. Change-Id: I909503801572d50e968610de163e56c05a946d36 --- .../home/room/detail/RoomDetailAction.kt | 2 +- .../home/room/detail/TimelineFragment.kt | 35 ++++++++++++++++++- .../home/room/detail/TimelineViewModel.kt | 9 +++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt index f6ea8b76ef..88ba65b00e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt @@ -46,7 +46,7 @@ sealed class RoomDetailAction : VectorViewModelAction { object AcceptInvite : RoomDetailAction() object RejectInvite : RoomDetailAction() - object EnterTrackingUnreadMessagesState : RoomDetailAction() + data class EnterTrackingUnreadMessagesState(val mostRecentDisplayedEvent: TimelineEvent?) : RoomDetailAction() object ExitTrackingUnreadMessagesState : RoomDetailAction() data class ResendMessage(val eventId: String) : RoomDetailAction() diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 76c21ed22f..dde54bf55f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -73,6 +73,7 @@ import com.vanniktech.emoji.EmojiPopup import de.spiritcroc.matrixsdk.util.DbgUtil import de.spiritcroc.matrixsdk.util.Dimber import de.spiritcroc.recyclerview.widget.BetterLinearLayoutManager +import de.spiritcroc.recyclerview.widget.LinearLayoutManager import im.vector.app.R import im.vector.app.core.animations.play import im.vector.app.core.dialogs.ConfirmationDialogBuilder @@ -166,6 +167,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlayb import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.home.room.detail.timeline.image.buildImageContentRendererData import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem +import im.vector.app.features.home.room.detail.timeline.item.ItemWithEvents import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem @@ -224,6 +226,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent @@ -2246,7 +2249,37 @@ class TimelineFragment @Inject constructor( } override fun onReadMarkerVisible() { - timelineViewModel.handle(RoomDetailAction.EnterTrackingUnreadMessagesState) + var mostRecentDisplayedEvent: TimelineEvent? = timelineViewModel.mostRecentDisplayedEvent() + val lm = views.timelineRecyclerView.layoutManager as? LinearLayoutManager + val room = session.roomService().getRoom(timelineArgs.roomId) + rmDimber.i { "Most recent check: ${mostRecentDisplayedEvent == null} ${lm?.findFirstVisibleItemPosition()}..${lm?.findLastVisibleItemPosition()}" } + if (mostRecentDisplayedEvent == null && lm != null && room != null) { + for (i in lm.findFirstVisibleItemPosition()..lm.findLastVisibleItemPosition()) { + val model = timelineEventController.adapter.getModelAtPosition(i) + rmDimber.i { "Most recent check: ${model.javaClass} / ${(model as? ItemWithEvents)?.isVisible()}" } + if (model is ItemWithEvents) { + if (!model.isVisible()) { + continue + } + rmDimber.i { "Most recent displayed model: ${model.getEventIds().firstOrNull()} - ${model.getEventIds().lastOrNull()}" } + model.getEventIds().reversed().forEach { eventId -> + if (mostRecentDisplayedEvent != null) { + return@forEach + } + val event = room.getTimelineEvent(eventId) + if (event != null) { + rmDimber.i { "Most recent displayed event: $eventId" } + mostRecentDisplayedEvent = event + return@forEach + } + } + } + if (mostRecentDisplayedEvent != null) { + break + } + } + } + timelineViewModel.handle(RoomDetailAction.EnterTrackingUnreadMessagesState(mostRecentDisplayedEvent)) } override fun onPreviewUrlClicked(url: String) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 22695065d0..fea487da8e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -172,6 +172,8 @@ class TimelineViewModel @AssistedInject constructor( } } + fun mostRecentDisplayedEvent() = mostRecentDisplayedEvent + private var prepareToEncrypt: Async = Uninitialized @AssistedFactory @@ -437,7 +439,7 @@ class TimelineViewModel @AssistedInject constructor( is RoomDetailAction.MarkAllAsRead -> handleMarkAllAsRead() is RoomDetailAction.ReportContent -> handleReportContent(action) is RoomDetailAction.IgnoreUser -> handleIgnoreUser(action) - is RoomDetailAction.EnterTrackingUnreadMessagesState -> startTrackingUnreadMessages() + is RoomDetailAction.EnterTrackingUnreadMessagesState -> startTrackingUnreadMessages(action) is RoomDetailAction.ExitTrackingUnreadMessagesState -> stopTrackingUnreadMessages() is RoomDetailAction.VoteToPoll -> handleVoteToPoll(action) is RoomDetailAction.AcceptVerificationRequest -> handleAcceptVerification(action) @@ -663,8 +665,11 @@ class TimelineViewModel @AssistedInject constructor( } } - private fun startTrackingUnreadMessages() { + private fun startTrackingUnreadMessages(action: RoomDetailAction.EnterTrackingUnreadMessagesState? = null) { trackUnreadMessages.set(true) + if (mostRecentDisplayedEvent == null && action != null) { + mostRecentDisplayedEvent = action.mostRecentDisplayedEvent + } withState { _viewEvents.post(RoomDetailViewEvents.ScDbgReadTracking(mostRecentDisplayedEvent, it.unreadState, trackUnreadMessages.get())) }