Fix scroll-to-bottom jumping back to initial event

Change-Id: I4d5ad6e2b2c2e47d79f5da2fd596de69a04c687a
This commit is contained in:
SpiritCroc 2022-03-21 21:22:31 +01:00
parent 5ad08e4b93
commit 6d5bdb4c88
5 changed files with 23 additions and 21 deletions

View File

@ -59,22 +59,22 @@ interface Timeline {
/**
* Event that should be displayed first, before the user scrolls.
*/
fun getInitialEventId(): String?
fun getTargetEventId(): String?
/**
* Change initial event id
* The event id we want to display first when showing the timeline
*/
fun setInitialEventId(eventId: String?)
fun setTargetEventId(eventId: String?)
/**
* Offset for the initial event, e.g. if we want to load the event just below said id
* Offset for the target event, e.g. if we want to load the event just below said id
*/
fun getInitialEventIdOffset(): Int
fun getTargetEventOffset(): Int
/**
* Set the offset for the initial event, e.g. if we want to load the event just below said id
* Set the offset for the target event, e.g. if we want to load the event just below said id
*/
fun setInitialEventIdOffset(offset: Int)
fun getTargetEventOffset(offset: Int)
/**
* Check if the timeline can be enriched by paginating.

View File

@ -53,7 +53,7 @@ import java.util.concurrent.atomic.AtomicReference
internal class DefaultTimeline(private val roomId: String,
private val initialEventId: String?,
private var initialEventIdOffset: Int = 0,
private var targetEventOffset: Int = 0,
private val realmConfiguration: RealmConfiguration,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val readReceiptHandler: ReadReceiptHandler,
@ -88,6 +88,7 @@ internal class DefaultTimeline(private val roomId: String,
private var isFromThreadTimeline = false
private var rootThreadEventId: String? = null
private var targetEventId = initialEventId
private val dimber = Dimber("TimelineChunks", DbgUtil.DBG_TIMELINE_CHUNKS)
private val strategyDependencies = LoadTimelineStrategy.Dependencies(
@ -252,6 +253,8 @@ internal class DefaultTimeline(private val roomId: String,
}
strategy.onStop()
setTargetEventId(eventId)
strategy = when {
rootThreadEventId != null -> buildStrategy(LoadTimelineStrategy.Mode.Thread(rootThreadEventId))
eventId == null -> buildStrategy(LoadTimelineStrategy.Mode.Live)
@ -393,21 +396,20 @@ internal class DefaultTimeline(private val roomId: String,
}
}
override fun getInitialEventId(): String? {
return initialEventId
override fun getTargetEventId(): String? {
return targetEventId
}
override fun setInitialEventId(eventId: String?) {
// SC-TODO?? -- just changing initialEventId to var is not enough, we get duplicated timelines :O
//initialEventId = eventId
override fun setTargetEventId(eventId: String?) {
targetEventId = eventId
}
override fun getInitialEventIdOffset(): Int {
return initialEventIdOffset
override fun getTargetEventOffset(): Int {
return targetEventOffset
}
override fun setInitialEventIdOffset(offset: Int) {
initialEventIdOffset = offset
override fun getTargetEventOffset(offset: Int) {
targetEventOffset = offset
}
}

View File

@ -65,8 +65,8 @@ class ScrollOnNewMessageCallback(private val layoutManager: BetterLinearLayoutMa
var scrollToEvent = initialForceScrollEventId
var scrollOffset = 0
if (initialForceScrollEventId == null) {
scrollToEvent = timelineEventController.timeline?.getInitialEventId()
scrollOffset = timelineEventController.timeline?.getInitialEventIdOffset() ?: 0
scrollToEvent = timelineEventController.timeline?.getTargetEventId()
scrollOffset = timelineEventController.timeline?.getTargetEventOffset() ?: 0
}
if (scrollToEvent == null) {
layoutManager.scrollToPositionWithOffset(0, 0)

View File

@ -959,7 +959,7 @@ class TimelineFragment @Inject constructor(
scrollOnNewMessageCallback.forceScrollOnNextUpdate()
timelineViewModel.timeline.restartWithEventId(null)
} else {
timelineViewModel.timeline.setInitialEventId(null)
timelineViewModel.timeline.setTargetEventId(null)
layoutManager.scrollToPositionWithOffset(0, 0)
}
}

View File

@ -141,7 +141,7 @@ class TimelineViewModel @AssistedInject constructor(
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId, initialState.rootThreadEventId).apply {
// Target the event just below $eventId in case that it is the readMarkerId
if (initialState.eventId == null && eventId != null) {
setInitialEventIdOffset(-1)
getTargetEventOffset(-1)
}
}