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())) }