Fix issue with chat colors not updating properly.

This commit is contained in:
Alex Hart 2023-10-13 10:37:09 -03:00
parent eafa1eabee
commit 5cc85cc860
3 changed files with 76 additions and 56 deletions

View file

@ -394,6 +394,8 @@ class ConversationFragment :
_binding.conversationItemRecycler.adapter = null
textDraftSaveDebouncer.clear()
ChatColorsDrawable.clearGlobalChatColors(_binding.conversationItemRecycler)
}
private val viewModel: ConversationViewModel by viewModel {
@ -1372,6 +1374,7 @@ class ConversationFragment :
colorFilter = PorterDuffColorFilter(chatColors.asSingleColor(), PorterDuff.Mode.MULTIPLY)
invalidateSelf()
}
ChatColorsDrawable.setGlobalChatColors(binding.conversationItemRecycler, chatColors)
}
private fun presentScrollButtons(scrollButtonState: ConversationScrollButtonState) {

View file

@ -19,9 +19,9 @@ import androidx.core.graphics.toRectF
import androidx.core.graphics.withClip
import androidx.core.graphics.withTranslation
import androidx.core.view.children
import androidx.core.view.doOnDetach
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.conversation.v2.items.ChatColorsDrawable.ChatColorsItemDecoration
import org.thoughtcrime.securesms.util.Projection
import org.thoughtcrime.securesms.util.Projection.Corners
@ -32,7 +32,8 @@ import org.thoughtcrime.securesms.util.Projection.Corners
class ChatColorsDrawable : Drawable() {
companion object {
private var maskDrawable: Drawable? = null
private var globalChatColors: ChatColors? = null
private var globalMask: Drawable? = null
private var latestBounds: Rect? = null
/**
@ -44,14 +45,34 @@ class ChatColorsDrawable : Drawable() {
}
recyclerView.addItemDecoration(ChatColorsItemDecoration)
recyclerView.doOnDetach {
maskDrawable = null
}
fun setGlobalChatColors(recyclerView: RecyclerView, chatColors: ChatColors) {
if (globalChatColors == chatColors) {
return
}
globalChatColors = chatColors
globalMask = if (chatColors.isGradient()) {
chatColors.chatBubbleMask
} else {
null
}
recyclerView.invalidateItemDecorations()
}
fun clearGlobalChatColors(recyclerView: RecyclerView) {
globalChatColors = null
globalMask = null
recyclerView.invalidateItemDecorations()
}
private fun applyBounds(bounds: Rect) {
latestBounds = bounds
maskDrawable?.bounds = bounds
globalMask?.bounds = bounds
}
}
@ -65,20 +86,18 @@ class ChatColorsDrawable : Drawable() {
* Clipping path that includes the dimensions and corners for this view.
*/
private val path = Path()
private val rect = RectF()
private var gradientColors: ChatColors? = null
private var corners: FloatArray = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
private var fillColor: Int = 0
private var localChatColors: ChatColors? = null
private var localMask: Drawable? = null
override fun draw(canvas: Canvas) {
if (gradientColors == null && fillColor == 0) {
return
}
val chatColors = getChatColors() ?: return
val mask = maskDrawable
if (gradientColors != null && mask != null) {
val mask = getMask()
if (chatColors.isGradient() && mask != null) {
canvas.withTranslation(-maskOffset.x, -maskOffset.y) {
canvas.withClip(path) {
mask.draw(canvas)
@ -89,7 +108,7 @@ class ChatColorsDrawable : Drawable() {
rect.set(bounds)
path.addRoundRect(rect, corners, Path.Direction.CW)
canvas.withClip(path) {
canvas.drawColor(fillColor)
canvas.drawColor(chatColors.asSingleColor())
}
}
}
@ -139,7 +158,7 @@ class ChatColorsDrawable : Drawable() {
}
fun isSolidColor(): Boolean {
return gradientColors == null
return getChatColors()?.isGradient() == false
}
fun setCorners(corners: FloatArray) {
@ -150,38 +169,41 @@ class ChatColorsDrawable : Drawable() {
}
/**
* Sets the chat color and shape as specified. If the colors are a gradient,
* Sets the 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
* the decorator.
*
* If a solid color is set, we can skip drawing as we move, since we haven't changed.
*/
fun setChatColors(
chatColors: ChatColors,
fun setCorners(
corners: Corners
) {
this.corners = corners.toRadii()
setCorners(corners.toRadii())
}
if (chatColors.isGradient()) {
if (maskDrawable == null) {
maskDrawable = chatColors.chatBubbleMask
fun setLocalChatColors(
chatColors: ChatColors
) {
localChatColors = chatColors
val maskBounds = latestBounds
if (maskBounds != null) {
maskDrawable?.bounds = maskBounds
}
}
this.fillColor = 0
this.gradientColors = chatColors
localMask = if (chatColors.isGradient()) {
chatColors.chatBubbleMask
} else {
this.fillColor = chatColors.asSingleColor()
this.gradientColors = null
null
}
invalidateSelf()
}
fun clearLocalChatColors() {
localChatColors = null
localMask = null
invalidateSelf()
}
private fun getChatColors(): ChatColors? = localChatColors ?: globalChatColors
private fun getMask(): Drawable? = localMask ?: globalMask
private object ChatColorsItemDecoration : RecyclerView.ItemDecoration() {
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
parent.children.map { parent.getChildViewHolder(it) }.filterIsInstance<ChatColorsDrawableInvalidator>().forEach { element ->

View file

@ -230,16 +230,14 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
presentSenderNameBackground()
presentReactions()
bodyBubbleDrawable.setChatColors(
if (binding.body.isJumbomoji) {
transparentChatColors
} else if (binding.isIncoming) {
ChatColors.forColor(ChatColors.Id.NotSet, themeDelegate.getBodyBubbleColor(conversationMessage))
} else {
conversationMessage.threadRecipient.chatColors
},
shapeDelegate.cornersLTR
)
bodyBubbleDrawable.setCorners(shapeDelegate.cornersLTR)
if (binding.body.isJumbomoji) {
bodyBubbleDrawable.setLocalChatColors(transparentChatColors)
} else if (binding.isIncoming) {
bodyBubbleDrawable.setLocalChatColors(ChatColors.forColor(ChatColors.Id.NotSet, themeDelegate.getBodyBubbleColor(conversationMessage)))
} else {
bodyBubbleDrawable.clearLocalChatColors()
}
binding.reply.setBackgroundColor(themeDelegate.getReplyIconBackgroundColor())
@ -506,10 +504,8 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
}
if (conversationContext.hasWallpaper()) {
senderDrawable.setChatColors(
ChatColors.forColor(ChatColors.Id.BuiltIn, themeDelegate.getFooterBubbleColor(conversationMessage)),
footerCorners
)
senderDrawable.setCorners(footerCorners)
senderDrawable.setLocalChatColors(ChatColors.forColor(ChatColors.Id.BuiltIn, themeDelegate.getFooterBubbleColor(conversationMessage)))
binding.senderName.background = senderDrawable
} else {
@ -606,14 +602,13 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
}
binding.footerBackground.visible = true
footerDrawable.setChatColors(
if (binding.isIncoming) {
ChatColors.forColor(ChatColors.Id.NotSet, themeDelegate.getFooterBubbleColor(conversationMessage))
} else {
conversationMessage.threadRecipient.chatColors
},
footerCorners
)
footerDrawable.setCorners(footerCorners)
if (binding.isIncoming) {
footerDrawable.setLocalChatColors(ChatColors.forColor(ChatColors.Id.NotSet, themeDelegate.getFooterBubbleColor(conversationMessage)))
} else {
footerDrawable.clearLocalChatColors()
}
}
private fun presentDate() {