From b3399b5242049b07b1138f387d4c2fbd6682b59f Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Mon, 25 Sep 2023 10:51:55 -0300 Subject: [PATCH] Fix RTL display of CIV2 bubble corners. --- .../v2/items/V2ConversationItemShapeTest.kt | 7 ------- .../v2/items/ChatColorsDrawable.kt | 7 +++++++ .../v2/items/V2ConversationItemShape.kt | 21 +++++++------------ .../V2ConversationItemTextOnlyViewHolder.kt | 4 +++- .../securesms/util/Projection.java | 11 ++++++++++ .../webp/WebpInputStreamResourceDecoder.kt | 1 - 6 files changed, 29 insertions(+), 22 deletions(-) diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShapeTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShapeTest.kt index cb6582d2bf..5befcad433 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShapeTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShapeTest.kt @@ -47,7 +47,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.SINGLE val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(), isGroupThread = false, adapterPosition = 5 @@ -69,7 +68,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.END val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(now), isGroupThread = false, adapterPosition = 5 @@ -91,7 +89,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.START val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(prev), isGroupThread = false, adapterPosition = 5 @@ -115,7 +112,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.MIDDLE val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(now), isGroupThread = false, adapterPosition = 5 @@ -137,7 +133,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.SINGLE val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(now), isGroupThread = false, adapterPosition = 5 @@ -159,7 +154,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.SINGLE val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(prev), isGroupThread = false, adapterPosition = 5 @@ -183,7 +177,6 @@ class V2ConversationItemShapeTest { val expected = V2ConversationItemShape.MessageShape.SINGLE val actual = testSubject.setMessageShape( - isLtr = true, currentMessage = getMessageRecord(now), isGroupThread = false, adapterPosition = 5 diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/ChatColorsDrawable.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/ChatColorsDrawable.kt index 6c6cb2acad..cb166bd2f6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/ChatColorsDrawable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/ChatColorsDrawable.kt @@ -142,6 +142,13 @@ class ChatColorsDrawable : Drawable() { return gradientColors == null } + fun setCorners(corners: FloatArray) { + if (!this.corners.contentEquals(corners)) { + this.corners = corners + invalidateSelf() + } + } + /** * Sets the chat color and shape as specified. If the colors are a gradient, * we will use masking to draw, and we will draw every time we're told to by diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShape.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShape.kt index 30da19d2d3..1e4177fbf7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShape.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemShape.kt @@ -39,7 +39,6 @@ class V2ConversationItemShape( * updates the class state. */ fun setMessageShape( - isLtr: Boolean, currentMessage: MessageRecord, isGroupThread: Boolean, adapterPosition: Int @@ -48,42 +47,38 @@ class V2ConversationItemShape( val previousMessage: MessageRecord? = conversationContext.getPreviousMessage(adapterPosition) if (isSingularMessage(currentMessage, previousMessage, nextMessage, isGroupThread)) { - setBodyBubbleCorners(isLtr, bigRadius, bigRadius, bigRadius, bigRadius) + setBodyBubbleCorners(bigRadius, bigRadius, bigRadius, bigRadius) return MessageShape.SINGLE } else if (isStartOfMessageCluster(currentMessage, previousMessage, isGroupThread)) { val bottomEnd = if (currentMessage.isOutgoing) smallRadius else bigRadius val bottomStart = if (currentMessage.isOutgoing) bigRadius else smallRadius - setBodyBubbleCorners(isLtr, bigRadius, bigRadius, bottomEnd, bottomStart) + setBodyBubbleCorners(bigRadius, bigRadius, bottomEnd, bottomStart) return MessageShape.START } else if (isEndOfMessageCluster(currentMessage, nextMessage)) { val topStart = if (currentMessage.isOutgoing) bigRadius else smallRadius val topEnd = if (currentMessage.isOutgoing) smallRadius else bigRadius - setBodyBubbleCorners(isLtr, topStart, topEnd, bigRadius, bigRadius) + setBodyBubbleCorners(topStart, topEnd, bigRadius, bigRadius) return MessageShape.END } else { val start = if (currentMessage.isOutgoing) bigRadius else smallRadius val end = if (currentMessage.isOutgoing) smallRadius else bigRadius - setBodyBubbleCorners(isLtr, start, end, end, start) + setBodyBubbleCorners(start, end, end, start) return MessageShape.MIDDLE } } private fun setBodyBubbleCorners( - isLtr: Boolean, topStart: Float, topEnd: Float, bottomEnd: Float, bottomStart: Float ) { val newCorners = Projection.Corners( - if (isLtr) topStart else topEnd, - if (isLtr) topEnd else topStart, - if (isLtr) bottomEnd else bottomStart, - if (isLtr) bottomStart else bottomEnd + topStart, + topEnd, + bottomEnd, + bottomStart ) - if (corners == newCorners) { - return - } corners = newCorners } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt index 72e32af0d6..c35c77bd61 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt @@ -50,6 +50,7 @@ import org.thoughtcrime.securesms.util.SearchUtil import org.thoughtcrime.securesms.util.SignalLocalMetrics import org.thoughtcrime.securesms.util.ThemeUtil import org.thoughtcrime.securesms.util.VibrateUtil +import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel import org.thoughtcrime.securesms.util.hasExtraText import org.thoughtcrime.securesms.util.hasNoBubble @@ -191,7 +192,6 @@ open class V2ConversationItemTextOnlyViewHolder>( conversationMessage = model.conversationMessage shape = shapeDelegate.setMessageShape( - isLtr = itemView.layoutDirection == View.LAYOUT_DIRECTION_LTR, currentMessage = conversationMessage.messageRecord, isGroupThread = conversationMessage.threadRecipient.isGroup, adapterPosition = bindingAdapterPosition @@ -345,6 +345,8 @@ open class V2ConversationItemTextOnlyViewHolder>( } private fun invalidateBodyBubbleDrawable(coordinateRoot: ViewGroup) { + bodyBubbleDrawable.setCorners(shapeDelegate.corners.toRelativeRadii(ViewUtil.isLtr(coordinateRoot))) + if (bodyBubbleDrawable.isSolidColor()) { return } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/Projection.java b/app/src/main/java/org/thoughtcrime/securesms/util/Projection.java index 213de56389..30156a17a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/Projection.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/Projection.java @@ -290,6 +290,17 @@ public final class Projection { return bottomRight; } + public float[] toRelativeRadii(boolean isLTR) { + float[] radii = new float[8]; + + radii[0] = radii[1] = isLTR ? topLeft : topRight; + radii[2] = radii[3] = isLTR ? topRight : topLeft; + radii[4] = radii[5] = isLTR ? bottomRight : bottomLeft; + radii[6] = radii[7] = isLTR ? bottomLeft : bottomRight; + + return radii; + } + public float[] toRadii() { float[] radii = new float[8]; diff --git a/glide-webp/lib/src/main/java/org/signal/glide/webp/WebpInputStreamResourceDecoder.kt b/glide-webp/lib/src/main/java/org/signal/glide/webp/WebpInputStreamResourceDecoder.kt index 194f9593b8..20e69d747d 100644 --- a/glide-webp/lib/src/main/java/org/signal/glide/webp/WebpInputStreamResourceDecoder.kt +++ b/glide-webp/lib/src/main/java/org/signal/glide/webp/WebpInputStreamResourceDecoder.kt @@ -64,7 +64,6 @@ class WebpInputStreamResourceDecoder(private val bitmapPool: BitmapPool) : Resou throw e } - val bitmap: Bitmap? = WebpDecoder().nativeDecodeBitmap(webp) return BitmapResource.obtain(bitmap, bitmapPool) }