mirror of https://github.com/NekoX-Dev/NekoX.git
672 lines
29 KiB
Java
672 lines
29 KiB
Java
package org.telegram.ui;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.animation.AnimatorSet;
|
|
import android.animation.ValueAnimator;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Color;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Path;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.PorterDuffXfermode;
|
|
import android.graphics.RectF;
|
|
import android.text.Layout;
|
|
import android.text.StaticLayout;
|
|
import android.text.TextPaint;
|
|
import android.view.Gravity;
|
|
import android.view.HapticFeedbackConstants;
|
|
import android.view.View;
|
|
|
|
import com.google.android.exoplayer2.util.Log;
|
|
|
|
import org.telegram.messenger.AccountInstance;
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.messenger.DialogObject;
|
|
import org.telegram.messenger.ImageLocation;
|
|
import org.telegram.messenger.ImageReceiver;
|
|
import org.telegram.messenger.LocaleController;
|
|
import org.telegram.messenger.MessagesController;
|
|
import org.telegram.messenger.NotificationCenter;
|
|
import org.telegram.messenger.R;
|
|
import org.telegram.messenger.UserConfig;
|
|
import org.telegram.tgnet.TLRPC;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
import org.telegram.ui.Components.AvatarDrawable;
|
|
import org.telegram.ui.Components.CounterView;
|
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
public class ChatPullingDownDrawable implements NotificationCenter.NotificationCenterDelegate {
|
|
|
|
public int dialogFolderId;
|
|
public int dialogFilterId;
|
|
int lastWidth;
|
|
float circleRadius;
|
|
|
|
Paint arrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
|
TextPaint textPaint2 = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
|
private Paint xRefPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
Path path = new Path();
|
|
|
|
StaticLayout chatNameLayout;
|
|
StaticLayout layout1;
|
|
StaticLayout layout2;
|
|
|
|
int chatNameWidth;
|
|
int layout1Width;
|
|
int layout2Width;
|
|
|
|
ImageReceiver imageReceiver = new ImageReceiver();
|
|
TLRPC.Chat nextChat;
|
|
|
|
AnimatorSet showReleaseAnimator;
|
|
|
|
float swipeToReleaseProgress;
|
|
float bounceProgress;
|
|
|
|
boolean animateSwipeToRelease;
|
|
boolean animateCheck;
|
|
float checkProgress;
|
|
long lastHapticTime;
|
|
float lastProgress;
|
|
boolean emptyStub;
|
|
float progressToBottomPannel;
|
|
private final View fragmentView;
|
|
|
|
boolean drawFolderBackground;
|
|
Runnable onAnimationFinishRunnable;
|
|
public long nextDialogId;
|
|
View parentView;
|
|
|
|
CounterView.CounterDrawable counterDrawable = new CounterView.CounterDrawable(null);
|
|
int params[] = new int[3];
|
|
private final int currentAccount;
|
|
private final int folderId;
|
|
private final int filterId;
|
|
private final long currentDialog;
|
|
|
|
public ChatPullingDownDrawable(int currentAccount, View fragmentView, long currentDialog, int folderId, int filterId) {
|
|
this.fragmentView = fragmentView;
|
|
this.currentAccount = currentAccount;
|
|
this.currentDialog = currentDialog;
|
|
this.folderId = folderId;
|
|
this.filterId = filterId;
|
|
|
|
arrowPaint.setStrokeWidth(AndroidUtilities.dpf2(2.8f));
|
|
arrowPaint.setStrokeCap(Paint.Cap.ROUND);
|
|
counterDrawable.gravity = Gravity.LEFT;
|
|
counterDrawable.setType(CounterView.CounterDrawable.TYPE_CHAT_PULLING_DOWN);
|
|
counterDrawable.circlePaint = Theme.chat_actionBackgroundPaint;
|
|
counterDrawable.textPaint = textPaint;
|
|
|
|
textPaint.setTextSize(AndroidUtilities.dp(13));
|
|
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
textPaint2.setTextSize(AndroidUtilities.dp(14));
|
|
|
|
xRefPaint.setColor(0xff000000);
|
|
xRefPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
|
|
|
updateDialog();
|
|
}
|
|
|
|
public void updateDialog() {
|
|
TLRPC.Dialog dialog = getNextUnreadDialog(currentDialog, folderId, filterId, true, params);
|
|
if (dialog != null) {
|
|
nextDialogId = dialog.id;
|
|
drawFolderBackground = params[0] == 1;
|
|
dialogFolderId = params[1];
|
|
dialogFilterId = params[2];
|
|
emptyStub = false;
|
|
nextChat = MessagesController.getInstance(currentAccount).getChat((int) -dialog.id);
|
|
if (nextChat == null) {
|
|
MessagesController.getInstance(currentAccount).getChat((int) dialog.id);
|
|
}
|
|
AvatarDrawable avatarDrawable = new AvatarDrawable();
|
|
avatarDrawable.setInfo(nextChat);
|
|
imageReceiver.setImage(ImageLocation.getForChat(nextChat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, UserConfig.getInstance(0).getCurrentUser(), 0);
|
|
MessagesController.getInstance(currentAccount).ensureMessagesLoaded(dialog.id, 0, null);
|
|
counterDrawable.setCount(dialog.unread_count, false);
|
|
} else {
|
|
drawFolderBackground = false;
|
|
emptyStub = true;
|
|
}
|
|
}
|
|
|
|
public void setWidth(int width) {
|
|
if (width != lastWidth) {
|
|
circleRadius = AndroidUtilities.dp(56) / 2f;
|
|
lastWidth = width;
|
|
|
|
String nameStr = nextChat != null ? nextChat.title : LocaleController.getString("SwipeToGoNextChannelEnd", R.string.SwipeToGoNextChannelEnd);
|
|
chatNameWidth = (int) textPaint.measureText(nameStr);
|
|
chatNameWidth = Math.min(chatNameWidth, lastWidth - AndroidUtilities.dp(60));
|
|
chatNameLayout = new StaticLayout(nameStr, textPaint, chatNameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
|
|
|
String str1 = null;
|
|
String str2 = null;
|
|
|
|
if (drawFolderBackground && dialogFolderId != folderId && dialogFolderId != 0) {
|
|
str1 = LocaleController.getString("SwipeToGoNextArchive", R.string.SwipeToGoNextArchive);
|
|
str2 = LocaleController.getString("ReleaseToGoNextArchive", R.string.ReleaseToGoNextArchive);
|
|
} else if (drawFolderBackground) {
|
|
str1 = LocaleController.getString("SwipeToGoNextFolder", R.string.SwipeToGoNextFolder);
|
|
str2 = LocaleController.getString("ReleaseToGoNextFolder", R.string.ReleaseToGoNextFolder);
|
|
} else {
|
|
str1 = LocaleController.getString("SwipeToGoNextChannel", R.string.SwipeToGoNextChannel);
|
|
str2 = LocaleController.getString("ReleaseToGoNextChannel", R.string.ReleaseToGoNextChannel);
|
|
}
|
|
layout1Width = (int) textPaint2.measureText(str1);
|
|
layout1Width = Math.min(layout1Width, lastWidth - AndroidUtilities.dp(60));
|
|
layout1 = new StaticLayout(str1, textPaint2, layout1Width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
|
|
|
|
|
layout2Width = (int) textPaint2.measureText(str2);
|
|
layout2Width = Math.min(layout2Width, lastWidth - AndroidUtilities.dp(60));
|
|
layout2 = new StaticLayout(str2, textPaint2, layout2Width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
|
|
|
|
|
float cx = lastWidth / 2f;
|
|
float cy = AndroidUtilities.dp(12) + circleRadius;
|
|
imageReceiver.setImageCoords(cx - AndroidUtilities.dp(40) / 2f, cy - AndroidUtilities.dp(40) / 2f, AndroidUtilities.dp(40), AndroidUtilities.dp(40));
|
|
imageReceiver.setRoundRadius((int) (AndroidUtilities.dp(40) / 2f));
|
|
|
|
counterDrawable.setSize(AndroidUtilities.dp(28), AndroidUtilities.dp(100));
|
|
}
|
|
|
|
}
|
|
|
|
public void draw(Canvas canvas, View parent, float progress, float alpha) {
|
|
this.parentView = parent;
|
|
counterDrawable.setParent(parent);
|
|
int oldAlpha, oldAlpha1, oldAlpha2, oldAlpha3;
|
|
float offset = AndroidUtilities.dp(110) * progress;
|
|
if (offset < AndroidUtilities.dp(8)) {
|
|
return;
|
|
}
|
|
|
|
if (progress < 0.2f) {
|
|
alpha *= progress * 5f;
|
|
}
|
|
Theme.applyServiceShaderMatrix(lastWidth, parent.getMeasuredHeight(), 0, parent.getMeasuredHeight() - offset);
|
|
|
|
textPaint.setColor(Theme.getColor(Theme.key_chat_serviceText));
|
|
arrowPaint.setColor(Theme.getColor(Theme.key_chat_serviceText));
|
|
textPaint2.setColor(Theme.getColor(Theme.key_chat_messagePanelHint));
|
|
|
|
oldAlpha = Theme.chat_actionBackgroundPaint.getAlpha();
|
|
oldAlpha1 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha();
|
|
oldAlpha2 = textPaint.getAlpha();
|
|
oldAlpha3 = arrowPaint.getAlpha();
|
|
Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha1 * alpha));
|
|
Theme.chat_actionBackgroundPaint.setAlpha((int) (oldAlpha * alpha));
|
|
textPaint.setAlpha((int) (oldAlpha2 * alpha));
|
|
imageReceiver.setAlpha(alpha);
|
|
|
|
if ((progress >= 1f && lastProgress < 1f) || (progress < 1f && lastProgress == 1f)) {
|
|
long time = System.currentTimeMillis();
|
|
if (time - lastHapticTime > 100) {
|
|
parent.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
|
lastHapticTime = time;
|
|
}
|
|
lastProgress = progress;
|
|
}
|
|
|
|
if (progress == 1f && !animateSwipeToRelease) {
|
|
animateSwipeToRelease = true;
|
|
animateCheck = true;
|
|
showReleaseState(true, parent);
|
|
} else if (progress != 1f && animateSwipeToRelease) {
|
|
animateSwipeToRelease = false;
|
|
showReleaseState(false, parent);
|
|
}
|
|
|
|
float cx = lastWidth / 2f;
|
|
float bounceOffset = bounceProgress * -AndroidUtilities.dp(4);
|
|
|
|
if (emptyStub) {
|
|
offset -= bounceOffset;
|
|
}
|
|
|
|
|
|
float widthRadius = Math.max(0, Math.min(circleRadius, offset / 2f - AndroidUtilities.dp(16) * progress - AndroidUtilities.dp(4)));
|
|
float widthRadius2 = Math.max(0, Math.min(circleRadius * progress, offset / 2f - AndroidUtilities.dp(8) * progress));
|
|
float size = (widthRadius2 * 2 - AndroidUtilities.dp2(16)) * (1f - swipeToReleaseProgress) + AndroidUtilities.dp(56) * swipeToReleaseProgress;
|
|
|
|
if (swipeToReleaseProgress < 1f || emptyStub) {
|
|
float bottom = -AndroidUtilities.dp(8) * (1f - swipeToReleaseProgress) + (-offset + AndroidUtilities.dp(56)) * swipeToReleaseProgress;
|
|
AndroidUtilities.rectTmp.set(cx - widthRadius, -offset, cx + widthRadius, bottom);
|
|
if (swipeToReleaseProgress > 0 && !emptyStub) {
|
|
float inset = AndroidUtilities.dp(16) * swipeToReleaseProgress;
|
|
AndroidUtilities.rectTmp.inset(inset, inset);
|
|
}
|
|
drawBackground(canvas, AndroidUtilities.rectTmp);
|
|
|
|
float arrowCy = -offset + AndroidUtilities.dp(24) + AndroidUtilities.dp(8) * (1f - progress) - AndroidUtilities.dp(36) * swipeToReleaseProgress;
|
|
canvas.save();
|
|
AndroidUtilities.rectTmp.inset(AndroidUtilities.dp(1), AndroidUtilities.dp(1));
|
|
canvas.clipRect(AndroidUtilities.rectTmp);
|
|
if (swipeToReleaseProgress > 0f) {
|
|
arrowPaint.setAlpha((int) ((1f - swipeToReleaseProgress) * 255));
|
|
}
|
|
drawArrow(canvas, cx, arrowCy, AndroidUtilities.dp(24) * progress);
|
|
|
|
if (emptyStub) {
|
|
float top = (-AndroidUtilities.dp(8) - AndroidUtilities.dp2(8) * progress - size) * (1f - swipeToReleaseProgress) + (-offset - AndroidUtilities.dp(2)) * swipeToReleaseProgress + bounceOffset;
|
|
arrowPaint.setAlpha(oldAlpha3);
|
|
drawCheck(canvas, cx, top + AndroidUtilities.dp(28));
|
|
}
|
|
canvas.restore();
|
|
}
|
|
|
|
if (chatNameLayout != null && swipeToReleaseProgress > 0) {
|
|
Theme.chat_actionBackgroundPaint.setAlpha((int) (oldAlpha * alpha));
|
|
textPaint.setAlpha((int) (oldAlpha2 * alpha));
|
|
|
|
float y = AndroidUtilities.dp(20) * (1f - swipeToReleaseProgress) - AndroidUtilities.dp(36) * swipeToReleaseProgress + bounceOffset;
|
|
AndroidUtilities.rectTmp.set((lastWidth - chatNameWidth) / 2f, y, lastWidth - (lastWidth - chatNameWidth) / 2f, y + chatNameLayout.getHeight());
|
|
AndroidUtilities.rectTmp.inset(-AndroidUtilities.dp(8), -AndroidUtilities.dp(4));
|
|
canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(15), AndroidUtilities.dp(15), Theme.chat_actionBackgroundPaint);
|
|
if (Theme.hasGradientService()) {
|
|
canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(15), AndroidUtilities.dp(15), Theme.chat_actionBackgroundGradientDarkenPaint);
|
|
}
|
|
|
|
canvas.save();
|
|
canvas.translate((lastWidth - chatNameWidth) / 2f, y);
|
|
chatNameLayout.draw(canvas);
|
|
canvas.restore();
|
|
}
|
|
|
|
if (!emptyStub && size > 0) {
|
|
float top = (-AndroidUtilities.dp(8) - AndroidUtilities.dp2(8) * progress - size) * (1f - swipeToReleaseProgress) + (-offset + AndroidUtilities.dp(4)) * swipeToReleaseProgress + bounceOffset;
|
|
imageReceiver.setRoundRadius((int) (size / 2f));
|
|
imageReceiver.setImageCoords(cx - size / 2f, top, size, size);
|
|
|
|
if (swipeToReleaseProgress > 0) {
|
|
canvas.saveLayerAlpha(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX() + imageReceiver.getImageWidth(), imageReceiver.getImageY() + imageReceiver.getImageHeight(), 255, Canvas.ALL_SAVE_FLAG);
|
|
imageReceiver.draw(canvas);
|
|
canvas.scale(swipeToReleaseProgress, swipeToReleaseProgress, cx + AndroidUtilities.dp(12) + counterDrawable.getCenterX(), top - AndroidUtilities.dp(6) + AndroidUtilities.dp(14));
|
|
canvas.translate(cx + AndroidUtilities.dp(12), top - AndroidUtilities.dp(6));
|
|
counterDrawable.updateBackgroundRect();
|
|
counterDrawable.rectF.inset(-AndroidUtilities.dp(2), -AndroidUtilities.dp(2));
|
|
canvas.drawRoundRect(counterDrawable.rectF, counterDrawable.rectF.height() / 2f, counterDrawable.rectF.height() / 2f, xRefPaint);
|
|
canvas.restore();
|
|
|
|
canvas.save();
|
|
canvas.scale(swipeToReleaseProgress, swipeToReleaseProgress, cx + AndroidUtilities.dp(12) + counterDrawable.getCenterX(), top - AndroidUtilities.dp(6) + AndroidUtilities.dp(14));
|
|
canvas.translate(cx + AndroidUtilities.dp(12), top - AndroidUtilities.dp(6));
|
|
counterDrawable.draw(canvas);
|
|
canvas.restore();
|
|
} else {
|
|
|
|
imageReceiver.draw(canvas);
|
|
}
|
|
}
|
|
|
|
Theme.chat_actionBackgroundPaint.setAlpha(oldAlpha);
|
|
Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(oldAlpha1);
|
|
textPaint.setAlpha(oldAlpha2);
|
|
arrowPaint.setAlpha(oldAlpha3);
|
|
imageReceiver.setAlpha(1f);
|
|
|
|
}
|
|
|
|
private void drawCheck(Canvas canvas, float cx, float cy) {
|
|
if (!animateCheck) {
|
|
return;
|
|
}
|
|
if (checkProgress < 1f) {
|
|
checkProgress += 16 / 220f;
|
|
if (checkProgress > 1f) {
|
|
checkProgress = 1f;
|
|
}
|
|
}
|
|
float p1 = checkProgress > 0.5f ? 1f : checkProgress / 0.5f;
|
|
float p2 = checkProgress < 0.5f ? 0 : (checkProgress - 0.5f) / 0.5f;
|
|
canvas.save();
|
|
canvas.clipRect(AndroidUtilities.rectTmp);
|
|
canvas.translate(cx - AndroidUtilities.dp(24), cy - AndroidUtilities.dp(24));
|
|
float x1 = AndroidUtilities.dp(16);
|
|
float y1 = AndroidUtilities.dp(26);
|
|
float x2 = AndroidUtilities.dp(22);
|
|
float y2 = AndroidUtilities.dp(32);
|
|
float x3 = AndroidUtilities.dp(32);
|
|
float y3 = AndroidUtilities.dp(20);
|
|
canvas.drawLine(x1, y1, x1 * (1f - p1) + x2 * p1, y1 * (1f - p1) + y2 * p1, arrowPaint);
|
|
if (p2 > 0) {
|
|
canvas.drawLine(x2, y2, x2 * (1f - p2) + x3 * p2, y2 * (1f - p2) + y3 * p2, arrowPaint);
|
|
}
|
|
canvas.restore();
|
|
}
|
|
|
|
private void drawBackground(Canvas canvas, RectF rectTmp) {
|
|
if (drawFolderBackground) {
|
|
path.reset();
|
|
float roundRadius = rectTmp.width() * 0.2f;
|
|
float folderOffset = rectTmp.width() * 0.1f;
|
|
float folderOffset2 = rectTmp.width() * 0.03f;
|
|
float roundRadius2 = folderOffset / 2f;
|
|
|
|
float h = rectTmp.height() - folderOffset;
|
|
|
|
path.moveTo(rectTmp.right, rectTmp.top + roundRadius + folderOffset);
|
|
path.rQuadTo(0, -roundRadius, -roundRadius, -roundRadius);
|
|
path.rLineTo(-(rectTmp.width() - (2 * roundRadius)) / 2 + roundRadius2 * 2 - folderOffset2, 0);
|
|
path.rQuadTo(-roundRadius2 / 2, 0, -roundRadius2 * 2, -folderOffset / 2);
|
|
path.rQuadTo(-roundRadius2 / 2, -folderOffset / 2, -roundRadius2 * 2, -folderOffset / 2);
|
|
path.rLineTo(-(rectTmp.width() - (2 * roundRadius)) / 2 + roundRadius2 * 2 + folderOffset2, 0);
|
|
path.rQuadTo(-roundRadius, 0, -roundRadius, roundRadius);
|
|
path.rLineTo(0, (h + folderOffset - (2 * roundRadius)));
|
|
path.rQuadTo(0, roundRadius, roundRadius, roundRadius);
|
|
path.rLineTo((rectTmp.width() - (2 * roundRadius)), 0);
|
|
path.rQuadTo(roundRadius, 0, roundRadius, -roundRadius);
|
|
path.rLineTo(0, -(h - (2 * roundRadius)));
|
|
path.close();
|
|
canvas.drawPath(path, Theme.chat_actionBackgroundPaint);
|
|
if (Theme.hasGradientService()) {
|
|
canvas.drawPath(path, Theme.chat_actionBackgroundGradientDarkenPaint);
|
|
}
|
|
} else {
|
|
canvas.drawRoundRect(AndroidUtilities.rectTmp, circleRadius, circleRadius, Theme.chat_actionBackgroundPaint);
|
|
if (Theme.hasGradientService()) {
|
|
canvas.drawRoundRect(AndroidUtilities.rectTmp, circleRadius, circleRadius, Theme.chat_actionBackgroundGradientDarkenPaint);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void showReleaseState(boolean show, View parent) {
|
|
if (showReleaseAnimator != null) {
|
|
showReleaseAnimator.removeAllListeners();
|
|
showReleaseAnimator.cancel();
|
|
}
|
|
if (show) {
|
|
ValueAnimator out = ValueAnimator.ofFloat(swipeToReleaseProgress, 1f);
|
|
out.addUpdateListener(animation -> {
|
|
swipeToReleaseProgress = (float) animation.getAnimatedValue();
|
|
parent.invalidate();
|
|
fragmentView.invalidate();
|
|
});
|
|
|
|
out.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
|
|
out.setDuration(250);
|
|
|
|
bounceProgress = 0;
|
|
|
|
ValueAnimator bounceUp = ValueAnimator.ofFloat(0f, 1f);
|
|
bounceUp.addUpdateListener(animation -> {
|
|
bounceProgress = (float) animation.getAnimatedValue();
|
|
parent.invalidate();
|
|
});
|
|
|
|
bounceUp.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
|
|
bounceUp.setDuration(180);
|
|
|
|
ValueAnimator bounceDown = ValueAnimator.ofFloat(1f, -0.5f);
|
|
bounceDown.addUpdateListener(animation -> {
|
|
bounceProgress = (float) animation.getAnimatedValue();
|
|
parent.invalidate();
|
|
});
|
|
|
|
bounceDown.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
|
|
bounceDown.setDuration(120);
|
|
|
|
ValueAnimator bounceOut = ValueAnimator.ofFloat(-0.5f, 0f);
|
|
bounceOut.addUpdateListener(animation -> {
|
|
bounceProgress = (float) animation.getAnimatedValue();
|
|
parent.invalidate();
|
|
});
|
|
|
|
bounceOut.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
|
|
bounceOut.setDuration(100);
|
|
|
|
showReleaseAnimator = new AnimatorSet();
|
|
showReleaseAnimator.addListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
bounceProgress = 0f;
|
|
swipeToReleaseProgress = 1f;
|
|
parent.invalidate();
|
|
fragmentView.invalidate();
|
|
if (onAnimationFinishRunnable != null) {
|
|
onAnimationFinishRunnable.run();
|
|
onAnimationFinishRunnable = null;
|
|
}
|
|
}
|
|
});
|
|
|
|
AnimatorSet bounce = new AnimatorSet();
|
|
bounce.playSequentially(bounceUp, bounceDown, bounceOut);
|
|
|
|
showReleaseAnimator.playTogether(out, bounce);
|
|
showReleaseAnimator.start();
|
|
} else {
|
|
ValueAnimator out = ValueAnimator.ofFloat(swipeToReleaseProgress, 0f);
|
|
out.addUpdateListener(animation -> {
|
|
swipeToReleaseProgress = (float) animation.getAnimatedValue();
|
|
fragmentView.invalidate();
|
|
parent.invalidate();
|
|
});
|
|
|
|
out.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
|
out.setDuration(220);
|
|
showReleaseAnimator = new AnimatorSet();
|
|
showReleaseAnimator.playTogether(out);
|
|
showReleaseAnimator.start();
|
|
}
|
|
}
|
|
|
|
private void drawArrow(Canvas canvas, float cx, float cy, float size) {
|
|
canvas.save();
|
|
float s = size / AndroidUtilities.dpf2(24);
|
|
canvas.scale(s, s, cx, cy - AndroidUtilities.dp(20));
|
|
canvas.translate(cx - AndroidUtilities.dp2(12), cy - AndroidUtilities.dp(12));
|
|
canvas.drawLine(AndroidUtilities.dpf2(12.5f), AndroidUtilities.dpf2(4f), AndroidUtilities.dpf2(12.5f), AndroidUtilities.dpf2(22), arrowPaint);
|
|
canvas.drawLine(AndroidUtilities.dpf2(3.5f), AndroidUtilities.dpf2(12), AndroidUtilities.dpf2(12.5f), AndroidUtilities.dpf2(3.5f), arrowPaint);
|
|
canvas.drawLine(AndroidUtilities.dpf2(25 - 3.5f), AndroidUtilities.dpf2(12), AndroidUtilities.dpf2(12.5f), AndroidUtilities.dpf2(3.5f), arrowPaint);
|
|
canvas.restore();
|
|
}
|
|
|
|
public void onAttach() {
|
|
imageReceiver.onAttachedToWindow();
|
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces);
|
|
}
|
|
|
|
public void onDetach() {
|
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateInterfaces);
|
|
imageReceiver.onDetachedFromWindow();
|
|
lastProgress = 0;
|
|
lastHapticTime = 0;
|
|
}
|
|
|
|
@Override
|
|
public void didReceivedNotification(int id, int account, Object... args) {
|
|
if (nextDialogId !=0 ) {
|
|
TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(nextDialogId);
|
|
if (dialog != null) {
|
|
counterDrawable.setCount(dialog.unread_count, true);
|
|
if (parentView != null) {
|
|
parentView.invalidate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static TLRPC.Dialog getNextUnreadDialog(long currentDialogId, int folderId, int filterId) {
|
|
return getNextUnreadDialog(currentDialogId, folderId, filterId, true, null);
|
|
}
|
|
|
|
public static TLRPC.Dialog getNextUnreadDialog(long currentDialogId, int folderId, int filterId, boolean searchNext, int[] params) {
|
|
MessagesController messagesController = AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController();
|
|
if (params != null) {
|
|
params[0] = 0;
|
|
params[1] = folderId;
|
|
params[2] = filterId;
|
|
}
|
|
ArrayList<TLRPC.Dialog> dialogs = null;
|
|
if (filterId != 0) {
|
|
dialogs = messagesController.dialogFiltersById.get(filterId).dialogs;
|
|
} else {
|
|
dialogs = messagesController.getDialogs(folderId);
|
|
}
|
|
if (dialogs == null) {
|
|
return null;
|
|
}
|
|
for (int i = 0; i < dialogs.size(); i++) {
|
|
TLRPC.Dialog dialog = dialogs.get(i);
|
|
int lower_id = (int) dialog.id;
|
|
TLRPC.Chat chat = messagesController.getChat(-lower_id);
|
|
if (chat != null && dialog.id != currentDialogId && dialog.unread_count > 0 && DialogObject.isChannel(dialog) && !chat.megagroup && !messagesController.isPromoDialog(dialog.id, false)) {
|
|
return dialog;
|
|
}
|
|
}
|
|
|
|
if (searchNext) {
|
|
if (filterId != 0) {
|
|
for (int i = 0; i < messagesController.dialogFilters.size(); i++) {
|
|
int newFilterId = messagesController.dialogFilters.get(i).id;
|
|
if (filterId != newFilterId) {
|
|
TLRPC.Dialog dialog = getNextUnreadDialog(currentDialogId, folderId, newFilterId, false, params);
|
|
if (dialog != null) {
|
|
if (params != null) {
|
|
params[0] = 1;
|
|
}
|
|
return dialog;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < messagesController.dialogsByFolder.size(); i++) {
|
|
int newFolderId = messagesController.dialogsByFolder.keyAt(i);
|
|
if (folderId != newFolderId) {
|
|
TLRPC.Dialog dialog = getNextUnreadDialog(currentDialogId, newFolderId, 0, false, params);
|
|
if (dialog != null) {
|
|
if (params != null) {
|
|
params[0] = 1;
|
|
}
|
|
return dialog;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public int getChatId() {
|
|
return nextChat.id;
|
|
}
|
|
|
|
public void drawBottomPanel(Canvas canvas, int top, int bottom, int width) {
|
|
if (showBottomPanel && progressToBottomPannel != 1f) {
|
|
progressToBottomPannel += 16f / 150f;
|
|
if (progressToBottomPannel > 1f) {
|
|
progressToBottomPannel = 1f;
|
|
} else {
|
|
fragmentView.invalidate();
|
|
}
|
|
} else if (!showBottomPanel && progressToBottomPannel != 0) {
|
|
progressToBottomPannel -= 16f / 150f;
|
|
if (progressToBottomPannel < 0) {
|
|
progressToBottomPannel = 0;
|
|
} else {
|
|
fragmentView.invalidate();
|
|
}
|
|
}
|
|
int oldAlpha = Theme.chat_composeBackgroundPaint.getAlpha();
|
|
int oldAlphaText = textPaint2.getAlpha();
|
|
|
|
Theme.chat_composeBackgroundPaint.setAlpha((int) (oldAlpha * progressToBottomPannel));
|
|
canvas.drawRect(0, top, width, bottom, Theme.chat_composeBackgroundPaint);
|
|
|
|
|
|
if (layout1 != null && swipeToReleaseProgress < 1f) {
|
|
textPaint2.setAlpha((int) (oldAlphaText * (1f - swipeToReleaseProgress) * progressToBottomPannel));
|
|
float y = top + AndroidUtilities.dp(18) - AndroidUtilities.dp(10) * swipeToReleaseProgress;
|
|
canvas.save();
|
|
canvas.translate((lastWidth - layout1Width) / 2f, y);
|
|
layout1.draw(canvas);
|
|
canvas.restore();
|
|
}
|
|
|
|
if (layout2 != null && swipeToReleaseProgress > 0) {
|
|
textPaint2.setAlpha((int) (oldAlphaText * swipeToReleaseProgress * progressToBottomPannel));
|
|
float y = top + AndroidUtilities.dp(18) + AndroidUtilities.dp(10) * (1f - swipeToReleaseProgress);
|
|
canvas.save();
|
|
canvas.translate((lastWidth - layout2Width) / 2f, y);
|
|
layout2.draw(canvas);
|
|
canvas.restore();
|
|
}
|
|
|
|
textPaint2.setAlpha(oldAlpha);
|
|
Theme.chat_composeBackgroundPaint.setAlpha(oldAlpha);
|
|
}
|
|
|
|
boolean showBottomPanel;
|
|
|
|
public void showBottomPanel(boolean b) {
|
|
showBottomPanel = b;
|
|
fragmentView.invalidate();
|
|
}
|
|
|
|
public boolean needDrawBottomPanel() {
|
|
return (showBottomPanel || progressToBottomPannel > 0) && !emptyStub;
|
|
}
|
|
|
|
public boolean animationIsRunning() {
|
|
return swipeToReleaseProgress != 1f;
|
|
}
|
|
|
|
public void runOnAnimationFinish(Runnable runnable) {
|
|
if (showReleaseAnimator != null) {
|
|
showReleaseAnimator.removeAllListeners();
|
|
showReleaseAnimator.cancel();
|
|
}
|
|
onAnimationFinishRunnable = runnable;
|
|
showReleaseAnimator = new AnimatorSet();
|
|
|
|
ValueAnimator out = ValueAnimator.ofFloat(swipeToReleaseProgress, 1f);
|
|
out.addUpdateListener(animation -> {
|
|
swipeToReleaseProgress = (float) animation.getAnimatedValue();
|
|
fragmentView.invalidate();
|
|
if (parentView != null) {
|
|
parentView.invalidate();
|
|
}
|
|
});
|
|
ValueAnimator bounceOut = ValueAnimator.ofFloat(bounceProgress, 0f);
|
|
bounceOut.addUpdateListener(animation -> {
|
|
bounceProgress = (float) animation.getAnimatedValue();
|
|
if (parentView != null) {
|
|
parentView.invalidate();
|
|
}
|
|
});
|
|
showReleaseAnimator.addListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
bounceProgress = 0f;
|
|
swipeToReleaseProgress = 1f;
|
|
if (parentView != null) {
|
|
parentView.invalidate();
|
|
}
|
|
fragmentView.invalidate();
|
|
if (onAnimationFinishRunnable != null) {
|
|
onAnimationFinishRunnable.run();
|
|
onAnimationFinishRunnable = null;
|
|
}
|
|
}
|
|
});
|
|
showReleaseAnimator.playTogether(out, bounceOut);
|
|
showReleaseAnimator.setDuration(120);
|
|
showReleaseAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
|
showReleaseAnimator.start();
|
|
}
|
|
|
|
public void reset() {
|
|
checkProgress = 0;
|
|
animateCheck = false;
|
|
}
|
|
}
|