From c13339ca5207a00e3a2da3fa1c1e7f4da8f632e9 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Wed, 19 Jul 2023 12:55:42 -0400 Subject: [PATCH] Fix scroll to bottom on send bug in CFv2. --- .../components/ScrollToPositionDelegate.kt | 30 +++++++++++++++++-- .../conversation/v2/ConversationFragment.kt | 3 +- .../res/layout/v2_conversation_fragment.xml | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ScrollToPositionDelegate.kt b/app/src/main/java/org/thoughtcrime/securesms/components/ScrollToPositionDelegate.kt index 8cb202481a..c342d10ed8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ScrollToPositionDelegate.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ScrollToPositionDelegate.kt @@ -8,6 +8,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.kotlin.addTo import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.subscribeBy import io.reactivex.rxjava3.subjects.BehaviorSubject @@ -27,7 +28,7 @@ class ScrollToPositionDelegate private constructor( private val recyclerView: RecyclerView, canJumpToPosition: (Int) -> Boolean, mapToTruePosition: (Int) -> Int, - disposables: CompositeDisposable + private val disposables: CompositeDisposable ) : Disposable by disposables { companion object { private val TAG = Log.tag(ScrollToPositionDelegate::class.java) @@ -41,10 +42,12 @@ class ScrollToPositionDelegate private constructor( ) } - private val listCommitted = BehaviorSubject.create() + private val listCommitted = BehaviorSubject.create() private val scrollPositionRequested = BehaviorSubject.createDefault(EMPTY) private val scrollPositionRequests: Observable = Observable.combineLatest(listCommitted, scrollPositionRequested) { _, b -> b } + private var markedListCommittedTimestamp: Long = 0L + constructor( recyclerView: RecyclerView, canJumpToPosition: (Int) -> Boolean = { true }, @@ -91,16 +94,37 @@ class ScrollToPositionDelegate private constructor( requestScrollPosition(0, true) } + /** + * Reset the scroll position to 0 after a list update is committed that occurs later + * than the version set by [markListCommittedVersion]. + */ + @AnyThread + fun resetScrollPositionAfterMarkListVersionSurpassed() { + val currentMark = markedListCommittedTimestamp + listCommitted + .observeOn(AndroidSchedulers.mainThread()) + .filter { it > currentMark } + .firstElement() + .subscribeBy { + requestScrollPosition(0, true) + } + .addTo(disposables) + } + /** * This should be called every time a list is submitted to the RecyclerView's adapter. */ @AnyThread fun notifyListCommitted() { - listCommitted.onNext(Unit) + listCommitted.onNext(System.currentTimeMillis()) } fun isListCommitted(): Boolean = listCommitted.value != null + fun markListCommittedVersion() { + markedListCommittedTimestamp = listCommitted.value ?: 0L + } + private fun handleScrollPositionRequest( request: ScrollToPositionRequest, recyclerView: RecyclerView diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt index b96ee7fb6e..55b01f065f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt @@ -1679,6 +1679,7 @@ class ConversationFragment : ) disposables += send + .doOnSubscribe { scrollToPositionDelegate.markListCommittedVersion() } .subscribeBy( onError = { t -> Log.w(TAG, "Error sending", t) @@ -1710,7 +1711,7 @@ class ConversationFragment : conversationItemDecorations.unreadCount = 0 - scrollToPositionDelegate.resetScrollPosition() + scrollToPositionDelegate.resetScrollPositionAfterMarkListVersionSurpassed() attachmentManager.cleanup() updateLinkPreviewState() diff --git a/app/src/main/res/layout/v2_conversation_fragment.xml b/app/src/main/res/layout/v2_conversation_fragment.xml index be3a49dddb..f0c5acc4b1 100644 --- a/app/src/main/res/layout/v2_conversation_fragment.xml +++ b/app/src/main/res/layout/v2_conversation_fragment.xml @@ -320,7 +320,7 @@ android:layout_marginHorizontal="16dp" android:layout_marginBottom="16dp" android:visibility="gone" - app:layout_constraintBottom_toBottomOf="@id/navigation_bar_guideline" + app:layout_constraintBottom_toBottomOf="@id/keyboard_guideline" app:layout_constraintEnd_toEndOf="@+id/parent_end_guideline" app:layout_constraintStart_toStartOf="@+id/parent_start_guideline" />