Fix scroll state of collapsed events.

This commit is contained in:
Michelle Tang
2026-03-31 11:29:26 -04:00
committed by Alex Hart
parent b0f7c36cc2
commit 0ce3eab3cd
9 changed files with 41 additions and 16 deletions

View File

@@ -359,8 +359,8 @@ class V2ConversationItemShapeTest {
override fun onViewPinnedMessage(messageId: Long) = Unit
override fun onExpandEvents(messageId: Long) = Unit
override fun onExpandEvents(messageId: Long, itemView: View, collapsedSize: Int) = Unit
override fun onCollapseEvents(messageId: Long) = Unit
override fun onCollapseEvents(messageId: Long, itemView: View, collapsedSize: Int) = Unit
}
}

View File

@@ -354,11 +354,11 @@ class InternalConversationTestFragment : Fragment(R.layout.conversation_test_fra
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
override fun onExpandEvents(messageId: Long) {
override fun onExpandEvents(messageId: Long, itemView: View, collapsedSize: Int) {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
override fun onCollapseEvents(messageId: Long) {
override fun onCollapseEvents(messageId: Long, itemView: View, collapsedSize: Int) {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
}

View File

@@ -148,7 +148,7 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
void onViewPollClicked(long messageId);
void onToggleVote(@NonNull PollRecord poll, @NonNull PollOption pollOption, Boolean isChecked);
void onViewPinnedMessage(long messageId);
void onExpandEvents(long messageId);
void onCollapseEvents(long messageId);
void onExpandEvents(long messageId, @NonNull View itemView, int collapsedSize);
void onCollapseEvents(long messageId, @NonNull View itemView, int collapsedSize);
}
}

View File

@@ -875,9 +875,9 @@ public final class ConversationUpdateItem extends FrameLayout
collapsedButton.setOnClickListener(v -> {
if (eventListener != null) {
if (CollapsedState.isCollapsed(collapsedState)) {
eventListener.onExpandEvents(conversationMessage.getMessageRecord().getId());
eventListener.onExpandEvents(conversationMessage.getMessageRecord().getId(), ConversationUpdateItem.this, conversationMessage.getCollapsedSize());
} else if (!anyCollapsibleChildrenSelected()) {
eventListener.onCollapseEvents(conversationMessage.getMessageRecord().getId());
eventListener.onCollapseEvents(conversationMessage.getMessageRecord().getId(), ConversationUpdateItem.this, conversationMessage.getCollapsedSize());
}
} else {
passthroughClickListener.onClick(v);

View File

@@ -94,6 +94,6 @@ object EmptyConversationAdapterListener : ConversationAdapter.ItemClickListener
override fun onViewPollClicked(messageId: Long) = Unit
override fun onToggleVote(poll: PollRecord, pollOption: PollOption, isChecked: Boolean?) = Unit
override fun onViewPinnedMessage(messageId: Long) = Unit
override fun onExpandEvents(messageId: Long) = Unit
override fun onCollapseEvents(messageId: Long) = Unit
override fun onExpandEvents(messageId: Long, itemView: View, collapsedSize: Int) = Unit
override fun onCollapseEvents(messageId: Long, itemView: View, collapsedSize: Int) = Unit
}

View File

@@ -387,6 +387,7 @@ class ConversationAdapterV2(
return
}
bindable.setParentScrolling(true)
bindable.bind(
lifecycleOwner,
model.conversationMessage,
@@ -404,6 +405,7 @@ class ConversationAdapterV2(
colorizer,
displayMode
)
bindable.setParentScrolling(isParentInScroll)
}
}
@@ -415,6 +417,7 @@ class ConversationAdapterV2(
return
}
bindable.setParentScrolling(true)
bindable.bind(
lifecycleOwner,
model.conversationMessage,
@@ -432,6 +435,7 @@ class ConversationAdapterV2(
colorizer,
displayMode
)
bindable.setParentScrolling(isParentInScroll)
}
}

View File

@@ -587,6 +587,7 @@ class ConversationFragment :
private var progressDialog: ProgressCardDialogFragment? = null
private var firstPinRender: Boolean = true
private var skipNextBackPressHandling: Boolean = false
private var collapsibleEventScrollPosition: CollapsibleEventScrollPosition? = null
private val jumpAndPulseScrollStrategy = object : ScrollToPositionDelegate.ScrollStrategy {
override fun performScroll(recyclerView: RecyclerView, layoutManager: LinearLayoutManager, position: Int, smooth: Boolean) {
@@ -1147,6 +1148,13 @@ class ConversationFragment :
doAfterFirstRender()
}
}
if (collapsibleEventScrollPosition != null) {
val scrollState = collapsibleEventScrollPosition!!
val offset = binding.conversationItemRecycler.height - scrollState.top - scrollState.height
layoutManager.scrollToPositionWithOffset(scrollState.position, offset)
collapsibleEventScrollPosition = null
}
}
})
}
@@ -3812,11 +3820,19 @@ class ConversationFragment :
}
}
override fun onExpandEvents(messageId: Long) {
override fun onExpandEvents(messageId: Long, itemView: View, collapsedSize: Int) {
val position = binding.conversationItemRecycler.getChildAdapterPosition(itemView)
if (position != RecyclerView.NO_POSITION && position != 0) {
collapsibleEventScrollPosition = CollapsibleEventScrollPosition(position = position + (collapsedSize - 1), top = itemView.top, height = itemView.height)
}
viewModel.onExpandEvents(messageId)
}
override fun onCollapseEvents(messageId: Long) {
override fun onCollapseEvents(messageId: Long, itemView: View, collapsedSize: Int) {
val position = binding.conversationItemRecycler.getChildAdapterPosition(itemView)
if (position != RecyclerView.NO_POSITION) {
collapsibleEventScrollPosition = CollapsibleEventScrollPosition(position = position - (collapsedSize - 1), top = itemView.top, height = itemView.height)
}
viewModel.onCollapseEvents(messageId)
}
@@ -5241,4 +5257,9 @@ class ConversationFragment :
override fun onDoubleTapEditEducationSheetNext(conversationMessage: ConversationMessage) {
handleEditMessage(conversationMessage)
}
/**
* Tracks the scroll position so that after collapsing/expanding, we can restore it properly
*/
private data class CollapsibleEventScrollPosition(val position: Int, val top: Int, val height: Int)
}

View File

@@ -417,11 +417,11 @@ class MessageDetailsFragment : Fragment(), MessageDetailsAdapter.Callbacks {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
override fun onExpandEvents(messageId: Long) {
override fun onExpandEvents(messageId: Long, itemView: View, collapsedSize: Int) {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}
override fun onCollapseEvents(messageId: Long) {
override fun onCollapseEvents(messageId: Long, itemView: View, collapsedSize: Int) {
Toast.makeText(requireContext(), "Can't touch this.", Toast.LENGTH_SHORT).show()
}

View File

@@ -421,6 +421,6 @@ private class StarredMessageClickListener(
override fun onUpdateSignalClicked() = Unit
override fun onViewPollClicked(messageId: Long) = Unit
override fun onViewPinnedMessage(messageId: Long) = Unit
override fun onCollapseEvents(messageId: Long) = Unit
override fun onExpandEvents(messageId: Long) = Unit
override fun onCollapseEvents(messageId: Long, itemView: View, collapsedSize: Int) = Unit
override fun onExpandEvents(messageId: Long, itemView: View, collapsedSize: Int) = Unit
}