mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 04:28:35 +00:00
Fix various CFv2 scrolling issues.
This commit is contained in:
@@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.R
|
|||||||
import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge
|
import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge.PulseRequest
|
import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge.PulseRequest
|
||||||
import org.thoughtcrime.securesms.conversation.v2.items.InteractiveConversationElement
|
import org.thoughtcrime.securesms.conversation.v2.items.InteractiveConversationElement
|
||||||
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||||
import org.thoughtcrime.securesms.util.ThemeUtil
|
import org.thoughtcrime.securesms.util.ThemeUtil
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil
|
import org.thoughtcrime.securesms.util.ViewUtil
|
||||||
@@ -570,7 +571,7 @@ class MultiselectItemDecoration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun RecyclerView.getMultiselectableChildren(): Sequence<Multiselectable> {
|
private fun RecyclerView.getMultiselectableChildren(): Sequence<Multiselectable> {
|
||||||
return if (FeatureFlags.useConversationFragmentV2()) {
|
return if (SignalStore.internalValues().useConversationItemV2()) {
|
||||||
children.map { getChildViewHolder(it) }.filterIsInstance<Multiselectable>()
|
children.map { getChildViewHolder(it) }.filterIsInstance<Multiselectable>()
|
||||||
} else {
|
} else {
|
||||||
children.filterIsInstance<Multiselectable>()
|
children.filterIsInstance<Multiselectable>()
|
||||||
@@ -578,7 +579,7 @@ class MultiselectItemDecoration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun RecyclerView.getInteractableChildren(): Sequence<InteractiveConversationElement> {
|
private fun RecyclerView.getInteractableChildren(): Sequence<InteractiveConversationElement> {
|
||||||
return if (FeatureFlags.useConversationFragmentV2()) {
|
return if (SignalStore.internalValues().useConversationItemV2()) {
|
||||||
children.map { getChildViewHolder(it) }.filterIsInstance<InteractiveConversationElement>()
|
children.map { getChildViewHolder(it) }.filterIsInstance<InteractiveConversationElement>()
|
||||||
} else {
|
} else {
|
||||||
children.filterIsInstance<InteractiveConversationElement>()
|
children.filterIsInstance<InteractiveConversationElement>()
|
||||||
@@ -586,7 +587,7 @@ class MultiselectItemDecoration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveMultiselectable(parent: RecyclerView, child: View): Multiselectable? {
|
private fun resolveMultiselectable(parent: RecyclerView, child: View): Multiselectable? {
|
||||||
return if (FeatureFlags.useConversationFragmentV2()) {
|
return if (SignalStore.internalValues().useConversationItemV2()) {
|
||||||
parent.getChildViewHolder(child) as? Multiselectable
|
parent.getChildViewHolder(child) as? Multiselectable
|
||||||
} else {
|
} else {
|
||||||
child as? Multiselectable
|
child as? Multiselectable
|
||||||
|
|||||||
@@ -168,11 +168,6 @@ class ConversationAdapterV2(
|
|||||||
notifyItemRangeChanged(0, itemCount)
|
notifyItemRangeChanged(0, itemCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** [messagePosition] is one-based index and adapter is zero-based. */
|
|
||||||
fun getAdapterPositionForMessagePosition(messagePosition: Int): Int {
|
|
||||||
return messagePosition - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLastVisibleConversationMessage(position: Int): ConversationMessage? {
|
fun getLastVisibleConversationMessage(position: Int): ConversationMessage? {
|
||||||
return try {
|
return try {
|
||||||
getConversationMessage(position) ?: getConversationMessage(position - 1)
|
getConversationMessage(position) ?: getConversationMessage(position - 1)
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import androidx.core.app.ActivityOptionsCompat
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.doOnNextLayout
|
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@@ -135,6 +134,7 @@ import org.thoughtcrime.securesms.conversation.AttachmentKeyboardButton
|
|||||||
import org.thoughtcrime.securesms.conversation.BadDecryptLearnMoreDialog
|
import org.thoughtcrime.securesms.conversation.BadDecryptLearnMoreDialog
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter
|
import org.thoughtcrime.securesms.conversation.ConversationAdapter
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationBottomSheetCallback
|
import org.thoughtcrime.securesms.conversation.ConversationBottomSheetCallback
|
||||||
|
import org.thoughtcrime.securesms.conversation.ConversationData
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationHeaderView
|
import org.thoughtcrime.securesms.conversation.ConversationHeaderView
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationIntents.ConversationScreenType
|
import org.thoughtcrime.securesms.conversation.ConversationIntents.ConversationScreenType
|
||||||
@@ -757,12 +757,7 @@ class ConversationFragment :
|
|||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.doOnSuccess { state ->
|
.doOnSuccess { state ->
|
||||||
SignalLocalMetrics.ConversationOpen.onDataLoaded()
|
SignalLocalMetrics.ConversationOpen.onDataLoaded()
|
||||||
binding.conversationItemRecycler.doOnNextLayout {
|
moveToStartPosition(state.meta)
|
||||||
layoutManager.scrollToPositionWithOffset(
|
|
||||||
adapter.getAdapterPositionForMessagePosition(state.meta.getStartPosition()),
|
|
||||||
binding.conversationItemRecycler.height
|
|
||||||
)
|
|
||||||
}
|
|
||||||
conversationItemDecorations.setFirstUnreadCount(state.meta.unreadCount)
|
conversationItemDecorations.setFirstUnreadCount(state.meta.unreadCount)
|
||||||
}
|
}
|
||||||
.flatMapObservable { it.items.data }
|
.flatMapObservable { it.items.data }
|
||||||
@@ -1411,9 +1406,8 @@ class ConversationFragment :
|
|||||||
)
|
)
|
||||||
|
|
||||||
scrollToPositionDelegate = ScrollToPositionDelegate(
|
scrollToPositionDelegate = ScrollToPositionDelegate(
|
||||||
binding.conversationItemRecycler,
|
recyclerView = binding.conversationItemRecycler,
|
||||||
adapter::canJumpToPosition,
|
canJumpToPosition = adapter::canJumpToPosition
|
||||||
adapter::getAdapterPositionForMessagePosition
|
|
||||||
)
|
)
|
||||||
|
|
||||||
adapter.setPagingController(viewModel.pagingController)
|
adapter.setPagingController(viewModel.pagingController)
|
||||||
@@ -2106,6 +2100,18 @@ class ConversationFragment :
|
|||||||
|
|
||||||
//region Scroll Handling
|
//region Scroll Handling
|
||||||
|
|
||||||
|
private fun moveToStartPosition(meta: ConversationData) {
|
||||||
|
scrollToPositionDelegate.requestScrollPosition(
|
||||||
|
position = meta.getStartPosition(),
|
||||||
|
smooth = true,
|
||||||
|
scrollStrategy = if (meta.shouldJumpToMessage()) {
|
||||||
|
jumpAndPulseScrollStrategy
|
||||||
|
} else {
|
||||||
|
ScrollToPositionDelegate.DefaultScrollStrategy
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests a jump to the desired position, and ensures that the position desired will be visible on the screen.
|
* Requests a jump to the desired position, and ensures that the position desired will be visible on the screen.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -298,16 +298,15 @@ class ConversationRepository(
|
|||||||
oldConversationRepository.markGiftBadgeRevealed(messageId)
|
oldConversationRepository.markGiftBadgeRevealed(messageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Quoted Message position is a zero-based index, so we need to convert it to 1-based */
|
|
||||||
fun getQuotedMessagePosition(threadId: Long, quote: Quote): Single<Int> {
|
fun getQuotedMessagePosition(threadId: Long, quote: Quote): Single<Int> {
|
||||||
return Single.fromCallable {
|
return Single.fromCallable {
|
||||||
SignalDatabase.messages.getQuotedMessagePosition(threadId, quote.id, quote.author) + 1
|
SignalDatabase.messages.getQuotedMessagePosition(threadId, quote.id, quote.author)
|
||||||
}.subscribeOn(Schedulers.io())
|
}.subscribeOn(Schedulers.io())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMessageResultPosition(threadId: Long, messageResult: MessageResult): Single<Int> {
|
fun getMessageResultPosition(threadId: Long, messageResult: MessageResult): Single<Int> {
|
||||||
return Single.fromCallable {
|
return Single.fromCallable {
|
||||||
SignalDatabase.messages.getMessagePositionInConversation(threadId, messageResult.receivedTimestampMs) + 1
|
SignalDatabase.messages.getMessagePositionInConversation(threadId, messageResult.receivedTimestampMs)
|
||||||
}.subscribeOn(Schedulers.io())
|
}.subscribeOn(Schedulers.io())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user