mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Suppress LayoutTransition during scroll events.
This commit is contained in:
@@ -217,6 +217,7 @@ class V2ConversationItemShapeTest {
|
||||
override val isMessageRequestAccepted: Boolean = true
|
||||
override val searchQuery: String? = null
|
||||
override val glideRequests: GlideRequests = mockk()
|
||||
override val isParentInScroll: Boolean = false
|
||||
|
||||
override fun onStartExpirationTimeout(messageRecord: MessageRecord) = Unit
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
|
||||
|
||||
void setEventListener(@Nullable EventListener listener);
|
||||
|
||||
default void setParentScrolling(boolean isParentScrolling) {
|
||||
// Intentionally Blank.
|
||||
}
|
||||
|
||||
default void updateTimestamps() {
|
||||
// Intentionally Blank.
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ interface ConversationAdapterBridge {
|
||||
const val PAYLOAD_TIMESTAMP = 0
|
||||
const val PAYLOAD_NAME_COLORS = 1
|
||||
const val PAYLOAD_SELECTED = 2
|
||||
const val PAYLOAD_PARENT_SCROLLING = 3
|
||||
}
|
||||
|
||||
fun hasNoConversationMessages(): Boolean
|
||||
|
||||
@@ -418,6 +418,11 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
this.conversationRecipient.observeForever(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentScrolling(boolean isParentScrolling) {
|
||||
bodyBubble.setParentScrolling(isParentScrolling);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSelectedState() {
|
||||
setHasBeenQuoted(conversationMessage);
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
|
||||
import com.annimon.stream.Collectors;
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.components.Outliner;
|
||||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@@ -30,19 +31,33 @@ public class ConversationItemBodyBubble extends LinearLayout {
|
||||
private Projection quoteViewProjection;
|
||||
private Projection videoPlayerProjection;
|
||||
|
||||
private final BodyBubbleLayoutTransition bodyBubbleLayoutTransition = new BodyBubbleLayoutTransition();
|
||||
|
||||
public ConversationItemBodyBubble(Context context) {
|
||||
super(context);
|
||||
setLayoutTransition(new BodyBubbleLayoutTransition());
|
||||
init();
|
||||
}
|
||||
|
||||
public ConversationItemBodyBubble(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setLayoutTransition(new BodyBubbleLayoutTransition());
|
||||
init();
|
||||
}
|
||||
|
||||
public ConversationItemBodyBubble(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setLayoutTransition(new BodyBubbleLayoutTransition());
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setLayoutTransition(bodyBubbleLayoutTransition);
|
||||
}
|
||||
|
||||
public void setParentScrolling(boolean isParentScrolling) {
|
||||
if (isParentScrolling) {
|
||||
setLayoutTransition(null);
|
||||
} else {
|
||||
setLayoutTransition(bodyBubbleLayoutTransition);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOutliners(@NonNull List<Outliner> outliners) {
|
||||
|
||||
@@ -90,6 +90,10 @@ class ConversationAdapterV2(
|
||||
|
||||
override var isMessageRequestAccepted: Boolean = false
|
||||
|
||||
override var isParentInScroll: Boolean = false
|
||||
|
||||
private val onScrollStateChangedListener = OnScrollStateChangedListener()
|
||||
|
||||
init {
|
||||
registerFactory(ThreadHeader::class.java, ::ThreadHeaderViewHolder, R.layout.conversation_item_thread_header)
|
||||
|
||||
@@ -162,6 +166,8 @@ class ConversationAdapterV2(
|
||||
recyclerView.recycledViewPool.setMaxRecycledViews(type, count)
|
||||
}
|
||||
}
|
||||
|
||||
recyclerView.addOnScrollListener(onScrollStateChangedListener)
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: MappingViewHolder<*>) {
|
||||
@@ -176,6 +182,8 @@ class ConversationAdapterV2(
|
||||
.children
|
||||
.filterIsInstance<Unbindable>()
|
||||
.forEach { it.unbind() }
|
||||
|
||||
recyclerView.removeOnScrollListener(onScrollStateChangedListener)
|
||||
}
|
||||
|
||||
override val displayMode: ConversationItemDisplayMode
|
||||
@@ -498,6 +506,11 @@ class ConversationAdapterV2(
|
||||
fun bindPayloadsIfAvailable(): Boolean {
|
||||
var payloadApplied = false
|
||||
|
||||
bindable.setParentScrolling(isParentInScroll)
|
||||
if (payload.contains(ConversationAdapterBridge.PAYLOAD_PARENT_SCROLLING)) {
|
||||
payloadApplied = true
|
||||
}
|
||||
|
||||
if (payload.contains(ConversationAdapterBridge.PAYLOAD_TIMESTAMP)) {
|
||||
bindable.updateTimestamps()
|
||||
payloadApplied = true
|
||||
@@ -627,4 +640,14 @@ class ConversationAdapterV2(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OnScrollStateChangedListener : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
val oldState = isParentInScroll
|
||||
isParentInScroll = newState != RecyclerView.SCROLL_STATE_IDLE
|
||||
if (isParentInScroll != oldState) {
|
||||
notifyItemRangeChanged(0, itemCount, ConversationAdapterBridge.PAYLOAD_PARENT_SCROLLING)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ interface V2ConversationContext {
|
||||
val selectedItems: Set<MultiselectPart>
|
||||
val isMessageRequestAccepted: Boolean
|
||||
val searchQuery: String?
|
||||
val isParentInScroll: Boolean
|
||||
|
||||
fun onStartExpirationTimeout(messageRecord: MessageRecord)
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
||||
|
||||
private val bodyBubbleDrawable = ChatColorsDrawable()
|
||||
private val footerDrawable = ChatColorsDrawable()
|
||||
private val bodyBubbleLayoutTransition = BodyBubbleLayoutTransition()
|
||||
|
||||
protected lateinit var shape: V2ConversationItemShape.MessageShape
|
||||
|
||||
@@ -155,7 +156,7 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
||||
}
|
||||
|
||||
binding.conversationItemBodyWrapper.background = bodyBubbleDrawable
|
||||
binding.conversationItemBodyWrapper.layoutTransition = BodyBubbleLayoutTransition()
|
||||
binding.conversationItemBodyWrapper.layoutTransition = bodyBubbleLayoutTransition
|
||||
|
||||
binding.conversationItemFooterBackground.background = footerDrawable
|
||||
}
|
||||
@@ -166,6 +167,22 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
||||
}
|
||||
|
||||
override fun bind(model: Model) {
|
||||
var hasProcessedSupportedPayload = false
|
||||
|
||||
binding.conversationItemBodyWrapper.layoutTransition = if (conversationContext.isParentInScroll) {
|
||||
null
|
||||
} else {
|
||||
bodyBubbleLayoutTransition
|
||||
}
|
||||
|
||||
if (ConversationAdapterBridge.PAYLOAD_PARENT_SCROLLING in payload) {
|
||||
if (payload.size == 1) {
|
||||
return
|
||||
} else {
|
||||
hasProcessedSupportedPayload = true
|
||||
}
|
||||
}
|
||||
|
||||
check(model is ConversationMessageElement)
|
||||
conversationMessage = model.conversationMessage
|
||||
|
||||
@@ -176,7 +193,6 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
|
||||
adapterPosition = bindingAdapterPosition
|
||||
)
|
||||
|
||||
var hasProcessedSupportedPayload = false
|
||||
if (ConversationAdapterBridge.PAYLOAD_TIMESTAMP in payload) {
|
||||
presentDate()
|
||||
hasProcessedSupportedPayload = true
|
||||
|
||||
Reference in New Issue
Block a user