Signal-Android/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemSelection.kt

125 wiersze
3.4 KiB
Kotlin

package org.thoughtcrime.securesms.conversation
import android.graphics.Bitmap
import android.graphics.Path
import android.view.ViewGroup
import androidx.core.graphics.applyCanvas
import androidx.core.graphics.createBitmap
import androidx.core.graphics.withClip
import androidx.core.graphics.withTranslation
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import org.signal.core.util.DimensionUnit
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.util.hasNoBubble
object ConversationItemSelection {
@JvmStatic
fun snapshotView(
conversationItem: ConversationItem,
list: RecyclerView,
messageRecord: MessageRecord,
videoBitmap: Bitmap?
): Bitmap {
val isOutgoing = messageRecord.isOutgoing
val hasNoBubble = messageRecord.hasNoBubble(conversationItem.context)
return snapshotMessage(
conversationItem = conversationItem,
list = list,
videoBitmap = videoBitmap,
drawConversationItem = !isOutgoing || hasNoBubble,
hasReaction = messageRecord.reactions.isNotEmpty()
)
}
private fun snapshotMessage(
conversationItem: ConversationItem,
list: RecyclerView,
videoBitmap: Bitmap?,
drawConversationItem: Boolean,
hasReaction: Boolean
): Bitmap {
val bodyBubble = conversationItem.bodyBubble
val reactionsView = conversationItem.reactionsView
val originalScale = bodyBubble.scaleX
bodyBubble.scaleX = 1.0f
bodyBubble.scaleY = 1.0f
val projections = conversationItem.getSnapshotProjections(list, false)
val path = Path()
val xTranslation = -conversationItem.x - bodyBubble.x
val yTranslation = -conversationItem.y - bodyBubble.y
val mp4Projection = conversationItem.getGiphyMp4PlayableProjection(list)
var scaledVideoBitmap = videoBitmap
if (videoBitmap != null) {
scaledVideoBitmap = Bitmap.createScaledBitmap(
videoBitmap,
(videoBitmap.width / originalScale).toInt(),
(videoBitmap.height / originalScale).toInt(),
true
)
mp4Projection.translateX(xTranslation)
mp4Projection.translateY(yTranslation)
mp4Projection.applyToPath(path)
}
projections.use {
it.forEach { p ->
p.translateX(xTranslation)
p.translateY(yTranslation)
p.applyToPath(path)
}
}
conversationItem.destroyAllDrawingCaches()
var bitmapHeight = bodyBubble.height
if (hasReaction) {
bitmapHeight += (reactionsView.height - DimensionUnit.DP.toPixels(4f)).toInt()
}
return createBitmap(bodyBubble.width, bitmapHeight).applyCanvas {
if (drawConversationItem) {
bodyBubble.draw(this)
}
withClip(path) {
withTranslation(x = xTranslation, y = yTranslation) {
list.draw(this)
if (scaledVideoBitmap != null) {
drawBitmap(scaledVideoBitmap, mp4Projection.x - xTranslation, mp4Projection.y - yTranslation, null)
}
}
}
withTranslation(
x = reactionsView.x - bodyBubble.x,
y = reactionsView.y - bodyBubble.y
) {
reactionsView.draw(this)
}
}.also {
mp4Projection.release()
bodyBubble.scaleX = originalScale
bodyBubble.scaleY = originalScale
}
}
}
private fun ViewGroup.destroyAllDrawingCaches() {
children.forEach {
it.destroyDrawingCache()
if (it is ViewGroup) {
it.destroyAllDrawingCaches()
}
}
}