Update to 8.4.4

This commit is contained in:
xaxtix 2022-01-18 23:51:58 +03:00
parent ad6629f6fc
commit f0f858ad3f
31 changed files with 1304 additions and 259 deletions

View file

@ -300,7 +300,7 @@ android {
}
}
defaultConfig.versionCode = 2531
defaultConfig.versionCode = 2538
applicationVariants.all { variant ->
variant.outputs.all { output ->
@ -319,7 +319,7 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionName "8.4.3"
versionName "8.4.4"
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']

View file

@ -102,7 +102,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f);
valueAnimator.addUpdateListener(animation -> {
if (activity != null) {
activity.onListItemAniamtorTick();
activity.onListItemAnimatorTick();
} else {
recyclerListView.invalidate();
}

View file

@ -39,7 +39,6 @@ import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
@ -96,7 +95,6 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.android.internal.telephony.ITelephony;
import com.google.android.exoplayer2.util.Log;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.auth.api.phone.SmsRetrieverClient;
import com.google.android.gms.tasks.Task;
@ -190,6 +188,7 @@ public class AndroidUtilities {
private static RectF bitmapRect;
public static final RectF rectTmp = new RectF();
public static final Rect rectTmp2 = new Rect();
public static Pattern WEB_URL = null;
public static Pattern BAD_CHARS_PATTERN = null;

View file

@ -20,8 +20,8 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
public static int BUILD_VERSION = 2531;
public static String BUILD_VERSION_STRING = "8.4.3";
public static int BUILD_VERSION = 2538;
public static String BUILD_VERSION_STRING = "8.4.4";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -534,6 +534,8 @@ public class ImageLoader {
} else if (e instanceof FileNotFoundException) {
canRetry = false;
sentLogs = false;
} else if (e instanceof InterruptedException) {
sentLogs = false;
}
FileLog.e(e, sentLogs);
}
@ -909,7 +911,7 @@ public class ImageLoader {
compressed = true;
}
} catch (Exception e) {
FileLog.e(e);
FileLog.e(e, false);
} finally {
if (randomAccessFile != null) {
try {

View file

@ -309,7 +309,7 @@ public class MediaDataController extends BaseController {
date = c.intValue(2);
}
} catch (Exception e) {
FileLog.e(e);
FileLog.e(e, false);
} finally {
if (c != null) {
c.dispose();
@ -360,6 +360,14 @@ public class MediaDataController extends BaseController {
imageReceiver.setImage(ImageLocation.getForDocument(reaction.appear_animation), "60_60_nolimit", null, null, 0, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
imageReceiver = new ImageReceiver();
imageReceiver.setImage(ImageLocation.getForDocument(reaction.around_animation), null, null, null, 0, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
imageReceiver = new ImageReceiver();
imageReceiver.setImage(ImageLocation.getForDocument(reaction.center_icon), null, null, null, 0, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
imageReceiver = new ImageReceiver();
imageReceiver.setImage(ImageLocation.getForDocument(reaction.static_icon), null, null, null, 0, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);

View file

@ -14899,6 +14899,12 @@ public class MessagesController extends BaseController implements NotificationCe
processUpdates((TLRPC.Updates) response, false);
TLRPC.ChatFull full = getChatFull(chatId);
if (full != null) {
if (full instanceof TLRPC.TL_chatFull) {
full.flags |= 262144;
}
if (full instanceof TLRPC.TL_channelFull) {
full.flags |= 1073741824;
}
full.available_reactions = new ArrayList<>(reactions);
getMessagesStorage().updateChatInfo(full, false);
}

View file

@ -77,7 +77,6 @@ public class SharedConfig {
public static boolean searchMessagesAsListUsed;
public static boolean stickersReorderingHintUsed;
public static boolean disableVoiceAudioEffects;
public static boolean drawSnowInChat;
private static int lastLocalId = -210000;
public static String storageCacheDir;
@ -107,6 +106,7 @@ public class SharedConfig {
public static boolean saveStreamMedia = true;
public static boolean smoothKeyboard = true;
public static boolean pauseMusicOnRecord = true;
public static boolean chatBlur = false;
public static boolean noiseSupression;
public static boolean noStatusBar;
public static boolean sortContactsByName;
@ -349,6 +349,7 @@ public class SharedConfig {
saveStreamMedia = preferences.getBoolean("saveStreamMedia", true);
smoothKeyboard = preferences.getBoolean("smoothKeyboard2", true);
pauseMusicOnRecord = preferences.getBoolean("pauseMusicOnRecord", false);
chatBlur = preferences.getBoolean("chatBlur", false);
streamAllVideo = preferences.getBoolean("streamAllVideo", BuildVars.DEBUG_VERSION);
streamMkv = preferences.getBoolean("streamMkv", false);
suggestStickers = preferences.getInt("suggestStickers", 0);
@ -381,7 +382,6 @@ public class SharedConfig {
mediaColumnsCount = preferences.getInt("mediaColumnsCount", 3);
fastScrollHintCount = preferences.getInt("fastScrollHintCount", 3);
dontAskManageStorage = preferences.getBoolean("dontAskManageStorage", false);
drawSnowInChat = preferences.getBoolean("drawSnowInChat", BuildVars.DEBUG_VERSION);
preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true);
@ -715,14 +715,6 @@ public class SharedConfig {
editor.commit();
}
public static void toggleDrawSnowInChat() {
drawSnowInChat = !drawSnowInChat;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("drawSnowInChat", drawSnowInChat);
editor.commit();
}
public static void toggleNoiseSupression() {
noiseSupression = !noiseSupression;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
@ -941,6 +933,14 @@ public class SharedConfig {
editor.commit();
}
public static void toggleDebugChatBlur() {
chatBlur = !chatBlur;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("chatBlur", chatBlur);
editor.commit();
}
public static void toggleInappCamera() {
inappCamera = !inappCamera;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
@ -1194,4 +1194,11 @@ public class SharedConfig {
dontAskManageStorage = b;
ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().putBoolean("dontAskManageStorage", dontAskManageStorage).apply();
}
public static boolean canBlurChat() {
return BuildVars.DEBUG_VERSION && getDevicePerformanceClass() == PERFORMANCE_CLASS_HIGH;
}
public static boolean chatBlurEnabled() {
return canBlurChat() && chatBlur;
}
}

View file

@ -64,7 +64,7 @@ public class TLRPC {
public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800;
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
public static final int LAYER = 136;
public static final int LAYER = 137;
public static class TL_stats_megagroupStats extends TLObject {
public static int constructor = 0xef7ff916;
@ -36623,7 +36623,7 @@ public class TLRPC {
}
public static class TL_availableReaction extends TLObject {
public static int constructor = 0x21d7c4b;
public static int constructor = 0xc077ec01;
public int flags;
public boolean inactive;
@ -36634,6 +36634,8 @@ public class TLRPC {
public Document select_animation;
public Document activate_animation;
public Document effect_animation;
public Document around_animation;
public Document center_icon;
public int positionInList; //custom
public static TL_availableReaction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -36659,6 +36661,12 @@ public class TLRPC {
select_animation = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
activate_animation = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
effect_animation = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 2) != 0) {
around_animation = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 2) != 0) {
center_icon = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
@ -36672,6 +36680,12 @@ public class TLRPC {
select_animation.serializeToStream(stream);
activate_animation.serializeToStream(stream);
effect_animation.serializeToStream(stream);
if ((flags & 2) != 0) {
around_animation.serializeToStream(stream);
}
if ((flags & 2) != 0) {
center_icon.serializeToStream(stream);
}
}
}
@ -39861,6 +39875,52 @@ public class TLRPC {
}
}
public static abstract class messages_TranslatedText extends TLObject {
public static messages_TranslatedText TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
messages_TranslatedText result = null;
switch (constructor) {
case 0x67ca4737:
result = new TL_messages_translateNoResult();
break;
case 0xa214f7d0:
result = new TL_messages_translateResultText();
break;
}
if (result == null && exception) {
throw new RuntimeException(String.format("can't parse magic %x in messages_TranslatedText", constructor));
}
if (result != null) {
result.readParams(stream, exception);
}
return result;
}
}
public static class TL_messages_translateNoResult extends messages_TranslatedText {
public static int constructor = 0x67ca4737;
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
}
}
public static class TL_messages_translateResultText extends messages_TranslatedText {
public static int constructor = 0xa214f7d0;
public String text;
public void readParams(AbstractSerializedData stream, boolean exception) {
text = stream.readString(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(text);
}
}
public static abstract class MessagesFilter extends TLObject {
public int flags;
public boolean missed;
@ -49479,6 +49539,39 @@ public class TLRPC {
}
}
public static class TL_messages_translateText extends TLObject {
public static int constructor = 0x24ce6dee;
public int flags;
public InputPeer peer;
public int msg_id;
public String text;
public String from_lang;
public String to_lang;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return messages_TranslatedText.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
if ((flags & 1) != 0) {
peer.serializeToStream(stream);
}
if ((flags & 1) != 0) {
stream.writeInt32(msg_id);
}
if ((flags & 2) != 0) {
stream.writeString(text);
}
if ((flags & 4) != 0) {
stream.writeString(from_lang);
}
stream.writeString(to_lang);
}
}
public static class TL_messages_getMessagesReactions extends TLObject {
public static int constructor = 0x8bba90e6;

View file

@ -47,6 +47,7 @@ import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EllipsizeSpanAnimator;
import org.telegram.ui.Components.FireworksEffect;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.SizeNotifierFrameLayout;
import org.telegram.ui.Components.SnowflakesEffect;
import java.util.ArrayList;
@ -1516,4 +1517,26 @@ public class ActionBar extends FrameLayout {
}
return color != null ? color : Theme.getColor(key);
}
SizeNotifierFrameLayout contentView;
boolean blurredBackground;
public void setDrawBlurBackground(SizeNotifierFrameLayout contentView) {
blurredBackground = true;
this.contentView = contentView;
contentView.blurBehindViews.add(this);
setBackground(null);
}
Paint blurScrimPaint = new Paint();
Rect rectTmp = new Rect();
@Override
protected void dispatchDraw(Canvas canvas) {
if (blurredBackground) {
rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
blurScrimPaint.setColor(actionBarColor);
contentView.drawBlur(canvas, 0, rectTmp, blurScrimPaint, true);
}
super.dispatchDraw(canvas);
}
}

View file

@ -65,8 +65,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.core.graphics.ColorUtils;
import com.google.android.exoplayer2.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import org.telegram.messenger.AndroidUtilities;
@ -3454,6 +3452,7 @@ public class Theme {
public static final String key_chat_inTextSelectionHighlight = "chat_inTextSelectionHighlight";
public static final String key_chat_recordedVoiceHighlight = "key_chat_recordedVoiceHighlight";
public static final String key_chat_TextSelectionCursor = "chat_TextSelectionCursor";
public static final String key_chat_BlurAlpha = "chat_BlurAlpha";
public static final String key_voipgroup_listSelector = "voipgroup_listSelector";
public static final String key_voipgroup_inviteMembersBackground = "voipgroup_inviteMembersBackground";
@ -4446,6 +4445,7 @@ public class Theme {
defaultColors.put(key_chat_outTextSelectionHighlight, 0x2E3F9923);
defaultColors.put(key_chat_inTextSelectionHighlight, 0x5062A9E3);
defaultColors.put(key_chat_TextSelectionCursor, 0xFF419FE8);
defaultColors.put(key_chat_BlurAlpha, 0xAF000000);
defaultColors.put(key_statisticChartSignature, 0x7f252529);
defaultColors.put(key_statisticChartSignatureAlpha, 0x7f252529);
@ -7683,7 +7683,8 @@ public class Theme {
if (gradientRotation == null) {
gradientRotation = 45;
}
final int[] gradientColors = {backColor, gradientToColor2};
int gradientToColorInt = gradientToColor2 == null ? 0 : gradientToColor2;
final int[] gradientColors = {backColor, gradientToColorInt};
wallpaperDrawable = BackgroundGradientDrawable.createDitheredGradientBitmapDrawable(gradientRotation, gradientColors, bitmap.getWidth(), bitmap.getHeight() - 120);
quality = 90;
}

View file

@ -64,6 +64,7 @@ import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.animation.Interpolator;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.graphics.ColorUtils;
@ -375,6 +376,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
default boolean isLandscape() {
return false;
}
default void invalidateBlur() { }
}
private final static int DOCUMENT_ATTACH_TYPE_NONE = 0;
@ -421,7 +424,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
public boolean pinnedTop;
public boolean pinnedBottom;
private boolean drawPinnedTop;
private boolean drawPinnedBottom;
public boolean drawPinnedBottom;
private MessageObject.GroupedMessages currentMessagesGroup;
private MessageObject.GroupedMessagePosition currentPosition;
private boolean groupPhotoInvisible;
@ -946,6 +949,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private Stack<SpoilerEffect> captionSpoilersPool = new Stack<>();
private AtomicReference<Layout> captionPatchedSpoilersLayout = new AtomicReference<>();
private Path sPath = new Path();
public boolean isBlurred;
public ChatMessageCell(Context context) {
this(context, false, null);
@ -3918,10 +3922,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
backgroundWidth = reactionsLayoutInBubble.width;
}
if ((hasLinkPreview || hasInvoicePreview) && !drawInstantView) {
reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(6);
reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(3);
}
totalHeight += reactionsLayoutInBubble.totalHeight;
}
}
@ -4868,7 +4868,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (!reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(maxWidth - AndroidUtilities.dp(24));
if (!reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(12);
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height;
if (TextUtils.isEmpty(messageObject.caption)) {
reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(12);
} else {
reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(8);
}
measureTime(messageObject);
if (reactionsLayoutInBubble.width > backgroundWidth) {
backgroundWidth = reactionsLayoutInBubble.width;
@ -5309,19 +5314,29 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
int lineCount = infoLayout.getLineCount();
measureTime(messageObject);
int timeLeft = backgroundWidth - AndroidUtilities.dp(40 + 18 + 56 + 8) - infoWidth;
if (timeLeft < timeWidth && (reactionsLayoutInBubble.isSmall || reactionsLayoutInBubble.isEmpty)) {
if (reactionsLayoutInBubble.isSmall || reactionsLayoutInBubble.isEmpty) {
if (timeLeft < timeWidth) {
photoHeight += AndroidUtilities.dp(12);
} else if (lineCount == 1) {
photoHeight += AndroidUtilities.dp(4);
}
}
}
}
if (!reactionsLayoutInBubble.isSmall && !reactionsLayoutInBubble.isEmpty) {
if (captionLayout != null && currentPosition != null && currentMessagesGroup != null && currentMessagesGroup.isDocuments) {
reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10);
}
if (!drawPhotoImage && !TextUtils.isEmpty(messageObject.caption) && docTitleLayout != null && docTitleLayout.getLineCount() > 1) {
reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10);
}
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8);
measureTime(messageObject);
if (drawPhotoImage && captionLayout == null) {
reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(8);
}
int timeLeft = backgroundWidth - reactionsLayoutInBubble.lastLineX - AndroidUtilities.dp(24);
if (timeLeft < timeWidth) {
@ -5747,7 +5762,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (messageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
availableTimeWidth = (int) (AndroidUtilities.roundMessageSize - Math.ceil(Theme.chat_audioTimePaint.measureText("00:00")) + AndroidUtilities.dp(40));
availableTimeWidth = (int) (AndroidUtilities.roundMessageSize - Math.ceil(Theme.chat_audioTimePaint.measureText("00:00")) - AndroidUtilities.dp(46));
}
measureTime(messageObject);
int timeWidthTotal = timeWidth + AndroidUtilities.dp((SharedConfig.bubbleRadius >= 10 ? 22 : 18) + (messageObject.isOutOwner() ? 20 : 0));
@ -5949,7 +5964,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (!reactionsLayoutInBubble.isSmall) {
boolean useBackgroundWidth = backgroundWidth - AndroidUtilities.dp(24) > widthForCaption;
int maxWidth = Math.max(backgroundWidth - AndroidUtilities.dp(24), widthForCaption);
int maxWidth = Math.max(backgroundWidth - AndroidUtilities.dp(36), widthForCaption);
reactionsLayoutInBubble.measure(maxWidth);
if (!reactionsLayoutInBubble.isEmpty) {
if (shouldDrawTimeOnMedia()) {
@ -6253,7 +6268,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
captionWidth = width;
captionHeight = captionLayout.getHeight();
totalHeight += captionHeight + AndroidUtilities.dp(9);
if (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) {
if ((reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0)) {
int timeWidthTotal = timeWidth + (messageObject.isOutOwner() ? AndroidUtilities.dp(20) : 0) + getExtraTimeX();
float lastLineWidth = captionLayout.getLineWidth(captionLayout.getLineCount() - 1) + captionLayout.getLineLeft(captionLayout.getLineCount() - 1);
if (width - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) {
@ -6790,6 +6805,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
parent.invalidate();
}
}
if (isBlurred && delegate != null) {
delegate.invalidateBlur();
}
}
@Override
@ -8428,7 +8446,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (hasNewLineForTime) {
reactionsLayoutInBubble.y -= AndroidUtilities.dp(16);
}
if (captionLayout != null) {
if (captionLayout != null && ((currentMessageObject.type != 2 && !(currentMessageObject.type == 9 && drawPhotoImage)) || (currentPosition != null && currentMessagesGroup != null))) {
reactionsLayoutInBubble.y -= AndroidUtilities.dp(14);
}
if (!botButtons.isEmpty() && currentMessageObject.type == 9) {
@ -10052,6 +10070,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else {
edited = false;
hasReplies = currentMessagesGroup.messages.get(0).hasReplies();
if (!currentMessagesGroup.messages.get(0).messageOwner.edit_hide) {
for (int a = 0, size = currentMessagesGroup.messages.size(); a < size; a++) {
MessageObject object = currentMessagesGroup.messages.get(a);
if ((object.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 || object.isEditing()) {
@ -10060,6 +10079,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
}
}
if (currentMessageObject.isSponsored()) {
timeString = LocaleController.getString("SponsoredMessage", R.string.SponsoredMessage);
} else if (currentMessageObject.scheduled && currentMessageObject.messageOwner.date == 0x7FFFFFFE) {
@ -11418,6 +11438,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
sideStartY -= getTranslationY();
}
}
if (!reactionsLayoutInBubble.isSmall && reactionsLayoutInBubble.drawServiceShaderBackground) {
sideStartY -= reactionsLayoutInBubble.getCurrentTotalHeight(transitionParams.animateChangeProgress);
}
if (!currentMessageObject.isOutOwner() && isRoundVideo && isAvatarVisible) {
float offsetSize = (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f;
float offsetX = isPlayingRound ? offsetSize : 0;
@ -14673,7 +14696,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
accessibilityText = sb;
}
info.setText(accessibilityText);
info.setEnabled(true);
if (Build.VERSION.SDK_INT >= 19) {

View file

@ -177,7 +177,7 @@ public class ThemePreviewMessagesCell extends LinearLayout {
requestLayout();
ReactionsEffectOverlay.removeCurrent(false);
if (added) {
ReactionsEffectOverlay.show(fragment, null, cells[1], e.getX(), e.getY(), MediaDataController.getInstance(currentAccount).getDoubleTapReaction(), currentAccount);
ReactionsEffectOverlay.show(fragment, null, cells[1], e.getX(), e.getY(), MediaDataController.getInstance(currentAccount).getDoubleTapReaction(), currentAccount, ReactionsEffectOverlay.LONG_ANIMATION);
ReactionsEffectOverlay.startAnimation();
}
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

View file

@ -61,7 +61,6 @@ import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.URLSpan;
import android.util.Log;
import android.util.Property;
import android.util.SparseArray;
import android.util.SparseIntArray;
@ -188,6 +187,7 @@ import org.telegram.ui.Components.ChatAttachAlert;
import org.telegram.ui.Components.ChatAttachAlertDocumentLayout;
import org.telegram.ui.Components.ChatAvatarContainer;
import org.telegram.ui.Components.ChatBigEmptyView;
import org.telegram.ui.Components.ChatBlurredFrameLayout;
import org.telegram.ui.Components.ChatGreetingsView;
import org.telegram.ui.Components.ChatScrimPopupContainerLayout;
import org.telegram.ui.Components.ChatThemeBottomSheet;
@ -239,6 +239,7 @@ import org.telegram.ui.Components.SizeNotifierFrameLayout;
import org.telegram.ui.Components.StickersAlert;
import org.telegram.ui.Components.TextSelectionHint;
import org.telegram.ui.Components.TextStyleSpan;
import org.telegram.ui.Components.ThemeEditorView;
import org.telegram.ui.Components.TranslateAlert;
import org.telegram.ui.Components.TrendingStickersAlert;
import org.telegram.ui.Components.TypefaceSpan;
@ -312,7 +313,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private ImageView bottomOverlayImage;
private RadialProgressView bottomOverlayProgress;
private AnimatorSet bottomOverlayAnimation;
private FrameLayout bottomOverlayChat;
private ChatBlurredFrameLayout bottomOverlayChat;
private FrameLayout bottomMessagesActionContainer;
private TextView forwardButton;
private TextView replyButton;
@ -353,7 +354,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private ExtendedGridLayoutManager mentionGridLayoutManager;
private AnimatorSet mentionListAnimation;
private ChatAttachAlert chatAttachAlert;
private FrameLayout topChatPanelView;
private ChatBlurredFrameLayout topChatPanelView;
private AnimatorSet reportSpamViewAnimator;
private TextView addToContactsButton;
private boolean addToContactsButtonArchive;
@ -382,7 +383,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private HintView forwardHintView;
private ChecksHintView checksHintView;
private View emojiButtonRed;
private FrameLayout pinnedMessageView;
private ChatBlurredFrameLayout pinnedMessageView;
private BluredView blurredView;
private PinnedLineView pinnedLineView;
private boolean setPinnedTextTranslationX;
@ -665,7 +666,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private boolean scrollToVideo;
private Path aspectPath;
private Paint aspectPaint;
private Runnable destroyTextureViewRunnable = this::destroyTextureView;
private Runnable destroyTextureViewRunnable = () -> {
destroyTextureView();
};
private Paint scrimPaint;
private View scrimView;
@ -860,6 +863,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private PinchToZoomHelper pinchToZoomHelper;
private EmojiAnimationsOverlay emojiAnimationsOverlay;
public float drawingChatLisViewYoffset;
private boolean drawListBackgroundBlur;
private boolean drawListBackgroundBlurTop;
private int blurredViewTopOffset;
private int blurredViewBottomOffset;
public void deleteHistory(int dateSelectedStart, int dateSelectedEnd, boolean forAll) {
chatAdapter.frozenMessages.clear();
@ -1404,10 +1411,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
}
if (!available) {
if (!available || !(view instanceof ChatMessageCell)) {
return false;
}
return (view instanceof ChatMessageCell) && ((ChatMessageCell)view).getMessageObject().type != 16 && !actionBar.isActionModeShowed() && !isSecretChat() && !isInScheduleMode();
ChatMessageCell cell = (ChatMessageCell) view;
return !cell.getMessageObject().isSending() && !cell.getMessageObject().isEditing() && cell.getMessageObject().type != 16 && !actionBar.isActionModeShowed() && !isSecretChat() && !isInScheduleMode();
}
@Override
@ -1434,7 +1442,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (!available) {
return;
}
selectReaction(primaryMessage, null, x, y, reaction, true);
selectReaction(primaryMessage, null, x, y, reaction, true, false);
}
};
@ -2792,6 +2800,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
Paint backgroundPaint;
int backgroundColor;
@Override
protected void drawList(Canvas blurCanvas, boolean top) {
blurCanvas.save();
blurCanvas.translate(chatListView.getX(), chatListView.getY());
drawListBackgroundBlurTop = top;
drawListBackgroundBlur = true;
chatListView.draw(blurCanvas);
drawListBackgroundBlur = false;
blurCanvas.restore();
}
@Override
protected int getScrollOffset() {
return chatListView.computeVerticalScrollOffset();
}
@Override
protected float getBottomOffset() {
return chatListView.getBottom();
}
AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) {
@Override
@ -3054,7 +3083,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
float canvasOffsetX = chatListView.getLeft() + cell.getLeft();
float canvasOffsetY = chatListView.getY() + cell.getY();
float alpha = cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f;
canvas.clipRect(chatListView.getLeft(), listTop, chatListView.getRight(), chatListView.getY() + chatListView.getMeasuredHeight());
canvas.clipRect(chatListView.getLeft(), listTop, chatListView.getRight(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset);
canvas.translate(canvasOffsetX, canvasOffsetY);
cell.setInvalidatesParent(true);
if (type == 0) {
@ -3183,7 +3212,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
canvas.save();
canvas.clipRect(0, listTop, getMeasuredWidth(), chatListView.getY() + chatListView.getHeight());
canvas.clipRect(0, listTop, getMeasuredWidth(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset);
canvas.translate(0, chatListView.getY());
scrimGroup.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, scrimGroup.transitionParams.pinnedTop, scrimGroup.transitionParams.pinnedBotton, selected, contentView.getKeyboardHeight());
canvas.restore();
@ -3197,7 +3226,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
float viewClipLeft = chatListView.getLeft();
float viewClipTop = listTop;
float viewClipRight = chatListView.getRight();
float viewClipBottom = chatListView.getY() + chatListView.getMeasuredHeight();
float viewClipBottom = chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset;
if (cell == null || !cell.getTransitionParams().animateBackgroundBoundsInner) {
viewClipLeft = Math.max(viewClipLeft, chatListView.getLeft() + child.getX());
@ -3335,8 +3364,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = allHeight = MeasureSpec.getSize(heightMeasureSpec);
long time = System.currentTimeMillis();
if (lastWidth != widthSize) {
globalIgnoreLayout = true;
lastWidth = widthMeasureSpec;
@ -3439,7 +3466,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
chatActivityEnterView.runEmojiPanelAnimation();
}
int childCount = getChildCount();
measureChildWithMargins(chatActivityEnterView, widthMeasureSpec, 0, heightMeasureSpec, 0);
@ -3452,6 +3478,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
listViewTopHeight = AndroidUtilities.dp(49);
}
blurredViewTopOffset = 0;
blurredViewBottomOffset = 0;
if (SharedConfig.chatBlurEnabled()) {
blurredViewTopOffset = actionBarHeight;
blurredViewBottomOffset = AndroidUtilities.dp(203);
}
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@ -3468,7 +3500,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
child.measure(contentWidthSpec, contentHeightSpec);
} else if (child == chatListView) {
int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
int h = heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
int h = heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) + blurredViewTopOffset + blurredViewBottomOffset;
if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) {
h += keyboardSize;
}
@ -3553,7 +3585,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else if (child == textSelectionHelper.getOverlayView(context)) {
int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
int h = heightSize;
int h = heightSize + blurredViewTopOffset;
if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) {
h += keyboardSize;
textSelectionHelper.setKeyboardSize(keyboardSize);
@ -3693,6 +3725,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (child == gifHintTextView || child == voiceHintTextView || child == mediaBanTooltip) {
childTop -= inputFieldHeight;
} else if (child == chatListView || child == floatingDateView || child == infoTopView) {
childTop -= blurredViewTopOffset;
if (!inPreviewMode) {
childTop -= (inputFieldHeight - AndroidUtilities.dp(51));
}
@ -3722,6 +3755,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) {
childTop -= keyboardSize;
}
childTop -= blurredViewTopOffset;
} else if (chatActivityEnterView != null && child == chatActivityEnterView.botCommandsMenuContainer) {
childTop -= inputFieldHeight;
} else if (child == forwardingPreviewView) {
@ -3778,6 +3812,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
};
contentView = (SizeNotifierFrameLayout) fragmentView;
contentView.needBlur = true;
if (inBubbleMode) {
contentView.setOccupyStatusBar(false);
}
@ -4288,7 +4323,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (pullingDownAnimateProgress != 0) {
transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress;
}
c.translate(0, getMeasuredHeight() - transitionOffset);
c.translate(0, getMeasuredHeight() - blurredViewBottomOffset - transitionOffset);
if (pullingDownDrawable == null) {
pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, themeDelegate);
pullingDownDrawable.onAttach();
@ -4574,13 +4609,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public boolean drawChild(Canvas canvas, View child, long drawingTime) {
int clipLeft = 0;
int clipBottom = 0;
boolean skipDraw = child == scrimView;
boolean skipDraw = !drawListBackgroundBlur && child == scrimView;
ChatMessageCell cell;
float cilpTop = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4);
if (drawListBackgroundBlur) {
if (drawListBackgroundBlurTop && child.getY() > cilpTop + AndroidUtilities.dp(40)) {
skipDraw = true;
}
if (!drawListBackgroundBlurTop && child.getY() + child.getMeasuredHeight() < AndroidUtilities.dp(203)) {
skipDraw = true;
}
} else {
if (child.getY() > getMeasuredHeight() || child.getY() + child.getMeasuredHeight() < cilpTop) {
skipDraw = true;
}
}
MessageObject.GroupedMessages group = null;
@ -5065,6 +5109,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
return super.createAccessibilityNodeInfo();
}
@Override
public void invalidate() {
super.invalidate();
contentView.invalidateBlur();
}
};
if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) {
chatListView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
@ -5621,7 +5671,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
if (currentEncryptedChat == null) {
pinnedMessageView = new FrameLayout(context) {
pinnedMessageView = new ChatBlurredFrameLayout(context, ChatActivity.this) {
float lastY;
float startY;
@ -5691,6 +5741,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
pinnedMessageEnterOffset = -AndroidUtilities.dp(50);
pinnedMessageView.setVisibility(View.GONE);
pinnedMessageView.setBackgroundResource(R.drawable.blockpanel);
pinnedMessageView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground);
pinnedMessageView.backgroundPaddingBottom = AndroidUtilities.dp(2);
pinnedMessageView.getBackground().mutate().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY));
contentView.addView(pinnedMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT));
pinnedMessageView.setOnClickListener(v -> {
@ -5851,7 +5903,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
});
}
topChatPanelView = new FrameLayout(context) {
topChatPanelView = new ChatBlurredFrameLayout(context, this) {
private boolean ignoreLayout;
@ -5897,6 +5949,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
super.requestLayout();
}
};
topChatPanelView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground);
topChatPanelView.backgroundPaddingBottom = AndroidUtilities.dp(2);
topChatPanelView.setTag(1);
topChatPanelViewOffset = -AndroidUtilities.dp(50);
invalidateChatListViewTopPadding();
@ -6799,6 +6853,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
undoView.showWithAction(0, Math.abs(value - 1.0f) > 0.001f ? UndoView.ACTION_PLAYBACK_SPEED_ENABLED : UndoView.ACTION_PLAYBACK_SPEED_DISABLED, value, null, null);
}
}
};
contentView.addView(fragmentLocationContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0));
contentView.addView(fragmentContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0));
@ -7796,7 +7852,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
bottomOverlayText.setTextColor(getThemedColor(Theme.key_chat_secretChatStatusText));
bottomOverlay.addView(bottomOverlayText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 14, 0, 14, 0));
bottomOverlayChat = new FrameLayout(context) {
bottomOverlayChat = new ChatBlurredFrameLayout(context, this) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int allWidth = MeasureSpec.getSize(widthMeasureSpec);
@ -7810,9 +7866,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight();
Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom);
Theme.chat_composeShadowDrawable.draw(canvas);
if (SharedConfig.chatBlurEnabled()) {
AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight());
contentView.drawBlur(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false);
} else {
canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground));
}
}
};
bottomOverlayChat.isTopView = false;
bottomOverlayChat.drawBlur = false;
bottomOverlayChat.setWillNotDraw(false);
bottomOverlayChat.setPadding(0, AndroidUtilities.dp(1.5f), 0, 0);
bottomOverlayChat.setVisibility(View.INVISIBLE);
@ -8166,6 +8229,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
topBottom[0] = chatListView.getTop() + chatListViewPaddingTop - AndroidUtilities.dp(4);
});
emojiAnimationsOverlay = new EmojiAnimationsOverlay(ChatActivity.this, contentView, chatListView, currentAccount, dialog_id, threadMessageId);
actionBar.setDrawBlurBackground(contentView);
return fragmentView;
}
@ -8731,6 +8795,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
float oldPadding = chatListViewPaddingTop;
chatListViewPaddingTopOnlyTopViews = topPanelViewH + pinnedViewH;
chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH;
chatListViewPaddingTop += blurredViewTopOffset;
chatListViewPaddingVisibleOffset = 0;
chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY;
@ -8781,7 +8846,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3));
chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset);
if (firstVisPos != RecyclerView.NO_POSITION && scrollToMessageObject != null) {
chatAdapter.updateRowsSafe();
@ -11569,6 +11634,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
int top = (int) view.getY();
int bottom = top + view.getMeasuredHeight();
ChatMessageCell messageCell = null;
if (view instanceof ChatMessageCell) {
messageCell = (ChatMessageCell) view;
}
if (messageCell != null) {
messageCell.isBlurred = view.getY() < clipTop || view.getY() + view.getMeasuredHeight() > AndroidUtilities.dp(203);
}
if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight()) {
continue;
}
@ -11583,8 +11656,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
keyboardOffset = chatActivityEnterView.getEmojiPadding();
}
if (view instanceof ChatMessageCell) {
ChatMessageCell messageCell = (ChatMessageCell) view;
if (messageCell != null) {
messageObject = messageCell.getMessageObject();
if (messageObject.getDialogId() == dialog_id && messageObject.getId() > maxVisibleId) {
maxVisibleId = messageObject.getId();
@ -20974,6 +21046,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
TranslateAlert.OnLinkPress onLinkPress = (link) -> {
didPressMessageUrl(link, false, selectedObject, v instanceof ChatMessageCell ? (ChatMessageCell) v : null);
};
TLRPC.InputPeer inputPeer = getMessagesController().getInputPeer(dialog_id);
int messageId = selectedObject.messageOwner.id;
if (LanguageDetector.hasSupport()) {
final String[] fromLang = { null };
cell.setVisibility(View.GONE);
@ -20993,7 +21067,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
},
(Exception e) -> {
Log.e("mlkit", "failed to detect language in message");
FileLog.e("mlkit: failed to detect language in message");
e.printStackTrace();
waitForLangDetection.set(false);
if (onLangDetectionDone.get() != null) {
@ -21006,7 +21080,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (selectedObject == null || i >= options.size() || getParentActivity() == null) {
return;
}
TranslateAlert.showAlert(getParentActivity(), this, fromLang[0], toLang, finalMessageText, currentChat != null && currentChat.noforwards, onLinkPress);
TranslateAlert.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageId, fromLang[0], toLang, finalMessageText, currentChat != null && currentChat.noforwards, onLinkPress);
scrimView = null;
scrimViewReaction = null;
contentView.invalidate();
@ -21026,7 +21100,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (selectedObject == null || i >= options.size() || getParentActivity() == null) {
return;
}
TranslateAlert.showAlert(getParentActivity(), this, "und", toLang, finalMessageText, currentChat != null && currentChat.noforwards, onLinkPress);
TranslateAlert.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageId, "und", toLang, finalMessageText, currentChat != null && currentChat.noforwards, onLinkPress);
scrimView = null;
scrimViewReaction = null;
contentView.invalidate();
@ -21087,13 +21161,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int sPad = 24;
reactionsLayout.setPadding(AndroidUtilities.dp(4) + (LocaleController.isRTL ? 0 : sPad), AndroidUtilities.dp(4), AndroidUtilities.dp(4) + (LocaleController.isRTL ? sPad : 0), AndroidUtilities.dp(pad));
reactionsLayout.setDelegate((rView, reaction) -> {
selectReaction(primaryMessage, reactionsLayout, 0, 0, reaction, false);
reactionsLayout.setDelegate((rView, reaction, longress) -> {
selectReaction(primaryMessage, reactionsLayout, 0, 0, reaction, false, longress);
});
LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 0, 0, -20);
LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 50, 0, -20);
scrimPopupContainerLayout.addView(reactionsLayout, params);
scrimPopupContainerLayout.reactionsLayout = reactionsLayout;
scrimPopupContainerLayout.setClipChildren(false);
reactionsLayout.setMessage(message, chatInfo);
reactionsLayout.setTransitionProgress(0);
@ -21333,12 +21408,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
Runnable updateReactionRunnable;
private void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, float x, float y, TLRPC.TL_availableReaction reaction, boolean fromDoubleTap) {
private void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, float x, float y, TLRPC.TL_availableReaction reaction, boolean fromDoubleTap, boolean bigEmoji) {
ReactionsEffectOverlay.removeCurrent(false);
boolean added = primaryMessage.selectReaction(reaction.reaction, fromDoubleTap);
int messageIdForCell = primaryMessage.getId();
if (groupedMessagesMap.get(primaryMessage.getGroupId()) != null) {
MessageObject messageObject = groupedMessagesMap.get(primaryMessage.getGroupId()).findMessageWithFlags(MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_LEFT);
int flags = primaryMessage.shouldDrawReactionsInLayout() ? MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_LEFT : MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_RIGHT;
MessageObject messageObject = groupedMessagesMap.get(primaryMessage.getGroupId()).findMessageWithFlags(flags);
if (messageObject != null) {
messageIdForCell = messageObject.getId();
}
@ -21348,7 +21424,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (added && !fromDoubleTap) {
ChatMessageCell cell = findMessageCell(finalMessageIdForCell);
ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount);
ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount, reactionsLayout != null ? (bigEmoji ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.ONLY_MOVE_ANIMATION) : ReactionsEffectOverlay.SHORT_ANIMATION);
}
getSendMessagesHelper().sendReaction(primaryMessage, added ? reaction.reaction : null, ChatActivity.this, updateReactionRunnable = new Runnable() {
@Override
@ -21360,7 +21436,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
AndroidUtilities.runOnUIThread(() -> {
ChatMessageCell cell = findMessageCell(finalMessageIdForCell);
if (added) {
ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount);
ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount, ReactionsEffectOverlay.SHORT_ANIMATION);
ReactionsEffectOverlay.startAnimation();
}
}, 50);
@ -21383,8 +21459,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updateReactionRunnable.run();
}
AndroidUtilities.runOnUIThread(updateReactionRunnable, 50);
}
@SuppressLint("NotifyDataSetChanged")
@ -22363,7 +22437,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updateVisibleRows();
}
public void onListItemAniamtorTick() {
public void onListItemAnimatorTick() {
invalidateMessagesVisiblePart();
if (scrimView != null) {
fragmentView.invalidate();
@ -24106,7 +24180,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
} else {
selectReaction(cell.getPrimaryMessageObject(), null, 0, 0, getMediaDataController().getReactionsMap().get(reaction.reaction), false);
selectReaction(cell.getPrimaryMessageObject(), null, 0, 0, getMediaDataController().getReactionsMap().get(reaction.reaction), false, false);
}
}
@ -24445,6 +24519,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public boolean isLandscape() {
return contentView.getMeasuredWidth() > contentView.getMeasuredHeight();
}
@Override
public void invalidateBlur() {
contentView.invalidateBlur();
}
});
if (currentEncryptedChat == null) {
chatMessageCell.setAllowAssistant(true);
@ -25551,6 +25630,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (avatarContainer != null) {
avatarContainer.updateColors();
}
if (pinnedMessageView != null) {
pinnedMessageView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground);
}
if (topChatPanelView != null) {
topChatPanelView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground);
}
};
ArrayList<ThemeDescription> themeDescriptions = new ArrayList<>();
@ -26126,6 +26211,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_outReactionButtonText));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inReactionButtonTextSelected));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inReactionButtonTextSelected));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_BlurAlpha));
if (chatActivityEnterView != null) {
themeDescriptions.add(new ThemeDescription(chatActivityEnterView.botCommandsMenuContainer.listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotCommandsMenuView.BotCommandView.class}, new String[]{"description"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
@ -26362,7 +26448,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
setupChatTheme(chatTheme, false, true);
}
}
if (!setup) {
if (!setup && ThemeEditorView.getInstance() == null) {
Theme.refreshThemeColors(true, true);
}
}

View file

@ -1,5 +1,7 @@
package org.telegram.ui.Components;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@ -51,9 +53,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static java.lang.annotation.RetentionPolicy.SOURCE;
public final class Bulletin {
public class Bulletin {
public static final int DURATION_SHORT = 1500;
public static final int DURATION_LONG = 2750;
@ -117,6 +117,12 @@ public final class Bulletin {
private Delegate currentDelegate;
private Layout.Transition layoutTransition;
private Bulletin() {
layout = null;
parentLayout = null;
containerLayout = null;
}
private Bulletin(@NonNull FrameLayout containerLayout, @NonNull Layout layout, int duration) {
this.layout = layout;
this.parentLayout = new ParentLayout(layout) {
@ -214,7 +220,7 @@ public final class Bulletin {
}
private void setCanHide(boolean canHide) {
if (this.canHide != canHide) {
if (this.canHide != canHide && layout != null) {
this.canHide = canHide;
if (canHide) {
layout.postDelayed(hideRunnable, duration);
@ -225,7 +231,7 @@ public final class Bulletin {
}
private void ensureLayoutTransitionCreated() {
if (layoutTransition == null) {
if (layout != null && layoutTransition == null) {
layoutTransition = layout.createTransition();
}
}
@ -239,6 +245,9 @@ public final class Bulletin {
}
public void hide(boolean animated, long duration) {
if (layout == null) {
return;
}
if (showing) {
showing = false;
@ -1216,4 +1225,16 @@ public final class Bulletin {
}
}
//endregion
public static class EmptyBulletin extends Bulletin {
public EmptyBulletin() {
super();
}
@Override
public Bulletin show() {
return this;
}
}
}

View file

@ -1,6 +1,7 @@
package org.telegram.ui.Components;
import android.content.Context;
import android.os.Build;
import android.widget.FrameLayout;
import androidx.annotation.CheckResult;
@ -196,6 +197,9 @@ public final class BulletinFactory {
@CheckResult
public Bulletin createCopyLinkBulletin(boolean isPrivate, Theme.ResourcesProvider resourcesProvider) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
return new Bulletin.EmptyBulletin();
}
if (isPrivate) {
final Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(getContext(), resourcesProvider);
layout.setAnimation(R.raw.voip_invite, 36, 36, "Wibe", "Circle");

View file

@ -147,7 +147,7 @@ import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicReference;
public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate {
public class ChatActivityEnterView extends ChatBlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate {
public interface ChatActivityEnterViewDelegate {
void onMessageSend(CharSequence message, boolean notify, int scheduleDate);
@ -1680,8 +1680,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
@SuppressLint("ClickableViewAccessibility")
public ChatActivityEnterView(Activity context, SizeNotifierFrameLayout parent, ChatActivity fragment, final boolean isChat, Theme.ResourcesProvider resourcesProvider) {
super(context);
super(context, fragment);
this.resourcesProvider = resourcesProvider;
this.backgroundColor = getThemedColor(Theme.key_chat_messagePanelBackground);
this.drawBlur = false;
smoothKeyboard = isChat && SharedConfig.smoothKeyboard && !AndroidUtilities.isInMultiwindow && (fragment == null || !fragment.isInBubbleMode());
dotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@ -2988,7 +2990,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
senderSelectView.setVisibility(GONE);
frameLayout.addView(senderSelectView, LayoutHelper.createFrame(32, 32, Gravity.BOTTOM | Gravity.LEFT, 10, 8, 10, 8));
recordedAudioPanel = new FrameLayout(context);
recordedAudioPanel = new FrameLayout(context) {
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
updateSendAsButton();
}
};
recordedAudioPanel.setVisibility(audioToSend == null ? GONE : VISIBLE);
recordedAudioPanel.setFocusable(true);
recordedAudioPanel.setFocusableInTouchMode(true);
@ -3648,8 +3656,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom);
Theme.chat_composeShadowDrawable.draw(canvas);
backgroundPaint.setColor(getThemedColor(Theme.key_chat_messagePanelBackground));
if (SharedConfig.chatBlurEnabled() && chatActivity != null) {
AndroidUtilities.rectTmp2.set(0, bottom, getWidth(), getHeight());
chatActivity.contentView.drawBlur(canvas, getY(), AndroidUtilities.rectTmp2, backgroundPaint, false);
} else {
canvas.drawRect(0, bottom, getWidth(), getHeight(), backgroundPaint);
}
}
@Override
public boolean hasOverlappingRendering() {
@ -4670,7 +4683,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
recordPannelAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
recordedAudioPanel.setVisibility(GONE);
recordedAudioSeekBar.setAlpha(1f);
recordedAudioSeekBar.setTranslationX(0);
recordedAudioPlayButton.setAlpha(1f);
@ -4684,6 +4696,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
messageEditText.setAlpha(1f);
messageEditText.setTranslationX(0);
messageEditText.requestFocus();
recordedAudioPanel.setVisibility(GONE);
}
});
@ -6826,7 +6839,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
}
public void updateSendAsButton() {
if (parentFragment == null) {
if (parentFragment == null || delegate == null) {
return;
}
TLRPC.ChatFull full = parentFragment.getMessagesController().getChatFull(-dialog_id);
@ -6844,7 +6857,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
}
}
boolean wasVisible = senderSelectView.getVisibility() == View.VISIBLE;
boolean isVisible = delegate.getSendAsPeers() != null && defPeer != null && delegate.getSendAsPeers().peers.size() > 1 && !isEditingMessage() && !isRecordingAudioVideo();
boolean isVisible = delegate.getSendAsPeers() != null && defPeer != null && delegate.getSendAsPeers().peers.size() > 1 && !isEditingMessage() && !isRecordingAudioVideo() && recordedAudioPanel.getVisibility() != View.VISIBLE;
int pad = AndroidUtilities.dp(2);
MarginLayoutParams params = (MarginLayoutParams) senderSelectView.getLayoutParams();
float sA = isVisible ? 0 : 1;
@ -6861,6 +6874,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
if (parentFragment.getOtherSameChatsDiff() == 0 && parentFragment.fragmentOpened) {
ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(150);
senderSelectView.setTranslationX(sX);
messageEditText.setTranslationX(senderSelectView.getTranslationX());
anim.addUpdateListener(animation -> {
float val = (float) animation.getAnimatedValue();

View file

@ -49,6 +49,14 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Keep;
import androidx.core.graphics.ColorUtils;
import androidx.exifinterface.media.ExifInterface;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
@ -86,14 +94,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import androidx.annotation.Keep;
import androidx.core.graphics.ColorUtils;
import androidx.exifinterface.media.ExifInterface;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayout implements NotificationCenter.NotificationCenterDelegate {
private RecyclerListView cameraPhotoRecyclerView;
@ -362,6 +362,11 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
}
@Override
public void onApplyCaption(CharSequence caption) {
parentAlert.commentTextView.setText(caption);
}
@Override
public boolean cancelButtonPressed() {
return false;
@ -2510,16 +2515,25 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
@Override
void applyCaption(CharSequence text) {
int imageId = (Integer) selectedPhotosOrder.get(0);
Object entry = selectedPhotos.get(imageId);
if (entry instanceof MediaController.PhotoEntry) {
MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) entry;
photoEntry.caption = text;
photoEntry.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(new CharSequence[] {text}, false);
} else if (entry instanceof MediaController.SearchImage) {
MediaController.SearchImage searchImage = (MediaController.SearchImage) entry;
searchImage.caption = text;
searchImage.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(new CharSequence[] {text}, false);
for (int a = 0; a < selectedPhotosOrder.size(); a++) {
Object o = selectedPhotos.get(selectedPhotosOrder.get(a));
if (o instanceof MediaController.PhotoEntry) {
MediaController.PhotoEntry photoEntry1 = (MediaController.PhotoEntry) o;
if (a == 0) {
photoEntry1.caption = text;
photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(new CharSequence[] {text}, false);
} else {
photoEntry1.caption = null;
}
} else if (o instanceof MediaController.SearchImage) {
MediaController.SearchImage photoEntry1 = (MediaController.SearchImage) o;
if (a == 0) {
photoEntry1.caption = text;
photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(new CharSequence[] {text}, false);
} else {
photoEntry1.caption = null;
}
}
}
}

View file

@ -0,0 +1,73 @@
package org.telegram.ui.Components;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.SharedConfig;
import org.telegram.ui.ChatActivity;
public class ChatBlurredFrameLayout extends FrameLayout {
ChatActivity chatActivity;
Paint backgroundPaint;
public int backgroundColor;
public int backgroundPaddingBottom;
public int backgroundPaddingTop;
public boolean isTopView = true;
public boolean drawBlur = true;
public ChatBlurredFrameLayout(@NonNull Context context, ChatActivity chatActivity) {
super(context);
this.chatActivity = chatActivity;
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (SharedConfig.chatBlurEnabled() && chatActivity != null && drawBlur) {
if (backgroundPaint == null) {
backgroundPaint = new Paint();
}
backgroundPaint.setColor(backgroundColor);
AndroidUtilities.rectTmp2.set(0, backgroundPaddingTop, getMeasuredWidth(), getMeasuredHeight() - backgroundPaddingBottom);
float y = 0;
View view = this;
while (view != chatActivity.contentView) {
y += view.getY();
view = (View) view.getParent();
}
chatActivity.contentView.drawBlur(canvas, y, AndroidUtilities.rectTmp2, backgroundPaint, isTopView);
}
super.dispatchDraw(canvas);
}
@Override
public void setBackgroundColor(int color) {
if (SharedConfig.chatBlurEnabled() && chatActivity != null) {
backgroundColor = color;
} else {
super.setBackgroundColor(color);
}
}
@Override
protected void onAttachedToWindow() {
if (SharedConfig.chatBlurEnabled() && chatActivity != null) {
chatActivity.contentView.blurBehindViews.add(this);
}
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
if (SharedConfig.chatBlurEnabled() && chatActivity != null) {
chatActivity.contentView.blurBehindViews.remove(this);
}
super.onDetachedFromWindow();
}
}

View file

@ -27,9 +27,6 @@ import android.graphics.Shader;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.Keep;
import android.os.SystemClock;
import android.text.Layout;
import android.text.SpannableStringBuilder;
@ -49,6 +46,8 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Keep;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
@ -89,6 +88,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private AudioPlayerAlert.ClippingTextViewSwitcher subtitleTextView;
private AnimatorSet animatorSet;
private BaseFragment fragment;
private ChatActivity chatActivity;
private View applyingView;
private FrameLayout frameLayout;
private View shadow;
@ -215,6 +215,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
this.resourcesProvider = resourcesProvider;
fragment = parentFragment;
if (fragment instanceof ChatActivity) {
chatActivity = (ChatActivity) fragment;
}
applyingView = paddingView;
visible = true;
isLocation = location;
@ -223,7 +226,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
setTag(1);
frameLayout = new FrameLayout(context) {
frameLayout = new ChatBlurredFrameLayout(context, chatActivity) {
@Override
public void invalidate() {
super.invalidate();

View file

@ -39,17 +39,15 @@ public class ReactionTabHolderView extends FrameLayout {
private BackupImageView reactView;
private ImageView iconView;
private TextView counterView;
View overlaySelectorView;
private float outlineProgress;
Drawable drawable;
public ReactionTabHolderView(@NonNull Context context) {
super(context);
View overlaySelectorView = new View(context);
overlaySelectorView.setBackground(Theme.createSimpleSelectorRoundRectDrawable((int) radius, Color.TRANSPARENT, Theme.getColor(Theme.key_chat_inReactionButtonTextSelected)));
overlaySelectorView = new View(context);
addView(overlaySelectorView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
iconView = new ImageView(context);
drawable = ContextCompat.getDrawable(context, R.drawable.msg_reactions_filled).mutate();
iconView.setImageDrawable(drawable);
@ -82,6 +80,12 @@ public class ReactionTabHolderView extends FrameLayout {
bgPaint.setColor(ColorUtils.blendARGB(backgroundColor, backgroundSelectedColor, outlineProgress));
counterView.setTextColor(textFinalColor);
drawable.setColorFilter(new PorterDuffColorFilter(textFinalColor, PorterDuff.Mode.MULTIPLY));
if (outlineProgress == 1f) {
overlaySelectorView.setBackground(Theme.createSimpleSelectorRoundRectDrawable((int) radius, Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_chat_inReactionButtonTextSelected), (int) (0.3f * 255))));
} else if (outlineProgress == 0) {
overlaySelectorView.setBackground(Theme.createSimpleSelectorRoundRectDrawable((int) radius, Color.TRANSPARENT, ColorUtils.setAlphaComponent(backgroundSelectedColor, (int) (0.3f * 255))));
}
invalidate();
}

View file

@ -1,8 +1,10 @@
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.WindowManager;
import android.widget.FrameLayout;
@ -21,19 +23,28 @@ import org.telegram.ui.Components.ReactionsContainerLayout;
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;
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 unicPrefix;
private static int uniqPrefix;
int[] loc = new int[2];
private WindowManager windowManager;
@ -47,12 +58,17 @@ public class ReactionsEffectOverlay {
private boolean started;
private ReactionsContainerLayout.ReactionHolderView holderView = null;
private boolean wasScrolled;
private ChatMessageCell cell;
private boolean finished;
private ReactionsEffectOverlay(Context context, BaseFragment fragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount) {
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;
@ -66,10 +82,10 @@ public class ReactionsEffectOverlay {
}
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();
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();
@ -84,7 +100,14 @@ public class ReactionsEffectOverlay {
fromWidth = 0;
}
int size = Math.round(Math.min(AndroidUtilities.dp(350), Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y)) * 0.8f);
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;
@ -125,6 +148,7 @@ public class ReactionsEffectOverlay {
} else {
if (holderView != null) {
holderView.backupImageView.setAlpha(0);
holderView.pressedBackupImageView.setAlpha(0);
}
}
ChatMessageCell drawingCell;
@ -133,7 +157,13 @@ public class ReactionsEffectOverlay {
} else {
drawingCell = cell;
}
float toX, toY;
float toX, toY, toH;
if (cell.getMessageObject().shouldDrawReactionsInLayout()) {
toH = AndroidUtilities.dp(20);
} else {
toH = AndroidUtilities.dp(14);
}
if (drawingCell != null) {
cell.getLocationInWindow(loc);
@ -147,31 +177,40 @@ public class ReactionsEffectOverlay {
if (chatActivity != null) {
toY += chatActivity.drawingChatLisViewYoffset;
}
if (drawingCell.drawPinnedBottom && !drawingCell.shouldDrawTimeOnMedia()) {
toY += AndroidUtilities.dp(2);
}
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;
}
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 (fromHolder) {
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 {
@ -180,31 +219,41 @@ public class ReactionsEffectOverlay {
float scale = animateInProgressX + (1f - animateInProgressX) * fromScale;
float toScale;
if (cell.getMessageObject().shouldDrawReactionsInLayout()) {
toScale = AndroidUtilities.dp(20) / (float) emojiSize;
float toScale = toH / (float) emojiSize;
float x;
float y;
if (animationType == SHORT_ANIMATION) {
x = previewX;
y = previewY;
scale = 1f;
} else {
toScale = AndroidUtilities.dp(14) / (float) emojiSize;
x = fromX * (1f - animateInProgressX) + previewX * animateInProgressX;
y = fromY * (1f - animateInProgressY) + previewY * animateInProgressY;
}
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 (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);
@ -214,7 +263,7 @@ public class ReactionsEffectOverlay {
super.dispatchDraw(canvas);
if (emojiImageView.wasPlaying && animateInProgress != 1f) {
if ((animationType == SHORT_ANIMATION || emojiImageView.wasPlaying) && animateInProgress != 1f) {
if (fromHolder) {
animateInProgress += 16f / 350f;
} else {
@ -225,12 +274,28 @@ public class ReactionsEffectOverlay {
}
}
if (wasScrolled || (emojiImageView.wasPlaying && emojiImageView.getImageReceiver().getLottieAnimation() != null && !emojiImageView.getImageReceiver().getLottieAnimation().isRunning())) {
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) {
ReactionsEffectOverlay.this.animateOutProgress += 16f / 220f;
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();
@ -254,9 +319,10 @@ public class ReactionsEffectOverlay {
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() + "_");
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);
@ -266,29 +332,46 @@ public class ReactionsEffectOverlay {
effectImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false);
effectImageView.getImageReceiver().getLottieAnimation().start();
}
}
document = availableReaction.activate_animation;
emojiImageView.getImageReceiver().setUniqKeyPrefix((unicPrefix++) + "_" + cell.getMessageObject().getId() + "_");
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 = size - emojiSize;
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;
@ -311,12 +394,14 @@ public class ReactionsEffectOverlay {
((FrameLayout.LayoutParams) effectImageView.getLayoutParams()).topMargin = -topOffset;
((FrameLayout.LayoutParams) effectImageView.getLayoutParams()).leftMargin = -leftOffset;
// if (!SHORT_ANIMATION) {
container.setPivotX(leftOffset);
container.setPivotY(topOffset);
//}
}
}
public static void show(BaseFragment baseFragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount) {
public static void show(BaseFragment baseFragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount, int animationType) {
if (cell == null) {
return;
}
@ -324,8 +409,16 @@ public class ReactionsEffectOverlay {
if (!animationEnabled) {
return;
}
ReactionsEffectOverlay reactionsEffectOverlay = new ReactionsEffectOverlay(baseFragment.getParentActivity(), baseFragment, reactionsLayout, cell, x, y, reaction, currentAccount);
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;
}
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.width = lp.height = WindowManager.LayoutParams.MATCH_PARENT;
@ -339,31 +432,50 @@ public class ReactionsEffectOverlay {
if (cell.getCurrentMessagesGroup() != null && cell.getParent() != null) {
((View) cell.getParent()).invalidate();
}
}
public static void startAnimation() {
if (currentOverlay != null) {
currentOverlay.started = true;
} 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) {
currentShortOverlay.cell.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
}
}
public static void removeCurrent(boolean instant) {
if (currentOverlay != null) {
for (int i = 0; i < 2; i++) {
ReactionsEffectOverlay overlay = i == 0 ? currentOverlay : currentShortOverlay;
if (overlay != null) {
if (instant) {
try {
currentOverlay.windowManager.removeView(currentOverlay.windowView);
overlay.windowManager.removeView(overlay.windowView);
} catch (Exception e) {
}
} else {
currentOverlay.dismissed = true;
overlay.dismissed = true;
}
}
}
currentShortOverlay = null;
currentOverlay = null;
}
public static boolean isPlaying(int messageId, long groupId, String reaction) {
if (currentOverlay != null) {
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;
@ -384,9 +496,13 @@ public class ReactionsEffectOverlay {
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);
}
}

View file

@ -51,6 +51,7 @@ public class ReactionsLayoutInBubble {
private boolean wasDrawn;
private boolean animateMove;
private boolean animateWidth;
private boolean animateHeight;
public int positionOffsetY;
int currentAccount;
public int height;
@ -72,8 +73,12 @@ public class ReactionsLayoutInBubble {
int availableWidth;
private int lastDrawnWidth;
boolean attached;
private static int animationUniq;
private final static ButtonsComparator comparator = new ButtonsComparator();
HashMap<String, ImageReceiver> animatedReactions = new HashMap<>();
private int lastDrawTotalHeight;
private int animateFromTotalHeight;
public ReactionsLayoutInBubble(ChatMessageCell parentView) {
this.parentView = parentView;
@ -151,6 +156,7 @@ public class ReactionsLayoutInBubble {
height = 0;
width = 0;
positionOffsetY = 0;
totalHeight = 0;
if (isEmpty) {
return;
}
@ -192,7 +198,6 @@ public class ReactionsLayoutInBubble {
lastLineX = currentX;
width = maxWidth;
height = currentY + (reactionButtons.size() == 0 ? 0 : AndroidUtilities.dp(26));
drawServiceShaderBackground = false;
}
@ -255,6 +260,7 @@ public class ReactionsLayoutInBubble {
lastDrawnX = x;
lastDrawnY = y;
lastDrawnWidth = width;
lastDrawTotalHeight = totalHeight;
}
public boolean animateChange() {
@ -325,6 +331,12 @@ public class ReactionsLayoutInBubble {
changed = true;
}
if (lastDrawTotalHeight != totalHeight) {
animateHeight = true;
animateFromTotalHeight = lastDrawTotalHeight;
changed = true;
}
return changed;
}
@ -335,6 +347,7 @@ public class ReactionsLayoutInBubble {
outButtons.clear();
animateMove = false;
animateWidth = false;
animateHeight = false;
for (int i = 0; i < reactionButtons.size(); i++) {
reactionButtons.get(i).animationType = 0;
}
@ -507,7 +520,28 @@ public class ReactionsLayoutInBubble {
private void drawImage(Canvas canvas) {
if (drawImage && ((realCount > 1 || !ReactionsEffectOverlay.isPlaying(messageObject.getId(), messageObject.getGroupId(), reaction)) || !isSelected)) {
ImageReceiver imageReceiver2 = animatedReactions.get(reaction);
boolean drawStaticImage = true;
if (imageReceiver2 != null) {
imageReceiver2.setAlpha(imageReceiver.getAlpha());
imageReceiver2.setImageCoords(imageReceiver.getImageX() - imageReceiver.getImageWidth() / 2, imageReceiver.getImageY() - imageReceiver.getImageWidth() / 2, imageReceiver.getImageWidth() * 2, imageReceiver.getImageHeight() * 2);
imageReceiver2.draw(canvas);
if (imageReceiver2.getLottieAnimation() != null && imageReceiver2.getLottieAnimation().hasBitmap()) {
drawStaticImage = false;
}
if (imageReceiver2.getLottieAnimation() != null && !imageReceiver2.getLottieAnimation().isRunning()) {
float alpha = imageReceiver2.getAlpha() - 16f / 200;
if (alpha < 0) {
imageReceiver2.onDetachedFromWindow();
animatedReactions.remove(reaction);
} else {
imageReceiver2.setAlpha(alpha);
}
}
}
if (drawStaticImage) {
imageReceiver.draw(canvas);
}
lastImageDrawn = true;
} else {
imageReceiver.setAlpha(0);
@ -633,6 +667,13 @@ public class ReactionsLayoutInBubble {
return width;
}
public float getCurrentTotalHeight(float transitionProgress) {
if (animateHeight) {
return animateFromTotalHeight * (1f - transitionProgress) + totalHeight * transitionProgress;
}
return totalHeight;
}
private static class ButtonsComparator implements Comparator<ReactionButton> {
int currentAccount;
@ -661,5 +702,29 @@ public class ReactionsLayoutInBubble {
for (int i = 0; i < reactionButtons.size(); i++) {
reactionButtons.get(i).detach();
}
if (!animatedReactions.isEmpty()) {
for (ImageReceiver imageReceiver : animatedReactions.values()) {
imageReceiver.onDetachedFromWindow();
}
}
animatedReactions.clear();
}
public void animateReaction(String reaction) {
if (animatedReactions.get(reaction) == null) {
ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setParentView(parentView);
imageReceiver.setUniqKeyPrefix(Integer.toString(animationUniq++));
if (reaction != null) {
TLRPC.TL_availableReaction r = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction);
if (r != null) {
imageReceiver.setImage(ImageLocation.getForDocument(r.center_icon), "40_40_nolimit", null, "tgs", r, 1);
}
}
imageReceiver.setAutoRepeat(0);
imageReceiver.onAttachedToWindow();
animatedReactions.put(reaction, imageReceiver);
}
}
}

View file

@ -15,12 +15,14 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.Property;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
@ -55,7 +57,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
public final static Property<ReactionsContainerLayout, Float> TRANSITION_PROGRESS_VALUE = new Property<ReactionsContainerLayout, Float>(Float.class, "transitionProgress") {
@Override
public Float get(ReactionsContainerLayout reactionsContainerLayout) {
return reactionsContainerLayout.transitionProgress ;
return reactionsContainerLayout.transitionProgress;
}
@Override
@ -86,6 +88,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
private MessageObject messageObject;
private int currentAccount;
private long waitingLoadingChatId;
ValueAnimator cancelPressedAnimation;
private List<TLRPC.TL_availableReaction> reactionsList = Collections.emptyList();
@ -102,6 +105,13 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
private List<String> triggeredReactions = new ArrayList<>();
Theme.ResourcesProvider resourcesProvider;
private String pressedReaction;
private int pressedReactionPosition;
private float pressedProgress;
private float cancelPressedProgress;
private float pressedViewScale;
private float otherViewsScale;
private boolean clicked;
public ReactionsContainerLayout(@NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) {
super(context);
@ -114,7 +124,15 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = AndroidUtilities.dp(7);
shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow), PorterDuff.Mode.MULTIPLY));
recyclerListView = new RecyclerListView(context);
recyclerListView = new RecyclerListView(context) {
@Override
public boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (pressedReaction != null && ((ReactionHolderView) child).currentReaction.equals(pressedReaction)) {
return true;
}
return super.drawChild(canvas, child, drawingTime);
}
};
linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
recyclerListView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
@ -155,11 +173,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
return reactionsList.size();
}
});
recyclerListView.setOnItemClickListener((view, position) -> {
ReactionHolderView h = (ReactionHolderView) view;
if (delegate != null)
delegate.onReactionClicked(h, h.currentReaction);
});
recyclerListView.addOnScrollListener(new LeftRightShadowsListener());
recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
@ -177,8 +190,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
int dX1 = ch1X - rX;
float s1 = SIDE_SCALE + (1f - Math.min(1, -Math.min(dX1, 0f) / ch1.getWidth())) * sideDiff;
if (Float.isNaN(s1)) s1 = 1f;
ch1.setScaleX(s1);
ch1.setScaleY(s1);
((ReactionHolderView) ch1).sideScale = s1;
View ch2 = recyclerView.getChildAt(recyclerView.getChildCount() - 1);
ch2.getLocationInWindow(location);
@ -187,14 +199,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
int dX2 = rX + recyclerView.getWidth() - (ch2X + ch2.getWidth());
float s2 = SIDE_SCALE + (1f - Math.min(1, -Math.min(dX2, 0f) / ch2.getWidth())) * sideDiff;
if (Float.isNaN(s2)) s2 = 1f;
ch2.setScaleX(s2);
ch2.setScaleY(s2);
((ReactionHolderView) ch2).sideScale = s2;
}
for (int i = 1; i < recyclerListView.getChildCount() - 1; i++) {
View ch = recyclerListView.getChildAt(i);
float sc = 1f;
ch.setScaleX(sc);
ch.setScaleY(sc);
((ReactionHolderView) ch).sideScale = 1f;
}
invalidate();
}
@ -238,46 +247,24 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
lastVisibleViewsTmp.clear();
lastVisibleViewsTmp.addAll(lastVisibleViews);
lastVisibleViews.clear();
if (transitionProgress != 0) {
int delay = 0;
for (int i = 0; i < recyclerListView.getChildCount(); i++) {
ReactionHolderView view = (ReactionHolderView) recyclerListView.getChildAt(i);
if (view.backupImageView.getImageReceiver().getLottieAnimation() == null) {
continue;
}
if (view.getX() + view.getMeasuredWidth() / 2f > 0 && view.getX() + view.getMeasuredWidth() / 2f < recyclerListView.getWidth()) {
if (!lastVisibleViewsTmp.contains(view)) {
view.play(delay);
delay += 30;
}
lastVisibleViews.add(view);
} else if (!view.isEnter) {
view.resetAnimation();
if (pressedReaction != null) {
if (pressedProgress != 1f) {
pressedProgress += 16f / 2000f;
if (pressedProgress >= 1f) {
pressedProgress = 1f;
}
invalidate();
}
}
float cPr = (Math.max(CLIP_PROGRESS, Math.min(transitionProgress, 1f)) - CLIP_PROGRESS) / (1f - CLIP_PROGRESS);
float br = bigCircleRadius * cPr, sr = smallCircleRadius * cPr;
float cx = LocaleController.isRTL ? bigCircleOffset : getWidth() - bigCircleOffset, cy = getHeight() - getPaddingBottom();
int sPad = AndroidUtilities.dp(3);
shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr));
shadow.draw(canvas);
canvas.drawCircle(cx, cy, br, bgPaint);
cx = LocaleController.isRTL ? bigCircleOffset - bigCircleRadius : getWidth() - bigCircleOffset + bigCircleRadius;
cy = getHeight() - smallCircleRadius - sPad;
sPad = -AndroidUtilities.dp(1);
shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr));
shadow.draw(canvas);
canvas.drawCircle(cx, cy, sr, bgPaint);
pressedViewScale = 1 + 2 * pressedProgress;
otherViewsScale = 1 - 0.15f * pressedProgress;
int s = canvas.save();
mPath.rewind();
mPath.addCircle(LocaleController.isRTL ? bigCircleOffset : getWidth() - bigCircleOffset, getHeight() - getPaddingBottom(), br, Path.Direction.CW);
canvas.clipPath(mPath, Region.Op.DIFFERENCE);
float pivotX = LocaleController.isRTL ? getWidth() * 0.125f : getWidth() * 0.875f;
if (transitionProgress <= SCALE_PROGRESS) {
@ -291,7 +278,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
} else {
lt = (1f - Math.max(CLIP_PROGRESS, transitionProgress));
}
rect.set(getPaddingLeft() + (getWidth() - getPaddingRight()) * lt, getPaddingTop(), (getWidth() - getPaddingRight()) * rt, getHeight() - getPaddingBottom());
rect.set(getPaddingLeft() + (getWidth() - getPaddingRight()) * lt, getPaddingTop() + recyclerListView.getMeasuredHeight() * (1f - otherViewsScale), (getWidth() - getPaddingRight()) * rt, getHeight() - getPaddingBottom());
radius = rect.height() / 2f;
shadow.setBounds((int) (getPaddingLeft() + (getWidth() - getPaddingRight() + shadowPad.right) * lt - shadowPad.left), getPaddingTop() - shadowPad.top, (int) ((getWidth() - getPaddingRight() + shadowPad.right) * rt), getHeight() - getPaddingBottom() + shadowPad.bottom);
shadow.draw(canvas);
canvas.restoreToCount(s);
@ -312,18 +300,31 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
float sc = transitionProgress / SCALE_PROGRESS;
canvas.scale(sc, sc, pivotX, getHeight() / 2f);
}
if (transitionProgress != 0) {
int delay = 0;
for (int i = 0; i < recyclerListView.getChildCount(); i++) {
ReactionHolderView view = (ReactionHolderView) recyclerListView.getChildAt(i);
checkPressedProgress(canvas, view);
if (view.backupImageView.getImageReceiver().getLottieAnimation() == null) {
continue;
}
if (view.getX() + view.getMeasuredWidth() / 2f > 0 && view.getX() + view.getMeasuredWidth() / 2f < recyclerListView.getWidth()) {
if (!lastVisibleViewsTmp.contains(view)) {
view.play(delay);
delay += 30;
}
lastVisibleViews.add(view);
} else if (!view.isEnter) {
view.resetAnimation();
}
}
}
canvas.clipPath(mPath);
canvas.translate((LocaleController.isRTL ? -1 : 1) * getWidth() * (1f - transitionProgress), 0);
super.dispatchDraw(canvas);
canvas.restoreToCount(s);
s = canvas.save();
if (LocaleController.isRTL) rt = Math.max(CLIP_PROGRESS, Math.min(1, transitionProgress));
else lt = 1f - Math.max(CLIP_PROGRESS, Math.min(1f, transitionProgress));
rect.set(getPaddingLeft() + (getWidth() - getPaddingRight()) * lt, getPaddingTop(), (getWidth() - getPaddingRight()) * rt, getHeight() - getPaddingBottom());
mPath.rewind();
mPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(mPath);
if (leftShadowPaint != null) {
leftShadowPaint.setAlpha((int) (leftAlpha * transitionProgress * 0xFF));
canvas.drawRect(rect, leftShadowPaint);
@ -334,6 +335,73 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
canvas.restoreToCount(s);
canvas.save();
canvas.clipRect(0, rect.bottom, getMeasuredWidth(), getMeasuredHeight());
float cx = LocaleController.isRTL ? bigCircleOffset : getWidth() - bigCircleOffset, cy = getHeight() - getPaddingBottom();
int sPad = AndroidUtilities.dp(3);
shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr));
shadow.draw(canvas);
canvas.drawCircle(cx, cy, br, bgPaint);
cx = LocaleController.isRTL ? bigCircleOffset - bigCircleRadius : getWidth() - bigCircleOffset + bigCircleRadius;
cy = getHeight() - smallCircleRadius - sPad;
sPad = -AndroidUtilities.dp(1);
shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr));
shadow.draw(canvas);
canvas.drawCircle(cx, cy, sr, bgPaint);
canvas.restore();
}
private void checkPressedProgress(Canvas canvas, ReactionHolderView view) {
if (view.currentReaction.reaction.equals(pressedReaction)) {
view.setPivotX(view.getMeasuredWidth() >> 1);
view.setPivotY(view.backupImageView.getY() + view.backupImageView.getMeasuredHeight());
view.setScaleX(pressedViewScale);
view.setScaleY(pressedViewScale);
if (!clicked) {
if (cancelPressedAnimation == null) {
view.pressedBackupImageView.setVisibility(View.VISIBLE);
view.pressedBackupImageView.setAlpha(1f);
if (view.pressedBackupImageView.getImageReceiver().hasBitmapImage()) {
view.backupImageView.setAlpha(0f);
}
} else {
view.pressedBackupImageView.setAlpha(1f - cancelPressedProgress);
view.backupImageView.setAlpha(cancelPressedProgress);
}
if (pressedProgress == 1f) {
clicked = true;
delegate.onReactionClicked(view, view.currentReaction, true);
}
}
canvas.save();
canvas.translate(recyclerListView.getX() + view.getX(), recyclerListView.getY() + view.getY());
canvas.scale(view.getScaleX(), view.getScaleY(), view.getPivotX(), view.getPivotY());
view.draw(canvas);
canvas.restore();
} else {
int position = recyclerListView.getChildAdapterPosition(view);
float translationX;
translationX = (view.getMeasuredWidth() * (pressedViewScale - 1f)) / 3f - view.getMeasuredWidth() * (1f - otherViewsScale) * (Math.abs(pressedReactionPosition - position) - 1);
if (position < pressedReactionPosition) {
view.setPivotX(0);
view.setTranslationX(-translationX);
} else {
view.setPivotX(view.getMeasuredWidth());
view.setTranslationX(translationX);
}
view.setPivotY(view.backupImageView.getY() + view.backupImageView.getMeasuredHeight());
view.setScaleX(otherViewsScale);
view.setScaleY(otherViewsScale);
view.backupImageView.setScaleX(view.sideScale);
view.backupImageView.setScaleY(view.sideScale);
view.pressedBackupImageView.setVisibility(View.INVISIBLE);
view.backupImageView.setAlpha(1f);
}
}
@Override
@ -451,7 +519,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
public final class ReactionHolderView extends FrameLayout {
public BackupImageView backupImageView;
public BackupImageView pressedBackupImageView;
public TLRPC.TL_availableReaction currentReaction;
public float sideScale;
private boolean isEnter;
Runnable playRunnable = new Runnable() {
@ -460,6 +530,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
if (backupImageView.getImageReceiver().getLottieAnimation() != null && !backupImageView.getImageReceiver().getLottieAnimation().isRunning() && !backupImageView.getImageReceiver().getLottieAnimation().isGeneratingCache()) {
backupImageView.getImageReceiver().getLottieAnimation().start();
}
}
};
@ -475,7 +546,16 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
};
backupImageView.getImageReceiver().setAutoRepeat(0);
backupImageView.getImageReceiver().setAllowStartLottieAnimation(false);
pressedBackupImageView = new BackupImageView(context) {
@Override
public void invalidate() {
super.invalidate();
ReactionsContainerLayout.this.invalidate();
}
};
addView(backupImageView, LayoutHelper.createFrame(34, 34, Gravity.CENTER));
addView(pressedBackupImageView, LayoutHelper.createFrame(34, 34, Gravity.CENTER));
}
private void setReaction(TLRPC.TL_availableReaction react) {
@ -486,6 +566,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
currentReaction = react;
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(currentReaction.activate_animation, Theme.key_windowBackgroundGray, 1.0f);
backupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(currentReaction.appear_animation), "60_60_nolimit", null, null, svgThumb, 0, "tgs", react, 0);
pressedBackupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(currentReaction.select_animation), "60_60_nolimit", null, null, svgThumb, 0, "tgs", react, 0);
}
@Override
@ -532,10 +613,80 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
isEnter = false;
}
Runnable longPressRunnable = new Runnable() {
@Override
public void run() {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
pressedReactionPosition = reactionsList.indexOf(currentReaction);
pressedReaction = currentReaction.reaction;
ReactionsContainerLayout.this.invalidate();
}
};
float pressedX, pressedY;
boolean pressed;
@Override
public boolean onTouchEvent(MotionEvent event) {
if (cancelPressedAnimation != null) {
return false;
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
pressed = true;
pressedX = event.getX();
pressedY = event.getY();
if (sideScale == 1f) {
AndroidUtilities.runOnUIThread(longPressRunnable, ViewConfiguration.getLongPressTimeout());
}
}
float touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop() * 2f;
boolean cancelByMove = event.getAction() == MotionEvent.ACTION_MOVE && (Math.abs(pressedX - event.getX()) > touchSlop || Math.abs(pressedY - event.getY()) > touchSlop);
if (cancelByMove || event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
if (event.getAction() == MotionEvent.ACTION_UP && pressed && (pressedReaction == null || pressedProgress > 0.8f) && delegate != null) {
clicked = true;
delegate.onReactionClicked(this, currentReaction, pressedProgress > 0.8f);
}
if (!clicked) {
cancelPressed();
}
AndroidUtilities.cancelRunOnUIThread(longPressRunnable);
pressed = false;
}
return true;
}
}
private void cancelPressed() {
if (pressedReaction != null) {
cancelPressedProgress = 0f;
float fromProgress = pressedProgress;
cancelPressedAnimation = ValueAnimator.ofFloat(0, 1f);
cancelPressedAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
cancelPressedProgress = (float) valueAnimator.getAnimatedValue();
pressedProgress = fromProgress * (1f - cancelPressedProgress);
ReactionsContainerLayout.this.invalidate();
}
});
cancelPressedAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
cancelPressedAnimation = null;
pressedProgress = 0;
pressedReaction = null;
ReactionsContainerLayout.this.invalidate();
}
});
cancelPressedAnimation.setDuration(150);
cancelPressedAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT);
cancelPressedAnimation.start();
}
}
public interface ReactionsContainerDelegate {
void onReactionClicked(View v, TLRPC.TL_availableReaction reaction);
void onReactionClicked(View v, TLRPC.TL_availableReaction reaction, boolean longpress);
}
@Override

View file

@ -8,8 +8,16 @@
package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
@ -21,12 +29,17 @@ import android.view.View;
import android.widget.FrameLayout;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.AdjustPanLayoutHelper;
import org.telegram.ui.ActionBar.Theme;
import java.util.ArrayList;
public class SizeNotifierFrameLayout extends FrameLayout {
private Rect rect = new Rect();
@ -51,6 +64,11 @@ public class SizeNotifierFrameLayout extends FrameLayout {
private boolean skipBackgroundDrawing;
SnowflakesEffect snowflakesEffect;
public void invalidateBlur() {
invalidateBlur = true;
}
public interface SizeNotifierFrameLayoutDelegate {
void onSizeChanged(int keyboardHeight, boolean isWidthGreater);
}
@ -337,7 +355,7 @@ public class SizeNotifierFrameLayout extends FrameLayout {
}
private void checkSnowflake(Canvas canvas) {
if (SharedConfig.drawSnowInChat || Theme.canStartHolidayAnimation()) {
if (Theme.canStartHolidayAnimation()) {
if (snowflakesEffect == null) {
snowflakesEffect = new SnowflakesEffect(1);
}
@ -366,4 +384,265 @@ public class SizeNotifierFrameLayout extends FrameLayout {
protected boolean verifyDrawable(Drawable who) {
return who == getBackgroundImage() || super.verifyDrawable(who);
}
public boolean needBlur;
public boolean blurIsRunning;
public boolean blurGeneratingTuskIsRunning;
BlurBitmap currentBitmap;
public ArrayList<BlurBitmap> unusedBitmaps = new ArrayList<>(10);
public ArrayList<View> blurBehindViews = new ArrayList<>();
Matrix matrix = new Matrix();
public Paint blurPaintTop = new Paint();
public Paint blurPaintTop2 = new Paint();
public Paint blurPaintBottom = new Paint();
public Paint blurPaintBottom2 = new Paint();
public float blurCrossfadeProgress;
private final float DOWN_SCALE = 12f;
private static DispatchQueue blurQueue;
ValueAnimator blurCrossfade;
public boolean invalidateBlur;
int count;
int times;
public void startBlur() {
if (!blurIsRunning || blurGeneratingTuskIsRunning || !invalidateBlur || !SharedConfig.chatBlurEnabled()) {
return;
}
invalidateBlur = false;
blurGeneratingTuskIsRunning = true;
int lastW = getMeasuredWidth();
int lastH = ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight + AndroidUtilities.dp(100);
int bitmapH = (int) (lastH / DOWN_SCALE) + 10;
int bitmapW = (int) (lastW / DOWN_SCALE);
BlurBitmap bitmap = null;
if (unusedBitmaps.size() > 0) {
bitmap = unusedBitmaps.remove(unusedBitmaps.size() - 1);
}
if (bitmap == null) {
bitmap = new BlurBitmap();
bitmap.topBitmap = Bitmap.createBitmap(bitmapW, bitmapH, Bitmap.Config.ARGB_8888);
bitmap.topCanvas = new Canvas(bitmap.topBitmap);
bitmap.bottomBitmap = Bitmap.createBitmap(bitmapW, bitmapH, Bitmap.Config.ARGB_8888);
bitmap.bottomCanvas = new Canvas(bitmap.bottomBitmap);
}
bitmap.topBitmap.eraseColor(Color.TRANSPARENT);
bitmap.bottomBitmap.eraseColor(Color.TRANSPARENT);
BlurBitmap finalBitmap = bitmap;
float sX = (float) finalBitmap.topBitmap.getWidth() / (float) lastW;
float sY = (float) (finalBitmap.topBitmap.getHeight() - 10) / (float) lastH;
finalBitmap.topCanvas.save();
finalBitmap.topCanvas.clipRect(0, 10 * sY, finalBitmap.topBitmap.getWidth(), finalBitmap.topBitmap.getHeight());
finalBitmap.topCanvas.scale(sX, sY);
finalBitmap.topScaleX = 1f / sX;
finalBitmap.topScaleY = 1f / sY;
// finalBitmap.pixelFixOffset = getScrollOffset() % (int) DOWN_SCALE;
finalBitmap.topCanvas.translate(0, finalBitmap.pixelFixOffset);
drawList(finalBitmap.topCanvas, true);
finalBitmap.topCanvas.restore();
sX = (float) finalBitmap.bottomBitmap.getWidth() / (float) lastW;
sY = (float) (finalBitmap.bottomBitmap.getHeight() - 10) / (float) lastH;
finalBitmap.bottomOffset = getBottomOffset() - lastH;
finalBitmap.bottomCanvas.save();
finalBitmap.bottomCanvas.clipRect(0, 10 * sY, finalBitmap.bottomBitmap.getWidth(), finalBitmap.bottomBitmap.getHeight());
finalBitmap.bottomCanvas.scale(sX, sY);
finalBitmap.bottomCanvas.translate(0, 10 - finalBitmap.bottomOffset);
finalBitmap.bottomScaleX = 1f / sX;
finalBitmap.bottomScaleY = 1f / sY;
drawList(finalBitmap.bottomCanvas, false);
finalBitmap.bottomCanvas.restore();
int radius = (int) (Math.max(6, Math.max(lastH, lastW) / 180) * 2.5f);
if (blurQueue == null) {
blurQueue = new DispatchQueue("BlurQueue");
}
blurQueue.postRunnable(new Runnable() {
@Override
public void run() {
long time = System.currentTimeMillis();
Utilities.stackBlurBitmap(finalBitmap.topBitmap, radius);
Utilities.stackBlurBitmap(finalBitmap.bottomBitmap, radius);
times += System.currentTimeMillis() - time;
count++;
if (count > 1000) {
FileLog.d("chat blur generating average time" + (times / (float) count));
count = 0;
times = 0;
}
AndroidUtilities.runOnUIThread(() -> {
BlurBitmap oldBitmap = currentBitmap;
blurPaintTop2.setShader(blurPaintTop.getShader());
blurPaintBottom2.setShader(blurPaintBottom.getShader());
BitmapShader bitmapShader = new BitmapShader(finalBitmap.topBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
blurPaintTop.setShader(bitmapShader);
bitmapShader = new BitmapShader(finalBitmap.bottomBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
blurPaintBottom.setShader(bitmapShader);
blurCrossfadeProgress = 0;
if (blurCrossfade != null) {
blurCrossfade.cancel();
}
blurCrossfade = ValueAnimator.ofFloat(0, 1f);
blurCrossfade.addUpdateListener(valueAnimator -> {
blurCrossfadeProgress = (float) valueAnimator.getAnimatedValue();
for (int i = 0; i < blurBehindViews.size(); i++) {
blurBehindViews.get(i).invalidate();
}
});
blurCrossfade.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
unusedBitmaps.add(oldBitmap);
super.onAnimationEnd(animation);
}
});
blurCrossfade.setDuration(50);
blurCrossfade.start();
for (int i = 0; i < blurBehindViews.size(); i++) {
blurBehindViews.get(i).invalidate();
}
currentBitmap = finalBitmap;
AndroidUtilities.runOnUIThread(() -> {
blurGeneratingTuskIsRunning = false;
startBlur();
}, 32);
});
}
});
}
protected float getBottomOffset() {
return getMeasuredHeight();
}
protected Theme.ResourcesProvider getResourceProvider() {
return null;
}
protected void drawList(Canvas blurCanvas, boolean top) {
}
protected int getScrollOffset() {
return 0;
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (blurIsRunning) {
startBlur();
}
super.dispatchDraw(canvas);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (needBlur && !blurIsRunning) {
blurIsRunning = true;
invalidateBlur = true;
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
blurPaintTop.setShader(null);
blurPaintTop2.setShader(null);
blurPaintBottom.setShader(null);
blurPaintBottom2.setShader(null);
if (blurCrossfade != null) {
blurCrossfade.cancel();
}
if (currentBitmap != null) {
currentBitmap.recycle();
currentBitmap = null;
}
for (int i = 0; i < unusedBitmaps.size(); i++) {
if (unusedBitmaps.get(i) != null) {
unusedBitmaps.get(i).recycle();
}
}
unusedBitmaps.clear();
blurIsRunning = false;
}
public void drawBlur(Canvas canvas, float y, Rect rectTmp, Paint blurScrimPaint, boolean top) {
if (currentBitmap == null || !SharedConfig.chatBlurEnabled()) {
canvas.drawRect(rectTmp, blurScrimPaint);
return;
}
Paint blurPaint = top ? blurPaintTop : blurPaintBottom;
Paint blurPaint2 = top ? blurPaintTop2 : blurPaintBottom2;
if (blurPaint.getShader() != null) {
matrix.reset();
if (!top) {
matrix.setTranslate(0, -y + currentBitmap.bottomOffset - currentBitmap.pixelFixOffset);
matrix.preScale(currentBitmap.bottomScaleX, currentBitmap.bottomScaleY);
} else {
matrix.setTranslate(0, -y);
matrix.preScale(currentBitmap.topScaleX, currentBitmap.topScaleY);
}
blurPaint.getShader().setLocalMatrix(matrix);
if (blurPaint2.getShader() != null) {
blurPaint2.getShader().setLocalMatrix(matrix);
}
}
if (blurCrossfadeProgress != 1f && blurPaint2.getShader() != null) {
canvas.drawRect(rectTmp, blurScrimPaint);
canvas.drawRect(rectTmp, blurPaint2);
canvas.saveLayerAlpha(rectTmp.left, rectTmp.top, rectTmp.right, rectTmp.bottom, (int) (blurCrossfadeProgress * 255), Canvas.ALL_SAVE_FLAG);
// blurScrimPaint.setAlpha((int) (blurCrossfadeProgress * 255));
// blurPaint.setAlpha((int) (blurCrossfadeProgress * 255));
canvas.drawRect(rectTmp, blurScrimPaint);
canvas.drawRect(rectTmp, blurPaint);
canvas.restore();
} else {
canvas.drawRect(rectTmp, blurScrimPaint);
canvas.drawRect(rectTmp, blurPaint);
}
blurScrimPaint.setAlpha(Color.alpha(Theme.getColor(Theme.key_chat_BlurAlpha)));
canvas.drawRect(rectTmp, blurScrimPaint);
}
private static class BlurBitmap {
int pixelFixOffset;
Canvas topCanvas;
Bitmap topBitmap;
float topScaleX, topScaleY;
float bottomScaleX, bottomScaleY;
float bottomOffset;
Canvas bottomCanvas;
Bitmap bottomBitmap;
public void recycle() {
topBitmap.recycle();
bottomBitmap.recycle();
}
}
}

View file

@ -78,8 +78,10 @@ import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.BackDrawable;
@ -87,6 +89,7 @@ import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.Paint.Input;
import java.io.BufferedReader;
import java.io.IOException;
@ -269,8 +272,15 @@ public class TranslateAlert extends Dialog {
private boolean noforwards;
private OnLinkPress onLinkPress = null;
public TranslateAlert(BaseFragment fragment, Context context, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress) {
this(fragment, context, -1, null, -1, fromLanguage, toLanguage, text, noforwards, onLinkPress);
}
public TranslateAlert(BaseFragment fragment, Context context, int currentAccount, TLRPC.InputPeer peer, int msgId, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress) {
super(context, R.style.TransparentDialog);
if (peer != null) {
translateText(currentAccount, peer, msgId, fromLanguage != null && fromLanguage.equals("und") ? null : fromLanguage, toLanguage);
}
this.onLinkPress = onLinkPress;
this.noforwards = noforwards;
this.fragment = fragment;
@ -1345,7 +1355,39 @@ public class TranslateAlert extends Dialog {
}
}.start();
}
private static void translateText(int currentAccount, TLRPC.InputPeer peer, int msg_id, String from_lang, String to_lang) {
TLRPC.TL_messages_translateText req = new TLRPC.TL_messages_translateText();
req.peer = peer;
req.msg_id = msg_id;
req.flags |= 1;
if (from_lang != null) {
req.from_lang = from_lang;
req.flags |= 4;
}
req.to_lang = to_lang;
try {
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (error, res) -> {
// TODO
});
} catch (Exception e) {
FileLog.e(e);
}
}
public static void showAlert(Context context, BaseFragment fragment, int currentAccount, TLRPC.InputPeer peer, int msgId, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress) {
TranslateAlert alert = new TranslateAlert(fragment, context, currentAccount, peer, msgId, fromLanguage, toLanguage, text, noforwards, onLinkPress);
if (fragment != null) {
if (fragment.getParentActivity() != null) {
fragment.showDialog(alert);
}
} else {
alert.show();
}
}
public static void showAlert(Context context, BaseFragment fragment, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress) {
TranslateAlert alert = new TranslateAlert(fragment, context, fromLanguage, toLanguage, text, noforwards, onLinkPress);
if (fragment != null) {

View file

@ -12,6 +12,7 @@ import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.SystemClock;
import android.text.Layout;
import android.text.Selection;
@ -431,6 +432,9 @@ public class UndoView extends FrameLayout {
}
public void showWithAction(ArrayList<Long> dialogIds, int action, Object infoObject, Object infoObject2, Runnable actionRunnable, Runnable cancelRunnable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && currentAction == ACTION_MESSAGE_COPIED || currentAction == ACTION_USERNAME_COPIED || currentAction == ACTION_HASHTAG_COPIED || currentAction == ACTION_TEXT_COPIED || currentAction == ACTION_LINK_COPIED || currentAction == ACTION_PHONE_COPIED || currentAction == ACTION_EMAIL_COPIED || currentAction == ACTION_VOIP_LINK_COPIED) {
return;
}
if (currentActionRunnable != null) {
currentActionRunnable.run();
}

View file

@ -564,7 +564,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
public void setCaption(CharSequence caption) {
hasCaptionForAllMedia = !TextUtils.isEmpty(caption);
hasCaptionForAllMedia = true;//!TextUtils.isEmpty(caption);
captionForAllMedia = caption;
}
@ -1903,6 +1903,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
public boolean validateGroupId(long groupId) {
return true;
}
@Override
public void onApplyCaption(CharSequence caption) {
}
}
public interface PhotoViewerProvider {
@ -1939,6 +1944,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
void onCaptionChanged(CharSequence caption);
boolean closeKeyboard();
boolean validateGroupId(long groupId);
void onApplyCaption(CharSequence caption);
}
private class FrameLayoutDrawer extends SizeNotifierFrameLayoutPhoto {
@ -6755,6 +6761,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (captionEditText.getFieldCharSequence().length() != 0 && !placeProvider.isPhotoChecked(currentIndex)) {
setPhotoChecked();
}
if (placeProvider != null) {
placeProvider.onApplyCaption(caption);
}
setCurrentCaption(null, result[0], false);
}
captionEditText.setTag(null);

View file

@ -14,7 +14,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
@ -113,7 +112,6 @@ import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.AlertDialog;
@ -2729,7 +2727,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
Build.VERSION.SDK_INT >= 21 ? (SharedConfig.noStatusBar ? "Show status bar background" : "Hide status bar background") : null,
BuildVars.DEBUG_PRIVATE_VERSION ? "Clean app update" : null,
BuildVars.DEBUG_PRIVATE_VERSION ? "Reset suggestions" : null,
SharedConfig.drawSnowInChat ? "Hide snow in chat" : "Show snow in chat"
SharedConfig.canBlurChat() ? (SharedConfig.chatBlur ? "Disable blur in chat" : "Enable blur in chat") : null
};
builder.setItems(items, (dialog, which) -> {
if (which == 0) {
@ -2801,7 +2799,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
suggestions.add("VALIDATE_PASSWORD");
getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable);
} else if (which == 17) {
SharedConfig.toggleDrawSnowInChat();
SharedConfig.toggleDebugChatBlur();
}
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);

View file

@ -1698,7 +1698,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent
buf.write(service.getGA());
auth_key = buf.toByteArray();
} catch (Exception checkedExceptionsAreBad) {
FileLog.e(checkedExceptionsAreBad);
FileLog.e(checkedExceptionsAreBad, false);
}
if (auth_key == null) {
return;

View file

@ -4937,7 +4937,6 @@
<string name="DoubleTapPreviewSenderName">Dino</string>
<string name="DoubleTapSetting">Quick Reactions</string>
<string name="DoubleTapPreviewRational">Double tap this message for a quck reaction.</string>
<string name="DebugDrawSnowInChat">Snow in chat</string>
<string name="ActionReactionsChanged">un1 changed chat reactions \nfrom: %1$s \nto: %2$s</string>
<string name="NobodyViewed">Nobody viewed</string>
<string name="QrCode">QR Code</string>