NekoX/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition....

733 lines
34 KiB
Java

package org.telegram.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.view.View;
import android.view.animation.LinearInterpolator;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.ChatListItemAnimator;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatMessageCell;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AnimatedEmojiSpan;
import org.telegram.ui.Components.ChatActivityEnterView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EmptyStubSpan;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.spoilers.SpoilerEffect;
public class TextMessageEnterTransition implements MessageEnterTransitionContainer.Transition {
float fromRadius;
float progress;
Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Bitmap textLayoutBitmap;
Bitmap textLayoutBitmapRtl;
Bitmap crossfadeTextBitmap;
boolean hasReply;
private ValueAnimator animator;
boolean initBitmaps = false;
float replyFromStartX;
float replyFromStartY;
float replyFromObjectStartY;
int replayFromColor;
int replayObjectFromColor;
float crossfadeTextOffset;
float drawableFromTop;
MessageObject currentMessageObject;
boolean drawBitmaps = false;
float toXOffset;
float toXOffsetRtl;
boolean crossfade;
boolean changeColor;
StaticLayout layout;
StaticLayout rtlLayout;
ChatMessageCell messageView;
RecyclerListView listView;
MessageEnterTransitionContainer container;
private Matrix gradientMatrix;
private Paint gradientPaint;
private int messageId;
private float drawableFromBottom;
private float scaleY;
private float fromStartX;
private float fromStartY;
private ChatActivity chatActivity;
private LinearGradient gradientShader;
private float scaleFrom;
private final int currentAccount;
private int animationIndex = -1;
MessageObject.TextLayoutBlock textLayoutBlock;
Drawable fromMessageDrawable;
ChatActivityEnterView enterView;
private AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiStack;
float textX;
float textY;
float replyNameDx;
float replyMessageDx;
int fromColor;
int toColor;
private final Theme.ResourcesProvider resourcesProvider;
@SuppressLint("WrongConstant")
public TextMessageEnterTransition(ChatMessageCell messageView, ChatActivity chatActivity, RecyclerListView listView, MessageEnterTransitionContainer container, Theme.ResourcesProvider resourcesProvider) {
this.resourcesProvider = resourcesProvider;
currentAccount = UserConfig.selectedAccount;
if (messageView.getMessageObject().textLayoutBlocks == null || messageView.getMessageObject().textLayoutBlocks.size() > 1 || messageView.getMessageObject().textLayoutBlocks.isEmpty() || messageView.getMessageObject().textLayoutBlocks.get(0).textLayout.getLineCount() > 10) {
return;
}
this.messageView = messageView;
this.listView = listView;
this.container = container;
this.chatActivity = chatActivity;
enterView = chatActivity.getChatActivityEnterView();
ChatActivityEnterView chatActivityEnterView = chatActivity.getChatActivityEnterView();
if (chatActivityEnterView == null || chatActivityEnterView.getEditField() == null || chatActivityEnterView.getEditField().getLayout() == null) {
return;
}
fromRadius = chatActivityEnterView.getRecordCicle().drawingCircleRadius;
bitmapPaint.setFilterBitmap(true);
currentMessageObject = messageView.getMessageObject();
if (!messageView.getTransitionParams().wasDraw) {
messageView.draw(new Canvas());
}
messageView.setEnterTransitionInProgress(true);
CharSequence editText = chatActivityEnterView.getEditField().getLayout().getText();
CharSequence text = messageView.getMessageObject().messageText;
crossfade = false;
int linesOffset = 0;
int layoutH = chatActivityEnterView.getEditField().getLayout().getHeight();
TextPaint textPaint = Theme.chat_msgTextPaint;
int emojiSize = AndroidUtilities.dp(20);
if (messageView.getMessageObject().getEmojiOnlyCount() != 0) {
switch (messageView.getMessageObject().getEmojiOnlyCount()) {
case 0:
case 1:
case 2:
textPaint = Theme.chat_msgTextPaintEmoji[0];
break;
case 3:
textPaint = Theme.chat_msgTextPaintEmoji[1];
break;
case 4:
textPaint = Theme.chat_msgTextPaintEmoji[2];
break;
case 5:
textPaint = Theme.chat_msgTextPaintEmoji[3];
break;
case 6:
textPaint = Theme.chat_msgTextPaintEmoji[4];
break;
case 7:
case 8:
case 9:
default:
textPaint = Theme.chat_msgTextPaintEmoji[5];
break;
}
if (textPaint != null) {
emojiSize = (int) (textPaint.getTextSize() + AndroidUtilities.dp(4));
}
}
boolean containsSpans = false;
if (text instanceof Spannable) {
Spannable spannable = (Spannable) text;
Object[] objects = spannable.getSpans(0, text.length(), Object.class);
for (int i = 0; i < objects.length; i++) {
if (!(objects[i] instanceof Emoji.EmojiSpan)) {
containsSpans = true;
break;
}
}
}
if (editText.length() != text.length() || containsSpans) {
crossfade = true;
int[] newStart = new int[1];
CharSequence trimmedStr = AndroidUtilities.trim(editText, newStart);
if (newStart[0] > 0) {
linesOffset = chatActivityEnterView.getEditField().getLayout().getLineTop(chatActivityEnterView.getEditField().getLayout().getLineForOffset(newStart[0]));
layoutH = chatActivityEnterView.getEditField().getLayout().getLineBottom(chatActivityEnterView.getEditField().getLayout().getLineForOffset(newStart[0] + trimmedStr.length())) - linesOffset;
}
text = Emoji.replaceEmoji(editText, textPaint.getFontMetricsInt(), emojiSize, false);
text = AnimatedEmojiSpan.cloneSpans(text);
}
scaleFrom = chatActivityEnterView.getEditField().getTextSize() / textPaint.getTextSize();
int n = chatActivityEnterView.getEditField().getLayout().getLineCount();
int width = (int) (chatActivityEnterView.getEditField().getLayout().getWidth() / scaleFrom);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
layout = StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, width)
.setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE)
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.build();
} else {
layout = new StaticLayout(text, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
}
animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, null, animatedEmojiStack, layout);
float textViewY = chatActivityEnterView.getY() + chatActivityEnterView.getEditField().getY() + ((View) chatActivityEnterView.getEditField().getParent()).getY() + ((View) chatActivityEnterView.getEditField().getParent().getParent()).getY();
fromStartX = chatActivityEnterView.getX() + chatActivityEnterView.getEditField().getX() + ((View) chatActivityEnterView.getEditField().getParent()).getX() + ((View) chatActivityEnterView.getEditField().getParent().getParent()).getX();
fromStartY = textViewY + AndroidUtilities.dp(10) - chatActivityEnterView.getEditField().getScrollY() + linesOffset;
toXOffset = 0;
float minX = Float.MAX_VALUE;
for (int i = 0; i < layout.getLineCount(); i++) {
float begin = layout.getLineLeft(i);
if (begin < minX) {
minX = begin;
}
}
if (minX != Float.MAX_VALUE) {
toXOffset = minX;
}
scaleY = (layoutH) / (layout.getHeight() * scaleFrom);
drawableFromTop = textViewY + AndroidUtilities.dp(4);
if (enterView.isTopViewVisible()) {
drawableFromTop -= AndroidUtilities.dp(12);
}
drawableFromBottom = textViewY + chatActivityEnterView.getEditField().getMeasuredHeight();
textLayoutBlock = messageView.getMessageObject().textLayoutBlocks.get(0);
StaticLayout messageTextLayout = textLayoutBlock.textLayout;
int normalLinesCount = 0;
int rtlLinesCount = 0;
if (Math.abs(ColorUtils.calculateLuminance(getThemedColor(Theme.key_chat_messageTextOut)) - ColorUtils.calculateLuminance(getThemedColor(Theme.key_chat_messagePanelText))) > 0.2f) {
crossfade = true;
changeColor = true;
}
fromColor = getThemedColor(Theme.key_chat_messagePanelText);
toColor = getThemedColor(Theme.key_chat_messageTextOut);
if (messageTextLayout.getLineCount() == layout.getLineCount()) {
n = messageTextLayout.getLineCount();
for (int i = 0; i < n; i++) {
if (isRtlLine(layout, i)) {
rtlLinesCount++;
} else {
normalLinesCount++;
}
if (messageTextLayout.getLineEnd(i) != layout.getLineEnd(i)) {
crossfade = true;
break;
}
}
} else {
crossfade = true;
}
minX = Float.MAX_VALUE;
if (!crossfade && rtlLinesCount > 0 && normalLinesCount > 0) {
SpannableString normalText = new SpannableString(text);
SpannableString rtlText = new SpannableString(text);
for (int i = 0; i < n; i++) {
if (isRtlLine(layout, i)) {
normalText.setSpan(new EmptyStubSpan(), layout.getLineStart(i), layout.getLineEnd(i), 0);
float begin = layout.getLineLeft(i);
if (begin < minX) {
minX = begin;
}
} else {
rtlText.setSpan(new EmptyStubSpan(), layout.getLineStart(i), layout.getLineEnd(i), 0);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
layout = StaticLayout.Builder.obtain(normalText, 0, normalText.length(), textPaint, width)
.setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE)
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.build();
rtlLayout = StaticLayout.Builder.obtain(rtlText, 0, rtlText.length(), textPaint, width)
.setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE)
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.build();
} else {
layout = new StaticLayout(normalText, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false);
rtlLayout = new StaticLayout(rtlText, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false);
}
}
toXOffsetRtl = layout.getWidth() - messageView.getMessageObject().textLayoutBlocks.get(0).textLayout.getWidth();
try {
if (drawBitmaps) {
textLayoutBitmap = Bitmap.createBitmap(layout.getWidth(), layout.getHeight(), Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(textLayoutBitmap);
layout.draw(bitmapCanvas);
if (rtlLayout != null) {
textLayoutBitmapRtl = Bitmap.createBitmap(rtlLayout.getWidth(), rtlLayout.getHeight(), Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(textLayoutBitmapRtl);
rtlLayout.draw(bitmapCanvas);
}
if (crossfade) {
if (messageView.getMeasuredHeight() < listView.getMeasuredHeight()) {
crossfadeTextOffset = 0;
crossfadeTextBitmap = Bitmap.createBitmap(messageView.getMeasuredWidth(), messageView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
} else {
crossfadeTextOffset = messageView.getTop();
crossfadeTextBitmap = Bitmap.createBitmap(messageView.getMeasuredWidth(), listView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
}
}
}
} catch (Exception e) {
drawBitmaps = false;
}
hasReply = messageView.getMessageObject().getReplyMsgId() != 0 && messageView.replyNameLayout != null;
if (hasReply) {
SimpleTextView replyNameTextView = chatActivity.getReplyNameTextView();
replyFromStartX = replyNameTextView.getX() + ((View) replyNameTextView.getParent()).getX();
replyFromStartY = replyNameTextView.getY() + ((View) replyNameTextView.getParent().getParent()).getY() + ((View) replyNameTextView.getParent().getParent().getParent()).getY();
replyNameTextView = chatActivity.getReplyObjectTextView();
replyFromObjectStartY = replyNameTextView.getY() + ((View) replyNameTextView.getParent().getParent()).getY() + ((View) replyNameTextView.getParent().getParent().getParent()).getY();
replayFromColor = chatActivity.getReplyNameTextView().getTextColor();
replayObjectFromColor = chatActivity.getReplyObjectTextView().getTextColor();
drawableFromTop -= AndroidUtilities.dp(46);
}
gradientMatrix = new Matrix();
gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
gradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
gradientShader = new LinearGradient(0, AndroidUtilities.dp(12), 0, 0, 0, 0xFF000000, Shader.TileMode.CLAMP);
gradientPaint.setShader(gradientShader);
messageId = messageView.getMessageObject().stableId;
chatActivityEnterView.getEditField().setAlpha(0f);
chatActivityEnterView.setTextTransitionIsRunning(true);
if (messageView.replyNameLayout != null && messageView.replyNameLayout.getText().length() > 1) {
if (messageView.replyNameLayout.getPrimaryHorizontal(0) != 0) {
replyNameDx = messageView.replyNameLayout.getWidth() - messageView.replyNameLayout.getLineWidth(0);
}
}
if (messageView.replyTextLayout != null && messageView.replyTextLayout.getText().length() >= 1) {
if (messageView.replyTextLayout.getPrimaryHorizontal(0) != 0) {
replyMessageDx = messageView.replyTextLayout.getWidth() - messageView.replyTextLayout.getLineWidth(0);
}
}
animator = ValueAnimator.ofFloat(0f, 1f);
animator.addUpdateListener(valueAnimator -> {
progress = (float) valueAnimator.getAnimatedValue();
chatActivityEnterView.getEditField().setAlpha(progress);
container.invalidate();
});
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(ChatListItemAnimator.DEFAULT_DURATION);
container.addTransition(this);
animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, null);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
NotificationCenter.getInstance(currentAccount).onAnimationFinish(animationIndex);
container.removeTransition(TextMessageEnterTransition.this);
messageView.setEnterTransitionInProgress(false);
chatActivityEnterView.setTextTransitionIsRunning(false);
chatActivityEnterView.getEditField().setAlpha(1f);
chatActivity.getReplyNameTextView().setAlpha(1f);
chatActivity.getReplyObjectTextView().setAlpha(1f);
AnimatedEmojiSpan.release(null, animatedEmojiStack);
}
});
if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH) {
Theme.MessageDrawable drawable = messageView.getCurrentBackgroundDrawable(true);
if (drawable != null) {
fromMessageDrawable = drawable.getTransitionDrawable(getThemedColor(Theme.key_chat_messagePanelBackground));
}
}
}
public void start() {
if (animator != null) {
animator.start();
}
}
private boolean isRtlLine(Layout layout, int line) {
return layout.getLineRight(line) == layout.getWidth() && layout.getLineLeft(line) != 0;
}
float lastMessageX;
float lastMessageY;
public void onDraw(Canvas canvas) {
if (drawBitmaps && !initBitmaps && crossfadeTextBitmap != null && messageView.getTransitionParams().wasDraw) {
initBitmaps = true;
Canvas bitmapCanvas = new Canvas(crossfadeTextBitmap);
bitmapCanvas.translate(0, crossfadeTextOffset);
if (messageView.animatedEmojiStack != null) {
messageView.animatedEmojiStack.clearPositions();
}
messageView.drawMessageText(bitmapCanvas, messageView.getMessageObject().textLayoutBlocks, true, 1f, true);
messageView.drawAnimatedEmojis(bitmapCanvas, 1f);
}
float listViewBottom = listView.getY() - container.getY() + listView.getMeasuredHeight();
float fromX = fromStartX - container.getX();
float fromY = fromStartY - container.getY();
textX = messageView.getTextX();
textY = messageView.getTextY();
float messageViewX;
float messageViewY;
if (messageView.getMessageObject().stableId != messageId) {
return;
} else {
messageViewX = messageView.getX() + listView.getX() - container.getX();
messageViewY = messageView.getTop() + listView.getTop() - container.getY();
messageViewY += enterView.getTopViewHeight();
lastMessageX = messageViewX;
lastMessageY = messageViewY;
}
float progress = ChatListItemAnimator.DEFAULT_INTERPOLATOR.getInterpolation(this.progress);
float alphaProgress = this.progress > 0.4f ? 1f : this.progress / 0.4f;
float p2 = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(this.progress);
float progressX = CubicBezierInterpolator.EASE_OUT.getInterpolation(p2);
float toX = messageViewX + textX;
float toY = messageViewY + textY;
int clipBottom = (int) (container.getMeasuredHeight() * (1f - progressX) + listViewBottom * progressX);
boolean messageViewOverscrolled = messageView.getBottom() - AndroidUtilities.dp(4) > listView.getMeasuredHeight();
boolean clipBottomWithAlpha = messageViewOverscrolled && (messageViewY + messageView.getMeasuredHeight() - AndroidUtilities.dp(8) > clipBottom) && container.getMeasuredHeight() > 0;
if (clipBottomWithAlpha) {
canvas.saveLayerAlpha(0, Math.max(0, messageViewY), container.getMeasuredWidth(), container.getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG);
}
canvas.save();
canvas.clipRect(0, listView.getY() + chatActivity.getChatListViewPadding() - container.getY() - AndroidUtilities.dp(3), container.getMeasuredWidth(), container.getMeasuredHeight());
canvas.save();
float drawableX = messageViewX + messageView.getBackgroundDrawableLeft() + (fromX - (toX - toXOffset)) * (1f - progressX);
float drawableToTop = messageViewY + messageView.getBackgroundDrawableTop();
float drawableTop = (drawableFromTop - container.getY()) * (1f - progress) + (drawableToTop) * progress;
float drawableH = messageView.getBackgroundDrawableBottom() - messageView.getBackgroundDrawableTop();
float drawableBottom = (drawableFromBottom - container.getY()) * (1f - progress) + (drawableToTop + drawableH) * progress;
int drawableRight = (int) (messageViewX + messageView.getBackgroundDrawableRight() + AndroidUtilities.dp(4) * (1f - progressX));
Theme.MessageDrawable drawable = null;
if (!currentMessageObject.isAnimatedEmojiStickers()) {
drawable = messageView.getCurrentBackgroundDrawable(true);
}
if (drawable != null) {
messageView.setBackgroundTopY(container.getTop() - listView.getTop());
Drawable shadowDrawable = drawable.getShadowDrawable();
if (alphaProgress != 1f && fromMessageDrawable != null) {
fromMessageDrawable.setBounds((int) drawableX, (int) drawableTop, drawableRight, (int) drawableBottom);
fromMessageDrawable.draw(canvas);
}
if (shadowDrawable != null) {
shadowDrawable.setAlpha((int) (255 * progressX));
shadowDrawable.setBounds((int) drawableX, (int) drawableTop, drawableRight, (int) drawableBottom);
shadowDrawable.draw(canvas);
shadowDrawable.setAlpha(255);
}
drawable.setAlpha((int) (255 * alphaProgress));
drawable.setBounds((int) drawableX, (int) drawableTop, drawableRight, (int) drawableBottom);
drawable.setDrawFullBubble(true);
drawable.draw(canvas);
drawable.setDrawFullBubble(false);
drawable.setAlpha(255);
}
canvas.restore();
canvas.save();
if (drawable != null) {
if (currentMessageObject.isOutOwner()) {
canvas.clipRect(
drawableX + AndroidUtilities.dp(4), drawableTop + AndroidUtilities.dp(4),
drawableRight - AndroidUtilities.dp(10), drawableBottom - AndroidUtilities.dp(4)
);
} else {
canvas.clipRect(
drawableX + AndroidUtilities.dp(4), drawableTop + AndroidUtilities.dp(4),
drawableRight - AndroidUtilities.dp(4), drawableBottom - AndroidUtilities.dp(4)
);
}
}
canvas.translate(messageView.getLeft() + listView.getX() - container.getX(), messageViewY + (fromY - toY) * (1f - progress));
messageView.drawTime(canvas, alphaProgress, false);
messageView.drawNamesLayout(canvas, alphaProgress);
messageView.drawCommentButton(canvas, alphaProgress);
messageView.drawCaptionLayout(canvas, false, alphaProgress);
messageView.drawLinkPreview(canvas, alphaProgress);
canvas.restore();
if (hasReply) {
chatActivity.getReplyNameTextView().setAlpha(0f);
chatActivity.getReplyObjectTextView().setAlpha(0f);
float fromReplayX = replyFromStartX - container.getX();
float fromReplayY = replyFromStartY - container.getY();
float toReplayX = messageViewX + messageView.replyStartX;
float toReplayY = messageViewY + messageView.replyStartY;
int replyMessageColor;
int replyOwnerMessageColor;
int replyLineColor;
if (currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == 0 || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame || currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice)) {
replyMessageColor = getThemedColor(Theme.key_chat_outReplyMessageText);
} else {
replyMessageColor = getThemedColor(Theme.key_chat_outReplyMediaMessageText);
}
if (currentMessageObject.isOutOwner()) {
replyOwnerMessageColor = getThemedColor(Theme.key_chat_outReplyNameText);
replyLineColor = getThemedColor(Theme.key_chat_outReplyLine);
} else {
replyOwnerMessageColor = getThemedColor(Theme.key_chat_inReplyNameText);
replyLineColor = getThemedColor(Theme.key_chat_inReplyLine);
}
Theme.chat_replyTextPaint.setColor(ColorUtils.blendARGB(replayObjectFromColor, replyMessageColor, progress));
Theme.chat_replyNamePaint.setColor(ColorUtils.blendARGB(replayFromColor, replyOwnerMessageColor, progress));
if (messageView.needReplyImage) {
fromReplayX -= AndroidUtilities.dp(44);
}
float replyX = fromReplayX * (1f - progressX) + toReplayX * progressX;
float replyY = (fromReplayY + AndroidUtilities.dp(12) * progress) * (1f - progress) + toReplayY * progress;
Theme.chat_replyLinePaint.setColor(ColorUtils.setAlphaComponent(replyLineColor, (int) (Color.alpha(replyLineColor) * progressX)));
canvas.drawRect(replyX, replyY, replyX + AndroidUtilities.dp(2), replyY + AndroidUtilities.dp(35), Theme.chat_replyLinePaint);
canvas.save();
canvas.translate(AndroidUtilities.dp(10) * progressX, 0);
if (messageView.needReplyImage) {
canvas.save();
messageView.replyImageReceiver.setImageCoords(replyX, replyY, AndroidUtilities.dp(35), AndroidUtilities.dp(35));
messageView.replyImageReceiver.draw(canvas);
canvas.translate(replyX, replyY);
canvas.restore();
canvas.translate(AndroidUtilities.dp(44), 0);
}
float replyToMessageX = toReplayX - replyMessageDx;
float replyToNameX = toReplayX - replyNameDx;
float replyMessageX =(fromReplayX - replyMessageDx) * (1f - progressX) + replyToMessageX * progressX;
float replyNameX = fromReplayX * (1f - progressX) + replyToNameX * progressX;
if (messageView.replyNameLayout != null) {
canvas.save();
canvas.translate(replyNameX, replyY);
messageView.replyNameLayout.draw(canvas);
canvas.restore();
}
if (messageView.replyTextLayout != null) {
canvas.save();
canvas.translate(replyMessageX, replyY + AndroidUtilities.dp(19));
canvas.save();
SpoilerEffect.clipOutCanvas(canvas, messageView.replySpoilers);
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, messageView.replyTextLayout, messageView.animatedEmojiReplyStack, 0, messageView.replySpoilers, 0, 0, 0, 1f);
messageView.replyTextLayout.draw(canvas);
canvas.restore();
for (SpoilerEffect eff : messageView.replySpoilers) {
if (eff.shouldInvalidateColor()) eff.setColor(messageView.replyTextLayout.getPaint().getColor());
eff.draw(canvas);
}
canvas.restore();
}
canvas.restore();
}
canvas.save();
if (messageView.getMessageObject() == null || messageView.getMessageObject().type != MessageObject.TYPE_EMOJIS) {
canvas.clipRect(drawableX + AndroidUtilities.dp(4), drawableTop + AndroidUtilities.dp(4), drawableRight - AndroidUtilities.dp(4), drawableBottom - AndroidUtilities.dp(4));
}
float scale = progressX + scaleFrom * (1f - progressX);
float scale2;
if (drawBitmaps) {
scale2 = progressX + scaleY * (1f - progressX);
} else {
scale2 = 1f;
}
canvas.save();
canvas.translate(fromX * (1f - progressX) + (toX - toXOffset) * progressX, fromY * (1f - progress) + (toY + textLayoutBlock.textYOffset) * progress);
canvas.scale(scale, scale * scale2, 0, 0);
if (drawBitmaps) {
if (crossfade) {
bitmapPaint.setAlpha((int) (255 * (1f - alphaProgress)));
}
canvas.drawBitmap(textLayoutBitmap, 0, 0, bitmapPaint);
} else {
if (crossfade && changeColor) {
int oldColor = layout.getPaint().getColor();
int oldAlpha = Color.alpha(oldColor);
layout.getPaint().setColor(ColorUtils.setAlphaComponent(ColorUtils.blendARGB(fromColor, toColor, alphaProgress), (int) (oldAlpha * (1f - alphaProgress))));
layout.draw(canvas);
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, animatedEmojiStack, 0, null, 0, 0, 0, 1f - alphaProgress);
layout.getPaint().setColor(oldColor);
} else if (crossfade) {
int oldAlpha = Theme.chat_msgTextPaint.getAlpha();
Theme.chat_msgTextPaint.setAlpha((int) (oldAlpha * (1f - alphaProgress)));
layout.draw(canvas);
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, animatedEmojiStack, 0, null, 0, 0, 0, 1f - alphaProgress);
Theme.chat_msgTextPaint.setAlpha(oldAlpha);
} else {
layout.draw(canvas);
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, animatedEmojiStack, 0, null, 0, 0, 0, 1f);
}
}
canvas.restore();
if (rtlLayout != null) {
canvas.save();
canvas.translate(fromX * (1f - progressX) + (toX - toXOffsetRtl) * progressX, fromY * (1f - progress) + (toY + textLayoutBlock.textYOffset) * progress);
canvas.scale(scale, scale * scale2, 0, 0);
if (drawBitmaps) {
if (crossfade) {
bitmapPaint.setAlpha((int) (255 * (1f - alphaProgress)));
}
canvas.drawBitmap(textLayoutBitmapRtl, 0, 0, bitmapPaint);
} else {
if (crossfade && changeColor) {
int oldColor = rtlLayout.getPaint().getColor();
int oldAlpha = Color.alpha(oldColor);
rtlLayout.getPaint().setColor(ColorUtils.setAlphaComponent(ColorUtils.blendARGB(fromColor, toColor, alphaProgress), (int) (oldAlpha * (1f - alphaProgress))));
rtlLayout.draw(canvas);
rtlLayout.getPaint().setColor(oldColor);
} else if (crossfade) {
int oldAlpha = rtlLayout.getPaint().getAlpha();
rtlLayout.getPaint().setAlpha((int) (oldAlpha * (1f - alphaProgress)));
rtlLayout.draw(canvas);
rtlLayout.getPaint().setAlpha(oldAlpha);
} else {
rtlLayout.draw(canvas);
}
}
canvas.restore();
}
if (crossfade) {
canvas.save();
canvas.translate(messageView.getLeft() + listView.getX() - container.getX() + (fromX - toX) * (1f - progressX), messageViewY + (fromY - toY) * (1f - progress));
canvas.scale(scale, scale * scale2, messageView.getTextX(), messageView.getTextY());
canvas.translate(0, -crossfadeTextOffset);
if (crossfadeTextBitmap != null) {
bitmapPaint.setAlpha((int) (255 * alphaProgress));
canvas.drawBitmap(crossfadeTextBitmap, 0, 0, bitmapPaint);
} else {
int oldColor = Theme.chat_msgTextPaint.getColor();
Theme.chat_msgTextPaint.setColor(toColor);
messageView.drawMessageText(canvas, messageView.getMessageObject().textLayoutBlocks, false, alphaProgress, true);
messageView.drawAnimatedEmojis(canvas, alphaProgress);
if (Theme.chat_msgTextPaint.getColor() != oldColor) {
Theme.chat_msgTextPaint.setColor(oldColor);
}
}
canvas.restore();
}
canvas.restore();
if (clipBottomWithAlpha) {
gradientMatrix.setTranslate(0, clipBottom);
gradientShader.setLocalMatrix(gradientMatrix);
canvas.drawRect(0, clipBottom, container.getMeasuredWidth(), container.getMeasuredHeight(), gradientPaint);
canvas.restore();
}
float sendProgress = this.progress > 0.4f ? 1f : this.progress / 0.4f;
if (sendProgress == 1f) {
enterView.setTextTransitionIsRunning(false);
}
if (enterView.getSendButton().getVisibility() == View.VISIBLE && sendProgress < 1f) {
canvas.save();
canvas.translate(enterView.getX() + enterView.getSendButton().getX() + ((View) enterView.getSendButton().getParent()).getX() + ((View) enterView.getSendButton().getParent().getParent()).getX() - container.getX() + AndroidUtilities.dp(52) * sendProgress, enterView.getY() + enterView.getSendButton().getY() + ((View) enterView.getSendButton().getParent()).getY() + ((View) enterView.getSendButton().getParent().getParent()).getY() - container.getY());
enterView.getSendButton().draw(canvas);
canvas.restore();
canvas.restore();
}
}
private int getThemedColor(String key) {
Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null;
return color != null ? color : Theme.getColor(key);
}
}