NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java

403 lines
18 KiB
Java

package org.telegram.ui.Components.Reactions;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.MediaDataController;
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.BackupImageView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.ReactionsContainerLayout;
public class ReactionsEffectOverlay {
public static ReactionsEffectOverlay currentOverlay;
private final AnimationView effectImageView;
private final AnimationView emojiImageView;
private final AnimationView emojiStaticImageView;
private final FrameLayout container;
boolean animateIn;
float animateInProgress;
float animateOutProgress;
FrameLayout windowView;
BackupImageView backupImageView;
private static int unicPrefix;
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 ReactionsEffectOverlay(Context context, BaseFragment fragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount) {
this.messageId = cell.getMessageObject().getId();
this.groupId = cell.getMessageObject().getGroupId();
this.reaction = reaction;
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;
}
}
}
boolean fromHolder = holderView != null || (x != 0 && y != 0);
if (holderView != null) {
reactionsLayout.getLocationOnScreen(loc);
fromX = loc[0] + holderView.getX() + holderView.backupImageView.getX() + AndroidUtilities.dp(16);
fromY = loc[1] + holderView.getY() + holderView.backupImageView.getY() + AndroidUtilities.dp(16);
fromHeight = holderView.backupImageView.getWidth();
} 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 = 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(() -> {
try {
windowManager.removeView(windowView);
} catch (Exception e) {
}
});
}
}
if (dismissProgress != 1f) {
setAlpha(1f - dismissProgress);
super.dispatchDraw(canvas);
}
invalidate();
return;
}
if (!started) {
invalidate();
return;
} else {
if (holderView != null) {
holderView.backupImageView.setAlpha(0);
}
}
ChatMessageCell drawingCell;
if (fragment instanceof ChatActivity) {
drawingCell = ((ChatActivity) fragment).findMessageCell(messageId);
} else {
drawingCell = cell;
}
float toX, toY;
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;
}
lastDrawnToX = toX;
lastDrawnToY = toY;
} else {
toX = lastDrawnToX;
toY = lastDrawnToY;
}
float previewX = toX - emojiSize / 2f;
float previewY = toY - emojiSize / 2f;
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;
}
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 (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;
if (cell.getMessageObject().shouldDrawReactionsInLayout()) {
toScale = AndroidUtilities.dp(20) / (float) emojiSize;
} else {
toScale = AndroidUtilities.dp(14) / (float) emojiSize;
}
float x = fromX * (1f - animateInProgressX) + previewX * animateInProgressX;
float y = fromY * (1f - animateInProgressY) + previewY * animateInProgressY;
effectImageView.setTranslationX(x);
effectImageView.setTranslationY(y);
effectImageView.setAlpha((1f - animateOutProgress));
effectImageView.setScaleX(scale);
effectImageView.setScaleY(scale);
if (animateOutProgress != 0) {
scale = scale * (1f - animateOutProgress) + toScale * animateOutProgress;
x = x * (1f - animateOutProgress) + toX * animateOutProgress;
y = y * (1f - animateOutProgress) + toY * animateOutProgress;
}
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 (emojiImageView.wasPlaying && animateInProgress != 1f) {
if (fromHolder) {
animateInProgress += 16f / 350f;
} else {
animateInProgress += 16f / 220f;
}
if (animateInProgress > 1f) {
animateInProgress = 1f;
}
}
if (wasScrolled || (emojiImageView.wasPlaying && emojiImageView.getImageReceiver().getLottieAnimation() != null && !emojiImageView.getImageReceiver().getLottieAnimation().isRunning())) {
if (ReactionsEffectOverlay.this.animateOutProgress != 1f) {
ReactionsEffectOverlay.this.animateOutProgress += 16f / 220f;
if (ReactionsEffectOverlay.this.animateOutProgress > 1f) {
ReactionsEffectOverlay.this.animateOutProgress = 1f;
currentOverlay = null;
cell.invalidate();
if (cell.getCurrentMessagesGroup() != null && cell.getParent() != null) {
((View) cell.getParent()).invalidate();
}
AndroidUtilities.runOnUIThread(() -> {
try {
windowManager.removeView(windowView);
} catch (Exception e) {
}
});
}
}
}
invalidate();
}
};
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) {
TLRPC.Document document = availableReaction.effect_animation;
effectImageView.getImageReceiver().setUniqKeyPrefix((unicPrefix++) + "_" + 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();
}
document = availableReaction.activate_animation;
emojiImageView.getImageReceiver().setUniqKeyPrefix((unicPrefix++) + "_" + 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) {
emojiImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false);
emojiImageView.getImageReceiver().getLottieAnimation().start();
}
int topOffset = (size - emojiSize) >> 1;
int 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;
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;
container.setPivotX(leftOffset);
container.setPivotY(topOffset);
}
}
public static void show(BaseFragment baseFragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount) {
if (cell == null) {
return;
}
boolean animationEnabled = MessagesController.getGlobalMainSettings().getBoolean("view_animations", true);
if (!animationEnabled) {
return;
}
ReactionsEffectOverlay reactionsEffectOverlay = new ReactionsEffectOverlay(baseFragment.getParentActivity(), baseFragment, reactionsLayout, cell, x, y, reaction, currentAccount);
currentOverlay = reactionsEffectOverlay;
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);
cell.invalidate();
if (cell.getCurrentMessagesGroup() != null && cell.getParent() != null) {
((View) cell.getParent()).invalidate();
}
}
public static void startAnimation() {
if (currentOverlay != null) {
currentOverlay.started = true;
}
}
public static void removeCurrent(boolean instant) {
if (currentOverlay != null) {
if (instant) {
try {
currentOverlay.windowManager.removeView(currentOverlay.windowView);
} catch (Exception e) {
}
} else {
currentOverlay.dismissed = true;
}
}
currentOverlay = null;
}
public static boolean isPlaying(int messageId, long groupId, String reaction) {
if (currentOverlay != null) {
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()) {
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;
}
}
}
}