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

View File

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

View File

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

View File

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