Add proper context menu positioning for CIV2.

This commit is contained in:
Alex Hart
2023-08-22 16:27:01 -03:00
committed by Cody Henthorne
parent b762d95622
commit 630d9492cd
5 changed files with 41 additions and 15 deletions

View File

@@ -206,7 +206,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
contextMenu = new ConversationContextMenu(dropdownAnchor, getMenuActionItems(conversationMessage));
conversationItem.setX(selectedConversationModel.getBubbleX());
conversationItem.setX(selectedConversationModel.getSnapshotMetrics().getSnapshotOffset());
conversationItem.setY(selectedConversationModel.getItemY() + selectedConversationModel.getBubbleY() - statusBarHeight);
Bitmap conversationItemSnapshot = selectedConversationModel.getBitmap();
@@ -215,7 +215,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
int overlayHeight = getHeight() - bottomNavigationBarHeight;
int bubbleWidth = selectedConversationModel.getBubbleWidth();
float endX = selectedConversationModel.getBubbleX();
float endX = selectedConversationModel.getSnapshotMetrics().getSnapshotOffset();
float endY = conversationItem.getY();
float endApparentTop = endY;
float endScale = 1f;
@@ -346,7 +346,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
float offsetX = isMessageOnLeft ? scrubberRight + menuPadding : scrubberX - contextMenu.getMaxWidth() - menuPadding;
contextMenu.show((int) offsetX, (int) Math.min(backgroundView.getY(), overlayHeight - contextMenu.getMaxHeight()));
} else {
float contentX = selectedConversationModel.getBubbleX();
float contentX = selectedConversationModel.getSnapshotMetrics().getContextMenuPadding();
float offsetX = isMessageOnLeft ? contentX : -contextMenu.getMaxWidth() + contentX + bubbleWidth;
float menuTop = endApparentTop + (conversationItemSnapshot.getHeight() * endScale);
@@ -859,7 +859,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
ObjectAnimator itemXAnim = new ObjectAnimator();
itemXAnim.setProperty(View.X);
itemXAnim.setFloatValues(selectedConversationModel.getBubbleX());
itemXAnim.setFloatValues(selectedConversationModel.getSnapshotMetrics().getSnapshotOffset());
itemXAnim.setTarget(conversationItem);
itemXAnim.setDuration(duration);
animators.add(itemXAnim);

View File

@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.conversation
import android.graphics.Bitmap
import android.net.Uri
import android.view.View
import org.thoughtcrime.securesms.conversation.v2.items.InteractiveConversationElement
/**
* Contains information on a single selected conversation item. This is used when transitioning
@@ -12,10 +13,10 @@ data class SelectedConversationModel(
val bitmap: Bitmap,
val itemX: Float,
val itemY: Float,
val bubbleX: Float,
val bubbleY: Float,
val bubbleWidth: Int,
val audioUri: Uri? = null,
val isOutgoing: Boolean,
val focusedView: View?
val focusedView: View?,
val snapshotMetrics: InteractiveConversationElement.SnapshotMetrics
)

View File

@@ -2868,15 +2868,18 @@ class ConversationFragment :
val focusedView = if (container.isInputShowing || !container.isKeyboardShowing) null else itemView.rootView.findFocus()
val bodyBubble = target.bubbleView
val selectedConversationModel = SelectedConversationModel(
snapshot,
itemView.x,
itemView.y + binding.conversationItemRecycler.translationY,
if (target.getSnapshotStrategy() != null) itemView.x else bodyBubble.x,
bodyBubble.y,
bodyBubble.width,
audioUri,
messageRecord.isOutgoing,
focusedView
bitmap = snapshot,
itemX = itemView.x,
itemY = itemView.y + binding.conversationItemRecycler.translationY,
bubbleY = bodyBubble.y,
bubbleWidth = bodyBubble.width,
audioUri = audioUri,
isOutgoing = messageRecord.isOutgoing,
focusedView = focusedView,
snapshotMetrics = target.getSnapshotStrategy()?.snapshotMetrics ?: InteractiveConversationElement.SnapshotMetrics(
snapshotOffset = bodyBubble.x,
contextMenuPadding = bodyBubble.x
)
)
bodyBubble.visibility = View.INVISIBLE

View File

@@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.conversation.v2.items
import android.graphics.Canvas
import android.view.View
import android.view.ViewGroup
import androidx.annotation.Px
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.conversation.ConversationMessage
import org.thoughtcrime.securesms.util.ProjectionList
@@ -50,5 +51,21 @@ interface InteractiveConversationElement : ChatColorsDrawable.ChatColorsDrawable
interface SnapshotStrategy {
fun snapshot(canvas: Canvas)
val snapshotMetrics: SnapshotMetrics
}
/**
* Metrics describing how the snapshot is oriented.
*
* @param snapshotOffset Describes the horizontal offset of the top-level that will be captured.
* This is used to ensure the content is translated appropriately.
* @param contextMenuPadding Describes the distance between the edge of the view's container to the
* edge of the content (for example, the bubble). This is used to position
* the context menu.
*/
data class SnapshotMetrics(
@Px val snapshotOffset: Float,
@Px val contextMenuPadding: Float
)
}

View File

@@ -31,6 +31,11 @@ class V2TextOnlySnapshotStrategy(
binding.senderBadge
)
override val snapshotMetrics = InteractiveConversationElement.SnapshotMetrics(
snapshotOffset = 0f,
contextMenuPadding = binding.conversationItemBodyWrapper.x
)
override fun snapshot(canvas: Canvas) {
val originalScales = viewsToRestoreScale.associateWith { Pair(it.scaleX, it.scaleY) }
viewsToRestoreScale.forEach {