mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Add proper context menu positioning for CIV2.
This commit is contained in:
committed by
Cody Henthorne
parent
b762d95622
commit
630d9492cd
@@ -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);
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user