mirror of https://github.com/NekoX-Dev/NekoX.git
731 lines
35 KiB
Java
731 lines
35 KiB
Java
package org.telegram.ui.Components.Reactions;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.content.Context;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.PixelFormat;
|
|
import android.view.HapticFeedbackConstants;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.WindowManager;
|
|
import android.widget.FrameLayout;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.messenger.ImageLocation;
|
|
import org.telegram.messenger.ImageReceiver;
|
|
import org.telegram.messenger.MediaDataController;
|
|
import org.telegram.messenger.MessageObject;
|
|
import org.telegram.messenger.MessagesController;
|
|
import org.telegram.tgnet.TLRPC;
|
|
import org.telegram.ui.ActionBar.BaseFragment;
|
|
import org.telegram.ui.Cells.ChatMessageCell;
|
|
import org.telegram.ui.ChatActivity;
|
|
import org.telegram.ui.Components.AvatarDrawable;
|
|
import org.telegram.ui.Components.BackupImageView;
|
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
|
import org.telegram.ui.Components.RLottieDrawable;
|
|
import org.telegram.ui.Components.ReactionsContainerLayout;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Random;
|
|
|
|
public class ReactionsEffectOverlay {
|
|
|
|
public final static int LONG_ANIMATION = 0;
|
|
public final static int SHORT_ANIMATION = 1;
|
|
public final static int ONLY_MOVE_ANIMATION = 2;
|
|
|
|
private final int animationType;
|
|
@SuppressLint("StaticFieldLeak")
|
|
public static ReactionsEffectOverlay currentOverlay;
|
|
@SuppressLint("StaticFieldLeak")
|
|
public static ReactionsEffectOverlay currentShortOverlay;
|
|
|
|
private final AnimationView effectImageView;
|
|
private final AnimationView emojiImageView;
|
|
private final AnimationView emojiStaticImageView;
|
|
private final FrameLayout container;
|
|
private final BaseFragment fragment;
|
|
private final int currentAccount;
|
|
boolean animateIn;
|
|
float animateInProgress;
|
|
float animateOutProgress;
|
|
|
|
FrameLayout windowView;
|
|
BackupImageView backupImageView;
|
|
private static int uniqPrefix;
|
|
|
|
int[] loc = new int[2];
|
|
private WindowManager windowManager;
|
|
private boolean dismissed;
|
|
private float dismissProgress;
|
|
private final int messageId;
|
|
private final long groupId;
|
|
private final String reaction;
|
|
private float lastDrawnToX;
|
|
private float lastDrawnToY;
|
|
private boolean started;
|
|
private ReactionsContainerLayout.ReactionHolderView holderView = null;
|
|
private boolean wasScrolled;
|
|
private ChatMessageCell cell;
|
|
private boolean finished;
|
|
private boolean useWindow;
|
|
private ViewGroup decorView;
|
|
private static long lastHapticTime;
|
|
ArrayList<AvatarParticle> avatars = new ArrayList<>();
|
|
|
|
|
|
private ReactionsEffectOverlay(Context context, BaseFragment fragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount, int animationType) {
|
|
this.fragment = fragment;
|
|
this.messageId = cell.getMessageObject().getId();
|
|
this.groupId = cell.getMessageObject().getGroupId();
|
|
this.reaction = reaction;
|
|
this.animationType = animationType;
|
|
this.currentAccount = currentAccount;
|
|
this.cell = cell;
|
|
ReactionsLayoutInBubble.ReactionButton reactionButton = cell.getReactionButton(reaction);
|
|
float fromX, fromY, fromHeight, fromWidth;
|
|
ChatActivity chatActivity = (fragment instanceof ChatActivity) ? (ChatActivity) fragment : null;
|
|
if (reactionsLayout != null) {
|
|
for (int i = 0; i < reactionsLayout.recyclerListView.getChildCount(); i++) {
|
|
if (((ReactionsContainerLayout.ReactionHolderView) reactionsLayout.recyclerListView.getChildAt(i)).currentReaction.reaction.equals(reaction)) {
|
|
holderView = ((ReactionsContainerLayout.ReactionHolderView) reactionsLayout.recyclerListView.getChildAt(i));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (animationType == SHORT_ANIMATION) {
|
|
Random random = new Random();
|
|
ArrayList<TLRPC.TL_messagePeerReaction> recentReactions = null;
|
|
if (cell.getMessageObject().messageOwner.reactions != null) {
|
|
recentReactions = cell.getMessageObject().messageOwner.reactions.recent_reactions;
|
|
}
|
|
if (recentReactions != null) {
|
|
for (int i = 0; i < recentReactions.size(); i++) {
|
|
if (reaction.equals(recentReactions.get(i).reaction) && recentReactions.get(i).unread) {
|
|
TLRPC.User user;
|
|
TLRPC.Chat chat;
|
|
|
|
AvatarDrawable avatarDrawable = new AvatarDrawable();
|
|
ImageReceiver imageReceiver = new ImageReceiver();
|
|
long peerId = MessageObject.getPeerId(recentReactions.get(i).peer_id);
|
|
if (peerId < 0) {
|
|
chat = MessagesController.getInstance(currentAccount).getChat(-peerId);
|
|
if (chat == null) {
|
|
continue;
|
|
}
|
|
avatarDrawable.setInfo(chat);
|
|
imageReceiver.setForUserOrChat(chat, avatarDrawable);
|
|
} else {
|
|
user = MessagesController.getInstance(currentAccount).getUser(peerId);
|
|
if (user == null) {
|
|
continue;
|
|
}
|
|
avatarDrawable.setInfo(user);
|
|
imageReceiver.setForUserOrChat(user, avatarDrawable);
|
|
}
|
|
|
|
AvatarParticle avatarParticle = new AvatarParticle();
|
|
avatarParticle.imageReceiver = imageReceiver;
|
|
avatarParticle.fromX = 0.5f;// + Math.abs(random.nextInt() % 100) / 100f * 0.2f;
|
|
avatarParticle.fromY = 0.5f;// + Math.abs(random.nextInt() % 100) / 100f * 0.2f;
|
|
avatarParticle.jumpY = 0.3f + Math.abs(random.nextInt() % 100) / 100f * 0.1f;
|
|
avatarParticle.randomScale = 0.8f + Math.abs(random.nextInt() % 100) / 100f * 0.4f;
|
|
avatarParticle.randomRotation = 60 * Math.abs(random.nextInt() % 100) / 100f;
|
|
avatarParticle.leftTime = (int) (400 + Math.abs(random.nextInt() % 100) / 100f * 200);
|
|
|
|
if (avatars.isEmpty()) {
|
|
avatarParticle.toX = 0.2f + 0.6f * Math.abs(random.nextInt() % 100) / 100f;
|
|
avatarParticle.toY = 0.4f * Math.abs(random.nextInt() % 100) / 100f;
|
|
} else {
|
|
float bestDistance = 0;
|
|
float bestX = 0;
|
|
float bestY = 0;
|
|
for (int k = 0; k < 10; k++) {
|
|
float randX = 0.2f + 0.6f * Math.abs(random.nextInt() % 100) / 100f;
|
|
float randY = 0.2f + 0.4f * Math.abs(random.nextInt() % 100) / 100f;
|
|
float minDistance = Integer.MAX_VALUE;
|
|
for (int j = 0; j < avatars.size(); j++) {
|
|
float rx = avatars.get(j).toX - randX;
|
|
float ry = avatars.get(j).toY - randY;
|
|
float distance = rx * rx + ry * ry;
|
|
if (distance < minDistance) {
|
|
minDistance = distance;
|
|
}
|
|
}
|
|
if (minDistance > bestDistance) {
|
|
bestDistance = minDistance;
|
|
bestX = randX;
|
|
bestY = randY;
|
|
}
|
|
}
|
|
avatarParticle.toX = bestX;
|
|
avatarParticle.toY = bestY;
|
|
}
|
|
|
|
avatars.add(avatarParticle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean fromHolder = holderView != null || (x != 0 && y != 0);
|
|
if (holderView != null) {
|
|
holderView.getLocationOnScreen(loc);
|
|
fromX = loc[0] + holderView.backupImageView.getX();
|
|
fromY = loc[1] + holderView.backupImageView.getY();
|
|
fromHeight = holderView.backupImageView.getWidth() * holderView.getScaleX();
|
|
} else if (reactionButton != null) {
|
|
cell.getLocationInWindow(loc);
|
|
fromX = loc[0] + cell.reactionsLayoutInBubble.x + reactionButton.x + reactionButton.imageReceiver.getImageX();
|
|
fromY = loc[1] + cell.reactionsLayoutInBubble.y + reactionButton.y + reactionButton.imageReceiver.getImageY();
|
|
fromHeight = reactionButton.imageReceiver.getImageHeight();
|
|
fromWidth = reactionButton.imageReceiver.getImageWidth();
|
|
} else {
|
|
((View) cell.getParent()).getLocationInWindow(loc);
|
|
fromX = loc[0] + x;
|
|
fromY = loc[1] + y;
|
|
fromHeight = 0;
|
|
fromWidth = 0;
|
|
}
|
|
|
|
int size;
|
|
if (animationType == ONLY_MOVE_ANIMATION) {
|
|
size = AndroidUtilities.dp(34);
|
|
} else if (animationType == SHORT_ANIMATION) {
|
|
size = AndroidUtilities.dp(80);
|
|
} else {
|
|
size = Math.round(Math.min(AndroidUtilities.dp(350), Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y)) * 0.8f);
|
|
}
|
|
int sizeForFilter = (int) (2f * size / AndroidUtilities.density);
|
|
int emojiSize = size >> 1;
|
|
int emojiSizeForFilter = sizeForFilter >> 1;
|
|
|
|
float fromScale = fromHeight / (float) emojiSize;
|
|
animateInProgress = 0f;
|
|
animateOutProgress = 0f;
|
|
|
|
container = new FrameLayout(context);
|
|
windowView = new FrameLayout(context) {
|
|
|
|
@Override
|
|
protected void dispatchDraw(Canvas canvas) {
|
|
if (dismissed) {
|
|
if (dismissProgress != 1f) {
|
|
dismissProgress += 16 / 150f;
|
|
if (dismissProgress > 1f) {
|
|
dismissProgress = 1f;
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
removeCurrentView();
|
|
});
|
|
}
|
|
}
|
|
if (dismissProgress != 1f) {
|
|
setAlpha(1f - dismissProgress);
|
|
super.dispatchDraw(canvas);
|
|
}
|
|
invalidate();
|
|
return;
|
|
}
|
|
if (!started) {
|
|
invalidate();
|
|
return;
|
|
} else {
|
|
if (holderView != null) {
|
|
holderView.backupImageView.setAlpha(0);
|
|
holderView.pressedBackupImageView.setAlpha(0);
|
|
}
|
|
}
|
|
ChatMessageCell drawingCell;
|
|
if (fragment instanceof ChatActivity) {
|
|
drawingCell = ((ChatActivity) fragment).findMessageCell(messageId, false);
|
|
} else {
|
|
drawingCell = cell;
|
|
}
|
|
float toX, toY, toH;
|
|
|
|
if (cell.getMessageObject().shouldDrawReactionsInLayout()) {
|
|
toH = AndroidUtilities.dp(20);
|
|
} else {
|
|
toH = AndroidUtilities.dp(14);
|
|
}
|
|
if (drawingCell != null) {
|
|
cell.getLocationInWindow(loc);
|
|
|
|
ReactionsLayoutInBubble.ReactionButton reactionButton = cell.getReactionButton(reaction);
|
|
toX = loc[0] + cell.reactionsLayoutInBubble.x;
|
|
toY = loc[1] + cell.reactionsLayoutInBubble.y;
|
|
if (reactionButton != null) {
|
|
toX += reactionButton.x + reactionButton.imageReceiver.getImageX();
|
|
toY += reactionButton.y + reactionButton.imageReceiver.getImageY();
|
|
}
|
|
if (chatActivity != null) {
|
|
toY += chatActivity.drawingChatLisViewYoffset;
|
|
}
|
|
if (drawingCell.drawPinnedBottom && !drawingCell.shouldDrawTimeOnMedia()) {
|
|
toY += AndroidUtilities.dp(2);
|
|
}
|
|
lastDrawnToX = toX;
|
|
lastDrawnToY = toY;
|
|
} else {
|
|
toX = lastDrawnToX;
|
|
toY = lastDrawnToY;
|
|
}
|
|
|
|
if (fragment.getParentActivity() != null && fragment.getFragmentView().getParent() != null && fragment.getFragmentView().getVisibility() == View.VISIBLE && fragment.getFragmentView() != null) {
|
|
fragment.getFragmentView().getLocationOnScreen(loc);
|
|
setAlpha(((View) fragment.getFragmentView().getParent()).getAlpha());
|
|
} else {
|
|
return;
|
|
}
|
|
float previewX = toX - (emojiSize - toH) / 2f;
|
|
float previewY = toY - (emojiSize - toH) / 2f;
|
|
|
|
if (animationType != SHORT_ANIMATION) {
|
|
if (previewX < loc[0]) {
|
|
previewX = loc[0];
|
|
}
|
|
if (previewX + emojiSize > loc[0] + getMeasuredWidth()) {
|
|
previewX = loc[0] + getMeasuredWidth() - emojiSize;
|
|
}
|
|
}
|
|
|
|
float animateInProgressX, animateInProgressY;
|
|
float animateOutProgress = CubicBezierInterpolator.DEFAULT.getInterpolation(ReactionsEffectOverlay.this.animateOutProgress);
|
|
if (animationType == ONLY_MOVE_ANIMATION) {
|
|
animateInProgressX = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(animateOutProgress);
|
|
animateInProgressY = CubicBezierInterpolator.DEFAULT.getInterpolation(animateOutProgress);
|
|
} else if (fromHolder) {
|
|
animateInProgressX = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(animateInProgress);
|
|
animateInProgressY = CubicBezierInterpolator.DEFAULT.getInterpolation(animateInProgress);
|
|
} else {
|
|
animateInProgressX = animateInProgressY = animateInProgress;
|
|
}
|
|
|
|
float scale = animateInProgressX + (1f - animateInProgressX) * fromScale;
|
|
|
|
float toScale = toH / (float) emojiSize;
|
|
|
|
float x;
|
|
float y;
|
|
if (animationType == SHORT_ANIMATION) {
|
|
x = previewX;
|
|
y = previewY;
|
|
scale = 1f;
|
|
} else {
|
|
x = fromX * (1f - animateInProgressX) + previewX * animateInProgressX;
|
|
y = fromY * (1f - animateInProgressY) + previewY * animateInProgressY;
|
|
}
|
|
|
|
|
|
effectImageView.setTranslationX(x);
|
|
effectImageView.setTranslationY(y);
|
|
effectImageView.setAlpha((1f - animateOutProgress));
|
|
effectImageView.setScaleX(scale);
|
|
effectImageView.setScaleY(scale);
|
|
|
|
if (animationType == ONLY_MOVE_ANIMATION) {
|
|
scale = fromScale * (1f - animateInProgressX) + toScale * animateInProgressX;
|
|
x = fromX * (1f - animateInProgressX) + toX * animateInProgressX;
|
|
y = fromY * (1f - animateInProgressY) + toY * animateInProgressY;
|
|
} else {
|
|
if (animateOutProgress != 0) {
|
|
scale = scale * (1f - animateOutProgress) + toScale * animateOutProgress;
|
|
x = x * (1f - animateOutProgress) + toX * animateOutProgress;
|
|
y = y * (1f - animateOutProgress) + toY * animateOutProgress;
|
|
}
|
|
}
|
|
|
|
if (animationType != SHORT_ANIMATION) {
|
|
emojiStaticImageView.setAlpha(animateOutProgress > 0.7f ? (animateOutProgress - 0.7f) / 0.3f : 0);
|
|
}
|
|
//emojiImageView.setAlpha(animateOutProgress < 0.5f ? 1f - (animateOutProgress / 0.5f) : 0f);
|
|
container.setTranslationX(x);
|
|
container.setTranslationY(y);
|
|
|
|
container.setScaleX(scale);
|
|
container.setScaleY(scale);
|
|
|
|
super.dispatchDraw(canvas);
|
|
|
|
if ((animationType == SHORT_ANIMATION || emojiImageView.wasPlaying) && animateInProgress != 1f) {
|
|
if (fromHolder) {
|
|
animateInProgress += 16f / 350f;
|
|
} else {
|
|
animateInProgress += 16f / 220f;
|
|
}
|
|
if (animateInProgress > 1f) {
|
|
animateInProgress = 1f;
|
|
}
|
|
}
|
|
|
|
if (animationType == ONLY_MOVE_ANIMATION || (wasScrolled && animationType == LONG_ANIMATION) || (animationType != SHORT_ANIMATION && emojiImageView.wasPlaying && emojiImageView.getImageReceiver().getLottieAnimation() != null && !emojiImageView.getImageReceiver().getLottieAnimation().isRunning()) ||
|
|
(animationType == SHORT_ANIMATION && effectImageView.wasPlaying && effectImageView.getImageReceiver().getLottieAnimation() != null && !effectImageView.getImageReceiver().getLottieAnimation().isRunning())) {
|
|
if (ReactionsEffectOverlay.this.animateOutProgress != 1f) {
|
|
if (animationType == SHORT_ANIMATION) {
|
|
ReactionsEffectOverlay.this.animateOutProgress = 1f;
|
|
} else {
|
|
float duration = animationType == ONLY_MOVE_ANIMATION ? 350f : 220f;
|
|
ReactionsEffectOverlay.this.animateOutProgress += 16f / duration;
|
|
}
|
|
if (ReactionsEffectOverlay.this.animateOutProgress > 0.7f && !finished) {
|
|
startShortAnimation();
|
|
}
|
|
if (ReactionsEffectOverlay.this.animateOutProgress >= 1f) {
|
|
if (animationType == LONG_ANIMATION || animationType == ONLY_MOVE_ANIMATION) {
|
|
cell.reactionsLayoutInBubble.animateReaction(reaction);
|
|
}
|
|
ReactionsEffectOverlay.this.animateOutProgress = 1f;
|
|
if (animationType == SHORT_ANIMATION) {
|
|
currentShortOverlay = null;
|
|
} else {
|
|
currentOverlay = null;
|
|
}
|
|
cell.invalidate();
|
|
if (cell.getCurrentMessagesGroup() != null && cell.getParent() != null) {
|
|
((View) cell.getParent()).invalidate();
|
|
}
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
removeCurrentView();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (!avatars.isEmpty() && effectImageView.wasPlaying) {
|
|
RLottieDrawable animation = effectImageView.getImageReceiver().getLottieAnimation();
|
|
|
|
for (int i = 0; i < avatars.size(); i++) {
|
|
AvatarParticle particle = avatars.get(i);
|
|
float progress = particle.progress;
|
|
boolean isLeft;
|
|
if (animation != null && animation.isRunning()) {
|
|
long duration = effectImageView.getImageReceiver().getLottieAnimation().getDuration();
|
|
int totalFramesCount = effectImageView.getImageReceiver().getLottieAnimation().getFramesCount();
|
|
int currentFrame = effectImageView.getImageReceiver().getLottieAnimation().getCurrentFrame();
|
|
int timeLeft = (int) (duration - duration * (currentFrame / (float) totalFramesCount));
|
|
isLeft = timeLeft < particle.leftTime;
|
|
} else {
|
|
isLeft = true;
|
|
}
|
|
|
|
if (isLeft && particle.outProgress != 1f) {
|
|
particle.outProgress += 16f / 150f;
|
|
if (particle.outProgress > 1f) {
|
|
particle.outProgress = 1f;
|
|
}
|
|
}
|
|
float jumpProgress = progress < 0.5f ? (progress / 0.5f) : (1f - ((progress - 0.5f) / 0.5f));
|
|
float avatarX = particle.fromX * (1f - progress) + particle.toX * progress;
|
|
float avatarY = particle.fromY * (1f - progress) + particle.toY * progress - particle.jumpY * jumpProgress;
|
|
|
|
float s = progress * particle.randomScale * (1f - particle.outProgress);
|
|
float cx = effectImageView.getX() + (effectImageView.getWidth() * effectImageView.getScaleX()) * avatarX;
|
|
float cy = effectImageView.getY() + (effectImageView.getHeight() * effectImageView.getScaleY()) * avatarY;
|
|
int size = AndroidUtilities.dp(16);
|
|
avatars.get(i).imageReceiver.setImageCoords(cx - size / 2f, cy - size / 2f, size, size);
|
|
avatars.get(i).imageReceiver.setRoundRadius(size >> 1);
|
|
canvas.save();
|
|
canvas.translate(0, particle.globalTranslationY);
|
|
canvas.scale(s, s, cx, cy);
|
|
canvas.rotate(particle.currentRotation, cx, cy);
|
|
|
|
avatars.get(i).imageReceiver.draw(canvas);
|
|
canvas.restore();
|
|
|
|
if (particle.progress < 1f) {
|
|
particle.progress += 16f / 350f;
|
|
if (particle.progress > 1f) {
|
|
particle.progress = 1f;
|
|
}
|
|
}
|
|
if (progress >= 1f) {
|
|
particle.globalTranslationY += AndroidUtilities.dp(20) * 16f / 500f;
|
|
}
|
|
|
|
if (particle.incrementRotation) {
|
|
particle.currentRotation += particle.randomRotation / 250f;
|
|
if (particle.currentRotation > particle.randomRotation) {
|
|
particle.incrementRotation = false;
|
|
}
|
|
} else {
|
|
particle.currentRotation -= particle.randomRotation / 250f;
|
|
if (particle.currentRotation < -particle.randomRotation) {
|
|
particle.incrementRotation = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
invalidate();
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToWindow() {
|
|
super.onAttachedToWindow();
|
|
for (int i = 0; i < avatars.size(); i++) {
|
|
avatars.get(i).imageReceiver.onAttachedToWindow();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onDetachedFromWindow() {
|
|
super.onDetachedFromWindow();
|
|
for (int i = 0; i < avatars.size(); i++) {
|
|
avatars.get(i).imageReceiver.onDetachedFromWindow();
|
|
}
|
|
}
|
|
};
|
|
effectImageView = new AnimationView(context);
|
|
emojiImageView = new AnimationView(context);
|
|
emojiStaticImageView = new AnimationView(context);
|
|
TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction);
|
|
if (availableReaction != null) {
|
|
|
|
if (animationType != ONLY_MOVE_ANIMATION) {
|
|
TLRPC.Document document = animationType == SHORT_ANIMATION ? availableReaction.around_animation : availableReaction.effect_animation;
|
|
effectImageView.getImageReceiver().setUniqKeyPrefix((uniqPrefix++) + "_" + cell.getMessageObject().getId() + "_");
|
|
effectImageView.setImage(ImageLocation.getForDocument(document), sizeForFilter + "_" + sizeForFilter + "_pcache", null, null, 0, null);
|
|
|
|
effectImageView.getImageReceiver().setAutoRepeat(0);
|
|
effectImageView.getImageReceiver().setAllowStartAnimation(false);
|
|
|
|
if (effectImageView.getImageReceiver().getLottieAnimation() != null) {
|
|
effectImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false);
|
|
effectImageView.getImageReceiver().getLottieAnimation().start();
|
|
}
|
|
}
|
|
|
|
if (animationType == ONLY_MOVE_ANIMATION) {
|
|
TLRPC.Document document = availableReaction.appear_animation;
|
|
emojiImageView.getImageReceiver().setUniqKeyPrefix((uniqPrefix++) + "_" + cell.getMessageObject().getId() + "_");
|
|
emojiImageView.setImage(ImageLocation.getForDocument(document), emojiSizeForFilter + "_" + emojiSizeForFilter, null, null, 0, null);
|
|
} else if (animationType == LONG_ANIMATION) {
|
|
TLRPC.Document document = availableReaction.activate_animation;
|
|
emojiImageView.getImageReceiver().setUniqKeyPrefix((uniqPrefix++) + "_" + cell.getMessageObject().getId() + "_");
|
|
emojiImageView.setImage(ImageLocation.getForDocument(document), emojiSizeForFilter + "_" + emojiSizeForFilter, null, null, 0, null);
|
|
}
|
|
|
|
emojiImageView.getImageReceiver().setAutoRepeat(0);
|
|
emojiImageView.getImageReceiver().setAllowStartAnimation(false);
|
|
|
|
if (emojiImageView.getImageReceiver().getLottieAnimation() != null) {
|
|
if (animationType == ONLY_MOVE_ANIMATION) {
|
|
emojiImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(emojiImageView.getImageReceiver().getLottieAnimation().getFramesCount() - 1, false);
|
|
} else {
|
|
emojiImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false);
|
|
emojiImageView.getImageReceiver().getLottieAnimation().start();
|
|
}
|
|
}
|
|
|
|
int topOffset = (size - emojiSize) >> 1;
|
|
int leftOffset;
|
|
if (animationType == SHORT_ANIMATION) {
|
|
leftOffset = topOffset;
|
|
} else {
|
|
leftOffset = size - emojiSize;
|
|
}
|
|
container.addView(emojiImageView);
|
|
emojiImageView.getLayoutParams().width = emojiSize;
|
|
emojiImageView.getLayoutParams().height = emojiSize;
|
|
((FrameLayout.LayoutParams) emojiImageView.getLayoutParams()).topMargin = topOffset;
|
|
((FrameLayout.LayoutParams) emojiImageView.getLayoutParams()).leftMargin = leftOffset;
|
|
|
|
if (animationType != SHORT_ANIMATION) {
|
|
emojiStaticImageView.getImageReceiver().setImage(ImageLocation.getForDocument(availableReaction.static_icon), "40_40", null, "webp", availableReaction, 1);
|
|
}
|
|
container.addView(emojiStaticImageView);
|
|
emojiStaticImageView.getLayoutParams().width = emojiSize;
|
|
emojiStaticImageView.getLayoutParams().height = emojiSize;
|
|
((FrameLayout.LayoutParams) emojiStaticImageView.getLayoutParams()).topMargin = topOffset;
|
|
((FrameLayout.LayoutParams) emojiStaticImageView.getLayoutParams()).leftMargin = leftOffset;
|
|
|
|
|
|
windowView.addView(container);
|
|
container.getLayoutParams().width = size;
|
|
container.getLayoutParams().height = size;
|
|
((FrameLayout.LayoutParams) container.getLayoutParams()).topMargin = -topOffset;
|
|
((FrameLayout.LayoutParams) container.getLayoutParams()).leftMargin = -leftOffset;
|
|
|
|
windowView.addView(effectImageView);
|
|
effectImageView.getLayoutParams().width = size;
|
|
effectImageView.getLayoutParams().height = size;
|
|
|
|
effectImageView.getLayoutParams().width = size;
|
|
effectImageView.getLayoutParams().height = size;
|
|
((FrameLayout.LayoutParams) effectImageView.getLayoutParams()).topMargin = -topOffset;
|
|
((FrameLayout.LayoutParams) effectImageView.getLayoutParams()).leftMargin = -leftOffset;
|
|
|
|
// if (!SHORT_ANIMATION) {
|
|
container.setPivotX(leftOffset);
|
|
container.setPivotY(topOffset);
|
|
//}
|
|
} else {
|
|
dismissed = true;
|
|
}
|
|
}
|
|
|
|
private void removeCurrentView() {
|
|
try {
|
|
if (useWindow) {
|
|
windowManager.removeView(windowView);
|
|
} else {
|
|
decorView.removeView(windowView);
|
|
}
|
|
} catch (Exception e) {
|
|
|
|
}
|
|
}
|
|
|
|
public static void show(BaseFragment baseFragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount, int animationType) {
|
|
if (cell == null || reaction == null || baseFragment == null || baseFragment.getParentActivity() == null) {
|
|
return;
|
|
}
|
|
boolean animationEnabled = MessagesController.getGlobalMainSettings().getBoolean("view_animations", true);
|
|
if (!animationEnabled) {
|
|
return;
|
|
}
|
|
if (animationType == ONLY_MOVE_ANIMATION || animationType == LONG_ANIMATION) {
|
|
show(baseFragment, null, cell, 0, 0, reaction, currentAccount, SHORT_ANIMATION);
|
|
}
|
|
|
|
ReactionsEffectOverlay reactionsEffectOverlay = new ReactionsEffectOverlay(baseFragment.getParentActivity(), baseFragment, reactionsLayout, cell, x, y, reaction, currentAccount, animationType);
|
|
if (animationType == SHORT_ANIMATION) {
|
|
currentShortOverlay = reactionsEffectOverlay;
|
|
} else {
|
|
currentOverlay = reactionsEffectOverlay;
|
|
}
|
|
|
|
boolean useWindow = false;
|
|
if (baseFragment instanceof ChatActivity) {
|
|
ChatActivity chatActivity = (ChatActivity) baseFragment;
|
|
if (chatActivity.scrimPopupWindow != null && chatActivity.scrimPopupWindow.isShowing()) {
|
|
useWindow = true;
|
|
}
|
|
}
|
|
|
|
reactionsEffectOverlay.useWindow = useWindow;
|
|
if (useWindow) {
|
|
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
|
lp.width = lp.height = WindowManager.LayoutParams.MATCH_PARENT;
|
|
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
|
|
lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
|
lp.format = PixelFormat.TRANSLUCENT;
|
|
|
|
reactionsEffectOverlay.windowManager = baseFragment.getParentActivity().getWindowManager();
|
|
reactionsEffectOverlay.windowManager.addView(reactionsEffectOverlay.windowView, lp);
|
|
} else {
|
|
reactionsEffectOverlay.decorView = (FrameLayout) baseFragment.getParentActivity().getWindow().getDecorView();
|
|
reactionsEffectOverlay.decorView.addView(reactionsEffectOverlay.windowView);
|
|
}
|
|
cell.invalidate();
|
|
if (cell.getCurrentMessagesGroup() != null && cell.getParent() != null) {
|
|
((View) cell.getParent()).invalidate();
|
|
}
|
|
|
|
}
|
|
|
|
public static void startAnimation() {
|
|
if (currentOverlay != null) {
|
|
currentOverlay.started = true;
|
|
if (currentOverlay.animationType == LONG_ANIMATION && System.currentTimeMillis() - lastHapticTime > 200) {
|
|
lastHapticTime = System.currentTimeMillis();
|
|
currentOverlay.cell.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
|
}
|
|
} else {
|
|
startShortAnimation();
|
|
if (currentShortOverlay != null) {
|
|
currentShortOverlay.cell.reactionsLayoutInBubble.animateReaction(currentShortOverlay.reaction);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void startShortAnimation() {
|
|
if (currentShortOverlay != null && !currentShortOverlay.started) {
|
|
currentShortOverlay.started = true;
|
|
if (currentShortOverlay.animationType == SHORT_ANIMATION && System.currentTimeMillis() - lastHapticTime > 200) {
|
|
lastHapticTime = System.currentTimeMillis();
|
|
currentShortOverlay.cell.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void removeCurrent(boolean instant) {
|
|
for (int i = 0; i < 2; i++) {
|
|
ReactionsEffectOverlay overlay = i == 0 ? currentOverlay : currentShortOverlay;
|
|
if (overlay != null) {
|
|
if (instant) {
|
|
overlay.removeCurrentView();
|
|
} else {
|
|
overlay.dismissed = true;
|
|
}
|
|
}
|
|
}
|
|
currentShortOverlay = null;
|
|
currentOverlay = null;
|
|
}
|
|
|
|
public static boolean isPlaying(int messageId, long groupId, String reaction) {
|
|
if (currentOverlay != null && (currentOverlay.animationType == ONLY_MOVE_ANIMATION || currentOverlay.animationType == LONG_ANIMATION)) {
|
|
return ((currentOverlay.groupId != 0 && groupId == currentOverlay.groupId) || messageId == currentOverlay.messageId) && currentOverlay.reaction.equals(reaction);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
private class AnimationView extends BackupImageView {
|
|
|
|
public AnimationView(Context context) {
|
|
super(context);
|
|
}
|
|
|
|
boolean wasPlaying;
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
if (getImageReceiver().getLottieAnimation() != null && getImageReceiver().getLottieAnimation().isRunning()) {
|
|
wasPlaying = true;
|
|
}
|
|
if (!wasPlaying && getImageReceiver().getLottieAnimation() != null && !getImageReceiver().getLottieAnimation().isRunning()) {
|
|
if (animationType == ONLY_MOVE_ANIMATION) {
|
|
getImageReceiver().getLottieAnimation().setCurrentFrame(getImageReceiver().getLottieAnimation().getFramesCount() - 1, false);
|
|
} else {
|
|
getImageReceiver().getLottieAnimation().setCurrentFrame(0, false);
|
|
getImageReceiver().getLottieAnimation().start();
|
|
}
|
|
}
|
|
super.onDraw(canvas);
|
|
}
|
|
}
|
|
|
|
public static void onScrolled(int dy) {
|
|
if (currentOverlay != null) {
|
|
currentOverlay.lastDrawnToY -= dy;
|
|
if (dy != 0) {
|
|
currentOverlay.wasScrolled = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private class AvatarParticle {
|
|
ImageReceiver imageReceiver;
|
|
|
|
public int leftTime;
|
|
float progress;
|
|
float outProgress;
|
|
float jumpY;
|
|
float fromX;
|
|
float fromY;
|
|
float toX;
|
|
float toY;
|
|
float randomScale;
|
|
float randomRotation;
|
|
float currentRotation;
|
|
boolean incrementRotation;
|
|
float globalTranslationY;
|
|
|
|
}
|
|
}
|