mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 04:28:35 +00:00
Fix scroll to bottom on send bug in CFv2.
This commit is contained in:
@@ -8,6 +8,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.rxjava3.core.Observable
|
import io.reactivex.rxjava3.core.Observable
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
|
import io.reactivex.rxjava3.kotlin.addTo
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||||
@@ -27,7 +28,7 @@ class ScrollToPositionDelegate private constructor(
|
|||||||
private val recyclerView: RecyclerView,
|
private val recyclerView: RecyclerView,
|
||||||
canJumpToPosition: (Int) -> Boolean,
|
canJumpToPosition: (Int) -> Boolean,
|
||||||
mapToTruePosition: (Int) -> Int,
|
mapToTruePosition: (Int) -> Int,
|
||||||
disposables: CompositeDisposable
|
private val disposables: CompositeDisposable
|
||||||
) : Disposable by disposables {
|
) : Disposable by disposables {
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = Log.tag(ScrollToPositionDelegate::class.java)
|
private val TAG = Log.tag(ScrollToPositionDelegate::class.java)
|
||||||
@@ -41,10 +42,12 @@ class ScrollToPositionDelegate private constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val listCommitted = BehaviorSubject.create<Unit>()
|
private val listCommitted = BehaviorSubject.create<Long>()
|
||||||
private val scrollPositionRequested = BehaviorSubject.createDefault(EMPTY)
|
private val scrollPositionRequested = BehaviorSubject.createDefault(EMPTY)
|
||||||
private val scrollPositionRequests: Observable<ScrollToPositionRequest> = Observable.combineLatest(listCommitted, scrollPositionRequested) { _, b -> b }
|
private val scrollPositionRequests: Observable<ScrollToPositionRequest> = Observable.combineLatest(listCommitted, scrollPositionRequested) { _, b -> b }
|
||||||
|
|
||||||
|
private var markedListCommittedTimestamp: Long = 0L
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
recyclerView: RecyclerView,
|
recyclerView: RecyclerView,
|
||||||
canJumpToPosition: (Int) -> Boolean = { true },
|
canJumpToPosition: (Int) -> Boolean = { true },
|
||||||
@@ -91,16 +94,37 @@ class ScrollToPositionDelegate private constructor(
|
|||||||
requestScrollPosition(0, true)
|
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.
|
* This should be called every time a list is submitted to the RecyclerView's adapter.
|
||||||
*/
|
*/
|
||||||
@AnyThread
|
@AnyThread
|
||||||
fun notifyListCommitted() {
|
fun notifyListCommitted() {
|
||||||
listCommitted.onNext(Unit)
|
listCommitted.onNext(System.currentTimeMillis())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isListCommitted(): Boolean = listCommitted.value != null
|
fun isListCommitted(): Boolean = listCommitted.value != null
|
||||||
|
|
||||||
|
fun markListCommittedVersion() {
|
||||||
|
markedListCommittedTimestamp = listCommitted.value ?: 0L
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleScrollPositionRequest(
|
private fun handleScrollPositionRequest(
|
||||||
request: ScrollToPositionRequest,
|
request: ScrollToPositionRequest,
|
||||||
recyclerView: RecyclerView
|
recyclerView: RecyclerView
|
||||||
|
|||||||
@@ -1679,6 +1679,7 @@ class ConversationFragment :
|
|||||||
)
|
)
|
||||||
|
|
||||||
disposables += send
|
disposables += send
|
||||||
|
.doOnSubscribe { scrollToPositionDelegate.markListCommittedVersion() }
|
||||||
.subscribeBy(
|
.subscribeBy(
|
||||||
onError = { t ->
|
onError = { t ->
|
||||||
Log.w(TAG, "Error sending", t)
|
Log.w(TAG, "Error sending", t)
|
||||||
@@ -1710,7 +1711,7 @@ class ConversationFragment :
|
|||||||
|
|
||||||
conversationItemDecorations.unreadCount = 0
|
conversationItemDecorations.unreadCount = 0
|
||||||
|
|
||||||
scrollToPositionDelegate.resetScrollPosition()
|
scrollToPositionDelegate.resetScrollPositionAfterMarkListVersionSurpassed()
|
||||||
attachmentManager.cleanup()
|
attachmentManager.cleanup()
|
||||||
|
|
||||||
updateLinkPreviewState()
|
updateLinkPreviewState()
|
||||||
|
|||||||
@@ -320,7 +320,7 @@
|
|||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:visibility="gone"
|
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_constraintEnd_toEndOf="@+id/parent_end_guideline"
|
||||||
app:layout_constraintStart_toStartOf="@+id/parent_start_guideline" />
|
app:layout_constraintStart_toStartOf="@+id/parent_start_guideline" />
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user