diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 49664a98f..bc7ba0287 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -300,7 +300,7 @@ android { } } - defaultConfig.versionCode = 2522 + defaultConfig.versionCode = 2531 applicationVariants.all { variant -> variant.outputs.all { output -> @@ -319,7 +319,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 30 - versionName "8.4.1" + versionName "8.4.3" vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index d269a04b3..644b08d98 100644 --- a/TMessagesProj/src/main/assets/bluebubbles.attheme +++ b/TMessagesProj/src/main/assets/bluebubbles.attheme @@ -34,6 +34,7 @@ dialogTextLink=-14057020 chat_status=-2627597 windowBackgroundWhiteBlueHeader=-14380330 chat_messagePanelVoiceBackground=-10374934 +switchTrackBlueChecked=-12940870 chat_topPanelLine=-11949852 chat_outInstantSelected=-14770977 chat_outSentCheck=-14967834 @@ -80,8 +81,8 @@ dialogTextGray4=-7565423 chat_attachContactText=-2121728 chat_searchPanelIcons=-12937244 windowBackgroundWhiteLinkText=-13990712 -chat_outVenueInfoText=-9396792 -chat_outContactPhoneText=-9396792 +chat_outVenueInfoText=-8216913 +chat_outContactPhoneText=-8612185 chat_inAudioTitleText=-15061445 chat_messageLinkIn=-16090691 chat_inBubbleSelected=-1509892 @@ -92,7 +93,7 @@ chat_outSiteNameText=-14515511 dialogTextGray=-7565423 chat_messageLinkOut=-16155709 avatar_backgroundArchived=-4998207 -chat_outFileInfoSelectedText=-9396792 +chat_outFileInfoSelectedText=-8674358 chat_outAudioDurationSelectedText=-8674358 avatar_backgroundArchivedHidden=-10832396 statisticChartLine_orange=-1853657 @@ -105,7 +106,7 @@ chat_outReplyLine=-13133085 chat_inAudioSeekbarFill=-10572824 chat_inContactBackground=-431707662 progressCircle=-14375188 -chat_outVenueInfoSelectedText=-9396792 +chat_outVenueInfoSelectedText=-8674358 chats_menuItemIcon=-7433063 wallpaperFileOffset=-1 chat_outBubbleShadow=-16699318 @@ -130,8 +131,8 @@ chat_outBubbleSelected=-2690305 chat_inFileNameText=-15654091 statisticChartLine_blue=-13467675 chat_inInstantSelected=-14707230 -chat_outFileInfoText=-9396792 -chat_outContactPhoneSelectedText=-9396792 +chat_outFileInfoText=-7953740 +chat_outContactPhoneSelectedText=-9725764 chat_wallpaper=-11300655 chat_outMenuSelected=-7026959 chat_outLoaderPhotoSelected=-263935502 @@ -142,14 +143,14 @@ avatar_actionBarSelectorBlue=-12091735 switchTrackChecked=-11424793 chat_inLoader=-431707662 chat_outPreviewInstantSelectedText=-14514998 -chat_outTimeText=-143614520 +chat_outTimeText=-141776195 chat_attachAudioText=-2209977 chat_outBubble=-1641732 chat_attachHideBackground=-4866356 chats_menuItemText=-12632257 chat_outReplyNameText=-14382642 chats_menuTopBackgroundCats=-10906430 -chat_outReplyMediaMessageText=-9396792 +chat_outReplyMediaMessageText=-7558467 actionBarTabSelector=-12554340 chat_outLoaderPhotoIcon=-263935502 chat_attachFileText=-15423260 @@ -178,9 +179,9 @@ chats_actionPressedBackground=-11166764 chat_replyPanelName=-13397538 windowBackgroundWhiteValueText=-13003565 chat_outAudioDurationText=-7558467 -chat_outMenu=-5782571 +chat_outMenu=-5716778 statisticChartActiveLine=335544320 -chat_outReplyMediaMessageSelectedText=-9396792 +chat_outReplyMediaMessageSelectedText=-8674357 chats_attachMessage=-14843710 chat_outSentClock=-594761027 chat_searchPanelText=-12609056 diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index d7d8af39e..05d86b069 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -36,6 +36,7 @@ chat_inMediaIcon=-1 actionBarDefaultArchived=-13748149 avatar_subtitleInProfileViolet=-7628894 chat_messagePanelCancelInlineBot=-8549479 +voipgroup_topPanelGray=-10521727 dialogSearchBackground=-14010037 chat_outAudioSeekbarFill=-7944965 chat_botKeyboardButtonBackgroundPressed=-12956574 @@ -373,6 +374,7 @@ chat_outReplyMediaMessageText=-7357217 chat_textSelectBackground=1516415459 chat_messagePanelVoiceDelete=-1 chat_inAudioProgress=-1 +chat_inReactionButtonTextSelected=-1 chats_date=-9207925 chat_messagePanelText=-1 actionBarTabSelector=926307434 @@ -431,6 +433,7 @@ chat_outReplyMessageText=-1 chat_recordedVoiceDot=-1221292 chat_messagePanelBackground=-14602949 chat_inLoaderPhotoSelected=-14925725 +chat_inReactionButtonText=-1 chat_inVoiceSeekbarFill=-10177041 graySection=-15459033 chat_outAudioSeekbar=-429551165 @@ -462,4 +465,3 @@ chat_outSentClock=-8213557 dialogBackgroundGray=-14932431 chat_searchPanelText=-8796932 chat_inContactIcon=-1 -voipgroup_topPanelGray=-10521727 diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index f70fae2af..1a30d904e 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -393,6 +393,7 @@ chat_outReplyMediaMessageText=-7023626 chat_textSelectBackground=1516415459 chat_messagePanelVoiceDelete=-1 chat_inAudioProgress=-1 +chat_inReactionButtonTextSelected=-1 chats_date=-8882056 chat_messagePanelText=-1 actionBarTabSelector=827876202 @@ -456,6 +457,7 @@ chat_recordedVoiceDot=-1221292 chat_messagePanelBackground=-14803425 chat_wallpaper_gradient_to=-15790320 chat_inLoaderPhotoSelected=-14925725 +chat_inReactionButtonText=-1 chats_messageArchived=-8224126 chat_inVoiceSeekbarFill=-10177041 graySection=-16053492 diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java index 69accd45b..b5e44f1c4 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java @@ -427,6 +427,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { view.setTranslationX(-deltaX); } mPendingMoves.add(moveInfo); + checkIsRunning(); return true; } @@ -655,6 +656,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { } mPendingMoves.add(moveInfo); + checkIsRunning(); return true; } @@ -926,6 +928,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator { newHolder.itemView.setAlpha(0); } mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); + checkIsRunning(); return true; } diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java index fd28a07bd..9d45b4015 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java @@ -210,6 +210,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { public boolean animateRemove(final RecyclerView.ViewHolder holder, ItemHolderInfo info) { resetAnimation(holder); mPendingRemovals.add(holder); + checkIsRunning(); return true; } @@ -247,6 +248,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { resetAnimation(holder); holder.itemView.setAlpha(0); mPendingAdditions.add(holder); + checkIsRunning(); return true; } @@ -296,6 +298,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { view.setTranslationY(-deltaY); } mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + checkIsRunning(); return true; } @@ -380,6 +383,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { newHolder.itemView.setAlpha(0); } mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); + checkIsRunning(); return true; } @@ -734,4 +738,8 @@ public class DefaultItemAnimator extends SimpleItemAnimator { public void setTranslationInterpolator(Interpolator translationInterpolator) { this.translationInterpolator = translationInterpolator; } + + public void checkIsRunning() { + + } } diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java index 1a58becd7..265c55aad 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java @@ -129,6 +129,9 @@ public class GridLayoutManagerFixed extends GridLayoutManager { int backupPosition = layoutState.mCurrentPosition; for (int a = layoutState.mCurrentPosition; a > startPosition; a--) { View view = layoutState.next(recycler); + if (view == null) { + continue; + } additionalViews.add(view); if (a != backupPosition) { calculateItemDecorationsForChild(view, mDecorInsets); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index b16846487..217bac40e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -39,6 +39,7 @@ 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; @@ -95,6 +96,7 @@ 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; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index dd625246b..6f2d8c755 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -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 = 2526; - public static String BUILD_VERSION_STRING = "8.4.2"; + public static int BUILD_VERSION = 2531; + public static String BUILD_VERSION_STRING = "8.4.3"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java index 8fd6623b2..140e2ad14 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java @@ -14,7 +14,6 @@ import android.util.Base64; import androidx.collection.LongSparseArray; -import com.google.android.exoplayer2.util.Log; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; @@ -1114,7 +1113,7 @@ public class GcmPushListenerService extends FirebaseMessagingService { } } - private String getReactedText(String loc_key, String[] args) { + private String getReactedText(String loc_key, Object[] args) { switch (loc_key) { case "REACT_TEXT": { return LocaleController.formatString("PushReactText", R.string.PushReactText, args); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 8f0d23579..74e6c6cbd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -14,8 +14,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; @@ -859,7 +857,7 @@ public class ImageLoader { if (args.length >= 3 && "pcache".equals(args[2])) { precache = true; } else { - precache = SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH; + precache = !cacheImage.filter.contains("nolimit") && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 4a05d3b82..36b91a936 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -27,6 +27,8 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.view.View; +import androidx.annotation.Keep; + import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AnimatedFileDrawable; @@ -34,8 +36,6 @@ import org.telegram.ui.Components.LoadingStickerDrawable; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RecyclableDrawable; -import androidx.annotation.Keep; - import java.util.ArrayList; public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate { @@ -263,6 +263,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private boolean centerRotation; private ImageReceiverDelegate delegate; private float currentAlpha; + private float previousAlpha = 1f; private long lastUpdateAlphaTime; private byte crossfadeAlpha = 1; private boolean manualAlphaAnimator; @@ -360,7 +361,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (strippedBitmap != null) { setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", strippedBitmap, null, parentObject, 0); } else if (hasStripped) { - setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_STRIPPED), "50_50", avatarDrawable, parentObject, 0); + setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_STRIPPED), "50_50_b", avatarDrawable, parentObject, 0); } else { setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, parentObject, 0); } @@ -578,6 +579,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg updateDrawableRadius(staticThumbDrawable); } currentAlpha = 1.0f; + previousAlpha = 1f; if (staticThumbDrawable instanceof SvgHelper.SvgDrawable) { ((SvgHelper.SvgDrawable) staticThumbDrawable).setParent(this); @@ -746,6 +748,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentSize = 0; currentCacheType = 0; currentAlpha = 1; + previousAlpha = 1f; if (setImageBackup != null) { setImageBackup.clear(); @@ -1335,6 +1338,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentAlpha += dt / (float) crossfadeDuration; if (currentAlpha > 1) { currentAlpha = 1; + previousAlpha = 1f; if (crossfadeImage != null) { recycleBitmap(null, 2); crossfadeShader = null; @@ -1410,6 +1414,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } if (drawable != null) { if (crossfadeAlpha != 0) { + if (previousAlpha != 1f && (drawable == currentImageDrawable || drawable == currentMediaDrawable) && staticThumbDrawable != null) { + drawDrawable(canvas, staticThumbDrawable, (int) (overrideAlpha * 255), shaderToUse, orientation); + } if (crossfadeWithThumb && animationNotReady) { drawDrawable(canvas, drawable, (int) (overrideAlpha * 255), shaderToUse, orientation); } else { @@ -1443,7 +1450,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (thumbDrawable instanceof SvgHelper.SvgDrawable || thumbDrawable instanceof Emoji.EmojiDrawable) { alpha = (int) (overrideAlpha * 255 * (1.0f - currentAlpha)); } else { - alpha = (int) (overrideAlpha * 255); + alpha = (int) (overrideAlpha * previousAlpha * 255); } drawDrawable(canvas, thumbDrawable, alpha, thumbShaderToUse, thumbOrientation); if (alpha != 255 && thumbDrawable instanceof Emoji.EmojiDrawable) { @@ -2077,7 +2084,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else if (currentImageDrawable instanceof RLottieDrawable) { allowCorssfade = staticThumbDrawable instanceof LoadingStickerDrawable || staticThumbDrawable instanceof SvgHelper.SvgDrawable || staticThumbDrawable instanceof Emoji.EmojiDrawable; } - if (allowCorssfade && (currentThumbDrawable == null && staticThumbDrawable == null || currentAlpha == 1.0f || forceCrossfade)) { + if (allowCorssfade && (currentThumbDrawable != null || staticThumbDrawable != null || forceCrossfade)) { + previousAlpha = currentAlpha; currentAlpha = 0.0f; lastUpdateAlphaTime = System.currentTimeMillis(); crossfadeWithThumb = crossfadeImage != null || currentThumbDrawable != null || staticThumbDrawable != null; @@ -2101,6 +2109,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg boolean allowCorssfade = true; if (!memCache && !forcePreview || forceCrossfade) { if (currentThumbDrawable == null && staticThumbDrawable == null || currentAlpha == 1.0f || forceCrossfade) { + previousAlpha = currentAlpha; currentAlpha = 0.0f; lastUpdateAlphaTime = System.currentTimeMillis(); crossfadeWithThumb = crossfadeImage != null || currentThumbDrawable != null || staticThumbDrawable != null; @@ -2139,7 +2148,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else { currentAlpha = 0.0f; lastUpdateAlphaTime = System.currentTimeMillis(); - crossfadeWithThumb = staticThumbDrawable != null && currentImageKey == null && currentMediaKey == null; + crossfadeWithThumb = staticThumbDrawable != null; } } else { currentAlpha = 1.0f; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 44aec5cbf..d81fc08ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -414,10 +414,10 @@ public class LocaleController { } return languagesDict.get(key.toLowerCase().replace("-", "_")); } - public LocaleInfo getLanguageByPlural(String plural) { + public LocaleInfo getBuiltinLanguageByPlural(String plural) { Collection values = languagesDict.values(); for (LocaleInfo l : values) - if (l.pluralLangCode != null && l.pluralLangCode.equals(plural)) + if (l.pathToFile != null && l.pathToFile.equals("remote") && l.pluralLangCode != null && l.pluralLangCode.equals(plural)) return l; return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 80637b205..87f0c4d03 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -10,7 +10,6 @@ package org.telegram.messenger; import android.app.Activity; import android.content.Context; -import android.content.Entity; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ShortcutManager; @@ -355,9 +354,15 @@ public class MediaDataController extends BaseController { ImageReceiver imageReceiver = new ImageReceiver(); TLRPC.TL_availableReaction reaction = reactions.get(i); imageReceiver.setImage(ImageLocation.getForDocument(reaction.activate_animation), null, null, null, 0, 1); - imageReceiver.setImage(ImageLocation.getForDocument(reaction.appear_animation), null, null, null, 0, 1); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); + + imageReceiver = new ImageReceiver(); + 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.static_icon), null, null, null, 0, 1); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.reactionsDidLoad); }); @@ -4589,23 +4594,31 @@ public class MediaDataController extends BaseController { } } - public static void addTextStyleRuns(TLRPC.DraftMessage msg, Spannable text) { - addTextStyleRuns(msg.entities, msg.message, text); + public static void addTextStyleRuns(MessageObject msg, Spannable text) { + addTextStyleRuns(msg.messageOwner.entities, msg.messageText, text, -1); } - public static void addTextStyleRuns(MessageObject msg, Spannable text) { - addTextStyleRuns(msg.messageOwner.entities, msg.messageText, text); + public static void addTextStyleRuns(TLRPC.DraftMessage msg, Spannable text, int allowedFlags) { + addTextStyleRuns(msg.entities, msg.message, text, allowedFlags); + } + + public static void addTextStyleRuns(MessageObject msg, Spannable text, int allowedFlags) { + addTextStyleRuns(msg.messageOwner.entities, msg.messageText, text, allowedFlags); } public static void addTextStyleRuns(ArrayList entities, CharSequence messageText, Spannable text) { + addTextStyleRuns(entities, messageText, text, -1); + } + + public static void addTextStyleRuns(ArrayList entities, CharSequence messageText, Spannable text, int allowedFlags) { for (TextStyleSpan prevSpan : text.getSpans(0, text.length(), TextStyleSpan.class)) text.removeSpan(prevSpan); - for (TextStyleSpan.TextStyleRun run : MediaDataController.getTextStyleRuns(entities, messageText)) { + for (TextStyleSpan.TextStyleRun run : MediaDataController.getTextStyleRuns(entities, messageText, allowedFlags)) { MediaDataController.addStyleToText(new TextStyleSpan(run), run.start, run.end, text, true); } } - public static ArrayList getTextStyleRuns(ArrayList entities, CharSequence text) { + public static ArrayList getTextStyleRuns(ArrayList entities, CharSequence text, int allowedFlags) { ArrayList runs = new ArrayList<>(); ArrayList entitiesCopy = new ArrayList<>(entities); @@ -4654,6 +4667,8 @@ public class MediaDataController extends BaseController { newRun.urlEntity = entity; } + newRun.flags &= allowedFlags; + for (int b = 0, N2 = runs.size(); b < N2; b++) { TextStyleSpan.TextStyleRun run = runs.get(b); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index bcc950d7d..377478938 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -98,9 +98,9 @@ public class MessageObject { public CharSequence caption; public MessageObject replyMessageObject; public int type = 1000; - public boolean reactionsVisibleOnScreen; public long reactionsLastCheckTime; public String customName; + public boolean reactionsChanged; private int isRoundVideoCached; public long eventId; public int contentType; @@ -6275,6 +6275,7 @@ public class MessageObject { } } } + reactionsChanged = true; return false; } @@ -6308,6 +6309,7 @@ public class MessageObject { action.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); action.reaction = reaction; } + reactionsChanged = true; return true; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 7ffc00709..a3a6dfe31 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -28,8 +28,6 @@ import android.util.SparseIntArray; import androidx.collection.LongSparseArray; import androidx.core.app.NotificationManagerCompat; -import com.google.android.exoplayer2.util.Log; - import org.telegram.SQLite.SQLiteCursor; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.messenger.support.LongSparseLongArray; @@ -135,11 +133,7 @@ public class MessagesController extends BaseController implements NotificationCe private LongSparseArray> pollsToCheck = new LongSparseArray<>(); private int pollsToCheckSize; private long lastViewsCheckTime; - - private LongSparseArray> reactionsToCheck = new LongSparseArray<>(); - private long lastReactionsCheckTime; - private LongSparseArray> reactionsTempDialogs = new LongSparseArray<>(); - + public ArrayList dialogFilters = new ArrayList<>(); public SparseArray dialogFiltersById = new SparseArray<>(); private boolean loadingSuggestedFilters; @@ -2610,7 +2604,6 @@ public class MessagesController extends BaseController implements NotificationCe channelViewsToSend.clear(); pollsToCheck.clear(); pollsToCheckSize = 0; - reactionsToCheck.clear(); dialogsServerOnly.clear(); dialogsForward.clear(); allDialogs.clear(); @@ -2842,12 +2835,6 @@ public class MessagesController extends BaseController implements NotificationCe object.pollVisibleOnScreen = false; } } - array = reactionsToCheck.get(dialogId); - if (array != null) { - for (int i = 0; i < array.size(); i++) { - array.valueAt(i).reactionsVisibleOnScreen = false; - } - } } } Utilities.stageQueue.postRunnable(() -> { @@ -5399,57 +5386,6 @@ public class MessagesController extends BaseController implements NotificationCe } } int currentServerTime = getConnectionsManager().getCurrentTime(); - if (Math.abs(System.currentTimeMillis() - lastReactionsCheckTime) >= 15000) { - lastReactionsCheckTime = System.currentTimeMillis(); - if (reactionsToCheck.size() > 0) { - AndroidUtilities.runOnUIThread(() -> { - long time = SystemClock.elapsedRealtime(); - for (int a = 0, N = reactionsToCheck.size(); a < N; a++) { - SparseArray array = reactionsToCheck.valueAt(a); - if (array == null) { - continue; - } - reactionsTempDialogs.clear(); - for (int b = 0, N2 = array.size(); b < N2; b++) { - MessageObject messageObject = array.valueAt(b); - List ids = reactionsTempDialogs.get(messageObject.getDialogId()); - if (ids == null) { - reactionsTempDialogs.put(messageObject.getDialogId(), ids = new ArrayList<>()); - } - ids.add(messageObject.getId()); - - int timeout = 15000; - if (Math.abs(time - messageObject.reactionsLastCheckTime) < timeout) { - if (!messageObject.reactionsVisibleOnScreen) { - array.remove(messageObject.getId()); - N2--; - b--; - } - } else { - messageObject.reactionsLastCheckTime = time; - } - } - if (array.size() == 0) { - reactionsToCheck.remove(reactionsToCheck.keyAt(a)); - N--; - a--; - } - } - - for (int i = 0; i < reactionsTempDialogs.size(); i++) { - TLRPC.TL_messages_getMessagesReactions req = new TLRPC.TL_messages_getMessagesReactions(); - req.peer = getInputPeer(reactionsTempDialogs.keyAt(i)); - req.id.addAll(reactionsTempDialogs.valueAt(i)); - getConnectionsManager().sendRequest(req, (response, error) -> { - if (error == null) { - TLRPC.Updates updates = (TLRPC.Updates) response; - processUpdates(updates, false); - } - }); - } - }); - } - } if (Math.abs(System.currentTimeMillis() - lastViewsCheckTime) >= 5000) { lastViewsCheckTime = System.currentTimeMillis(); if (channelViewsToSend.size() != 0) { @@ -8607,26 +8543,22 @@ public class MessagesController extends BaseController implements NotificationCe }); } - public void addToReactionsQueue(long dialogId, ArrayList visibleObjects) { - SparseArray array = reactionsToCheck.get(dialogId); - if (array == null) { - reactionsToCheck.put(dialogId, array = new SparseArray<>()); + public void loadReactionsForMessages(long dialogId, ArrayList visibleObjects) { + if (visibleObjects.isEmpty()) { + return; } - for (int a = 0, N = array.size(); a < N; a++) { - MessageObject object = array.valueAt(a); - object.reactionsVisibleOnScreen = false; + TLRPC.TL_messages_getMessagesReactions req = new TLRPC.TL_messages_getMessagesReactions(); + req.peer = getInputPeer(dialogId); + for (int i = 0; i < visibleObjects.size(); i++) { + MessageObject messageObject = visibleObjects.get(i); + req.id.add(messageObject.getId()); } - int time = getConnectionsManager().getCurrentTime(); - for (int a = 0, N = visibleObjects.size(); a < N; a++) { - MessageObject messageObject = visibleObjects.get(a); - int id = messageObject.getId(); - MessageObject object = array.get(id); - if (object != null) { - object.reactionsVisibleOnScreen = true; - } else { - array.put(id, messageObject); + getConnectionsManager().sendRequest(req, (response, error) -> { + if (error == null) { + TLRPC.Updates updates = (TLRPC.Updates) response; + processUpdates(updates, false); } - } + }); } public void addToPollsQueue(long dialogId, ArrayList visibleObjects) { @@ -14044,7 +13976,7 @@ public class MessagesController extends BaseController implements NotificationCe return info.messages; } TLRPC.Chat chat = getChat(-dialogId); - if (!ChatObject.isChannel(chat) || chat.megagroup || chat.gigagroup) { + if (!ChatObject.isChannel(chat)) { return null; } info = new SponsoredMessagesInfo(); @@ -14926,7 +14858,7 @@ public class MessagesController extends BaseController implements NotificationCe } public void markSponsoredAsRead(long dialog_id, MessageObject object) { - sponsoredMessages.remove(dialog_id); + // sponsoredMessages.remove(dialog_id); } public void deleteMessagesRange(long dialogId, long channelId, int minDate, int maxDate, boolean forAll, Runnable callback) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 5f592a475..70c6cd1aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -2663,8 +2663,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe return; } TLRPC.TL_messages_sendReaction req = new TLRPC.TL_messages_sendReaction(); - req.peer = getMessagesController().getInputPeer(messageObject.getDialogId()); - req.msg_id = messageObject.getId(); + if (messageObject.messageOwner.isThreadMessage) { + req.peer = getMessagesController().getInputPeer(messageObject.getFromChatId()); + req.msg_id = messageObject.messageOwner.fwd_from.saved_from_msg_id; + } else { + req.peer = getMessagesController().getInputPeer(messageObject.getDialogId()); + req.msg_id = messageObject.getId(); + } if (reaction != null) { req.reaction = reaction.toString(); req.flags |= 1; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 2e5629ea7..459459798 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -485,6 +485,14 @@ public class TLRPC { photo_big = new TL_fileLocationToBeDeprecated(); photo_big.volume_id = -photo_id; photo_big.local_id = 'c'; + + if (stripped_thumb != null && Build.VERSION.SDK_INT >= 21) { + try { + strippedBitmap = new BitmapDrawable(ImageLoader.getStrippedPhotoBitmap(stripped_thumb, "b")); + } catch (Throwable e) { + FileLog.e(e); + } + } } public void serializeToStream(AbstractSerializedData stream) { @@ -30395,6 +30403,14 @@ public class TLRPC { photo_big = new TL_fileLocationToBeDeprecated(); photo_big.volume_id = -photo_id; photo_big.local_id = 'c'; + + if (stripped_thumb != null && Build.VERSION.SDK_INT >= 21) { + try { + strippedBitmap = new BitmapDrawable(ImageLoader.getStrippedPhotoBitmap(stripped_thumb, "b")); + } catch (Throwable e) { + FileLog.e(e); + } + } } public void serializeToStream(AbstractSerializedData stream) { @@ -54106,6 +54122,7 @@ public class TLRPC { if ((flags & 33554432) != 0) { stream.writeInt32(ttl_period); } + writeAttachPath(stream); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index c29e0a8ff..0b7e615f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -22,6 +22,7 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -35,6 +36,8 @@ import android.widget.ScrollView; import androidx.annotation.Keep; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.NotificationCenter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index 4ab153f05..958e2084f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -65,6 +65,8 @@ 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; @@ -7525,7 +7527,9 @@ public class Theme { try { String[] wallpaperLink = new String[1]; HashMap colors = getThemeFileValues(new File(pathToFile), null, wallpaperLink); - checkIsDark(colors, accent.parentTheme); + if (accent != null) { + checkIsDark(colors, accent.parentTheme); + } Integer wallpaperFileOffset = colors.get("wallpaperFileOffset"); Bitmap bitmap = Bitmaps.createBitmap(560, 678, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 66d017cc9..3fa3592c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -8,6 +8,11 @@ package org.telegram.ui; +import static org.telegram.messenger.MessageObject.POSITION_FLAG_BOTTOM; +import static org.telegram.messenger.MessageObject.POSITION_FLAG_LEFT; +import static org.telegram.messenger.MessageObject.POSITION_FLAG_RIGHT; +import static org.telegram.messenger.MessageObject.POSITION_FLAG_TOP; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -169,11 +174,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; -import static org.telegram.messenger.MessageObject.POSITION_FLAG_BOTTOM; -import static org.telegram.messenger.MessageObject.POSITION_FLAG_LEFT; -import static org.telegram.messenger.MessageObject.POSITION_FLAG_RIGHT; -import static org.telegram.messenger.MessageObject.POSITION_FLAG_TOP; - public class ArticleViewer implements NotificationCenter.NotificationCenterDelegate { private Activity parentActivity; @@ -5954,7 +5954,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg currentBlock = block; parentBlock = null; currentDocument = parentAdapter.getDocumentWithId(currentBlock.video_id); - isGif = MessageObject.isGifDocument(currentDocument)/* && currentBlock.autoplay*/; + isGif = MessageObject.isVideoDocument(currentDocument) || MessageObject.isGifDocument(currentDocument)/* && currentBlock.autoplay*/; isFirst = first; channelCell.setVisibility(INVISIBLE); updateButtonState(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 68d207363..516523100 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -129,7 +129,6 @@ import org.telegram.ui.Components.SeekBar; import org.telegram.ui.Components.SeekBarAccessibilityDelegate; import org.telegram.ui.Components.SeekBarWaveform; import org.telegram.ui.Components.SlotsDrawable; -import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.Components.StaticLayoutEx; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TimerParticles; @@ -139,6 +138,7 @@ import org.telegram.ui.Components.URLSpanBrowser; import org.telegram.ui.Components.URLSpanMono; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.VideoForwardDrawable; +import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.PhotoViewer; import org.telegram.ui.PinchToZoomHelper; import org.telegram.ui.SecretMediaViewer; @@ -155,11 +155,14 @@ import java.util.concurrent.atomic.AtomicReference; public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate, ImageReceiver.ImageReceiverDelegate, DownloadController.FileDownloadProgressListener, TextSelectionHelper.SelectableView, NotificationCenter.NotificationCenterDelegate { + public boolean clipToGroupBounds; + public RadialProgress2 getRadialProgress() { return radialProgress; } boolean enterTransitionInPorgress; + public void setEnterTransitionInProgress(boolean b) { enterTransitionInPorgress = b; invalidate(); @@ -241,6 +244,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } + public void setScrimReaction(String scrimViewReaction) { + reactionsLayoutInBubble.setScrimReaction(scrimViewReaction); + } + + public void drawScrimReaction(Canvas canvas, String scrimViewReaction) { + reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress, scrimViewReaction); + + } + public interface ChatMessageCellDelegate { default void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { } @@ -1123,7 +1135,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate x -= textX - (block.isRtl() ? currentMessageObject.textXOffset : 0); y -= block.textYOffset; final int line = block.textLayout.getLineForVertical(y); - final int off = block.textLayout.getOffsetForHorizontal(line, x); + final int off = block.charactersOffset + block.textLayout.getOffsetForHorizontal(line, x); final float left = block.textLayout.getLineLeft(line); if (left <= x && left + block.textLayout.getLineWidth(line) >= x) { @@ -1147,6 +1159,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate try { LinkPath path = obtainNewUrlPath(false); int[] pos = getRealSpanStartAndEnd(buffer, pressedLink); + pos[0] -= block.charactersOffset; + pos[1] -= block.charactersOffset; path.setCurrentLayout(block.textLayout, pos[0], 0); block.textLayout.getSelectionPath(pos[0], pos[1], path); if (pos[1] >= block.charactersEnd) { @@ -1163,8 +1177,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } path = obtainNewUrlPath(false); path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.textYOffset - block.textYOffset); - nextBlock.textLayout.getSelectionPath(0, pos[1], path); - if (pos[1] < nextBlock.charactersEnd - 1) { + int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset; + nextBlock.textLayout.getSelectionPath(0, p1, path); + if (p1 < nextBlock.charactersEnd - 1) { break; } } @@ -1184,9 +1199,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } path = obtainNewUrlPath(false); offsetY -= nextBlock.height; - path.setCurrentLayout(nextBlock.textLayout, pos[0], offsetY); - nextBlock.textLayout.getSelectionPath(pos[0], pos[1], path); - if (pos[0] > nextBlock.charactersOffset) { + int p0 = pos[0] + block.charactersOffset - nextBlock.charactersOffset; + int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset; + path.setCurrentLayout(nextBlock.textLayout, p0, offsetY); + nextBlock.textLayout.getSelectionPath(p0, p1, path); + if (p0 > nextBlock.charactersOffset) { break; } } @@ -1896,7 +1913,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } currentMessageObject.audioProgress = p; updatePlayingMessageProgress(); - } if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + } + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { if (roundSeekbarTouched != 0) { if (event.getAction() == MotionEvent.ACTION_UP) { float localX = x - photoImage.getCenterX(); @@ -2137,7 +2155,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasCaptionLayout() && x >= captionX && y >= captionY && x <= captionX + captionLayout.getWidth() && y <= captionY + captionLayout.getHeight()) { for (SpoilerEffect eff : captionSpoilers) { - if (eff.getBounds().contains((int)(x - captionX), (int)(y - captionY))) { + if (eff.getBounds().contains((int) (x - captionX), (int) (y - captionY))) { spoilerPressed = eff; isCaptionSpoilerPressed = true; return true; @@ -2166,7 +2184,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate float rad = (float) Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); isSpoilerRevealing = true; - spoilerPressed.setOnRippleEndCallback(()->post(()->{ + spoilerPressed.setOnRippleEndCallback(() -> post(() -> { isSpoilerRevealing = false; getMessageObject().isSpoilersRevealed = true; if (isCaptionSpoilerPressed) { @@ -2198,7 +2216,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ChatMessageCell cell = (ChatMessageCell) ch; if (cell.getMessageObject() != null && cell.getMessageObject().getReplyMsgId() == getMessageObject().getId()) { if (!cell.replySpoilers.isEmpty()) { - cell.replySpoilers.get(0).setOnRippleEndCallback(()->post(()->{ + cell.replySpoilers.get(0).setOnRippleEndCallback(() -> post(() -> { cell.getMessageObject().replyMessageObject.isSpoilersRevealed = true; cell.replySpoilers.clear(); cell.invalidate(); @@ -2599,7 +2617,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } return false; } - return reactionsLayoutInBubble.chekTouchEvent(event); + return reactionsLayoutInBubble.chekTouchEvent(event); } @@ -2841,7 +2859,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate this.parentViewTopOffset = parentOffset; parentHeight = parent; } - if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground() || drawSideButton != 0 || !botButtons.isEmpty()) ) { + if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground() || drawSideButton != 0 || !botButtons.isEmpty())) { invalidate(); } @@ -3580,16 +3598,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setMediaStartEndTime(-1, -1); boolean canChangeRadius = true; - if (currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0)) { - if (currentPosition != null) { - reactionsLayoutInBubble.setMessage(groupedMessages.findPrimaryMessageObject(), !messageObject.shouldDrawReactionsInLayout(), resourcesProvider); + + if (messageIdChanged || messageObject.reactionsChanged) { + messageObject.reactionsChanged = false; + if (currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0)) { + if (currentPosition != null) { + reactionsLayoutInBubble.setMessage(groupedMessages.findPrimaryMessageObject(), !messageObject.shouldDrawReactionsInLayout(), resourcesProvider); + } else { + reactionsLayoutInBubble.setMessage(messageObject, !messageObject.shouldDrawReactionsInLayout(), resourcesProvider); + } } else { - reactionsLayoutInBubble.setMessage(messageObject, !messageObject.shouldDrawReactionsInLayout(), resourcesProvider); + reactionsLayoutInBubble.setMessage(null, false, resourcesProvider); } - } else { - reactionsLayoutInBubble.setMessage(null, false, resourcesProvider); } + if (messageChanged) { firstVisibleBlockNum = 0; lastVisibleBlockNum = 0; @@ -3895,11 +3918,11 @@ 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; + if ((hasLinkPreview || hasInvoicePreview) && !drawInstantView) { + reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(6); + reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(3); + } + totalHeight += reactionsLayoutInBubble.totalHeight; } } if (drawPinnedTop) { @@ -4515,7 +4538,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", w, h); if (webDocument != null) { - /*TODO*/photoImage.setImage(ImageLocation.getForWebFile(webDocument), currentPhotoFilter, null, null, webDocument.size, null, messageObject, 1); + /*TODO*/ + photoImage.setImage(ImageLocation.getForWebFile(webDocument), currentPhotoFilter, null, null, webDocument.size, null, messageObject, 1); } else { if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { if (messageObject.mediaExists) { @@ -4548,13 +4572,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setAllowDecodeSingleFrame(true); photoImage.setAllowStartAnimation(true); photoImage.startAnimation(); - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, null, documentAttach.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, null, documentAttach.size, null, messageObject, 0); autoPlayingMedia = true; } else { if (currentPhotoObjectThumb != null) { - /*TODO*/photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); } else { - /*TODO*/photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, 0, null, messageObject, 0); } } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { @@ -4572,23 +4599,28 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate autoPlayingMedia = true; TLRPC.VideoSize videoSize = MessageObject.getDocumentVideoThumb(document); if (!messageObject.mediaExists && videoSize != null && (currentPhotoObject == null || currentPhotoObjectThumb == null)) { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? filter : currentPhotoFilterThumb, null, document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? filter : currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } else { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } } else { - /*TODO*/photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, 0, null, currentMessageObject, 0); + /*TODO*/ + photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, 0, null, currentMessageObject, 0); } } else { boolean photoExist = messageObject.mediaExists; String fileName = FileLoader.getAttachFileName(currentPhotoObject); if (hasGamePreview || photoExist || DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { photoNotSet = false; - /*TODO*/photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); } else { photoNotSet = true; if (currentPhotoObjectThumb != null) { - /*TODO*/photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), String.format(Locale.US, "%d_%d_b", w, h), 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), String.format(Locale.US, "%d_%d_b", w, h), 0, null, messageObject, 0); } else { photoImage.setImageBitmap((Drawable) null); } @@ -5285,7 +5317,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (!reactionsLayoutInBubble.isSmall && !reactionsLayoutInBubble.isEmpty) { - // reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(12); + if (captionLayout != null && currentPosition != null && currentMessagesGroup != null && currentMessagesGroup.isDocuments) { + reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); + } reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8); measureTime(messageObject); int timeLeft = backgroundWidth - reactionsLayoutInBubble.lastLineX - AndroidUtilities.dp(24); @@ -5850,7 +5884,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { minCaptionWidth = (int) (Math.min(getParentWidth(), AndroidUtilities.displaySize.y) * 0.65f); } - if (!messageObject.needDrawBluredPreview() && (currentCaption != null || (!reactionsLayoutInBubble.isEmpty && !reactionsLayoutInBubble.isSmall) && photoWidth < minCaptionWidth)) { + if (!messageObject.needDrawBluredPreview() && (currentCaption != null || (!reactionsLayoutInBubble.isEmpty && !reactionsLayoutInBubble.isSmall)) && photoWidth < minCaptionWidth) { widthForCaption = minCaptionWidth; fixPhotoWidth = true; } else { @@ -6024,13 +6058,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate TLRPC.Document document = messageObject.getDocument(); if (currentMessageObject.videoEditedInfo != null && currentMessageObject.videoEditedInfo.canAutoPlaySourceVideo()) { - /*TODO*/photoImage.setImage(ImageLocation.getForPath(currentMessageObject.videoEditedInfo.originalPath), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForPath(currentMessageObject.videoEditedInfo.originalPath), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0); photoImage.setMediaStartEndTime(currentMessageObject.videoEditedInfo.startTime / 1000, currentMessageObject.videoEditedInfo.endTime / 1000); } else { if (!messageIdChanged && !dataChanged) { photoImage.setCrossfadeWithOldImage(true); } - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0); } } else if (messageObject.type == MessageObject.TYPE_PHOTO) { if (messageObject.useCustomPhoto) { @@ -6081,45 +6117,55 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setCrossfadeDuration(250); } if (localFile == 0 && videoSize != null && (currentPhotoObject == null || currentPhotoObjectThumb == null)) { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? currentPhotoFilter : currentPhotoFilterThumb, null, document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? currentPhotoFilter : currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } else { if (isRoundVideo && !messageIdChanged && photoImage.hasStaticThumb()) { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, null, null, photoImage.getStaticThumb(), document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, null, null, photoImage.getStaticThumb(), document.size, null, messageObject, 0); } else { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } } } else if (localFile == 1) { - /*TODO*/photoImage.setImage(ImageLocation.getForPath(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForPath(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, 0, null, messageObject, 0); } else { if (videoSize != null && (currentPhotoObject == null || currentPhotoObjectThumb == null)) { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? currentPhotoFilter : currentPhotoFilterThumb, null, document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? currentPhotoFilter : currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } else { - /*TODO*/photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } } } else { if (messageObject.videoEditedInfo != null && messageObject.type == MessageObject.TYPE_ROUND_VIDEO && !currentMessageObject.needDrawBluredPreview()) { - /*TODO*/photoImage.setImage(ImageLocation.getForPath(messageObject.videoEditedInfo.originalPath), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForPath(messageObject.videoEditedInfo.originalPath), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); photoImage.setMediaStartEndTime(currentMessageObject.videoEditedInfo.startTime / 1000, currentMessageObject.videoEditedInfo.endTime / 1000); } else { if (!messageIdChanged && !currentMessageObject.needDrawBluredPreview()) { photoImage.setCrossfadeWithOldImage(true); photoImage.setCrossfadeDuration(250); } - /*TODO*/photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); } } } else { if (messageObject.videoEditedInfo != null && messageObject.type == MessageObject.TYPE_ROUND_VIDEO && !currentMessageObject.needDrawBluredPreview()) { - /*TODO*/photoImage.setImage(ImageLocation.getForPath(messageObject.videoEditedInfo.originalPath), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForPath(messageObject.videoEditedInfo.originalPath), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); photoImage.setMediaStartEndTime(currentMessageObject.videoEditedInfo.startTime / 1000, currentMessageObject.videoEditedInfo.endTime / 1000); } else { if (!messageIdChanged && !currentMessageObject.needDrawBluredPreview()) { photoImage.setCrossfadeWithOldImage(true); photoImage.setCrossfadeDuration(250); } - /*TODO*/photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + /*TODO*/ + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); } } } @@ -6275,7 +6321,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate FileLog.e(e); } - if (messageObject.type == MessageObject.TYPE_PHOTO || messageObject.type == MessageObject.TYPE_VIDEO) { + if (messageObject.type == MessageObject.TYPE_PHOTO || messageObject.type == MessageObject.TYPE_VIDEO) { totalHeight += AndroidUtilities.dp(6); } @@ -7313,6 +7359,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { str = LocaleController.getString("InstantView", R.string.InstantView); } + if (currentMessageObject.isSponsored()) { + int buttonWidth = (int) (Theme.chat_instantViewPaint.measureText(str) + AndroidUtilities.dp(10 + 24 + 10 + 31)); + if (backgroundWidth < buttonWidth) { + backgroundWidth = buttonWidth; + } + } int mWidth = backgroundWidth - AndroidUtilities.dp(10 + 24 + 10 + 31); instantViewLayout = new StaticLayout(TextUtils.ellipsize(str, Theme.chat_instantViewPaint, mWidth, TextUtils.TruncateAt.END), Theme.chat_instantViewPaint, mWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (drawInstantViewType == 8) { @@ -7398,6 +7450,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } int lastSize; + @SuppressLint("DrawAllocation") @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { @@ -7638,7 +7691,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { invalidate(); } - } else if (!drawPause && roundToPauseProgress != 0f){ + } else if (!drawPause && roundToPauseProgress != 0f) { roundToPauseProgress -= 16 / 150f; if (roundToPauseProgress < 0) { roundToPauseProgress = 0f; @@ -7654,7 +7707,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { invalidate(); } - } else if (!drawTouchedSeekbar && roundToPauseProgress2 != 0f){ + } else if (!drawTouchedSeekbar && roundToPauseProgress2 != 0f) { roundToPauseProgress2 -= 16 / 150f; if (roundToPauseProgress2 < 0) { roundToPauseProgress2 = 0f; @@ -8072,7 +8125,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate toSeekBarProgress = 1f; } invalidate(); - } else if (!showSeekbar && toSeekBarProgress != 0){ + } else if (!showSeekbar && toSeekBarProgress != 0) { toSeekBarProgress -= 16f / 100f; if (toSeekBarProgress < 0) { toSeekBarProgress = 0; @@ -8184,7 +8237,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate updateCaptionLayout(); } updateReactionLayoutPosition(); - if (!currentMessageObject.preview && (currentPosition == null || currentMessagesGroup != null && currentMessagesGroup.isDocuments) && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInPorgress && currentMessageObject.isVoice())) { + if (!currentMessageObject.preview && (currentPosition == null || (currentMessagesGroup != null && currentMessagesGroup.isDocuments && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0)) && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInPorgress && currentMessageObject.isVoice())) { drawCaptionLayout(canvas, false, 1f); } @@ -8521,7 +8574,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int size = AndroidUtilities.dp(48); buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); - radialProgress.setProgressRect((int) buttonX, (int ) buttonY, (int) buttonX + size, (int) buttonY + size); + radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + size, (int) buttonY + size); } if (delegate == null || delegate.getPinchToZoomHelper() == null || !delegate.getPinchToZoomHelper().isInOverlayModeFor(this)) { if (alpha != 1f) { @@ -9740,7 +9793,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (setCurrentDiceValue(!memCache && !currentMessageObject.wasUnread)) { return; } - if (!thumb && !currentMessageObject.mediaExists && !currentMessageObject.attachPathExists && (currentMessageObject.type == 0 && (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_NONE || documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) || currentMessageObject.type == MessageObject.TYPE_PHOTO)){ + if (!thumb && !currentMessageObject.mediaExists && !currentMessageObject.attachPathExists && (currentMessageObject.type == 0 && (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_NONE || documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) || currentMessageObject.type == MessageObject.TYPE_PHOTO)) { currentMessageObject.mediaExists = true; updateButtonState(false, true, false); } @@ -10660,7 +10713,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public boolean isDrawPinnedBottom() { - return mediaBackground || drawPinnedBottom; + boolean forceMediaByGroup = currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) == 0 && currentMessagesGroup.isDocuments; + return mediaBackground || drawPinnedBottom || forceMediaByGroup; } public void drawCheckBox(Canvas canvas) { @@ -10719,6 +10773,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } float transitionYOffsetForDrawables; + public void setDrawableBoundsInner(Drawable drawable, int x, int y, int w, int h) { if (drawable != null) { transitionYOffsetForDrawables = (y + h + transitionParams.deltaBottom) - ((int) (y + h + transitionParams.deltaBottom)); @@ -10853,73 +10908,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.restore(); } - if (!transitionParams.animateBackgroundBoundsInner) { - if (!transitionParams.transitionBotButtons.isEmpty()) { - drawBotButtons(canvas, transitionParams.transitionBotButtons, 1f - transitionParams.animateChangeProgress); - } - if (!botButtons.isEmpty()) { - drawBotButtons(canvas, botButtons, transitionParams.animateChangeProgress); - } - } - - if (drawSideButton != 0) { - if (currentMessageObject.isOutOwner()) { - sideStartX = getCurrentBackgroundLeft() - AndroidUtilities.dp(8 + 32); - if (currentMessagesGroup != null) { - sideStartX += currentMessagesGroup.transitionParams.offsetLeft - animationOffsetX; - } - } else { - sideStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8); - if (currentMessagesGroup != null) { - sideStartX += currentMessagesGroup.transitionParams.offsetRight - animationOffsetX; - } - } - sideStartY = layoutHeight - AndroidUtilities.dp(41) + transitionParams.deltaBottom; - if (currentMessagesGroup != null) { - sideStartY += currentMessagesGroup.transitionParams.offsetBottom; - if (currentMessagesGroup.transitionParams.backgroundChangeBounds) { - sideStartY -= getTranslationY(); - } - } - if (!currentMessageObject.isOutOwner() && isRoundVideo && isAvatarVisible) { - float offsetSize = (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f; - float offsetX = isPlayingRound ? offsetSize : 0; - if (transitionParams.animatePlayingRound) { - offsetX = (isPlayingRound ? transitionParams.animateChangeProgress : (1f - transitionParams.animateChangeProgress)) * offsetSize; - } - sideStartX -= offsetX; - } - if (drawSideButton == 3) { - if (!(enterTransitionInPorgress && !currentMessageObject.isVoice())) { - drawCommentButton(canvas, 1f); - } - } else { - rect.set(sideStartX, sideStartY, sideStartX + AndroidUtilities.dp(32), sideStartY + AndroidUtilities.dp(32)); - applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); - canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), getThemedPaint(sideButtonPressed ? Theme.key_paint_chatActionBackgroundSelected : Theme.key_paint_chatActionBackground)); - if (hasGradientService()) { - canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); - } - - if (drawSideButton == 2) { - Drawable goIconDrawable = getThemedDrawable(Theme.key_drawable_goIcon); - if (currentMessageObject.isOutOwner()) { - setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(10), sideStartY + AndroidUtilities.dp(9)); - canvas.save(); - canvas.scale(-1, 1, goIconDrawable.getBounds().centerX(), goIconDrawable.getBounds().centerY()); - } else { - setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(12), sideStartY + AndroidUtilities.dp(9)); - } - goIconDrawable.draw(canvas); - if (currentMessageObject.isOutOwner()) { - canvas.restore(); - } - } else { - Drawable drawable = getThemedDrawable(Theme.key_drawable_shareIcon); - setDrawableBounds(drawable, sideStartX + AndroidUtilities.dp(8), sideStartY + AndroidUtilities.dp(9)); - drawable.draw(canvas); - } - } + if (!clipToGroupBounds) { + drawOutboundsContent(canvas); } if (replyNameLayout != null) { @@ -11399,12 +11389,74 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public void drawOutboundsContent(Canvas canvas) { - if (transitionParams.animateBackgroundWidth) { - if (!transitionParams.transitionBotButtons.isEmpty()) { - drawBotButtons(canvas, transitionParams.transitionBotButtons, 1f - transitionParams.animateChangeProgress); + if (!transitionParams.transitionBotButtons.isEmpty() && transitionParams.animateBotButtonsChanged) { + drawBotButtons(canvas, transitionParams.transitionBotButtons, 1f - transitionParams.animateChangeProgress); + } + if (!botButtons.isEmpty()) { + drawBotButtons(canvas, botButtons, transitionParams.animateBotButtonsChanged ? transitionParams.animateChangeProgress : 1f); + } + drawSideButton(canvas); + } + + private void drawSideButton(Canvas canvas) { + if (drawSideButton != 0) { + if (currentMessageObject.isOutOwner()) { + sideStartX = getCurrentBackgroundLeft() - AndroidUtilities.dp(8 + 32); + if (currentMessagesGroup != null) { + sideStartX += currentMessagesGroup.transitionParams.offsetLeft - animationOffsetX; + } + } else { + sideStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8); + if (currentMessagesGroup != null) { + sideStartX += currentMessagesGroup.transitionParams.offsetRight - animationOffsetX; + } } - if (!botButtons.isEmpty()) { - drawBotButtons(canvas, botButtons, transitionParams.animateChangeProgress); + sideStartY = layoutHeight - AndroidUtilities.dp(41) + transitionParams.deltaBottom; + if (currentMessagesGroup != null) { + sideStartY += currentMessagesGroup.transitionParams.offsetBottom; + if (currentMessagesGroup.transitionParams.backgroundChangeBounds) { + sideStartY -= getTranslationY(); + } + } + if (!currentMessageObject.isOutOwner() && isRoundVideo && isAvatarVisible) { + float offsetSize = (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f; + float offsetX = isPlayingRound ? offsetSize : 0; + if (transitionParams.animatePlayingRound) { + offsetX = (isPlayingRound ? transitionParams.animateChangeProgress : (1f - transitionParams.animateChangeProgress)) * offsetSize; + } + sideStartX -= offsetX; + } + if (drawSideButton == 3) { + if (!(enterTransitionInPorgress && !currentMessageObject.isVoice())) { + drawCommentButton(canvas, 1f); + } + } else { + rect.set(sideStartX, sideStartY, sideStartX + AndroidUtilities.dp(32), sideStartY + AndroidUtilities.dp(32)); + applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); + canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), getThemedPaint(sideButtonPressed ? Theme.key_paint_chatActionBackgroundSelected : Theme.key_paint_chatActionBackground)); + if (hasGradientService()) { + canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); + } + + if (drawSideButton == 2) { + Drawable goIconDrawable = getThemedDrawable(Theme.key_drawable_goIcon); + if (currentMessageObject.isOutOwner()) { + setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(10), sideStartY + AndroidUtilities.dp(9)); + canvas.save(); + canvas.scale(-1, 1, goIconDrawable.getBounds().centerX(), goIconDrawable.getBounds().centerY()); + } else { + setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(12), sideStartY + AndroidUtilities.dp(9)); + } + goIconDrawable.draw(canvas); + if (currentMessageObject.isOutOwner()) { + canvas.restore(); + } + } else { + + Drawable drawable = getThemedDrawable(Theme.key_drawable_shareIcon); + setDrawableBounds(drawable, sideStartX + AndroidUtilities.dp(8), sideStartY + AndroidUtilities.dp(9)); + drawable.draw(canvas); + } } } } @@ -11449,7 +11501,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int additionalTop = 0; if (currentPosition != null) { if ((currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { - additionalTop -= AndroidUtilities.dp( 3); + additionalTop -= AndroidUtilities.dp(3); } } return additionalTop + (drawPinnedTop ? 0 : AndroidUtilities.dp(1)); @@ -11730,7 +11782,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate forwardNameXLocal = transitionParams.animateForwardNameX; } if (currentMessageObject.isOutOwner() && currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO && transitionParams.animatePlayingRound || isPlayingRound) { - forwardNameXLocal -= AndroidUtilities.dp (78) * (isPlayingRound ? transitionParams.animateChangeProgress : (1f - transitionParams.animateChangeProgress)); + forwardNameXLocal -= AndroidUtilities.dp(78) * (isPlayingRound ? transitionParams.animateChangeProgress : (1f - transitionParams.animateChangeProgress)); } forwardNameY = AndroidUtilities.dp(12); @@ -12055,16 +12107,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawCaptionLayout(canvas, captionLayout, selectionOnly, alpha); } - if ((currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0)) && !reactionsLayoutInBubble.isSmall) { + if (!selectionOnly && (currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0)) && !reactionsLayoutInBubble.isSmall) { if (reactionsLayoutInBubble.drawServiceShaderBackground) { applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); } if (reactionsLayoutInBubble.drawServiceShaderBackground || !transitionParams.animateBackgroundBoundsInner || currentPosition != null) { - reactionsLayoutInBubble.draw(canvas, transitionParams.animateChange ? transitionParams.animateChangeProgress : 1f); + reactionsLayoutInBubble.draw(canvas, transitionParams.animateChange ? transitionParams.animateChangeProgress : 1f, null); } else { canvas.save(); canvas.clipRect(0, 0, getMeasuredWidth(), getBackgroundDrawableBottom() + transitionParams.deltaBottom); - reactionsLayoutInBubble.draw(canvas, transitionParams.animateChange ? transitionParams.animateChangeProgress : 1f); + reactionsLayoutInBubble.draw(canvas, transitionParams.animateChange ? transitionParams.animateChangeProgress : 1f, null); canvas.restore(); } @@ -12328,6 +12380,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate float captionY = this.captionY; float captionX = this.captionX; + if (transitionParams.animateBackgroundBoundsInner) { if (transitionParams.transformGroupToSingleMessage) { captionY -= getTranslationY(); @@ -12340,23 +12393,22 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - int restore = Integer.MIN_VALUE; if (renderingAlpha != 1.0f) { - rect.set(captionX, captionY, captionX + captionLayout.getWidth(), captionY + captionLayout.getHeight()); + rect.set(captionX, captionY, captionX + captionLayout.getWidth(), captionY + captionLayout.getHeight()); restore = canvas.saveLayerAlpha(rect, (int) (255 * renderingAlpha), Canvas.ALL_SAVE_FLAG); } if (transitionParams.animateBackgroundBoundsInner && currentBackgroundDrawable != null && currentMessagesGroup == null) { Rect r = currentBackgroundDrawable.getBounds(); if (currentMessageObject.isOutOwner() && !mediaBackground && !pinnedBottom) { canvas.clipRect( - r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), - r.right - AndroidUtilities.dp(10), r.bottom - AndroidUtilities.dp(4) + getBackgroundDrawableLeft() + transitionParams.deltaLeft + AndroidUtilities.dp(4), getBackgroundDrawableTop() + transitionParams.deltaTop + AndroidUtilities.dp(4), + getBackgroundDrawableRight() + transitionParams.deltaRight - AndroidUtilities.dp(10), getBackgroundDrawableBottom() + transitionParams.deltaBottom - AndroidUtilities.dp(4) ); } else { canvas.clipRect( - r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), - r.right - AndroidUtilities.dp(4), r.bottom - AndroidUtilities.dp(4) + getBackgroundDrawableLeft() + transitionParams.deltaLeft + AndroidUtilities.dp(4), getBackgroundDrawableTop() + transitionParams.deltaTop + AndroidUtilities.dp(4), + getBackgroundDrawableRight() + transitionParams.deltaRight - AndroidUtilities.dp(4), getBackgroundDrawableBottom() + transitionParams.deltaBottom - AndroidUtilities.dp(4) ); } } @@ -12418,7 +12470,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean drawSelectionBackground = i == 1; if (i == 1) { curentAplha *= currentSelectedBackgroundAlpha; - } else if (!shouldDrawTimeOnMedia()){ + } else if (!shouldDrawTimeOnMedia()) { curentAplha *= (1f - currentSelectedBackgroundAlpha); } if (transitionParams.animateShouldDrawTimeOnMedia && transitionParams.animateChangeProgress != 1f) { @@ -12501,7 +12553,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (transitionParams.animateBackgroundBoundsInner) { timeX += animationOffsetX; timeTitleTimeX += animationOffsetX; - } if (reactionsLayoutInBubble.isSmall) { if (transitionParams.animateBackgroundBoundsInner && transitionParams.deltaRight != 0) { @@ -12510,6 +12561,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate timeTitleTimeX += reactionsLayoutInBubble.getCurrentWidth(transitionParams.animateChangeProgress); } } + if (transitionParams.animateEditedEnter) { + timeTitleTimeX -= transitionParams.animateEditedWidthDiff * (1f - transitionParams.animateChangeProgress); + } int timeYOffset; if (shouldDrawTimeOnMedia()) { @@ -12550,11 +12604,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate float additionalX = -timeLayout.getLineLeft(0); if (reactionsLayoutInBubble.isSmall) { updateReactionLayoutPosition(); - reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress); + reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress, null); } if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 || repliesLayout != null || isPinned) { additionalX += this.timeWidth - timeLayout.getLineWidth(0); + if (reactionsLayoutInBubble.isSmall && !reactionsLayoutInBubble.isEmpty) { + additionalX -= reactionsLayoutInBubble.width; + } int currentStatus = transitionParams.createStatusDrawableParams(); if (transitionParams.lastStatusDrawableParams >= 0 && transitionParams.lastStatusDrawableParams != currentStatus && !statusDrawableAnimationInProgress) { @@ -12597,7 +12654,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate transitionParams.lastStatusDrawableParams = transitionParams.createStatusDrawableParams(); if (drawClock && fromParent && getParent() != null) { - ((View)getParent()).invalidate(); + ((View) getParent()).invalidate(); } } @@ -12618,7 +12675,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate float additionalX = -timeLayout.getLineLeft(0); if (reactionsLayoutInBubble.isSmall) { updateReactionLayoutPosition(); - reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress); + reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress, null); } if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 || (repliesLayout != null || transitionParams.animateReplies) || (isPinned || transitionParams.animatePinned)) { additionalX += this.timeWidth - timeLayout.getLineWidth(0); @@ -12666,7 +12723,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate transitionParams.lastStatusDrawableParams = transitionParams.createStatusDrawableParams(); if (drawClock && fromParent && getParent() != null) { - ((View)getParent()).invalidate(); + ((View) getParent()).invalidate(); } } @@ -12727,7 +12784,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!outDrawClock && !isBroadcast && !outIsBroadcast && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1) { drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, true, drawSelectionBackground); } else { - drawStatusDrawable(canvas, outDrawCheck1, outDrawCheck2, outDrawClock, outDrawError, outIsBroadcast, alpha, bigRadius, timeYOffset, layoutHeight,1f - statusDrawableProgress, false, drawSelectionBackground); + drawStatusDrawable(canvas, outDrawCheck1, outDrawCheck2, outDrawClock, outDrawError, outIsBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, 1f - statusDrawableProgress, false, drawSelectionBackground); drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, false, drawSelectionBackground); } } else { @@ -12760,7 +12817,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return; } statusDrawableProgress = 0f; - statusDrawableAnimator = ValueAnimator.ofFloat(0,1f); + statusDrawableAnimator = ValueAnimator.ofFloat(0, 1f); if (moveCheckTransition) { statusDrawableAnimator.setDuration(220); } else { @@ -12808,7 +12865,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } clockDrawable.setColor(clockColor); float timeY = shouldDrawTimeOnMedia() ? photoImage.getImageY2() + additionalTimeOffsetY - AndroidUtilities.dp(9.0f) : layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9.5f : 8.5f) + timeYOffset; - setDrawableBounds(clockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), timeY - clockDrawable.getIntrinsicHeight()); + setDrawableBounds(clockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), timeY - clockDrawable.getIntrinsicHeight()); clockDrawable.setAlpha((int) (255 * alpha)); if (useScale) { canvas.save(); @@ -13170,7 +13227,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.translate(AndroidUtilities.dp(4) * (1f - progress), 0); } drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutCheckReadSelected : Theme.key_drawable_msgOutCheckRead); - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); } else { drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutCheckSelected : Theme.key_drawable_msgOutCheck); setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); @@ -13343,7 +13400,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { imageW = 0; } - if (drawLoadingProgress && loadingProgressLayout != null){ + if (drawLoadingProgress && loadingProgressLayout != null) { imageW = 0; infoW = (int) loadingProgressLayout.getLineWidth(0); } else { @@ -13471,7 +13528,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate StaticLayout docTitleLayout = this.docTitleLayout; StaticLayout infoLayout = this.infoLayout; float alpha = 1f; - if (transitionParams.animateLocationIsExpired){ + if (transitionParams.animateLocationIsExpired) { progress = transitionParams.lastDrawLocationExpireProgress; text = transitionParams.lastDrawLocationExpireText; docTitleLayout = transitionParams.lastDrawDocTitleLayout; @@ -14945,7 +15002,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) { sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); } else if (action == AccessibilityNodeInfo.ACTION_CLICK) { - if (virtualViewId >= LINK_CAPTION_IDS_START) { + if (virtualViewId >= LINK_CAPTION_IDS_START) { ClickableSpan link = getLinkById(virtualViewId, true); if (link != null) { delegate.didPressUrl(ChatMessageCell.this, link, false); @@ -14998,16 +15055,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate delegate.didPressReplyMessage(ChatMessageCell.this, currentMessageObject.getReplyMsgId()); } } else if (virtualViewId == FORWARD) { - if (delegate != null) { - if (currentForwardChannel != null) { - delegate.didPressChannelAvatar(ChatMessageCell.this, currentForwardChannel, currentMessageObject.messageOwner.fwd_from.channel_post, lastTouchX, lastTouchY); - } else if (currentForwardUser != null) { - delegate.didPressUserAvatar(ChatMessageCell.this, currentForwardUser, lastTouchX, lastTouchY); - } else if (currentForwardName != null) { - delegate.didPressHiddenForward(ChatMessageCell.this); - } - } - } else if (virtualViewId == COMMENT) { + if (delegate != null) { + if (currentForwardChannel != null) { + delegate.didPressChannelAvatar(ChatMessageCell.this, currentForwardChannel, currentMessageObject.messageOwner.fwd_from.channel_post, lastTouchX, lastTouchY); + } else if (currentForwardUser != null) { + delegate.didPressUserAvatar(ChatMessageCell.this, currentForwardUser, lastTouchX, lastTouchY); + } else if (currentForwardName != null) { + delegate.didPressHiddenForward(ChatMessageCell.this); + } + } + } else if (virtualViewId == COMMENT) { if (delegate != null) { if (isRepliesChat) { delegate.didPressSideButton(ChatMessageCell.this); @@ -15211,6 +15268,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private StaticLayout animateTimeLayout; private int animateTimeWidth; private int lastTimeWidth; + private int animateEditedWidthDiff; private boolean lastDrawingEdited; boolean animateReplaceCaptionLayout; @@ -15264,6 +15322,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate float lastForwardNameX; int animateForwardNameWidth; int lastForwardNameWidth; + boolean animateBotButtonsChanged; public void recordDrawingState() { wasDraw = true; @@ -15283,10 +15342,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastDrawingCaptionY = captionY; lastDrawingCaptionLayout = captionLayout; - if (!botButtons.isEmpty()) { - lastDrawBotButtons.clear(); - lastDrawBotButtons.addAll(botButtons); - } + lastDrawBotButtons.clear(); + lastDrawBotButtons.addAll(botButtons); if (commentLayout != null) { lastCommentsCount = getRepliesCount(); @@ -15384,13 +15441,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate spannableStringBuilder.append(text.substring(editedStr.length())); spannableStringBuilder.setSpan(new EmptyStubSpan(), 0, editedStr.length(), 0); animateTimeLayout = new StaticLayout(spannableStringBuilder, Theme.chat_timePaint, timeTextWidth + AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + animateEditedWidthDiff = timeWidth - lastTimeWidth; } else { + animateEditedWidthDiff = 0; animateEditedLayout = null; animateTimeLayout = lastTimeLayout; } animateEditedEnter = true; animateTimeWidth = lastTimeWidth; animateFromTimeX = lastTimeX; + shouldAnimateTimeX = true; changed = true; } } @@ -15421,7 +15481,22 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (!lastDrawBotButtons.isEmpty() || !botButtons.isEmpty()) { - transitionBotButtons.addAll(lastDrawBotButtons); + if (lastDrawBotButtons.size() != botButtons.size()) { + animateBotButtonsChanged = true; + } + if (!animateBotButtonsChanged) { + for (int i = 0; i < botButtons.size(); i++) { + BotButton button1 = botButtons.get(i); + BotButton button2 = lastDrawBotButtons.get(i); + if (button1.x != button2.x || button1.width != button2.width) { + animateBotButtonsChanged = true; + break; + } + } + } + if (animateBotButtonsChanged) { + transitionBotButtons.addAll(lastDrawBotButtons); + } } if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 2ed16c261..e694cb3bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -68,12 +68,12 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.StaticLayoutEx; import org.telegram.ui.Components.StatusDrawable; import org.telegram.ui.Components.SwipeGestureSettingsView; +import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.URLSpanNoUnderlineBold; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.DialogsActivity; -import org.telegram.ui.Components.SwipeGestureSettingsView; import java.util.ArrayList; import java.util.List; @@ -955,7 +955,7 @@ public class DialogCell extends BaseCell { mess = mess.substring(0, 150); } Spannable messSpan = new SpannableStringBuilder(mess); - MediaDataController.addTextStyleRuns(draftMessage, messSpan); + MediaDataController.addTextStyleRuns(draftMessage, messSpan, TextStyleSpan.FLAG_STYLE_SPOILER); SpannableStringBuilder stringBuilder = AndroidUtilities.formatSpannable(messageFormat, AndroidUtilities.replaceNewLines(messSpan), messageNameString); if (!useForceThreeLines && !SharedConfig.useThreeLinesLayout) { @@ -1089,7 +1089,7 @@ public class DialogCell extends BaseCell { emoji = "\uD83D\uDCCE "; } SpannableStringBuilder msgBuilder = new SpannableStringBuilder(mess); - MediaDataController.addTextStyleRuns(message.messageOwner.entities, message.caption, msgBuilder); + MediaDataController.addTextStyleRuns(message.messageOwner.entities, message.caption, msgBuilder, TextStyleSpan.FLAG_STYLE_SPOILER); stringBuilder = AndroidUtilities.formatSpannable(messageFormat, new SpannableStringBuilder(emoji).append(AndroidUtilities.replaceNewLines(msgBuilder)), messageNameString); } else if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; @@ -1148,7 +1148,7 @@ public class DialogCell extends BaseCell { mess = AndroidUtilities.replaceNewLines(mess); } mess = new SpannableStringBuilder(mess); - MediaDataController.addTextStyleRuns(message, (Spannable) mess); + MediaDataController.addTextStyleRuns(message, (Spannable) mess, TextStyleSpan.FLAG_STYLE_SPOILER); stringBuilder = AndroidUtilities.formatSpannable(messageFormat, mess, messageNameString); } else { stringBuilder = SpannableStringBuilder.valueOf(""); @@ -1218,7 +1218,7 @@ public class DialogCell extends BaseCell { messageString = emoji + str; } else { SpannableStringBuilder msgBuilder = new SpannableStringBuilder(message.caption); - MediaDataController.addTextStyleRuns(message.messageOwner.entities, message.caption, msgBuilder); + MediaDataController.addTextStyleRuns(message.messageOwner.entities, message.caption, msgBuilder, TextStyleSpan.FLAG_STYLE_SPOILER); messageString = new SpannableStringBuilder(emoji).append(msgBuilder); } } else { @@ -1241,7 +1241,7 @@ public class DialogCell extends BaseCell { messageString = AndroidUtilities.ellipsizeCenterEnd(messageString, message.highlightedWords.get(0), w, currentMessagePaint, 130).toString(); } else { SpannableStringBuilder stringBuilder = new SpannableStringBuilder(msgText); - MediaDataController.addTextStyleRuns(message, stringBuilder); + MediaDataController.addTextStyleRuns(message, stringBuilder, TextStyleSpan.FLAG_STYLE_SPOILER); messageString = stringBuilder; } AndroidUtilities.highlightText(messageString, message.highlightedWords, resourcesProvider); @@ -2497,11 +2497,6 @@ public class DialogCell extends BaseCell { swipeMessageTextLayout.draw(canvas); canvas.restore(); } - -// if (width / 2 < AndroidUtilities.dp(40)) { - // canvas.drawText(swipeMessage, getMeasuredWidth() - AndroidUtilities.dp(43) - width / 2, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 62 : 59), Theme.dialogs_archiveTextPaint); -// } - canvas.restore(); } else if (translationDrawable != null) { translationDrawable.stop(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 540be0bbe..370d966cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -61,6 +61,7 @@ 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; @@ -92,8 +93,6 @@ import androidx.collection.LongSparseArray; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.core.graphics.ColorUtils; -import androidx.dynamicanimation.animation.SpringAnimation; -import androidx.dynamicanimation.animation.SpringForce; import androidx.recyclerview.widget.ChatListItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManagerFixed; @@ -670,6 +669,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Paint scrimPaint; private View scrimView; + private String scrimViewReaction; private int popupAnimationIndex = -1; private AnimatorSet scrimAnimatorSet; private ActionBarPopupWindow scrimPopupWindow; @@ -859,6 +859,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private PinchToZoomHelper pinchToZoomHelper; private EmojiAnimationsOverlay emojiAnimationsOverlay; + public float drawingChatLisViewYoffset; public void deleteHistory(int dateSelectedStart, int dateSelectedEnd, boolean forAll) { chatAdapter.frozenMessages.clear(); @@ -3121,7 +3122,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (scrimView != null) { - canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + if (scrimViewReaction == null) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + } float listTop = chatListView.getY() + chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4); MessageObject.GroupedMessages scrimGroup; if (scrimView instanceof ChatMessageCell) { @@ -3129,9 +3132,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { scrimGroup = null; } - boolean groupedBackgroundWasDraw = false; - int count = chatListView.getChildCount(); for (int num = 0; num < count; num++) { View child = chatListView.getChildAt(num); @@ -3193,10 +3194,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not invalidate(); } - float viewClipLeft = Math.max(chatListView.getLeft(), chatListView.getLeft() + child.getX()); - float viewClipTop = Math.max(listTop, chatListView.getTop() + child.getY()); - float viewClipRight = Math.min(chatListView.getRight(), chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); - float viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + child.getY() + child.getMeasuredHeight()); + float viewClipLeft = chatListView.getLeft(); + float viewClipTop = listTop; + float viewClipRight = chatListView.getRight(); + float viewClipBottom = chatListView.getY() + chatListView.getMeasuredHeight(); + + if (cell == null || !cell.getTransitionParams().animateBackgroundBoundsInner) { + viewClipLeft = Math.max(viewClipLeft, chatListView.getLeft() + child.getX()); + viewClipTop = Math.max(viewClipTop, chatListView.getTop() + child.getY()); + viewClipRight = Math.min(viewClipRight, chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); + viewClipBottom = Math.min(viewClipBottom, chatListView.getY() + child.getY() + child.getMeasuredHeight()); + } if (viewClipTop < viewClipBottom) { if (child.getAlpha() != 1f) { @@ -3206,6 +3214,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (cell != null) { cell.setInvalidatesParent(true); + cell.setScrimReaction(scrimViewReaction); } canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY()); @@ -3217,6 +3226,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (cell != null) { cell.setInvalidatesParent(false); + cell.setScrimReaction(null); } } @@ -3233,6 +3243,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawCaptionAfter.add(cell); } } + if (scrimViewReaction != null && cell != null) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + + if (viewClipTop < viewClipBottom) { + if (child.getAlpha() != 1f) { + canvas.saveLayerAlpha(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom, (int) (255 * child.getAlpha()), Canvas.ALL_SAVE_FLAG); + } else { + canvas.save(); + } + canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); + canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY()); + cell.drawScrimReaction(canvas, scrimViewReaction); + canvas.restore(); + } + } } int size = drawTimeAfter.size(); @@ -4301,7 +4326,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; } - canvas.translate(0, -pullingDownOffset - transitionOffset); + canvas.translate(0, drawingChatLisViewYoffset = -pullingDownOffset - transitionOffset); drawChatBackgroundElements(canvas); super.dispatchDraw(canvas); canvas.restore(); @@ -4611,11 +4636,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not b - AndroidUtilities.dp(4) ); } - result = super.drawChild(canvas, child, drawingTime); + if (cell != null && clipToGroupBounds) { + cell.clipToGroupBounds = true; + result = super.drawChild(canvas, child, drawingTime); + cell.clipToGroupBounds = false; + } else { + result = super.drawChild(canvas, child, drawingTime); + } if (clipToGroupBounds) { canvas.restore(); } - if (cell != null && cell.getTransitionParams().animateBackgroundBoundsInner) { + if (cell != null && clipToGroupBounds) { canvas.save(); canvas.translate(cell.getX(), cell.getY()); cell.drawOutboundsContent(canvas); @@ -5055,6 +5086,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Runnable finishRunnable; + @Override + public void checkIsRunning() { + if (scrollAnimationIndex == -1) { + scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, allowedNotificationsDuringChatListAnimations, false); + } + } + @Override public void onAnimationStart() { if (scrollAnimationIndex == -1) { @@ -5297,6 +5335,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } pullingDownOffset += dy * k; + ReactionsEffectOverlay.onScrolled((int) (dy * k)); chatListView.invalidate(); } if (pullingDownOffset == 0) { @@ -8126,7 +8165,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not topBottom[1] = chatListView.getBottom(); topBottom[0] = chatListView.getTop() + chatListViewPaddingTop - AndroidUtilities.dp(4); }); - emojiAnimationsOverlay = new EmojiAnimationsOverlay(ChatActivity.this, contentView, chatListView, currentAccount, dialog_id, threadMessageId); return fragmentView; } @@ -11219,12 +11257,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatListView != null && !messages.isEmpty() && !pinchToZoomHelper.isInOverlayMode()) { int position = 0; if (skipSponsored) { - while (position < messages.size()) { - if (!messages.get(position).isSponsored()) { - break; - } - position++; - } + position += getSponsoredMessagesCount(); } chatLayoutManager.scrollToPositionWithOffset(position, 0); chatListView.stopScroll(); @@ -11518,14 +11551,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int maxUnreadDate = Integer.MIN_VALUE; int recyclerChatViewHeight = (contentView.getHeightWithKeyboard() - (inPreviewMode ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop()); pollsToCheck.clear(); - reactionsToCheck.clear(); - float cilpTop = chatListViewPaddingTop; + float clipTop = chatListViewPaddingTop; + long currentTime = System.currentTimeMillis(); + int maxAdapterPosition = -1; + int minAdapterPosition = -1; for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); MessageObject messageObject = null; + int adapterPosition = chatListView.getChildAdapterPosition(view); + if (adapterPosition >= 0) { + if (adapterPosition > maxAdapterPosition || maxAdapterPosition == -1) { + maxAdapterPosition = adapterPosition; + } + if (adapterPosition < minAdapterPosition || minAdapterPosition == -1) { + minAdapterPosition = adapterPosition; + } + } int top = (int) view.getY(); int bottom = top + view.getMeasuredHeight(); - if (bottom <= cilpTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight()) { + if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight()) { continue; } @@ -11602,11 +11646,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.type == MessageObject.TYPE_POLL && messageObject.getId() > 0) { pollsToCheck.add(messageObject); } - if (messageObject.getId() > 0 && messageObject.messageOwner.action == null) { - reactionsToCheck.add(messageObject); - } } - if (bottom <= cilpTop) { + if (bottom <= clipTop) { if (view instanceof ChatActionCell && messageObject.isDateObject) { view.setAlpha(0); } @@ -11668,7 +11709,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } getMessagesController().addToPollsQueue(dialog_id, pollsToCheck); - getMessagesController().addToReactionsQueue(dialog_id, reactionsToCheck); + if (maxAdapterPosition >= 0 && minAdapterPosition >= 0) { + int from = minAdapterPosition - chatAdapter.messagesStartRow - 10; + int to = maxAdapterPosition - chatAdapter.messagesStartRow + 10; + if (from < 0) { + from = 0; + } + if (to > messages.size()) { + to = messages.size(); + } + reactionsToCheck.clear(); + for (int i = from; i < to; i++) { + MessageObject messageObject = messages.get(i); + if (threadMessageObject != messageObject && messageObject.getId() > 0 && messageObject.messageOwner.action == null && (currentTime - messageObject.reactionsLastCheckTime) > 15000L) { + messageObject.reactionsLastCheckTime = currentTime; + reactionsToCheck.add(messageObject); + } + } + getMessagesController().loadReactionsForMessages(dialog_id, reactionsToCheck); + } if (videoPlayerContainer != null) { if (!foundTextureViewMessage) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); @@ -11700,7 +11759,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); if (minDateChild != null) { boolean showFloatingView = false; - if (minDateChild.getY() > cilpTop || currentFloatingTopIsNotMessage) { + if (minDateChild.getY() > clipTop || currentFloatingTopIsNotMessage) { if (minDateChild.getAlpha() != 1.0f) { minDateChild.setAlpha(1.0f); } @@ -11724,7 +11783,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } showFloatingView = true; } - float offset = minDateChild.getY() + minDateChild.getMeasuredHeight() - cilpTop; + float offset = minDateChild.getY() + minDateChild.getMeasuredHeight() - clipTop; if (offset > floatingDateView.getMeasuredHeight() && offset < floatingDateView.getMeasuredHeight() * 2) { if (chatListView.getChildAdapterPosition(minDateChild) == chatAdapter.messagesStartRow + messages.size() - 1) { showFloatingView = false; @@ -15424,7 +15483,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); if (messageObject != null) { MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); - chatAdapter.notifyDataSetChanged(true); + messageObject.forceUpdate = true; + messageObject.reactionsChanged = true; + updateMessageAnimated(messageObject, true); } } } else if (id == NotificationCenter.didVerifyMessagesStickers) { @@ -16194,7 +16255,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean sponsoredMessagesAdded; private void addSponsoredMessages(boolean animated) { - if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || currentChat.megagroup || currentChat.gigagroup || !forwardEndReached[0]) { + if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0]) { return; } ArrayList arrayList = getMessagesController().getSponsoredMessages(dialog_id); @@ -16925,6 +16986,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (placeToPaste > messages.size()) { placeToPaste = messages.size(); } + + int sponsoredMessagesCount = getSponsoredMessagesCount(); + if (!isAd && placeToPaste < sponsoredMessagesCount) { + placeToPaste = sponsoredMessagesCount; + } if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); @@ -17072,7 +17138,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollToTopOnResume = true; } else { forceScrollToTop = true; - moveScrollToLastMessage(false); + moveScrollToLastMessage(true); } } } else { @@ -17085,6 +17151,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not canShowPagedownButton = true; updatePagedownButtonVisibility(true); } + } else { + if (child != null) { + chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom()); + } } if (newMentionsCount != 0 && mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); @@ -17129,6 +17199,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateReplyMessageHeader(true); } + private int getSponsoredMessagesCount() { + int sponsoredMessagesCount = 0; + while (sponsoredMessagesCount < messages.size()) { + if (!messages.get(sponsoredMessagesCount).isSponsored()) { + break; + } + sponsoredMessagesCount++; + } + return sponsoredMessagesCount; + } + private void processDeletedMessages(ArrayList markAsDeletedMessages, long channelId) { ArrayList removedIndexes = new ArrayList<>(); int loadIndex = 0; @@ -19768,6 +19849,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); scrimView = null; + scrimViewReaction = null; } if (!AndroidUtilities.isTablet()) { @@ -20103,7 +20185,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_EDIT); icons.add(R.drawable.msg_edit); } - if (!selectedObject.isOutOwner() && (messageText != null && messageText.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice()) && MessagesController.getGlobalMainSettings().getBoolean("translate_button", false)) { + if (selectedObject != null && selectedObject.contentType == 0 && (messageText != null && messageText.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice()) && MessagesController.getGlobalMainSettings().getBoolean("translate_button", false)) { items.add(LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); options.add(29); icons.add(R.drawable.msg_translate); @@ -20367,7 +20449,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(102); icons.add(R.drawable.msg_schedule); } - if (!selectedObject.isOutOwner() && (messageText != null && messageText.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice()) && MessagesController.getGlobalMainSettings().getBoolean("translate_button", false)) { + if (selectedObject != null && selectedObject.contentType == 0 && (messageText != null && messageText.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice()) && MessagesController.getGlobalMainSettings().getBoolean("translate_button", false)) { items.add(LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); options.add(29); icons.add(R.drawable.msg_translate); @@ -20488,11 +20570,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } + final AtomicBoolean waitForLangDetection = new AtomicBoolean(false); + final AtomicReference onLangDetectionDone = new AtomicReference(null); + Rect rect = new Rect(); List availableReacts = getMediaDataController().getEnabledReactionsList(); boolean isReactionsViewAvailable = !isSecretChat() && !isInScheduleMode() && currentUser == null && message.hasReactions() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && !availableReacts.isEmpty() && message.messageOwner.reactions.can_see_list; - boolean isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty() || (chatInfo == null && !ChatObject.isChannel(currentChat)) || currentUser != null) && !availableReacts.isEmpty(); + boolean isReactionsAvailable; + boolean needLoadReactionsChat = false; + if (message.isForwardedChannelPost()) { + TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(-message.getFromChatId()); + if (chatInfo == null) { + isReactionsAvailable = true; + needLoadReactionsChat = true; + } else { + isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty()) && !availableReacts.isEmpty(); + } + } else { + isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty() || (chatInfo == null && !ChatObject.isChannel(currentChat)) || currentUser != null) && !availableReacts.isEmpty(); + } boolean showMessageSeen = !isReactionsViewAvailable && !isInScheduleMode() && currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().chatReadMarkExpirePeriod) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count < getMessagesController().chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell); int flags = 0; @@ -20500,9 +20597,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not flags |= ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_USE_SWIPEBACK; } - final AtomicBoolean waitForLangDetection = new AtomicBoolean(false); - final AtomicReference onLangDetectionDone = new AtomicReference(null); - ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, themeDelegate, flags); popupLayout.setMinimumWidth(AndroidUtilities.dp(200)); Rect backgroundPaddings = new Rect(); @@ -20866,6 +20960,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } processSelectedOption(options.get(i)); scrimView = null; + scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); if (scrimPopupWindow != null) { @@ -20876,6 +20971,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not // "Translate" button String toLang = LocaleController.getInstance().getCurrentLocale().getLanguage(); final CharSequence finalMessageText = messageText; + TranslateAlert.OnLinkPress onLinkPress = (link) -> { + didPressMessageUrl(link, false, selectedObject, v instanceof ChatMessageCell ? (ChatMessageCell) v : null); + }; if (LanguageDetector.hasSupport()) { final String[] fromLang = { null }; cell.setVisibility(View.GONE); @@ -20895,7 +20993,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }, (Exception e) -> { - FileLog.e(e); + Log.e("mlkit", "failed to detect language in message"); + e.printStackTrace(); waitForLangDetection.set(false); if (onLangDetectionDone.get() != null) { onLangDetectionDone.get().run(); @@ -20907,9 +21006,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject == null || i >= options.size() || getParentActivity() == null) { return; } - boolean noForwards = currentChat != null && currentChat.noforwards; - TranslateAlert.showAlert(getParentActivity(), this, fromLang[0], toLang, finalMessageText, noForwards); + TranslateAlert.showAlert(getParentActivity(), this, fromLang[0], toLang, finalMessageText, currentChat != null && currentChat.noforwards, onLinkPress); scrimView = null; + scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); if (scrimPopupWindow != null) { @@ -20927,9 +21026,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject == null || i >= options.size() || getParentActivity() == null) { return; } - boolean noForwards = currentChat != null && currentChat.noforwards; - TranslateAlert.showAlert(getParentActivity(), this, "und", toLang, finalMessageText, noForwards); + TranslateAlert.showAlert(getParentActivity(), this, "und", toLang, finalMessageText, currentChat != null && currentChat.noforwards, onLinkPress); scrimView = null; + scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); if (scrimPopupWindow != null) { @@ -20948,6 +21047,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } return super.dispatchKeyEvent(event); } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean b = super.dispatchTouchEvent(ev); + if (ev.getAction() == MotionEvent.ACTION_DOWN && !b && scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } + return b; + } }; scrimPopupContainerLayout.setOnTouchListener(new View.OnTouchListener() { @@ -20973,48 +21081,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); - ReactionsContainerLayout reactionsLayout = new ReactionsContainerLayout(contentView.getContext(), getResourceProvider()); + ReactionsContainerLayout reactionsLayout = new ReactionsContainerLayout(contentView.getContext(), currentAccount, getResourceProvider()); if (isReactionsAvailable) { int pad = 22; 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)); - List l; - if (chatInfo != null) { - l = new ArrayList<>(chatInfo.available_reactions.size()); - for (String s : chatInfo.available_reactions) { - for (TLRPC.TL_availableReaction a : getMediaDataController().getEnabledReactionsList()) { - if (a.reaction.equals(s)) { - l.add(a); - break; - } - } - } - } else { - l = getMediaDataController().getEnabledReactionsList(); - } - reactionsLayout.setReactionsList(l); + reactionsLayout.setDelegate((rView, reaction) -> { selectReaction(primaryMessage, reactionsLayout, 0, 0, reaction, false); }); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 0, 0, -20); - int size = params.height - reactionsLayout.getPaddingTop() - reactionsLayout.getPaddingBottom(); - if (size * l.size() < AndroidUtilities.dp(200)) - params.width = ViewGroup.LayoutParams.WRAP_CONTENT; scrimPopupContainerLayout.addView(reactionsLayout, params); scrimPopupContainerLayout.reactionsLayout = reactionsLayout; + reactionsLayout.setMessage(message, chatInfo); reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { popupLayout.getSwipeBack().setOnSwipeBackProgressListener((layout, toProgress, progress) -> { if (toProgress == 0) { - reactionsLayout.setTransitionProgress(0); - reactionsLayout.setAlpha(1f); - new SpringAnimation(reactionsLayout, ReactionsContainerLayout.TRANSITION_PROGRESS_VALUE) - .setSpring(new SpringForce().setFinalPosition(100) - .setStiffness(240) - .setDampingRatio(0.7f)) - .start(); + reactionsLayout.startEnterAnimation(); } else if (toProgress == 1) reactionsLayout.setAlpha(1f - progress); }); @@ -21022,7 +21108,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } boolean showNoForwards = getMessagesController().isChatNoForwards(currentChat) && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED; - scrimPopupContainerLayout.addView(popupLayout, LayoutHelper.createLinearRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START, isReactionsAvailable ? 16 : 0, 0, isReactionsAvailable ? 36 : 0, 0)); + scrimPopupContainerLayout.addView(popupLayout, LayoutHelper.createLinearRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, 0, isReactionsAvailable ? 36 : 0, 0)); scrimPopupContainerLayout.popupWindowLayout = popupLayout; if (showNoForwards) { popupLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); @@ -21040,7 +21126,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FrameLayout fl = new FrameLayout(contentView.getContext()); fl.setBackground(shadowDrawable2); fl.addView(tv, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 11, 11, 11, 11)); - scrimPopupContainerLayout.addView(fl, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + scrimPopupContainerLayout.addView(fl, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, -8, isReactionsAvailable ? 36 : 0, 0)); } scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @@ -21077,6 +21163,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onAnimationEnd(Animator animation) { scrimView = null; + scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); } @@ -21114,7 +21201,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not popupX += location[0]; } int totalHeight = contentView.getHeight(); - int height = scrimPopupContainerLayout.getMeasuredHeight(); + int height = scrimPopupContainerLayout.getMeasuredHeight() + AndroidUtilities.dp(48); int keyboardHeight = contentView.measureKeyboardHeight(); if (keyboardHeight > AndroidUtilities.dp(20)) { totalHeight += keyboardHeight; @@ -21133,23 +21220,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } - scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, scrimPopupX = popupX, scrimPopupY = popupY); - if (isReactionsAvailable) { - reactionsLayout.setTransitionProgress(0); - new SpringAnimation(reactionsLayout, ReactionsContainerLayout.TRANSITION_PROGRESS_VALUE) - .setSpring(new SpringForce().setFinalPosition(100) - .setStiffness(240) - .setDampingRatio(0.7f)) - .start(); - } final int finalPopupX = scrimPopupX = popupX; final int finalPopupY = scrimPopupY = popupY; - Runnable showMenu = () -> scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); + Runnable showMenu = () -> { + scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); + if (isReactionsAvailable) { + reactionsLayout.startEnterAnimation(); + } + }; if (waitForLangDetection.get()) { onLangDetectionDone.set(showMenu); - } else { + } else showMenu.run(); - } chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); scrimView = v; @@ -21284,7 +21366,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }, 50); }); } else { - updateMessageAnimated(primaryMessage); + updateMessageAnimated(primaryMessage, true); ReactionsEffectOverlay.startAnimation(); } @@ -21297,7 +21379,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not //updateReactionRunnable.run(); if (fromDoubleTap) { - updateMessageAnimated(primaryMessage); + updateMessageAnimated(primaryMessage, true); updateReactionRunnable.run(); } AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); @@ -21306,7 +21388,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @SuppressLint("NotifyDataSetChanged") - private void updateMessageAnimated(MessageObject message) { + private void updateMessageAnimated(MessageObject message, boolean updateReactions) { if (chatAdapter == null) { return; } @@ -21318,6 +21400,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } for (int i = 0; i < group.messages.size(); i++) { group.messages.get(i).forceUpdate = true; + if (updateReactions) { + group.messages.get(i).reactionsChanged = true; + } } chatAdapter.notifyDataSetChanged(true); } else { @@ -22689,6 +22774,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (originalMessage != null && originalMessage.messageOwner.replies != null && chatActivity.threadMessageObject.messageOwner.replies != null) { originalMessage.messageOwner.replies.replies = chatActivity.threadMessageObject.messageOwner.replies.replies; } + if (originalMessage != null && originalMessage.messageOwner.reactions != null) { + chatActivity.threadMessageObject.messageOwner.reactions = originalMessage.messageOwner.reactions; + } presentFragment(chatActivity); if (isKeyboardVisible() && !chatActivity.hideKeyboardOnShow()) { chatActivity.chatActivityEnterView.getEditField().requestFocus(); @@ -23870,7 +23958,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (h == 0) { h = AndroidUtilities.dp(ReactedUsersListView.VISIBLE_ITEMS * ReactedUsersListView.ITEM_HEIGHT_DP); } - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST)); } }; @@ -23882,12 +23969,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not shadowDrawable2.getPadding(backgroundPaddings); scrimPopupContainerLayout.setBackground(shadowDrawable2); - int totalHeight = contentView.getHeight(); - int height = scrimPopupContainerLayout.getMeasuredHeight(); - int keyboardHeight = contentView.measureKeyboardHeight(); - if (keyboardHeight > AndroidUtilities.dp(20)) { - totalHeight += keyboardHeight; - } + ReactionsLayoutInBubble.ReactionButton button = cell.getReactionButton(reaction.reaction); if (button == null) { return; @@ -23896,7 +23978,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not float left = cell.reactionsLayoutInBubble.x + button.x; int[] loc = new int[2]; cell.getLocationInWindow(loc); - int finalTotalHeight = totalHeight; scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, cell.getPrimaryMessageObject(), reaction, false) .setOnProfileSelectedListener((view1, userId) -> { Bundle args = new Bundle(); @@ -23906,19 +23987,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } - }).setOnHeightChangedListener((view1, newHeight) -> { -// float delta = Math.max(0, loc[1] + bottom - scrimPopupY + backgroundPaddings.top); -// int h = scrimPopupContainerLayout.getHeight(); -// ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(240); -// anim.setInterpolator(CubicBezierInterpolator.DEFAULT); -// anim.addUpdateListener(animation -> { -// float val = (float) animation.getAnimatedValue(); -// float f = Math.min(delta * val, finalTotalHeight - newHeight); -// scrimPopupContainerLayout.setTranslationY(f); -// scrimPopupWindow.setHeight((int) (h + f)); -// }); -// anim.start(); - }), LayoutHelper.createFrame(200, LayoutHelper.WRAP_CONTENT)); + }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @Override @@ -23954,6 +24023,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onAnimationEnd(Animator animation) { scrimView = null; + scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); } @@ -23975,6 +24045,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); scrimPopupWindow.getContentView().setFocusableInTouchMode(true); + int totalHeight = contentView.getHeight(); + int height = scrimPopupContainerLayout.getMeasuredHeight(); + int keyboardHeight = contentView.measureKeyboardHeight(); + if (keyboardHeight > AndroidUtilities.dp(20)) { + totalHeight += keyboardHeight; + } + int popupX = (int) (left - AndroidUtilities.dp(28)); popupX = Math.max(AndroidUtilities.dp(6), Math.min(chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth(), popupX)); if (AndroidUtilities.isTablet()) { @@ -23984,14 +24061,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } int popupY; if (height < totalHeight) { - popupY = (int) (chatListView.getY() + cell.getY() + cell.getHeight()); - if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { - popupY += AndroidUtilities.dp(240) - height; - } - if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { - popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); - } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { - popupY = totalHeight - height - AndroidUtilities.dp(8); + if (height < totalHeight / 2f && chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y > totalHeight / 2f) { + popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y - height); + } else { + popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y + button.height); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; @@ -24001,6 +24074,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); scrimView = cell; + scrimViewReaction = reaction.reaction; cell.setInvalidatesParent(true); restartSticker(cell); contentView.invalidate(); @@ -26534,6 +26608,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Theme.applyTheme(activeTheme, false, isDark); } else { + if (ApplicationLoader.applicationContext != null) { + Theme.createChatResources(ApplicationLoader.applicationContext, false); + } currentColors = chatTheme.createColors(currentAccount, isDark ? 1 : 0); backgroundDrawable = getBackgroundDrawableFromTheme(chatTheme, prevPhase); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java index 127587bd3..8ec0d785d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java @@ -106,23 +106,7 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat enableReactionsCell.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); enableReactionsCell.setAnimatingToThumbInsteadOfTouch(true); enableReactionsCell.setOnClickListener(v -> { - boolean c = !enableReactionsCell.isChecked(); - enableReactionsCell.setChecked(c); - int clr = Theme.getColor(c ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked); - if (c) { - enableReactionsCell.setBackgroundColorAnimated(c, clr); - } else { - enableReactionsCell.setBackgroundColorAnimatedReverse(clr); - } - if (c) { - for (TLRPC.TL_availableReaction a : availableReactions) { - chatReactions.add(a.reaction); - } - listAdapter.notifyItemRangeInserted(1, 1 + availableReactions.size()); - } else { - chatReactions.clear(); - listAdapter.notifyItemRangeRemoved(1, 1 + availableReactions.size()); - } + setCheckedEnableReactionCell(!enableReactionsCell.isChecked()); }); ll.addView(enableReactionsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -185,8 +169,14 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat AvailableReactionCell cell = (AvailableReactionCell) view; TLRPC.TL_availableReaction react = availableReactions.get(position - 2); boolean nc = !chatReactions.contains(react.reaction); - if (nc) chatReactions.add(react.reaction); - else chatReactions.remove(react.reaction); + if (nc) { + chatReactions.add(react.reaction); + } else { + chatReactions.remove(react.reaction); + if (chatReactions.isEmpty()) { + setCheckedEnableReactionCell(false); + } + } cell.setChecked(nc, true); }); @@ -198,6 +188,28 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat return contentView; } + private void setCheckedEnableReactionCell(boolean c) { + if (enableReactionsCell.isChecked() == c) { + return; + } + enableReactionsCell.setChecked(c); + int clr = Theme.getColor(c ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked); + if (c) { + enableReactionsCell.setBackgroundColorAnimated(c, clr); + } else { + enableReactionsCell.setBackgroundColorAnimatedReverse(clr); + } + if (c) { + for (TLRPC.TL_availableReaction a : availableReactions) { + chatReactions.add(a.reaction); + } + listAdapter.notifyItemRangeInserted(1, 1 + availableReactions.size()); + } else { + chatReactions.clear(); + listAdapter.notifyItemRangeRemoved(1, 1 + availableReactions.size()); + } + } + @Override public void onFragmentDestroy() { super.onFragmentDestroy(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java index 63da64b40..f4cfcade6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java @@ -4,11 +4,12 @@ import android.content.Context; import android.view.View; import android.widget.LinearLayout; +import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.ActionBarPopupWindow; public class ChatScrimPopupContainerLayout extends LinearLayout { - public View reactionsLayout; + public ReactionsContainerLayout reactionsLayout; public ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout; public ChatScrimPopupContainerLayout(Context context) { @@ -18,9 +19,25 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (reactionsLayout != null && popupWindowLayout != null && popupWindowLayout.getSwipeBack() != null && reactionsLayout.getLayoutParams().width != LayoutHelper.WRAP_CONTENT) { + if (reactionsLayout != null && popupWindowLayout != null) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - int widthDiff = popupWindowLayout.getSwipeBack().getMeasuredWidth() - popupWindowLayout.getSwipeBack().getChildAt(0).getMeasuredWidth(); + int reactionsLayoutTotalWidth = reactionsLayout.getTotalWidth(); + View menuContainer = popupWindowLayout.getSwipeBack() != null ? popupWindowLayout.getSwipeBack().getChildAt(0) : popupWindowLayout.getChildAt(0); + int maxReactionsLayoutWidth = menuContainer.getMeasuredWidth() + AndroidUtilities.dp(16) + AndroidUtilities.dp(16) + AndroidUtilities.dp(36); + if (reactionsLayoutTotalWidth > maxReactionsLayoutWidth) { + int maxFullCount = ((maxReactionsLayoutWidth - AndroidUtilities.dp(16)) / AndroidUtilities.dp(36)) + 1; + int newWidth = maxFullCount * AndroidUtilities.dp(36) + AndroidUtilities.dp(16) - AndroidUtilities.dp(8); + if (newWidth > reactionsLayoutTotalWidth || maxFullCount == reactionsLayout.getItemsCount()) { + newWidth = reactionsLayoutTotalWidth; + } + reactionsLayout.getLayoutParams().width = newWidth; + } else { + reactionsLayout.getLayoutParams().width = LayoutHelper.WRAP_CONTENT; + } + int widthDiff = 0; + if (popupWindowLayout.getSwipeBack() != null) { + widthDiff = popupWindowLayout.getSwipeBack().getMeasuredWidth() - popupWindowLayout.getSwipeBack().getChildAt(0).getMeasuredWidth(); + } ((LayoutParams)reactionsLayout.getLayoutParams()).rightMargin = widthDiff; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java index 9fd913d9b..e2593d3d3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java @@ -132,7 +132,7 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen } setupLightDarkTheme(!forceDark); }); - rootLayout.addView(darkThemeView, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.END, 0, 0, 7, 0)); + rootLayout.addView(darkThemeView, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.END, 0, -2, 7, 0)); forceDark = !Theme.getActiveTheme().isDark(); setForceDark(Theme.getActiveTheme().isDark(), false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java index ee17c9e73..13213726c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java @@ -72,6 +72,7 @@ public class CounterView extends View { private final static int ANIMATION_TYPE_IN = 0; private final static int ANIMATION_TYPE_OUT = 1; private final static int ANIMATION_TYPE_REPLACE = 2; + public boolean shortFormat; int animationType = -1; @@ -180,14 +181,14 @@ public class CounterView extends View { } return; } - String newStr = String.valueOf(count); + String newStr = getStringOfCCount(count); countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr))); countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); if (parent != null) { parent.invalidate(); } } - String newStr = String.valueOf(count); + String newStr = getStringOfCCount(count); if (animated) { if (countAnimator != null) { @@ -231,7 +232,7 @@ public class CounterView extends View { countAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); } if (countLayout != null) { - String oldStr = String.valueOf(currentCount); + String oldStr = getStringOfCCount(currentCount); if (oldStr.length() == newStr.length()) { SpannableStringBuilder oldSpannableStr = new SpannableStringBuilder(oldStr); @@ -269,6 +270,13 @@ public class CounterView extends View { } } + private String getStringOfCCount(int count) { + if (shortFormat) { + return AndroidUtilities.formatWholeNumber(count, 0); + } + return String.valueOf(count); + } + public void draw(Canvas canvas) { if (type != TYPE_CHAT_PULLING_DOWN && type != TYPE_CHAT_REACTIONS) { int textColor = getThemedColor(textColorKey); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java index 91e4410b2..f20424138 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -505,10 +505,10 @@ public class FlickerLoadingView extends View { } else if (getViewType() == REACTED_TYPE) { int k = 0; while (h <= getMeasuredHeight()) { - int r = AndroidUtilities.dp(16); - canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(13) + r), h + AndroidUtilities.dp(24), r, paint); + int r = AndroidUtilities.dp(18); + canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(8) + r), h + AndroidUtilities.dp(24), r, paint); - rectF.set(paddingLeft + AndroidUtilities.dp(53), h + AndroidUtilities.dp(20), getWidth() - AndroidUtilities.dp(53), h + AndroidUtilities.dp(28)); + rectF.set(paddingLeft + AndroidUtilities.dp(58), h + AndroidUtilities.dp(20), getWidth() - AndroidUtilities.dp(53), h + AndroidUtilities.dp(28)); checkRtl(rectF); canvas.drawRoundRect(rectF, AndroidUtilities.dp(8), AndroidUtilities.dp(8), paint); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java index 5046120bb..4e5b1ba0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java @@ -98,6 +98,7 @@ public class MotionBackgroundDrawable extends Drawable { private ColorFilter patternColorFilter; private int roundRadius; private float patternAlpha = 1f; + private float backgroundAlpha = 1f; private int alpha = 255; private ColorFilter legacyBitmapColorFilter; @@ -422,6 +423,10 @@ public class MotionBackgroundDrawable extends Drawable { this.patternAlpha = alpha; invalidateParent(); } + public void setBackgroundAlpha(float alpha) { + this.backgroundAlpha = alpha; + invalidateParent(); + } @Override public void setBounds(int left, int top, int right, int bottom) { @@ -459,6 +464,192 @@ public class MotionBackgroundDrawable extends Drawable { } } + public void drawBackground(Canvas canvas) { + android.graphics.Rect bounds = getBounds(); + canvas.save(); + float tr = patternBitmap != null ? bounds.top : translationY; + int bitmapWidth = currentBitmap.getWidth(); + int bitmapHeight = currentBitmap.getHeight(); + float w = bounds.width(); + float h = bounds.height(); + float maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + float width = bitmapWidth * maxScale; + float height = bitmapHeight * maxScale; + float x = (w - width) / 2; + float y = (h - height) / 2; + if (isPreview) { + x += bounds.left; + y += bounds.top; + canvas.clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom); + } + if (intensity < 0) { + canvas.drawColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (alpha * backgroundAlpha))); + } else { + if (roundRadius != 0) { + matrix.reset(); + matrix.setTranslate(x, y); + float scaleW = (currentBitmap.getWidth() / (float) bounds.width()); + float scaleH = (currentBitmap.getHeight() / (float) bounds.height()); + float scale = 1.0f / Math.min(scaleW, scaleH); + matrix.preScale(scale, scale); + bitmapShader.setLocalMatrix(matrix); + + rect.set(bounds.left, bounds.top, bounds.right, bounds.bottom); + int wasAlpha = paint.getAlpha(); + paint.setAlpha((int) (wasAlpha * backgroundAlpha)); + canvas.drawRoundRect(rect, roundRadius, roundRadius, paint); + paint.setAlpha(wasAlpha); + } else { + canvas.translate(0, tr); + if (gradientDrawable != null) { + gradientDrawable.setBounds((int) x, (int) y, (int) (x + width), (int) (y + height)); + gradientDrawable.setAlpha((int) (255 * backgroundAlpha)); + gradientDrawable.draw(canvas); + } else { + rect.set(x, y, x + width, y + height); + Paint bitmapPaint = overrideBitmapPaint != null ? overrideBitmapPaint : paint; + int wasAlpha = bitmapPaint.getAlpha(); + bitmapPaint.setAlpha((int) (wasAlpha * backgroundAlpha)); + canvas.drawBitmap(currentBitmap, null, rect, bitmapPaint); + bitmapPaint.setAlpha(wasAlpha); + } + } + } + canvas.restore(); + + updateAnimation(); + } + public void drawPattern(Canvas canvas) { + android.graphics.Rect bounds = getBounds(); + canvas.save(); + float tr = patternBitmap != null ? bounds.top : translationY; + int bitmapWidth = currentBitmap.getWidth(); + int bitmapHeight = currentBitmap.getHeight(); + float w = bounds.width(); + float h = bounds.height(); + float maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + float width = bitmapWidth * maxScale; + float height = bitmapHeight * maxScale; + float x = (w - width) / 2; + float y = (h - height) / 2; + if (isPreview) { + x += bounds.left; + y += bounds.top; + canvas.clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom); + } + if (intensity < 0) { + if (patternBitmap != null) { + if (useLegacyBitmap) { + if (errorWhileGenerateLegacyBitmap) { + bitmapWidth = patternBitmap.getWidth(); + bitmapHeight = patternBitmap.getHeight(); + maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + width = bitmapWidth * maxScale; + height = bitmapHeight * maxScale; + x = (w - width) / 2; + y = (h - height) / 2; + rect.set(x, y, x + width, y + height); + + int averageColor = AndroidUtilities.getAverageColor(colors[2], AndroidUtilities.getAverageColor(colors[0], colors[1])); + if (colors[3] != 0) { + averageColor = AndroidUtilities.getAverageColor(colors[3], averageColor); + } + if (legacyBitmapColorFilter == null || averageColor != legacyBitmapColor) { + legacyBitmapColor = averageColor; + legacyBitmapColorFilter = new PorterDuffColorFilter(averageColor, PorterDuff.Mode.SRC_IN); + } + paint2.setColorFilter(legacyBitmapColorFilter); + paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * alpha * patternAlpha)); + canvas.translate(0, tr); + canvas.drawBitmap(patternBitmap, null, rect, paint2); + } else if (legacyBitmap != null) { + if (invalidateLegacy) { + rect.set(0, 0, legacyBitmap.getWidth(), legacyBitmap.getHeight()); + int oldAlpha = paint.getAlpha(); + paint.setAlpha(255); + legacyCanvas.drawBitmap(currentBitmap, null, rect, paint); + paint.setAlpha(oldAlpha); + + bitmapWidth = patternBitmap.getWidth(); + bitmapHeight = patternBitmap.getHeight(); + maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + width = bitmapWidth * maxScale; + height = bitmapHeight * maxScale; + x = (w - width) / 2; + y = (h - height) / 2; + rect.set(x, y, x + width, y + height); + + paint2.setColorFilter(null); + paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * 255)); + legacyCanvas.save(); + legacyCanvas.scale(legacyBitmapScale, legacyBitmapScale); + legacyCanvas.drawBitmap(patternBitmap, null, rect, paint2); + legacyCanvas.restore(); + invalidateLegacy = false; + } + + rect.set(bounds.left, bounds.top, bounds.right, bounds.bottom); + if (legacyBitmap2 != null && posAnimationProgress != 1f) { + paint.setAlpha((int) (alpha * patternAlpha * (1f - posAnimationProgress))); + canvas.drawBitmap(legacyBitmap2, null, rect, paint); + + paint.setAlpha((int) (alpha * patternAlpha * posAnimationProgress)); + canvas.drawBitmap(legacyBitmap, null, rect, paint); + paint.setAlpha(alpha); + } else { + canvas.drawBitmap(legacyBitmap, null, rect, paint); + } + } + } else { + if (matrix == null) { + matrix = new Matrix(); + } + matrix.reset(); + matrix.setTranslate(x, y + tr); + float scaleW = (currentBitmap.getWidth() / (float) bounds.width()); + float scaleH = (currentBitmap.getHeight() / (float) bounds.height()); + float scale = 1.0f / Math.min(scaleW, scaleH); + matrix.preScale(scale, scale); + bitmapShader.setLocalMatrix(matrix); + + matrix.reset(); + bitmapWidth = patternBitmap.getWidth(); + bitmapHeight = patternBitmap.getHeight(); + maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + width = bitmapWidth * maxScale; + height = bitmapHeight * maxScale; + x = (w - width) / 2; + y = (h - height) / 2; + matrix.setTranslate(x, y + tr); + matrix.preScale(maxScale, maxScale); + gradientShader.setLocalMatrix(matrix); + paint2.setColorFilter(null); + paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * alpha * patternAlpha)); + rect.set(bounds.left, bounds.top, bounds.right, bounds.bottom); + canvas.drawRoundRect(rect, roundRadius, roundRadius, paint2); + } + } + } else { + if (patternBitmap != null) { + bitmapWidth = patternBitmap.getWidth(); + bitmapHeight = patternBitmap.getHeight(); + maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + width = bitmapWidth * maxScale; + height = bitmapHeight * maxScale; + x = (w - width) / 2; + y = (h - height) / 2; + rect.set(x, y, x + width, y + height); + + paint2.setColorFilter(patternColorFilter); + paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * alpha * patternAlpha)); + canvas.drawBitmap(patternBitmap, null, rect, paint2); + } + } + canvas.restore(); + + updateAnimation(); + } + @Override public void draw(Canvas canvas) { android.graphics.Rect bounds = getBounds(); @@ -479,7 +670,7 @@ public class MotionBackgroundDrawable extends Drawable { canvas.clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom); } if (intensity < 0) { - canvas.drawColor(ColorUtils.setAlphaComponent(Color.BLACK, alpha)); + canvas.drawColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (alpha * backgroundAlpha))); if (patternBitmap != null) { if (useLegacyBitmap) { if (errorWhileGenerateLegacyBitmap) { @@ -587,10 +778,15 @@ public class MotionBackgroundDrawable extends Drawable { canvas.translate(0, tr); if (gradientDrawable != null) { gradientDrawable.setBounds((int) x, (int) y, (int) (x + width), (int) (y + height)); + gradientDrawable.setAlpha((int) (255 * backgroundAlpha)); gradientDrawable.draw(canvas); } else { rect.set(x, y, x + width, y + height); - canvas.drawBitmap(currentBitmap, null, rect, overrideBitmapPaint != null ? overrideBitmapPaint : paint); + Paint bitmapPaint = overrideBitmapPaint != null ? overrideBitmapPaint : paint; + int wasAlpha = bitmapPaint.getAlpha(); + bitmapPaint.setAlpha((int) (wasAlpha * backgroundAlpha)); + canvas.drawBitmap(currentBitmap, null, rect, bitmapPaint); + bitmapPaint.setAlpha(wasAlpha); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java index ce3373b96..ed45f075c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java @@ -194,18 +194,18 @@ public class PopupSwipeBackLayout extends FrameLayout { if (processTouchEvent(ev)) return true; + int act = ev.getActionMasked(); + if (act == MotionEvent.ACTION_DOWN && !mRect.contains(ev.getX(), ev.getY())) { + callOnClick(); + return true; + } + if (currentForegroundIndex < 0 || currentForegroundIndex >= getChildCount()) { return super.dispatchTouchEvent(ev); } View bv = getChildAt(0); View fv = getChildAt(currentForegroundIndex); - int act = ev.getActionMasked(); - if (act == MotionEvent.ACTION_DOWN && (ev.getX() > (bv.getMeasuredWidth() + (fv.getMeasuredWidth() - bv.getMeasuredWidth()) * transitionProgress) || - ev.getY() > (bv.getMeasuredHeight() + ((overrideForegroundHeight != 0 ? overrideForegroundHeight : fv.getMeasuredHeight()) - bv.getMeasuredHeight()) * transitionProgress))) { - callOnClick(); - return true; - } boolean b = (transitionProgress > 0.5f ? fv : bv).dispatchTouchEvent(ev); if (!b && act == MotionEvent.ACTION_DOWN) { @@ -345,7 +345,6 @@ public class PopupSwipeBackLayout extends FrameLayout { } } - int s = canvas.save(); mPath.rewind(); int rad = AndroidUtilities.dp(6); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java index ae313783d..d5213f429 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -22,6 +22,8 @@ import android.text.TextUtils; import android.view.HapticFeedbackConstants; import android.view.View; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DispatchQueuePool; @@ -164,6 +166,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { if (cacheGenerateTask == null) { return; } + createCache(nativePtr, width, height); uiHandler.post(uiRunnableCacheFinished); }); @@ -358,12 +361,14 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { this(file, w, h, precache, limitFps, null, 0); } + File file; public RLottieDrawable(File file, int w, int h, boolean precache, boolean limitFps, int[] colorReplacement, int fitzModifier) { width = w; height = h; shouldLimitFps = limitFps; getPaint().setFlags(Paint.FILTER_BITMAP_FLAG); + this.file = file; nativePtr = create(file.getAbsolutePath(), null, w, h, metaData, precache, colorReplacement, shouldLimitFps, fitzModifier); if (precache && lottieCacheGenerateQueue == null) { lottieCacheGenerateQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); @@ -809,7 +814,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } public void setCurrentFrame(int frame, boolean async, boolean resetFrame) { - if (frame < 0 || frame > metaData[0]) { + if (frame < 0 || frame > metaData[0] || currentFrame == frame) { return; } currentFrame = frame; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java index 260b8b3e6..7ab51e359 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java @@ -5,6 +5,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.os.Build; import android.text.TextUtils; import android.util.LongSparseArray; import android.util.TypedValue; @@ -24,6 +26,7 @@ import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; @@ -75,6 +78,9 @@ public class ReactedUsersListView extends FrameLayout { listView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); listView.setClipToPadding(false); } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + listView.setVerticalScrollbarThumbDrawable(new ColorDrawable(Theme.getColor(Theme.key_listSelector))); + } listView.setAdapter(adapter = new RecyclerView.Adapter() { @NonNull @Override @@ -163,6 +169,7 @@ public class ReactedUsersListView extends FrameLayout { TLRPC.TL_messages_messageReactionsList l = (TLRPC.TL_messages_messageReactionsList) response; for (TLRPC.User u : l.users) { + MessagesController.getInstance(currentAccount).putUser(u, false); users.put(u.id, u); } @@ -172,10 +179,11 @@ public class ReactedUsersListView extends FrameLayout { newReactions.addAll(userReactions); newReactions.addAll(l.reactions); - if (onlySeenNow) + if (onlySeenNow) { Collections.sort(newReactions, (o1, o2) -> Integer.compare(o1.reaction != null ? 1 : 0, o2.reaction != null ? 1 : 0)); + } - AndroidUtilities.runOnUIThread(()->{ + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> { userReactions = newReactions; if (onlySeenNow) { onlySeenNow = false; @@ -206,7 +214,7 @@ public class ReactedUsersListView extends FrameLayout { if (offset == null) canLoadMore = false; isLoading = false; - }); + })); } else isLoading = false; }, ConnectionsManager.RequestFlagInvokeAfter); } @@ -247,7 +255,7 @@ public class ReactedUsersListView extends FrameLayout { titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); titleView.setEllipsize(TextUtils.TruncateAt.END); - addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 65, 0, 44, 0)); + addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 58, 0, 44, 0)); reactView = new BackupImageView(context); addView(reactView, LayoutHelper.createFrameRelatively(24, 24, Gravity.END | Gravity.CENTER_VERTICAL, 0, 0, 12, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java index 2e287bd52..81f5de33c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java @@ -2,6 +2,7 @@ package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; @@ -16,6 +17,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DocumentObject; @@ -39,13 +41,17 @@ public class ReactionTabHolderView extends FrameLayout { private TextView counterView; 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))); + addView(overlaySelectorView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + iconView = new ImageView(context); - Drawable drawable = ContextCompat.getDrawable(context, R.drawable.msg_reactions_filled).mutate(); - drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_avatar_nameInMessageBlue), PorterDuff.Mode.MULTIPLY)); + drawable = ContextCompat.getDrawable(context, R.drawable.msg_reactions_filled).mutate(); iconView.setImageDrawable(drawable); addView(iconView, LayoutHelper.createFrameRelatively(24, 24, Gravity.START | Gravity.CENTER_VERTICAL, 8, 0, 8, 0)); @@ -58,20 +64,24 @@ public class ReactionTabHolderView extends FrameLayout { outlinePaint.setStyle(Paint.Style.STROKE); outlinePaint.setStrokeWidth(AndroidUtilities.dp(1)); - outlinePaint.setColor(Theme.getColor(Theme.key_avatar_nameInMessageBlue)); - - bgPaint.setColor(Theme.getColor(Theme.key_avatar_nameInMessageBlue)); - bgPaint.setAlpha(0x10); - - View overlaySelectorView = new View(context); - overlaySelectorView.setBackground(Theme.getSelectorDrawable(bgPaint.getColor(), false)); - addView(overlaySelectorView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); setWillNotDraw(false); + + setOutlineProgress(outlineProgress); } public void setOutlineProgress(float outlineProgress) { this.outlineProgress = outlineProgress; + int backgroundSelectedColor = Theme.getColor(Theme.key_chat_inReactionButtonBackground); + int backgroundColor = ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_chat_inReactionButtonBackground), 0x10); + + int textSelectedColor = Theme.getColor(Theme.key_chat_inReactionButtonTextSelected); + int textColor = Theme.getColor(Theme.key_chat_inReactionButtonText); + int textFinalColor = ColorUtils.blendARGB(textColor, textSelectedColor, outlineProgress); + + bgPaint.setColor(ColorUtils.blendARGB(backgroundColor, backgroundSelectedColor, outlineProgress)); + counterView.setTextColor(textFinalColor); + drawable.setColorFilter(new PorterDuffColorFilter(textFinalColor, PorterDuff.Mode.MULTIPLY)); invalidate(); } @@ -97,19 +107,14 @@ public class ReactionTabHolderView extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { - int s = canvas.save(); - path.rewind(); rect.set(0, 0, getWidth(), getHeight()); - path.addRoundRect(rect, radius, radius, Path.Direction.CW); - canvas.clipPath(path); canvas.drawRoundRect(rect, radius, radius, bgPaint); super.dispatchDraw(canvas); - outlinePaint.setAlpha((int) (outlineProgress * 0xFF)); - float w = outlinePaint.getStrokeWidth(); - rect.set(w, w, getWidth() - w, getHeight() - w); - canvas.drawRoundRect(rect, radius, radius, outlinePaint); - canvas.restoreToCount(s); +// outlinePaint.setAlpha((int) (outlineProgress * 0xFF)); +// float w = outlinePaint.getStrokeWidth(); +// rect.set(w, w, getWidth() - w, getHeight() - w); +// canvas.drawRoundRect(rect, radius, radius, outlinePaint); } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java index bb12d2072..f456d1c96 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java @@ -10,6 +10,7 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.ChatMessageCell; @@ -24,6 +25,7 @@ public class ReactionsEffectOverlay { private final AnimationView effectImageView; private final AnimationView emojiImageView; + private final AnimationView emojiStaticImageView; private final FrameLayout container; boolean animateIn; float animateInProgress; @@ -53,6 +55,7 @@ public class ReactionsEffectOverlay { this.reaction = reaction; ReactionsLayoutInBubble.ReactionButton reactionButton = cell.getReactionButton(reaction); float fromX, fromY, fromHeight, fromWidth; + ChatActivity chatActivity = (fragment instanceof ChatActivity) ? (ChatActivity) fragment : null; if (reactionsLayout != null) { for (int i = 0; i < reactionsLayout.recyclerListView.getChildCount(); i++) { if (((ReactionsContainerLayout.ReactionHolderView) reactionsLayout.recyclerListView.getChildAt(i)).currentReaction.reaction.equals(reaction)) { @@ -141,6 +144,9 @@ public class ReactionsEffectOverlay { toX += reactionButton.x + reactionButton.imageReceiver.getImageX(); toY += reactionButton.y + reactionButton.imageReceiver.getImageY(); } + if (chatActivity != null) { + toY += chatActivity.drawingChatLisViewYoffset; + } lastDrawnToX = toX; lastDrawnToY = toY; @@ -164,6 +170,7 @@ public class ReactionsEffectOverlay { } float animateInProgressX, animateInProgressY; + float animateOutProgress = CubicBezierInterpolator.DEFAULT.getInterpolation(ReactionsEffectOverlay.this.animateOutProgress); if (fromHolder) { animateInProgressX = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(animateInProgress); animateInProgressY = CubicBezierInterpolator.DEFAULT.getInterpolation(animateInProgress); @@ -187,6 +194,8 @@ public class ReactionsEffectOverlay { effectImageView.setTranslationX(x); effectImageView.setTranslationY(y); effectImageView.setAlpha((1f - animateOutProgress)); + effectImageView.setScaleX(scale); + effectImageView.setScaleY(scale); if (animateOutProgress != 0) { scale = scale * (1f - animateOutProgress) + toScale * animateOutProgress; @@ -194,6 +203,9 @@ public class ReactionsEffectOverlay { y = y * (1f - animateOutProgress) + toY * animateOutProgress; } + + emojiStaticImageView.setAlpha(animateOutProgress > 0.7f ? (animateOutProgress - 0.7f) / 0.3f : 0); + //emojiImageView.setAlpha(animateOutProgress < 0.5f ? 1f - (animateOutProgress / 0.5f) : 0f); container.setTranslationX(x); container.setTranslationY(y); @@ -214,10 +226,10 @@ public class ReactionsEffectOverlay { } if (wasScrolled || (emojiImageView.wasPlaying && emojiImageView.getImageReceiver().getLottieAnimation() != null && !emojiImageView.getImageReceiver().getLottieAnimation().isRunning())) { - if (animateOutProgress != 1f) { - animateOutProgress += 16f / 220f; - if (animateOutProgress > 1f) { - animateOutProgress = 1f; + if (ReactionsEffectOverlay.this.animateOutProgress != 1f) { + ReactionsEffectOverlay.this.animateOutProgress += 16f / 220f; + if (ReactionsEffectOverlay.this.animateOutProgress > 1f) { + ReactionsEffectOverlay.this.animateOutProgress = 1f; currentOverlay = null; cell.invalidate(); if (cell.getCurrentMessagesGroup() != null && cell.getParent() != null) { @@ -239,6 +251,7 @@ public class ReactionsEffectOverlay { }; effectImageView = new AnimationView(context); emojiImageView = new AnimationView(context); + emojiStaticImageView = new AnimationView(context); TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction); if (availableReaction != null) { TLRPC.Document document = availableReaction.effect_animation; @@ -274,6 +287,15 @@ public class ReactionsEffectOverlay { ((FrameLayout.LayoutParams) emojiImageView.getLayoutParams()).topMargin = topOffset; ((FrameLayout.LayoutParams) emojiImageView.getLayoutParams()).leftMargin = leftOffset; + emojiStaticImageView.getImageReceiver().setImage(ImageLocation.getForDocument(availableReaction.static_icon), "40_40", null, "webp", availableReaction, 1); + + container.addView(emojiStaticImageView); + emojiStaticImageView.getLayoutParams().width = emojiSize; + emojiStaticImageView.getLayoutParams().height = emojiSize; + ((FrameLayout.LayoutParams) emojiStaticImageView.getLayoutParams()).topMargin = topOffset; + ((FrameLayout.LayoutParams) emojiStaticImageView.getLayoutParams()).leftMargin = leftOffset; + + windowView.addView(container); container.getLayoutParams().width = size; container.getLayoutParams().height = size; @@ -298,6 +320,10 @@ public class ReactionsEffectOverlay { if (cell == null) { return; } + boolean animationEnabled = MessagesController.getGlobalMainSettings().getBoolean("view_animations", true); + if (!animationEnabled) { + return; + } ReactionsEffectOverlay reactionsEffectOverlay = new ReactionsEffectOverlay(baseFragment.getParentActivity(), baseFragment, reactionsLayout, cell, x, y, reaction, currentAccount); currentOverlay = reactionsEffectOverlay; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java index cd6282cb4..39ac444c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java @@ -67,6 +67,7 @@ public class ReactionsLayoutInBubble { ChatMessageCell parentView; MessageObject messageObject; Theme.ResourcesProvider resourcesProvider; + private String scrimViewReaction; int availableWidth; private int lastDrawnWidth; @@ -125,6 +126,9 @@ public class ReactionsLayoutInBubble { reactionButtons.add(new ReactionButton(reactionCount)); reactionButtons.get(0).isSelected = false; reactionButtons.get(1).isSelected = true; + reactionButtons.get(0).realCount = 1; + reactionButtons.get(1).realCount = 1; + reactionButtons.get(1).key = reactionButtons.get(1).key + "_"; break; } if (isSmall && i == 2) { @@ -135,8 +139,10 @@ public class ReactionsLayoutInBubble { } } } - comparator.currentAccount = currentAccount; - Collections.sort(reactionButtons, comparator); + if (!isSmall) { + comparator.currentAccount = currentAccount; + Collections.sort(reactionButtons, comparator); + } } isEmpty = reactionButtons.isEmpty(); } @@ -190,7 +196,7 @@ public class ReactionsLayoutInBubble { drawServiceShaderBackground = false; } - public void draw(Canvas canvas, float animationProgress) { + public void draw(Canvas canvas, float animationProgress, String drawOnlyReaction) { if (isEmpty && outButtons.isEmpty()) { return; } @@ -207,6 +213,9 @@ public class ReactionsLayoutInBubble { canvas.translate(totalX, totalY); for (int i = 0; i < reactionButtons.size(); i++) { ReactionButton reactionButton = reactionButtons.get(i); + if (reactionButton.reaction.equals(scrimViewReaction) || (drawOnlyReaction != null && !reactionButton.reaction.equals(drawOnlyReaction))) { + continue; + } canvas.save(); float x = reactionButton.x; float y = reactionButton.y; @@ -221,7 +230,7 @@ public class ReactionsLayoutInBubble { alpha = animationProgress; canvas.scale(s, s, reactionButton.width / 2f, reactionButton.height / 2f); } - reactionButton.draw(canvas, reactionButton.animationType == ANIMATION_TYPE_IN ? 1f : animationProgress, alpha); + reactionButton.draw(canvas, reactionButton.animationType == ANIMATION_TYPE_MOVE ? animationProgress : 1f, alpha, drawOnlyReaction != null); canvas.restore(); } @@ -231,7 +240,7 @@ public class ReactionsLayoutInBubble { canvas.translate(reactionButton.x, reactionButton.y); float s = 0.5f + 0.5f * (1f - animationProgress); canvas.scale(s, s, reactionButton.width / 2f, reactionButton.height / 2f); - outButtons.get(i).draw(canvas, 1f, (1f - animationProgress)); + outButtons.get(i).draw(canvas, 1f, (1f - animationProgress), false); canvas.restore(); } canvas.restore(); @@ -240,7 +249,7 @@ public class ReactionsLayoutInBubble { public void recordDrawingState() { lastDrawingReactionButtons.clear(); for (int i = 0; i < reactionButtons.size(); i++) { - lastDrawingReactionButtons.put(reactionButtons.get(i).reaction, reactionButtons.get(i)); + lastDrawingReactionButtons.put(reactionButtons.get(i).key, reactionButtons.get(i)); } wasDrawn = !isEmpty; lastDrawnX = x; @@ -249,6 +258,9 @@ public class ReactionsLayoutInBubble { } public boolean animateChange() { + if (messageObject == null) { + return false; + } boolean changed = false; lastDrawingReactionButtonsTmp.clear(); for (int i = 0; i < outButtons.size(); i++) { @@ -258,12 +270,13 @@ public class ReactionsLayoutInBubble { lastDrawingReactionButtonsTmp.putAll(lastDrawingReactionButtons); for (int i = 0; i < reactionButtons.size(); i++) { ReactionButton button = reactionButtons.get(i); - ReactionButton lastButton = lastDrawingReactionButtonsTmp.remove(button.reaction); + ReactionButton lastButton = lastDrawingReactionButtonsTmp.remove(button.key); if (lastButton != null) { - if (button.animateFromX != lastButton.x || button.animateFromY != lastButton.y || button.animateFromWidth != lastButton.width || button.count != lastButton.count || button.backgroundColor != lastButton.backgroundColor) { + if (button.x != lastButton.x || button.y != lastButton.y || button.width != lastButton.width || button.count != lastButton.count || button.backgroundColor != lastButton.backgroundColor) { button.animateFromX = lastButton.x; button.animateFromY = lastButton.y; button.animateFromWidth = lastButton.width; + button.fromTextColor = lastButton.lastDrawnTextColor; button.fromBackgroundColor = lastButton.lastDrawnBackgroundColor; button.animationType = ANIMATION_TYPE_MOVE; @@ -328,9 +341,19 @@ public class ReactionsLayoutInBubble { } public ReactionButton getReactionButton(String reaction) { + if (isSmall) { + ReactionButton button = lastDrawingReactionButtons.get(reaction + "_"); + if (button != null) { + return button; + } + } return lastDrawingReactionButtons.get(reaction); } + public void setScrimReaction(String scrimViewReaction) { + this.scrimViewReaction = scrimViewReaction; + } + public class ReactionButton { private final TLRPC.TL_reactionCount reactionCount; @@ -343,14 +366,17 @@ public class ReactionsLayoutInBubble { public int realCount; public boolean drawImage = true; public boolean lastImageDrawn; + public boolean wasDrawn; + public String key; String countText; String reaction; + int count; public int x; public int y; - int width; - int height; + public int width; + public int height; ImageReceiver imageReceiver = new ImageReceiver(); CounterView.CounterDrawable counterDrawable = new CounterView.CounterDrawable(parentView, false, null); int backgroundColor; @@ -369,10 +395,12 @@ public class ReactionsLayoutInBubble { this.reaction = reactionCount.reaction; this.count = reactionCount.count; this.realCount = reactionCount.count; + this.key = this.reaction; countText = Integer.toString(reactionCount.count); imageReceiver.setParentView(parentView); isSelected = reactionCount.chosen; counterDrawable.updateVisibility = false; + counterDrawable.shortFormat = true; if (reactionCount.chosen) { backgroundColor = Theme.getColor(messageObject.isOutOwner() ? Theme.key_chat_outReactionButtonBackground : Theme.key_chat_inReactionButtonBackground, resourcesProvider); textColor = Theme.getColor(messageObject.isOutOwner() ? Theme.key_chat_outReactionButtonTextSelected : Theme.key_chat_inReactionButtonTextSelected, resourcesProvider); @@ -402,20 +430,17 @@ public class ReactionsLayoutInBubble { counterDrawable.gravity = Gravity.LEFT; } - public void draw(Canvas canvas, float progress, float alpha) { + public void draw(Canvas canvas, float progress, float alpha, boolean drawOverlayScrim) { + wasDrawn = true; if (isSmall) { imageReceiver.setAlpha(alpha); imageReceiver.setImageCoords(0, 0, AndroidUtilities.dp(14), AndroidUtilities.dp(14)); drawImage(canvas); return; } - if (drawServiceShaderBackground) { - textPaint.setColor(lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, serviceTextColor, progress)); - paint.setColor(lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, serviceBackgroundColor, progress)); - } else { - textPaint.setColor(lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, textColor, progress)); - paint.setColor(lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, backgroundColor, progress)); - } + updateColors(progress); + textPaint.setColor(lastDrawnTextColor); + paint.setColor(lastDrawnBackgroundColor); if (alpha != 1f) { textPaint.setAlpha((int) (textPaint.getAlpha() * alpha)); @@ -443,6 +468,12 @@ public class ReactionsLayoutInBubble { paint1.setAlpha(oldAlpha); paint2.setAlpha(oldAlpha2); } + if (!drawServiceShaderBackground && drawOverlayScrim) { + Theme.MessageDrawable messageBackground = parentView.getCurrentBackgroundDrawable(false); + if (messageBackground != null) { + canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, messageBackground.getPaint()); + } + } canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint); imageReceiver.setImageCoords(AndroidUtilities.dp(8), (height - AndroidUtilities.dp(20)) / 2f, AndroidUtilities.dp(20), AndroidUtilities.dp(20)); @@ -464,6 +495,16 @@ public class ReactionsLayoutInBubble { } } + private void updateColors(float progress) { + if (drawServiceShaderBackground) { + lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, serviceTextColor, progress); + lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, serviceBackgroundColor, progress); + } else { + lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, textColor, progress); + lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, backgroundColor, progress); + } + } + private void drawImage(Canvas canvas) { if (drawImage && ((realCount > 1 || !ReactionsEffectOverlay.isPlaying(messageObject.getId(), messageObject.getGroupId(), reaction)) || !isSelected)) { imageReceiver.draw(canvas); @@ -497,8 +538,6 @@ public class ReactionsLayoutInBubble { } } - - public void attach() { if (imageReceiver != null) { imageReceiver.onAttachedToWindow(); @@ -517,7 +556,6 @@ public class ReactionsLayoutInBubble { } } } - static int attachedCount; float lastX; float lastY; @@ -526,7 +564,7 @@ public class ReactionsLayoutInBubble { Runnable longPressRunnable; public boolean chekTouchEvent(MotionEvent event) { - if (isEmpty || messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.reactions == null) { + if (isEmpty || isSmall || messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.reactions == null) { return false; } float x = event.getX() - this.x; @@ -538,16 +576,18 @@ public class ReactionsLayoutInBubble { lastX = event.getX(); lastY = event.getY(); lastSelectedButton = reactionButtons.get(i); - if (longPressRunnable != null && messageObject.messageOwner.reactions.can_see_list) { + if (longPressRunnable != null) { AndroidUtilities.cancelRunOnUIThread(longPressRunnable); longPressRunnable = null; } final ReactionButton selectedButtonFinal = lastSelectedButton; - AndroidUtilities.runOnUIThread(longPressRunnable = () -> { - parentView.getDelegate().didPressReaction(parentView, selectedButtonFinal.reactionCount, true); - longPressRunnable = null; - }, ViewConfiguration.getLongPressTimeout()); + if (messageObject.messageOwner.reactions.can_see_list) { + AndroidUtilities.runOnUIThread(longPressRunnable = () -> { + parentView.getDelegate().didPressReaction(parentView, selectedButtonFinal.reactionCount, true); + longPressRunnable = null; + }, ViewConfiguration.getLongPressTimeout()); + } pressed = true; break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java index d8b1a5706..a6b642b4f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -2,6 +2,7 @@ package org.telegram.ui.Components; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; @@ -17,15 +18,16 @@ 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.View; import android.view.ViewGroup; +import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.core.util.Consumer; -import androidx.dynamicanimation.animation.FloatPropertyCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -33,7 +35,12 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DocumentObject; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SvgHelper; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -44,16 +51,16 @@ import java.util.HashSet; import java.util.List; import java.util.Random; -public class ReactionsContainerLayout extends FrameLayout { - public final static FloatPropertyCompat TRANSITION_PROGRESS_VALUE = new FloatPropertyCompat("transitionProgress") { +public class ReactionsContainerLayout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + public final static Property TRANSITION_PROGRESS_VALUE = new Property(Float.class, "transitionProgress") { @Override - public float getValue(ReactionsContainerLayout object) { - return object.transitionProgress * 100f; + public Float get(ReactionsContainerLayout reactionsContainerLayout) { + return reactionsContainerLayout.transitionProgress ; } @Override - public void setValue(ReactionsContainerLayout object, float value) { - object.setTransitionProgress(value / 100f); + public void set(ReactionsContainerLayout object, Float value) { + object.setTransitionProgress(value); } }; @@ -76,6 +83,9 @@ public class ReactionsContainerLayout extends FrameLayout { private float bigCircleRadius = AndroidUtilities.dp(8); private float smallCircleRadius = bigCircleRadius / 2; private int bigCircleOffset = AndroidUtilities.dp(36); + private MessageObject messageObject; + private int currentAccount; + private long waitingLoadingChatId; private List reactionsList = Collections.emptyList(); @@ -88,13 +98,17 @@ public class ReactionsContainerLayout extends FrameLayout { private Rect shadowPad = new Rect(); private Drawable shadow; + private final boolean animationEnabled; private List triggeredReactions = new ArrayList<>(); Theme.ResourcesProvider resourcesProvider; - public ReactionsContainerLayout(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + public ReactionsContainerLayout(@NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; + this.currentAccount = currentAccount; + + animationEnabled = MessagesController.getGlobalMainSettings().getBoolean("view_animations", true) && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; shadow = ContextCompat.getDrawable(context, R.drawable.reactions_bubble_shadow).mutate(); shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = AndroidUtilities.dp(7); @@ -206,9 +220,14 @@ public class ReactionsContainerLayout extends FrameLayout { } @SuppressLint("NotifyDataSetChanged") - public void setReactionsList(List reactionsList) { + private void setReactionsList(List reactionsList) { this.reactionsList = reactionsList; + int size = getLayoutParams().height - getPaddingTop() - getPaddingBottom(); + if (size * reactionsList.size() < AndroidUtilities.dp(200)) { + getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; + } listAdapter.notifyDataSetChanged(); + } HashSet lastVisibleViews = new HashSet<>(); @@ -222,13 +241,18 @@ public class ReactionsContainerLayout extends FrameLayout { if (transitionProgress != 0) { int delay = 0; for (int i = 0; i < recyclerListView.getChildCount(); i++) { - View view = recyclerListView.getChildAt(i); - if (view.getX() + view.getMeasuredWidth() > 0 && view.getX() < getWidth()) { + 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)) { - ((ReactionHolderView) view).play(delay); - delay += 50; + view.play(delay); + delay += 30; } lastVisibleViews.add(view); + } else if (!view.isEnter) { + view.resetAnimation(); } } } @@ -335,6 +359,51 @@ public class ReactionsContainerLayout extends FrameLayout { invalidate(); } + public void setMessage(MessageObject message, TLRPC.ChatFull chatFull) { + this.messageObject = message; + TLRPC.ChatFull reactionsChat = chatFull; + List l; + if (message.isForwardedChannelPost()) { + reactionsChat = MessagesController.getInstance(currentAccount).getChatFull(-message.getFromChatId()); + if (reactionsChat == null) { + waitingLoadingChatId = -message.getFromChatId(); + MessagesController.getInstance(currentAccount).loadFullChat(-message.getFromChatId(), 0, true); + setVisibility(View.INVISIBLE); + return; + } + } + if (reactionsChat != null) { + l = new ArrayList<>(reactionsChat.available_reactions.size()); + for (String s : reactionsChat.available_reactions) { + for (TLRPC.TL_availableReaction a : MediaDataController.getInstance(currentAccount).getEnabledReactionsList()) { + if (a.reaction.equals(s)) { + l.add(a); + break; + } + } + } + } else { + l = MediaDataController.getInstance(currentAccount).getEnabledReactionsList(); + } + setReactionsList(l); + } + + public void startEnterAnimation() { + setTransitionProgress(0); + setAlpha(1f); + ObjectAnimator animator = ObjectAnimator.ofFloat(this, ReactionsContainerLayout.TRANSITION_PROGRESS_VALUE, 0f, 1f).setDuration(400); + animator.setInterpolator(new OvershootInterpolator(1.004f)); + animator.start(); + } + + public int getTotalWidth() { + return AndroidUtilities.dp(36) * reactionsList.size() + AndroidUtilities.dp(16); + } + + public int getItemsCount() { + return reactionsList.size(); + } + private final class LeftRightShadowsListener extends RecyclerView.OnScrollListener { private boolean leftVisible, rightVisible; private ValueAnimator leftAnimator, rightAnimator; @@ -383,11 +452,12 @@ public class ReactionsContainerLayout extends FrameLayout { public final class ReactionHolderView extends FrameLayout { public BackupImageView backupImageView; public TLRPC.TL_availableReaction currentReaction; + private boolean isEnter; Runnable playRunnable = new Runnable() { @Override public void run() { - if (backupImageView.getImageReceiver().getLottieAnimation() != null && !backupImageView.getImageReceiver().getLottieAnimation().isRunning()) { + if (backupImageView.getImageReceiver().getLottieAnimation() != null && !backupImageView.getImageReceiver().getLottieAnimation().isRunning() && !backupImageView.getImageReceiver().getLottieAnimation().isGeneratingCache()) { backupImageView.getImageReceiver().getLottieAnimation().start(); } } @@ -396,37 +466,100 @@ public class ReactionsContainerLayout extends FrameLayout { ReactionHolderView(Context context) { super(context); - backupImageView = new BackupImageView(context); + backupImageView = new BackupImageView(context) { + @Override + public void invalidate() { + super.invalidate(); + ReactionsContainerLayout.this.invalidate(); + } + }; backupImageView.getImageReceiver().setAutoRepeat(0); + backupImageView.getImageReceiver().setAllowStartLottieAnimation(false); addView(backupImageView, LayoutHelper.createFrame(34, 34, Gravity.CENTER)); } private void setReaction(TLRPC.TL_availableReaction react) { + if (currentReaction != null && currentReaction.reaction.equals(react.reaction)) { + return; + } + resetAnimation(); currentReaction = react; - SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(currentReaction.appear_animation, Theme.key_windowBackgroundGray, 1.0f); - backupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(currentReaction.appear_animation), "80_80_nolimit", null, null, svgThumb, 0, "tgs", react, 0); + 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); } - public void play(int delay) { + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + resetAnimation(); + } + + public boolean play(int delay) { + if (!animationEnabled) { + resetAnimation(); + isEnter = true; + return false; + } AndroidUtilities.cancelRunOnUIThread(playRunnable); - if (backupImageView.getImageReceiver().getLottieAnimation() != null) { - backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); + if (backupImageView.getImageReceiver().getLottieAnimation() != null && !backupImageView.getImageReceiver().getLottieAnimation().isGeneratingCache() && !isEnter) { + isEnter = true; if (delay == 0) { + backupImageView.getImageReceiver().getLottieAnimation().stop(); + backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); playRunnable.run(); } else { backupImageView.getImageReceiver().getLottieAnimation().stop(); backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); AndroidUtilities.runOnUIThread(playRunnable, delay); } - + return true; } - - + if (backupImageView.getImageReceiver().getLottieAnimation() != null && isEnter && !backupImageView.getImageReceiver().getLottieAnimation().isRunning() && !backupImageView.getImageReceiver().getLottieAnimation().isGeneratingCache()) { + backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(backupImageView.getImageReceiver().getLottieAnimation().getFramesCount() - 1, false); + } + return false; } + public void resetAnimation() { + AndroidUtilities.cancelRunOnUIThread(playRunnable); + if (backupImageView.getImageReceiver().getLottieAnimation() != null && !backupImageView.getImageReceiver().getLottieAnimation().isGeneratingCache()) { + backupImageView.getImageReceiver().getLottieAnimation().stop(); + if (animationEnabled) { + backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false, true); + } else { + backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(backupImageView.getImageReceiver().getLottieAnimation().getFramesCount() - 1, false, true); + } + } + isEnter = false; + } } public interface ReactionsContainerDelegate { void onReactionClicked(View v, TLRPC.TL_availableReaction reaction); } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatInfoDidLoad); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatInfoDidLoad); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.chatInfoDidLoad) { + TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0]; + if (chatFull.id == waitingLoadingChatId && getVisibility() != View.VISIBLE && !chatFull.available_reactions.isEmpty()) { + setMessage(messageObject, null); + setVisibility(View.VISIBLE); + startEnterAnimation(); + } + } + } + } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index e2764afac..0c21326c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -13,7 +13,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.Drawable; @@ -26,7 +25,6 @@ import android.transition.TransitionManager; import android.transition.TransitionSet; import android.transition.TransitionValues; import android.util.SparseArray; -import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -52,10 +50,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; public class ScrollSlidingTabStrip extends HorizontalScrollView { @@ -648,7 +643,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } if (sticker instanceof TLRPC.Document) { // String.format(Locale.US, "%d_%d_nr_%s" + messageObject.emojiAnimatedStickerColor, w, h, messageObject.toString()); - tabView.imageView.setImage(ImageLocation.getForDocument((TLRPC.Document) sticker), "36_36", thumbDrawable, null); + tabView.imageView.setImage(ImageLocation.getForDocument((TLRPC.Document) sticker), "36_36_nolimit", thumbDrawable, null); } else { tabView.imageView.setImageDrawable(thumbDrawable); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java index 748f98181..550f183b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java @@ -100,6 +100,7 @@ public class TextStyleSpan extends MetricAffectingSpan { public final static int FLAG_STYLE_SPOILER = 256; public final static int FLAG_STYLE_SPOILER_REVEALED = 512; + public TextStyleSpan(TextStyleRun run) { this(run, 0, 0); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java index 70e7d9c52..a75e53198 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java @@ -477,8 +477,10 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe if (backupImageView.getImageReceiver().getLottieAnimation() != null) { AndroidUtilities.cancelRunOnUIThread(animationCancelRunnable); backupImageView.setVisibility(View.VISIBLE); - backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); - backupImageView.getImageReceiver().getLottieAnimation().start(); + if (!backupImageView.getImageReceiver().getLottieAnimation().isRunning) { + backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, true); + backupImageView.getImageReceiver().getLottieAnimation().start(); + } backupImageView.animate().scaleX(2f).scaleY(2f).setDuration(300).setInterpolator(AndroidUtilities.overshootInterpolator).start(); AndroidUtilities.runOnUIThread(animationCancelRunnable = () -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert.java index 0ecb5c733..b0b58a49f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert.java @@ -1,11 +1,14 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.displayMetrics; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.getSystemProperty; import static org.telegram.messenger.AndroidUtilities.lerp; import android.animation.Animator; import android.animation.ValueAnimator; import android.app.Dialog; +import android.content.ClipboardManager; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; @@ -27,6 +30,7 @@ import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.text.Layout; +import android.text.Selection; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -69,6 +73,7 @@ import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONTokener; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; @@ -81,6 +86,7 @@ import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChatActivity; import java.io.BufferedReader; import java.io.IOException; @@ -96,7 +102,8 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; public class TranslateAlert extends Dialog { - private FrameLayout statusBar; + private FrameLayout bulletinContainer; +// private FrameLayout statusBar; private FrameLayout contentView; private FrameLayout container; private TextView titleView; @@ -110,7 +117,7 @@ public class TranslateAlert extends Dialog { private boolean scrollViewScrollable = false; private NestedScrollView scrollView; private LinearLayout textsView; - private TextView translateMoreView; +// private TextView translateMoreView; private TextView buttonTextView; private FrameLayout buttonView; private FrameLayout buttonShadowView; @@ -129,24 +136,36 @@ public class TranslateAlert extends Dialog { private float containerOpenAnimationT = 0f; private float openAnimationT = 0f; + private float epsilon = 0.001f; private void openAnimation(float t) { - t = Math.min(Math.max(t, 0), 1); + t = Math.min(Math.max(t, 0f), 1f); + if (containerOpenAnimationT == t) + return; containerOpenAnimationT = t; - container.forceLayout(); titleView.setScaleX(lerp(1f, 0.9473f, t)); titleView.setScaleY(lerp(1f, 0.9473f, t)); - titleLayout.topMargin = dp(lerp(22, 8, t)); - titleLayout.leftMargin = dp(lerp(22, 72, t)); + titleLayout.setMargins( + dp(lerp(22, 72, t)), + dp(lerp(22, 8, t)), + titleLayout.rightMargin, + titleLayout.bottomMargin + ); titleView.setLayoutParams(titleLayout); +// titleView.forceLayout(); // // statusBar.setAlpha(Math.max(0, (t - .8f) / .2f)); // statusBar.setTranslationY(Math.max(0, (1f - (t - .9f) / .1f) * dp(48))); // statusBar.setScaleY(Math.max(0, (t - .8f) / .2f)); - subtitleLayout.topMargin = dp(lerp(47, 30, t)) - LoadingTextView.padVert; - subtitleLayout.leftMargin = dp(lerp(22, 72, t)) - LoadingTextView.padHorz; + subtitleLayout.setMargins( + dp(lerp(22, 72, t)) - subtitleFromView.padHorz, + dp(lerp(47, 30, t)) - subtitleFromView.padVert, + subtitleLayout.rightMargin, + subtitleLayout.bottomMargin + ); subtitleView.setLayoutParams(subtitleLayout); +// subtitleView.forceLayout(); backButton.setAlpha(t); backButton.setScaleX(.75f + .25f * t); @@ -156,9 +175,19 @@ public class TranslateAlert extends Dialog { headerLayout.height = (int) lerp(dp(70), dp(56), t); header.setLayoutParams(headerLayout); +// header.forceLayout(); - scrollViewLayout.topMargin = (int) lerp(dp(70), dp(56), t); + scrollViewLayout.setMargins( + scrollViewLayout.leftMargin, + (int) lerp(dp(70), dp(56), t), + scrollViewLayout.rightMargin, + scrollViewLayout.bottomMargin + ); scrollView.setLayoutParams(scrollViewLayout); + +// container.invalidate(); + container.requestLayout(); +// contentView.forceLayout(); // allTextsView.setTextIsSelectable(t >= 1f); // for (int i = 0; i < textsView.getChildCount(); ++i) { // View child = textsView.getChildAt(i); @@ -166,6 +195,8 @@ public class TranslateAlert extends Dialog { // ((LoadingTextView) child).setTextIsSelectable(t >= 1f); // } } + + private boolean openAnimationToAnimatorPriority = false; private ValueAnimator openAnimationToAnimator = null; private void openAnimationTo(float to, boolean priority) { @@ -201,19 +232,19 @@ public class TranslateAlert extends Dialog { private int textsViewMinHeight = 0; private int minHeight() { return (textsView == null ? 0 : textsView.getMeasuredHeight()) + dp( - 66 + // header - 1 + // button separator - 16 + // button top padding - 48 + // button - 16 // button bottom padding + 66 + // header + 1 + // button separator + 16 + // button top padding + 48 + // button + 16 // button bottom padding ); } private boolean canExpand() { return ( - textsView.getChildCount() < textBlocks.size() || - minHeight() >= Math.min(dp(550), AndroidUtilities.displayMetrics.heightPixels / 2) //|| + textsView.getChildCount() < textBlocks.size() || + minHeight() >= (AndroidUtilities.displayMetrics.heightPixels * heightMaxPercent) //|| // (scrollView.canScrollVertically(1) || scrollView.canScrollVertically(-1)) - ); + ) && textsView.getChildCount() > 0 && ((LoadingTextView) textsView.getChildAt(0)).loaded; } private void updateCanExpand() { boolean canExpand = canExpand(); @@ -223,6 +254,12 @@ public class TranslateAlert extends Dialog { buttonShadowView.animate().alpha(canExpand ? 1f : 0f).setDuration((long) (Math.abs(buttonShadowView.getAlpha() - (canExpand ? 1f : 0f)) * 220)).start(); } + public interface OnLinkPress { + public void run(URLSpan urlSpan); + } + + private int textPadHorz, textPadVert; + private int scrollShouldBe = -1; private boolean allowScroll = true; private ValueAnimator scrollerToBottom = null; @@ -230,9 +267,11 @@ public class TranslateAlert extends Dialog { private CharSequence text; private BaseFragment fragment; private boolean noforwards; - public TranslateAlert(BaseFragment fragment, Context context, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards) { + private OnLinkPress onLinkPress = null; + public TranslateAlert(BaseFragment fragment, Context context, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress) { super(context, R.style.TransparentDialog); + this.onLinkPress = onLinkPress; this.noforwards = noforwards; this.fragment = fragment; this.fromLanguage = fromLanguage != null && fromLanguage.equals("und") ? "auto" : fromLanguage; @@ -286,19 +325,20 @@ public class TranslateAlert extends Dialog { int fullWidth = MeasureSpec.getSize(widthMeasureSpec); int fullHeight = MeasureSpec.getSize(widthMeasureSpec); boolean isPortrait = fullHeight > fullWidth; - int minHeight = (int) Math.min(dp(550), AndroidUtilities.displayMetrics.heightPixels * (isPortrait ? .5f : .85f)); +// int minHeight = (int) Math.min(dp(550), AndroidUtilities.displayMetrics.heightPixels * heightMaxPercent); + int minHeight = (int) (AndroidUtilities.displayMetrics.heightPixels * heightMaxPercent); int fromHeight = Math.min(minHeight, minHeight()); int height = (int) (fromHeight + (AndroidUtilities.displayMetrics.heightPixels - fromHeight) * containerOpenAnimationT); updateCanExpand(); super.onMeasure( - MeasureSpec.makeMeasureSpec( - (int) Math.max(fullWidth * 0.8f, Math.min(dp(480), fullWidth)), - MeasureSpec.getMode(widthMeasureSpec) - ), - MeasureSpec.makeMeasureSpec( - height, - MeasureSpec.EXACTLY - ) + MeasureSpec.makeMeasureSpec( + (int) Math.max(fullWidth * 0.8f, Math.min(dp(480), fullWidth)), + MeasureSpec.getMode(widthMeasureSpec) + ), + MeasureSpec.makeMeasureSpec( + height, + MeasureSpec.EXACTLY + ) ); } @@ -347,10 +387,10 @@ public class TranslateAlert extends Dialog { titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp(19)); header.addView(titleView, titleLayout = LayoutHelper.createFrame( - LayoutHelper.MATCH_PARENT, - LayoutHelper.WRAP_CONTENT, - Gravity.FILL_HORIZONTAL | Gravity.TOP, - 22, 22,22, 0 + LayoutHelper.MATCH_PARENT, + LayoutHelper.WRAP_CONTENT, + Gravity.FILL_HORIZONTAL | Gravity.TOP, + 22, 22,22, 0 )); titleView.post(() -> { titleView.setPivotX(LocaleController.isRTL ? titleView.getWidth() : 0); @@ -364,41 +404,63 @@ public class TranslateAlert extends Dialog { if (Build.VERSION.SDK_INT >= 17) subtitleView.setLayoutDirection(LocaleController.isRTL ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); subtitleView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - subtitleView.setPadding(0, 0, LoadingTextView.padHorz, 0); + + textPadHorz = dp(6); + textPadVert = dp(1.5f); String fromLanguageName = languageName(fromLanguage); - subtitleFromView = new LoadingTextView(context, fromLanguageName == null ? languageName(toLanguage) : fromLanguageName, false, true); + subtitleFromView = new LoadingTextView(context, dp(6), dp(1.5f), fromLanguageName == null ? languageName(toLanguage) : fromLanguageName, false, true) { + @Override + protected void onLoadAnimation(float t) { + MarginLayoutParams lp = (MarginLayoutParams) subtitleFromView.getLayoutParams(); + if (LocaleController.isRTL) { + lp.leftMargin = dp(2f - t * 6f); + } else { + lp.rightMargin = dp(2f - t * 6f); + } + subtitleFromView.setLayoutParams(lp); + } + }; subtitleFromView.showLoadingText(false); subtitleFromView.setLines(1); subtitleFromView.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); - subtitleFromView.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp(14)); + subtitleFromView.setTextSize(dp(14)); if (fromLanguageName != null) subtitleFromView.setText(fromLanguageName); - subtitleView.addView(subtitleFromView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); - subtitleFromView.updateHeight(); subtitleArrowView = new ImageView(context); subtitleArrowView.setImageResource(R.drawable.search_arrow); subtitleArrowView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_actionBarSubtitle), PorterDuff.Mode.MULTIPLY)); if (LocaleController.isRTL) subtitleArrowView.setScaleX(-1f); - subtitleView.addView(subtitleArrowView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, (int) (2 - LoadingTextView.padHorz / AndroidUtilities.density), 1, 3, 0)); subtitleToView = new TextView(context); subtitleToView.setLines(1); subtitleToView.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); subtitleToView.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp(14)); subtitleToView.setText(languageName(toLanguage)); - subtitleView.addView(subtitleToView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + + if (LocaleController.isRTL) { + subtitleView.setPadding(subtitleFromView.padHorz, 0, textPadHorz - subtitleFromView.padHorz, 0); + subtitleView.addView(subtitleToView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + subtitleView.addView(subtitleArrowView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 3, 1, 0, 0)); + subtitleView.addView(subtitleFromView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 2, 0, 0, 0)); + } else { + subtitleView.setPadding(textPadHorz - subtitleFromView.padHorz, 0, subtitleFromView.padHorz, 0); + subtitleView.addView(subtitleFromView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 2, 0)); + subtitleView.addView(subtitleArrowView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 1, 3, 0)); + subtitleView.addView(subtitleToView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + } + subtitleFromView.updateHeight(); header.addView(subtitleView, subtitleLayout = LayoutHelper.createFrame( - LayoutHelper.MATCH_PARENT, - LayoutHelper.WRAP_CONTENT, - Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), - 22 - LoadingTextView.padHorz / AndroidUtilities.density, - 47 - LoadingTextView.padVert / AndroidUtilities.density, - 22 - LoadingTextView.padHorz / AndroidUtilities.density, - 0 + LayoutHelper.MATCH_PARENT, + LayoutHelper.WRAP_CONTENT, + Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), + 22 - textPadHorz / AndroidUtilities.density, + 47 - textPadVert / AndroidUtilities.density, + 22 - textPadHorz / AndroidUtilities.density, + 0 )); backButton = new ImageView(context); @@ -430,6 +492,14 @@ public class TranslateAlert extends Dialog { public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (scrollAtBottom() && fetchNext()) { + openAnimationTo(1f, true); + } + } }; // scrollView.setOnTouchListener(new View.OnTouchListener() { // @Override @@ -446,51 +516,46 @@ public class TranslateAlert extends Dialog { } }; textsView.setOrientation(LinearLayout.VERTICAL); - textsView.setPadding(dp(22) - LoadingTextView.padHorz, dp(12) - LoadingTextView.padVert, dp(22) - LoadingTextView.padHorz, dp(12) - LoadingTextView.padVert); + textsView.setPadding(dp(22) - textPadHorz, dp(12) - textPadVert, dp(22) - textPadHorz, dp(12) - textPadVert); - translateMoreView = new TextView(context); - translateMoreView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue)); - translateMoreView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - translateMoreView.setText(LocaleController.getString("TranslateMore", R.string.TranslateMore)); - translateMoreView.setVisibility(textBlocks.size() > 1 ? View.INVISIBLE : View.GONE); - translateMoreView.getPaint().setAntiAlias(true); - translateMoreView.getPaint().setFlags(Paint.ANTI_ALIAS_FLAG); - translateMoreView.setBackgroundDrawable(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_dialogLinkSelection), dp(1), dp(1))); - translateMoreView.setOnClickListener(e -> { - boolean atBottom = (scrollView.getScrollY() >= scrollView.computeVerticalScrollRange() - scrollView.computeVerticalScrollExtent()); - - - openAnimationTo(1f, true); - fetchNext(); - - if (containerOpenAnimationT >= 1f && canExpand()/* && atBottom*/) { - if (scrollerToBottom != null) { - scrollerToBottom.cancel(); - scrollerToBottom = null; - } - allowScroll = false; - scrollView.stopNestedScroll(); - scrollerToBottom = ValueAnimator.ofFloat(0f, 1f); - int fromScroll = scrollView.getScrollY(); - scrollerToBottom.addUpdateListener(a -> { - scrollView.setScrollY((int) (fromScroll + dp(150) * (float) a.getAnimatedValue())); - }); - scrollerToBottom.addListener(new Animator.AnimatorListener() { - @Override public void onAnimationRepeat(Animator animator) {} - @Override public void onAnimationStart(Animator animator) {} - @Override public void onAnimationEnd(Animator animator) { - allowScroll = true; - } - @Override public void onAnimationCancel(Animator animator) { - allowScroll = true; - } - }); - scrollerToBottom.setDuration(220); - scrollerToBottom.start(); - } - }); - translateMoreView.setPadding(LoadingTextView.padHorz, LoadingTextView.padVert, LoadingTextView.padHorz, LoadingTextView.padVert); - textsView.addView(translateMoreView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT,0, 0, 0, 0)); +// translateMoreView = new TextView(context); +// translateMoreView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue)); +// translateMoreView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); +// translateMoreView.setText(LocaleController.getString("TranslateMore", R.string.TranslateMore)); +// translateMoreView.setVisibility(textBlocks.size() > 1 ? View.INVISIBLE : View.GONE); +// translateMoreView.getPaint().setAntiAlias(true); +// translateMoreView.getPaint().setFlags(Paint.ANTI_ALIAS_FLAG); +// translateMoreView.setBackgroundDrawable(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_dialogLinkSelection), dp(1), dp(1))); +// translateMoreView.setOnClickListener(e -> { +// openAnimationTo(1f, true); +// fetchNext(); +// +// if (containerOpenAnimationT >= 1f && canExpand()/* && atBottom*/) { +// if (scrollerToBottom != null) { +// scrollerToBottom.cancel(); +// scrollerToBottom = null; +// } +// allowScroll = false; +// scrollView.stopNestedScroll(); +// scrollerToBottom = ValueAnimator.ofFloat(0f, 1f); +// int fromScroll = scrollView.getScrollY(); +// scrollerToBottom.addUpdateListener(a -> { +// scrollView.setScrollY((int) (fromScroll + dp(150) * (float) a.getAnimatedValue())); +// }); +// scrollerToBottom.addListener(new Animator.AnimatorListener() { +// @Override public void onAnimationRepeat(Animator animator) {} +// @Override public void onAnimationStart(Animator animator) {} +// @Override public void onAnimationEnd(Animator animator) { +// allowScroll = true; +// } +// @Override public void onAnimationCancel(Animator animator) { allowScroll = true; } +// }); +// scrollerToBottom.setDuration(220); +// scrollerToBottom.start(); +// } +// }); +// translateMoreView.setPadding(textPadHorz, textPadVert, textPadHorz, textPadVert); +// textsView.addView(translateMoreView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT,0, 0, 0, 0)); Paint selectionPaint = new Paint(); selectionPaint.setColor(Theme.getColor(Theme.key_chat_inTextSelectionHighlight)); @@ -507,7 +572,7 @@ public class TranslateAlert extends Dialog { allTextsView = new TextView(context) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(999999, MeasureSpec.AT_MOST)); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(99999999, MeasureSpec.AT_MOST)); } private Paint pressedLinkPaint = null; private Path pressedLinkPath = new Path() { @@ -515,7 +580,7 @@ public class TranslateAlert extends Dialog { @Override public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) { // super.addRect(left, top, right, bottom, dir); - rectF.set(left - LoadingTextView.padHorz / 2, top - LoadingTextView.padVert, right + LoadingTextView.padHorz / 2, bottom + LoadingTextView.padVert); + rectF.set(left - textPadHorz / 2, top - textPadVert, right + textPadHorz / 2, bottom + textPadVert); addRoundRect(rectF, dp(4), dp(4), Direction.CW); } }; @@ -537,6 +602,25 @@ public class TranslateAlert extends Dialog { } catch (Exception e) { } } } + + @Override + public boolean onTextContextMenuItem(int id) { + if (id == android.R.id.copy && isFocused()) { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText( + "label", + getText().subSequence( + Math.max(0, Math.min(getSelectionStart(), getSelectionEnd())), + Math.max(0, Math.max(getSelectionStart(), getSelectionEnd())) + ) + ); + clipboard.setPrimaryClip(clip); + BulletinFactory.of(bulletinContainer, null).createCopyBulletin(LocaleController.getString("TextCopied", R.string.TextCopied)).show(); + clearFocus(); + return true; + } else + return super.onTextContextMenuItem(id); + } }; allTextsView.setTextColor(0x00000000); allTextsView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); @@ -565,7 +649,7 @@ public class TranslateAlert extends Dialog { container.addView(scrollView, scrollViewLayout = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 0, 70, 0, 81)); - translateMoreView.bringToFront(); +// translateMoreView.bringToFront(); fetchNext(); buttonShadowView = new FrameLayout(context); @@ -591,15 +675,29 @@ public class TranslateAlert extends Dialog { container.addView(buttonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM, 16, 16, 16, 16)); contentView.addView(container, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL)); + bulletinContainer = new FrameLayout(context); + contentView.addView(bulletinContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 81)); // setUseLightStatusBar(true); } + private boolean scrollAtBottom() { + View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1); + int bottom = view.getBottom(); + if (textsView.getChildCount() > 0) { + view = textsView.getChildAt(textsView.getChildCount() - 1); + if (view instanceof LoadingTextView && !((LoadingTextView) view).loaded) + bottom = view.getTop(); + } + int diff = (bottom - (scrollView.getHeight() + scrollView.getScrollY())); + return diff <= textsContainerView.getPaddingBottom(); + } private void setScrollY(float t) { openAnimation(t); openingT = Math.max(Math.min(1f + t, 1), 0); backDrawable.setAlpha((int) (openingT * 51)); container.invalidate(); + bulletinContainer.setTranslationY((1f - openingT) * Math.min(minHeight(), displayMetrics.heightPixels * heightMaxPercent)); } private void scrollYTo(float t) { openAnimationTo(t, false); @@ -627,14 +725,14 @@ public class TranslateAlert extends Dialog { private boolean fromScrollRect = false; private boolean fromTranslateMoreView = false; private float fromScrollViewY = 0; - private Spannable allTexts; + private Spannable allTexts = null; private ClickableSpan pressedLink; @Override public boolean dispatchTouchEvent(@NonNull MotionEvent event) { try { float x = event.getX(); float y = event.getY(); - container.invalidate(); +// container.invalidate(); container.getGlobalVisibleRect(containerRect); if (!containerRect.contains((int) x, (int) y)) { @@ -650,28 +748,33 @@ public class TranslateAlert extends Dialog { } } - allTextsContainer.getGlobalVisibleRect(textRect); - if (textRect.contains((int) x, (int) y) && !scrolling) { - Layout allTextsLayout = allTextsView.getLayout(); - int tx = (int) (x - allTextsView.getLeft() - container.getLeft()), + try { + allTextsContainer.getGlobalVisibleRect(textRect); + if (textRect.contains((int) x, (int) y) && !scrolling) { + Layout allTextsLayout = allTextsView.getLayout(); + int tx = (int) (x - allTextsView.getLeft() - container.getLeft()), ty = (int) (y - allTextsView.getTop() - container.getTop() - scrollView.getTop() + scrollView.getScrollY()); - final int line = allTextsLayout.getLineForVertical(ty); - final int off = allTextsLayout.getOffsetForHorizontal(line, tx); + final int line = allTextsLayout.getLineForVertical(ty); + final int off = allTextsLayout.getOffsetForHorizontal(line, tx); - final float left = allTextsLayout.getLineLeft(line); - if (allTexts != null && allTexts instanceof Spannable && left <= tx && left + allTextsLayout.getLineWidth(line) >= tx) { - ClickableSpan[] links = allTexts.getSpans(off, off, ClickableSpan.class); - if (links != null && links.length >= 1) { - if (event.getAction() == MotionEvent.ACTION_UP && pressedLink == links[0]) { - pressedLink.onClick(allTextsView); + final float left = allTextsLayout.getLineLeft(line); + if (allTexts != null && allTexts instanceof Spannable && left <= tx && left + allTextsLayout.getLineWidth(line) >= tx) { + ClickableSpan[] links = allTexts.getSpans(off, off, ClickableSpan.class); + if (links != null && links.length >= 1) { + if (event.getAction() == MotionEvent.ACTION_UP && pressedLink == links[0]) { + pressedLink.onClick(allTextsView); + pressedLink = null; + allTextsView.setTextIsSelectable(!noforwards); + } else if (event.getAction() == MotionEvent.ACTION_DOWN) { + pressedLink = links[0]; + } + allTextsView.invalidate(); + // return super.dispatchTouchEvent(event) || true; + return true; + } else if (pressedLink != null) { + allTextsView.invalidate(); pressedLink = null; - allTextsView.setTextIsSelectable(!noforwards); - } else if (event.getAction() == MotionEvent.ACTION_DOWN) { - pressedLink = links[0]; } - allTextsView.invalidate(); - // return super.dispatchTouchEvent(event) || true; - return true; } else if (pressedLink != null) { allTextsView.invalidate(); pressedLink = null; @@ -680,25 +783,24 @@ public class TranslateAlert extends Dialog { allTextsView.invalidate(); pressedLink = null; } - } else if (pressedLink != null) { - allTextsView.invalidate(); - pressedLink = null; + } catch (Exception e2) { + e2.printStackTrace(); } scrollView.getGlobalVisibleRect(scrollRect); backButton.getGlobalVisibleRect(backRect); buttonView.getGlobalVisibleRect(buttonRect); - translateMoreView.getGlobalVisibleRect(translateMoreRect); - fromTranslateMoreView = translateMoreRect.contains((int) x, (int) y); +// translateMoreView.getGlobalVisibleRect(translateMoreRect); + fromTranslateMoreView = false; // translateMoreRect.contains((int) x, (int) y); if (pressedLink == null && /*!(scrollRect.contains((int) x, (int) y) && !canExpand() && containerOpenAnimationT < .5f && !scrolling) &&*/ !fromTranslateMoreView && !hasSelection()) { if ( - !backRect.contains((int) x, (int) y) && - !buttonRect.contains((int) x, (int) y) && - event.getAction() == MotionEvent.ACTION_DOWN + !backRect.contains((int) x, (int) y) && + !buttonRect.contains((int) x, (int) y) && + event.getAction() == MotionEvent.ACTION_DOWN ) { fromScrollRect = scrollRect.contains((int) x, (int) y) && (containerOpenAnimationT > 0 || !canExpand()); maybeScrolling = true; - scrolling = false; + scrolling = scrollRect.contains((int) x, (int) y) && textsView.getChildCount() > 0 && !((LoadingTextView) textsView.getChildAt(0)).loaded; fromY = y; fromScrollY = getScrollY(); fromScrollViewY = scrollView.getScrollY(); @@ -718,7 +820,7 @@ public class TranslateAlert extends Dialog { allowScroll = false; } float fullHeight = AndroidUtilities.displayMetrics.heightPixels, - minHeight = Math.min(fullHeight, Math.min(dp(550), fullHeight * .5f)); + minHeight = Math.min(fullHeight, fullHeight * heightMaxPercent); float scrollYPx = minHeight * (1f - -Math.min(Math.max(fromScrollY, -1), 0)) + (fullHeight - minHeight) * Math.min(1, Math.max(fromScrollY, 0)) + dy; float scrollY = scrollYPx > minHeight ? (scrollYPx - minHeight) / (fullHeight - minHeight) : -(1f - scrollYPx / minHeight); @@ -734,9 +836,9 @@ public class TranslateAlert extends Dialog { maybeScrolling = false; allowScroll = true; scrollYTo( - Math.abs(dy) > dp(16) ? - /*fromScrollRect && Math.ceil(fromScrollY) >= 1f ? -1f :*/ Math.round(fromScrollY) + (scrollY > fromScrollY ? 1f : -1f) * (float) Math.ceil(Math.abs(fromScrollY - scrollY)) : - Math.round(fromScrollY) + Math.abs(dy) > dp(16) ? + /*fromScrollRect && Math.ceil(fromScrollY) >= 1f ? -1f :*/ Math.round(fromScrollY) + (scrollY > fromScrollY ? 1f : -1f) * (float) Math.ceil(Math.abs(fromScrollY - scrollY)) : + Math.round(fromScrollY) ); } // if (fromScrollRect) @@ -754,28 +856,51 @@ public class TranslateAlert extends Dialog { } return super.dispatchTouchEvent(event); } catch (Exception e) { + e.printStackTrace(); return super.dispatchTouchEvent(event); } } private LoadingTextView addBlock(CharSequence startText, boolean scaleFromZero) { - LoadingTextView textView = new LoadingTextView(getContext(), startText, scaleFromZero, false) { + LoadingTextView textView = new LoadingTextView(getContext(), textPadHorz, textPadVert, startText, scaleFromZero, false) { + boolean hadSelection = false; + int selStart, selEnd; + @Override + protected void onLoadStart() { + allTextsView.clearFocus(); + } @Override protected void onLoadEnd() { - scrollView.postDelayed(() -> { +// hadSelection = hasSelection(); +// selStart = Selection.getSelectionStart(allTexts); +// selEnd = Selection.getSelectionEnd(allTexts); + scrollView.post(() -> { allTextsView.setText(allTexts); - }, textBlocks.size() > 1 ? 700 : 0); + allTextsView.measure(MeasureSpec.makeMeasureSpec(allTextsContainer.getWidth() - allTextsContainer.getPaddingLeft() - allTextsContainer.getPaddingRight(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(textsView.getHeight(), MeasureSpec.AT_MOST)); + allTextsView.layout( + allTextsContainer.getLeft() + allTextsContainer.getPaddingLeft(), + allTextsContainer.getTop() + allTextsContainer.getPaddingTop(), + allTextsContainer.getLeft() + allTextsContainer.getPaddingLeft() + allTextsView.getMeasuredWidth(), + allTextsContainer.getTop() + allTextsContainer.getPaddingTop() + allTextsView.getMeasuredHeight() + ); +// if (hadSelection) +// Selection.setSelection(allTexts, selStart, selEnd); + }); + + contentView.post(() -> { + if (scrollAtBottom()) + fetchNext(); + }); } }; - textView.setLines(0); - textView.setMaxLines(0); - textView.setSingleLine(false); - textView.setEllipsizeNull(); +// textView.setLines(0); +// textView.setMaxLines(0); +// textView.setSingleLine(false); +// textView.setEllipsizeNull(); textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - textView.setTextIsSelectable(false); - textView.setTranslationY((textsView.getChildCount() - 1) * (LoadingTextView.padVert * -4f + dp(.48f))); - textsView.addView(textView, textsView.getChildCount() - 1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 0, 0)); + textView.setTextSize(dp(16)); + textView.setTranslationY((textsView.getChildCount()/* - 1*/) * (textPadVert * -4f + dp(.48f))); + textsView.addView(textView, textsView.getChildCount()/* - 1*/, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 0, 0)); return textView; } @@ -831,8 +956,8 @@ public class TranslateAlert extends Dialog { params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; if (Build.VERSION.SDK_INT >= 21) { params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | - WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | - WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; } params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; params.height = ViewGroup.LayoutParams.MATCH_PARENT; @@ -859,7 +984,7 @@ public class TranslateAlert extends Dialog { openAnimation(0); openTo(1, true, true); } - + private boolean dismissed = false; @Override public void dismiss() { @@ -875,6 +1000,9 @@ public class TranslateAlert extends Dialog { private void openTo(float t) { openTo(t, false); } + private float heightMaxPercent = .85f; + + private boolean fastHide = false; private boolean openingAnimatorPriority = false; private void openTo(float t, boolean priority, boolean setAfter) { final float T = Math.min(Math.max(t, 0), 1); @@ -889,6 +1017,7 @@ public class TranslateAlert extends Dialog { openingT = (float) a.getAnimatedValue(); container.invalidate(); backDrawable.setAlpha((int) (openingT * 51)); + bulletinContainer.setTranslationY((1f - openingT) * Math.min(minHeight(), displayMetrics.heightPixels * heightMaxPercent)); }); openingAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationCancel(Animator animator) { @@ -917,7 +1046,7 @@ public class TranslateAlert extends Dialog { @Override public void onAnimationStart(Animator animator) { } }); openingAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); - openingAnimator.setDuration((long) (Math.abs(openingT - T) * (setAfter ? 380 : 200))); + openingAnimator.setDuration((long) (Math.abs(openingT - T) * (fastHide ? 200 : 380))); openingAnimator.setStartDelay(setAfter ? 60 : 0); openingAnimator.start(); } @@ -937,7 +1066,7 @@ public class TranslateAlert extends Dialog { // if (passportLang != null && passportLang.length() > 0) // return passportLang; // } - LocaleController.LocaleInfo localeInfo = LocaleController.getInstance().getLanguageByPlural(locale); + LocaleController.LocaleInfo localeInfo = LocaleController.getInstance().getBuiltinLanguageByPlural(locale); boolean isCurrentLanguageEnglish = false; try { isCurrentLanguageEnglish = LocaleController.getInstance().getCurrentLocaleInfo().pluralLangCode.equals("en"); @@ -950,7 +1079,8 @@ public class TranslateAlert extends Dialog { public void updateSourceLanguage() { if (languageName(fromLanguage) != null) { subtitleView.setAlpha(1); - subtitleFromView.setText(languageName(fromLanguage)); + if (!subtitleFromView.loaded) + subtitleFromView.setText(languageName(fromLanguage)); } else if (loaded) { subtitleView.animate().alpha(0).setDuration(150).start(); } @@ -976,100 +1106,158 @@ public class TranslateAlert extends Dialog { public void showTranslateMoreView(boolean show) { - translateMoreView.setClickable(show); - translateMoreView.setVisibility(textBlocks.size() > 1 ? View.VISIBLE : View.GONE); - translateMoreView - .animate() -// .translationX(show ? 0f : dp(4)) - .alpha(show ? 1f : 0f) - .withEndAction(() -> { - if (!show) - translateMoreView.setVisibility(textBlocks.size() > 1 ? View.INVISIBLE : View.GONE); - }) - .setInterpolator(CubicBezierInterpolator.EASE_OUT) - .setDuration((long) (Math.abs(translateMoreView.getAlpha() - (show ? 1f : 0f)) * 85)) - .start(); +// translateMoreView.setClickable(show); +// translateMoreView.setVisibility(textBlocks.size() > 1 ? View.VISIBLE : View.GONE); +// translateMoreView +// .animate() +//// .translationX(show ? 0f : dp(4)) +// .alpha(show ? 1f : 0f) +// .withEndAction(() -> { +// if (!show) +// translateMoreView.setVisibility(textBlocks.size() > 1 ? View.INVISIBLE : View.GONE); +// }) +// .setInterpolator(CubicBezierInterpolator.EASE_OUT) +// .setDuration((long) (Math.abs(translateMoreView.getAlpha() - (show ? 1f : 0f)) * 85)) +// .start(); } private boolean loading = false; private boolean loaded = false; - private void fetchNext() { + private LoadingTextView lastLoadingBlock = null; + private boolean fetchNext() { if (loading) - return; + return false; loading = true; showTranslateMoreView(false); if (blockIndex >= textBlocks.size()) - return; + return false; CharSequence blockText = textBlocks.get(blockIndex); - LoadingTextView blockView = addBlock(blockText, blockIndex != 0); + lastLoadingBlock = lastLoadingBlock == null ? addBlock(blockText, blockIndex != 0) : lastLoadingBlock; + lastLoadingBlock.loading = true; fetchTranslation( - blockText, - (String translatedText, String sourceLanguage) -> { - loaded = true; - Spannable spannable = new SpannableStringBuilder(translatedText); - try { - AndroidUtilities.addLinks(spannable, Linkify.WEB_URLS); - MessageObject.addUrlsByPattern(false, spannable, false, 0, 0, true); - URLSpan[] urlSpans = spannable.getSpans(0, spannable.length(), URLSpan.class); - for (int i = 0; i < urlSpans.length; ++i) { - URLSpan urlSpan = urlSpans[i]; - int start = spannable.getSpanStart(urlSpan), - end = spannable.getSpanEnd(urlSpan); - spannable.removeSpan(urlSpan); - spannable.setSpan( - new ClickableSpan() { - @Override - public void onClick(@NonNull View view) { - AlertsCreator.showOpenUrlAlert(fragment, urlSpan.getURL(), false, false); - } + blockText, + (String translatedText, String sourceLanguage) -> { + loaded = true; + Spannable spannable = new SpannableStringBuilder(translatedText); + try { + MessageObject.addUrlsByPattern(false, spannable, false, 0, 0, true); + URLSpan[] urlSpans = spannable.getSpans(0, spannable.length(), URLSpan.class); + for (int i = 0; i < urlSpans.length; ++i) { + URLSpan urlSpan = urlSpans[i]; + int start = spannable.getSpanStart(urlSpan), + end = spannable.getSpanEnd(urlSpan); + if (start == -1 || end == -1) + continue; + spannable.removeSpan(urlSpan); + spannable.setSpan( + new ClickableSpan() { + @Override + public void onClick(@NonNull View view) { + if (onLinkPress != null) { + onLinkPress.run(urlSpan); + fastHide = true; + dismiss(); + } else + AlertsCreator.showOpenUrlAlert(fragment, urlSpan.getURL(), false, false); + } - @Override - public void updateDrawState(@NonNull TextPaint ds) { - int alpha = Math.min(ds.getAlpha(), ds.getColor() >> 24 & 0xff); - ds.setUnderlineText(true); - ds.setColor(Theme.getColor(Theme.key_dialogTextLink)); - ds.setAlpha(alpha); - } - }, - start, end, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ); - } - } catch (Exception e) { - e.printStackTrace(); + @Override + public void updateDrawState(@NonNull TextPaint ds) { + int alpha = Math.min(ds.getAlpha(), ds.getColor() >> 24 & 0xff); + if (!(urlSpan instanceof URLSpanNoUnderline)) + ds.setUnderlineText(true); + ds.setColor(Theme.getColor(Theme.key_dialogTextLink)); + ds.setAlpha(alpha); + } + }, + start, end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ); } - blockView.setText(spannable); - allTexts = new SpannableStringBuilder(allTextsView.getText()).append(blockIndex == 0 ? "" : "\n").append(spannable); - fromLanguage = sourceLanguage; - updateSourceLanguage(); + AndroidUtilities.addLinks(spannable, Linkify.WEB_URLS); + urlSpans = spannable.getSpans(0, spannable.length(), URLSpan.class); + for (int i = 0; i < urlSpans.length; ++i) { + URLSpan urlSpan = urlSpans[i]; + int start = spannable.getSpanStart(urlSpan), + end = spannable.getSpanEnd(urlSpan); + if (start == -1 || end == -1) + continue; + spannable.removeSpan(urlSpan); + spannable.setSpan( + new ClickableSpan() { + @Override + public void onClick(@NonNull View view) { + AlertsCreator.showOpenUrlAlert(fragment, urlSpan.getURL(), false, false); + } - blockIndex++; - showTranslateMoreView(blockIndex < textBlocks.size()); - loading = false; + @Override + public void updateDrawState(@NonNull TextPaint ds) { + int alpha = Math.min(ds.getAlpha(), ds.getColor() >> 24 & 0xff); + if (!(urlSpan instanceof URLSpanNoUnderline)) + ds.setUnderlineText(true); + ds.setColor(Theme.getColor(Theme.key_dialogTextLink)); + ds.setAlpha(alpha); + } + }, + start, end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ); + } - }, - (boolean rateLimit) -> { - if (rateLimit) - Toast.makeText(getContext(), LocaleController.getString("TranslationFailedAlert1", R.string.TranslationFailedAlert1), Toast.LENGTH_SHORT).show(); - else - Toast.makeText(getContext(), LocaleController.getString("TranslationFailedAlert2", R.string.TranslationFailedAlert2), Toast.LENGTH_SHORT).show(); - if (blockIndex == 0) - dismiss(); + spannable = (Spannable) Emoji.replaceEmoji(spannable, allTextsView.getPaint().getFontMetricsInt(), dp(14), false); + } catch (Exception e) { + e.printStackTrace(); } + +// boolean hadSelection = hasSelection(); +// int selectionStart = Selection.getSelectionStart(allTexts), +// selectionEnd = Selection.getSelectionEnd(allTexts); + allTexts = new SpannableStringBuilder(allTextsView.getText()).append(blockIndex == 0 ? "" : "\n").append(spannable); +// if (hadSelection) +// Selection.setSelection(allTexts, selectionStart, selectionEnd); + + if (lastLoadingBlock != null) { + lastLoadingBlock.setText(spannable); + lastLoadingBlock = null; + } + + + fromLanguage = sourceLanguage; + updateSourceLanguage(); + + blockIndex++; + showTranslateMoreView(blockIndex < textBlocks.size()); + loading = false; + + if (blockIndex < textBlocks.size()) { + CharSequence nextTextBlock = textBlocks.get(blockIndex); + lastLoadingBlock = addBlock(nextTextBlock, true); + lastLoadingBlock.loading = false; + } + }, + (boolean rateLimit) -> { + if (rateLimit) + Toast.makeText(getContext(), LocaleController.getString("TranslationFailedAlert1", R.string.TranslationFailedAlert1), Toast.LENGTH_SHORT).show(); + else + Toast.makeText(getContext(), LocaleController.getString("TranslationFailedAlert2", R.string.TranslationFailedAlert2), Toast.LENGTH_SHORT).show(); + if (blockIndex == 0) + dismiss(); + } ); + return true; } private String[] userAgents = new String[] { - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", // 13.5% - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", // 6.6% - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0", // 6.4% - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0", // 6.2% - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36", // 5.2% - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36" // 4.8% + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", // 13.5% + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", // 6.6% + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0", // 6.4% + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0", // 6.2% + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36", // 5.2% + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36" // 4.8% }; public interface OnTranslationSuccess { public void run(String translated, String sourceLanguage); @@ -1086,11 +1274,11 @@ public class TranslateAlert extends Dialog { HttpURLConnection connection = null; long start = SystemClock.elapsedRealtime(); try { - uri = "https://translate.goo"; - uri += "gleapis.com/transl"; - uri += "ate_a"; - uri += "/singl"; - uri += "e?client=gtx&sl=" + Uri.encode(fromLanguage) + "&tl=" + Uri.encode(toLanguage) + "&dt=t" + "&ie=UTF-8&oe=UTF-8&otf=1&ssel=0&tsel=0&kc=7&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&q="; + uri = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="; + uri += Uri.encode(fromLanguage); + uri += "&tl="; + uri += Uri.encode(toLanguage); + uri += "&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=0&tsel=0&kc=7&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&q="; uri += Uri.encode(text.toString()); connection = (HttpURLConnection) new URI(uri).toURL().openConnection(); connection.setRequestMethod("GET"); @@ -1158,8 +1346,8 @@ public class TranslateAlert extends Dialog { }.start(); } - public static void showAlert(Context context, BaseFragment fragment, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards) { - TranslateAlert alert = new TranslateAlert(fragment, context, fromLanguage, toLanguage, text, noforwards); + 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) { if (fragment.getParentActivity() != null) { fragment.showDialog(alert); @@ -1171,15 +1359,16 @@ public class TranslateAlert extends Dialog { private static class LoadingTextView extends FrameLayout { private TextView loadingTextView; - public TextView textView; + public TextView textView = null; private CharSequence loadingString; - // private StaticLayout loadingLayout; +// private StaticLayout loadingLayout; // private StaticLayout textLayout; private Paint loadingPaint = new Paint(); + private Paint loadingIdlePaint = new Paint(); private Path loadingPath = new Path(); private RectF fetchedPathRect = new RectF(); - public static int padHorz = dp(6), padVert = dp(1.5f); + public int padHorz = dp(6), padVert = dp(1.5f); private Path fetchPath = new Path() { private boolean got = false; @@ -1193,10 +1382,10 @@ public class TranslateAlert extends Dialog { public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) { if (!got) { fetchedPathRect.set( - left - padHorz, - top - padVert, - right + padHorz, - bottom + padVert + left - padHorz, + top - padVert, + right + padHorz, + bottom + padVert ); got = true; } @@ -1204,30 +1393,35 @@ public class TranslateAlert extends Dialog { }; public void resize() { - textView.forceLayout(); - loadingTextView.forceLayout(); - updateLoadingLayout(); - updateTextLayout(); - updateHeight(); + post(() -> { + loadingTextView.forceLayout(); + textView.forceLayout(); + updateLoadingLayout(); + updateTextLayout(); + updateHeight(); + }); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - LoadingTextView.this.resize(); +// if (changed) +// resize(); } private boolean animateWidth = false; private boolean scaleFromZero = false; private long scaleFromZeroStart = 0; private final long scaleFromZeroDuration = 220l; - public LoadingTextView(Context context, CharSequence loadingString, boolean scaleFromZero, boolean animateWidth) { + public LoadingTextView(Context context, int padHorz, int padVert, CharSequence loadingString, boolean scaleFromZero, boolean animateWidth) { super(context); this.animateWidth = animateWidth; this.scaleFromZero = scaleFromZero; this.scaleFromZeroStart = SystemClock.elapsedRealtime(); + this.padHorz = padHorz; + this.padVert = padVert; setPadding(padHorz, padVert, padHorz, padVert); loadingT = 0f; @@ -1235,19 +1429,18 @@ public class TranslateAlert extends Dialog { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( - animateWidth ? - MeasureSpec.makeMeasureSpec( - 999999, - MeasureSpec.AT_MOST - ) : widthMeasureSpec, + animateWidth ? MeasureSpec.makeMeasureSpec( - MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST ? 999999 : MeasureSpec.getSize(heightMeasureSpec), - MeasureSpec.getMode(heightMeasureSpec) - ) + 999999, + MeasureSpec.AT_MOST + ) : widthMeasureSpec, + MeasureSpec.makeMeasureSpec( + MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST ? 999999 : MeasureSpec.getSize(heightMeasureSpec), + MeasureSpec.getMode(heightMeasureSpec) + ) ); } }; - loadingString = Emoji.replaceEmoji(loadingString, loadingTextView.getPaint().getFontMetricsInt(), dp(14), false); loadingTextView.setText(this.loadingString = loadingString); loadingTextView.setVisibility(INVISIBLE); loadingTextView.measure(MeasureSpec.makeMeasureSpec(animateWidth ? 999999 : getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(9999999, MeasureSpec.AT_MOST)); @@ -1257,24 +1450,28 @@ public class TranslateAlert extends Dialog { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( - animateWidth ? - MeasureSpec.makeMeasureSpec( - 999999, - MeasureSpec.AT_MOST - ) : widthMeasureSpec, + animateWidth ? MeasureSpec.makeMeasureSpec( - MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST ? 999999 : MeasureSpec.getSize(heightMeasureSpec), - MeasureSpec.getMode(heightMeasureSpec) - ) + 999999, + MeasureSpec.AT_MOST + ) : widthMeasureSpec, + MeasureSpec.makeMeasureSpec( + MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST ? 999999 : MeasureSpec.getSize(heightMeasureSpec), + MeasureSpec.getMode(heightMeasureSpec) + ) ); } }; - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + textView.setText(""); + textView.setVisibility(INVISIBLE); + textView.measure(MeasureSpec.makeMeasureSpec(animateWidth ? 999999 : getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(9999999, MeasureSpec.AT_MOST)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP)); int c1 = Theme.getColor(Theme.key_dialogBackground), - c2 = Theme.getColor(Theme.key_dialogBackgroundGray); + c2 = Theme.getColor(Theme.key_dialogBackgroundGray); LinearGradient gradient = new LinearGradient(0, 0, gradientWidth, 0, new int[]{ c1, c2, c1 }, new float[] { 0, 0.67f, 1f }, Shader.TileMode.REPEAT); loadingPaint.setShader(gradient); + loadingIdlePaint.setColor(c2); setWillNotDraw(false); setClipChildren(false); @@ -1284,6 +1481,8 @@ public class TranslateAlert extends Dialog { protected void scrollToBottom() {} protected void onLoadEnd() {} + protected void onLoadStart() {} + protected void onLoadAnimation(float t) {} @Override protected void onAttachedToWindow() { @@ -1296,18 +1495,19 @@ public class TranslateAlert extends Dialog { private void updateHeight() { // int loadingHeight = loadingLayout != null ? loadingLayout.getHeight() : loadingTextView.getMeasuredHeight(); - int loadingHeight = loadingTextView.getMeasuredHeight(); + int loadingHeight = loadingTextView.getMeasuredHeight(), + textHeight = textView == null ? loadingHeight : textView.getMeasuredHeight(); float scaleFromZeroT = scaleFromZero ? Math.max(Math.min((float) (SystemClock.elapsedRealtime() - scaleFromZeroStart) / (float) scaleFromZeroDuration, 1f), 0f) : 1f; int height = ( - (int) ( - ( - padVert * 2 + - loadingHeight + ( - textView.getMeasuredHeight() - - loadingHeight - ) * loadingT - ) * scaleFromZeroT - ) + (int) ( + ( + padVert * 2 + + loadingHeight + ( + textHeight - + loadingHeight + ) * loadingT + ) * scaleFromZeroT + ) ); ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams(); boolean newHeight = false; @@ -1317,18 +1517,18 @@ public class TranslateAlert extends Dialog { } else newHeight = params.height != height; // if (height > 0 || scaleFromZero) - params.height = height; + params.height = height; if (animateWidth) { int loadingWidth = loadingTextView.getMeasuredWidth() + padHorz * 2; - int textWidth = (textView.getMeasuredWidth() <= 0 ? loadingTextView.getMeasuredWidth() : textView.getMeasuredWidth()) + padHorz * 2; + int textWidth = (textView == null || textView.getMeasuredWidth() <= 0 ? loadingTextView.getMeasuredWidth() : textView.getMeasuredWidth()) + padHorz * 2; params.width = (int) ((loadingWidth + (textWidth - loadingWidth) * loadingT) * scaleFromZeroT); } this.setLayoutParams(params); } - // private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); +// private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); // private TextPaint loadingTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private float gradientWidth = dp(350f); private void updateLoadingLayout() { @@ -1343,13 +1543,17 @@ public class TranslateAlert extends Dialog { // 1f, 0f, false // ); // loadingPath.reset(); - Layout loadingLayout = loadingTextView.getLayout(); - for (int i = 0; i < loadingLayout.getLineCount(); ++i) { - int start = loadingLayout.getLineStart(i), end = loadingLayout.getLineEnd(i); - if (start + 1 == end) - continue; - loadingLayout.getSelectionPath(start, end, fetchPath); - loadingPath.addRoundRect(fetchedPathRect, dp(4), dp(4), Path.Direction.CW); + if (loadingTextView != null) { + Layout loadingLayout = loadingTextView.getLayout(); + if (loadingLayout != null) { + for (int i = 0; i < loadingLayout.getLineCount(); ++i) { + int start = loadingLayout.getLineStart(i), end = loadingLayout.getLineEnd(i); + if (start + 1 == end) + continue; + loadingLayout.getSelectionPath(start, end, fetchPath); + loadingPath.addRoundRect(fetchedPathRect, dp(4), dp(4), Path.Direction.CW); + } + } } updateHeight(); @@ -1367,12 +1571,15 @@ public class TranslateAlert extends Dialog { loadingAnimator.start(); } } + + private TextPaint textPaint = new TextPaint(); private void updateTextLayout() { -// float textWidth = textView.getMeasuredWidth(); + textView.setWidth(getWidth() - padHorz * 2); +// float textWidth = getWidth() - padHorz * 2; // textPaint.setAntiAlias(true); // if (textWidth > 0) { // textLayout = new StaticLayout( -// textView.getText(), +// text, // textPaint, // (int) textWidth, // Layout.Alignment.ALIGN_NORMAL, @@ -1389,83 +1596,86 @@ public class TranslateAlert extends Dialog { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // updateLoadingLayout(); // updateTextLayout(); - this.resize(); + + updateLoadingLayout(); +// this.resize(); } + public boolean loading = true; public boolean loaded = false; private float loadingT = 0f; private ValueAnimator loadingAnimator = null; public void setEllipsizeNull() { loadingTextView.setEllipsize(null); - textView.setEllipsize(null); + if (textView != null) + textView.setEllipsize(null); } + private boolean singleLine = true; public void setSingleLine(boolean singleLine) { - loadingTextView.setSingleLine(singleLine); - textView.setSingleLine(singleLine); + loadingTextView.setSingleLine(this.singleLine = singleLine); + if (textView != null) + textView.setSingleLine(singleLine); } + private int lines = -1; public void setLines(int lines) { - loadingTextView.setLines(lines); - textView.setLines(lines); + loadingTextView.setLines(this.lines = lines); + if (textView != null) + textView.setLines(lines); } public void setGravity(int gravity) { loadingTextView.setGravity(gravity); - textView.setGravity(gravity); + if (textView != null) + textView.setGravity(gravity); } public void setMaxLines(int maxLines) { loadingTextView.setMaxLines(maxLines); - textView.setMaxLines(maxLines); - } - public void setTextIsSelectable(boolean selectable) { - textView.setTextIsSelectable(selectable); + if (textView != null) + textView.setMaxLines(maxLines); } private boolean showLoadingTextValue = true; public void showLoadingText(boolean show) { showLoadingTextValue = show; } + private int textColor = 0x00000000; public void setTextColor(int textColor) { // loadingTextPaint.setColor(multAlpha(textColor, showLoadingTextValue ? 0.08f : 0f)); // loadingTextView.setTextColor(multAlpha(textColor, showLoadingTextValue ? 0.08f : 0f)); // textPaint.setColor(textColor); - loadingTextView.setTextColor(textColor); - textView.setTextColor(textColor); + loadingTextView.setTextColor(this.textColor = textColor); + if (textView != null) + textView.setTextColor(textColor); } private float sz(int unit, float size) { Context c = getContext(); return TypedValue.applyDimension( - unit, size, (c == null ? Resources.getSystem() : c.getResources()).getDisplayMetrics() + unit, size, (c == null ? Resources.getSystem() : c.getResources()).getDisplayMetrics() ); } + private int textSize; public void setTextSize(int size) { - loadingTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size); - textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size); + loadingTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.textSize = size); + if (textView != null) + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size); // loadingTextPaint.setTextSize(size); // textPaint.setTextSize(size); loadingTextView.setText(loadingString = Emoji.replaceEmoji(loadingString, loadingTextView.getPaint().getFontMetricsInt(), dp(14), false)); loadingTextView.measure(MeasureSpec.makeMeasureSpec(animateWidth ? 999999 : getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(9999999, MeasureSpec.AT_MOST)); - textView.setText(Emoji.replaceEmoji(textView.getText(), textView.getPaint().getFontMetricsInt(), dp(14), false)); - updateLoadingLayout(); - } - public void setTextSize(int unit, float size) { - loadingTextView.setTextSize(unit, size); - textView.setTextSize(unit, size); -// loadingTextPaint.setTextSize(sz(unit, size)); -// textPaint.setTextSize(sz(unit, size)); - loadingTextView.setText(loadingString = Emoji.replaceEmoji(loadingString, loadingTextView.getPaint().getFontMetricsInt(), dp(14), false)); - loadingTextView.measure(MeasureSpec.makeMeasureSpec(animateWidth ? 999999 : getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(9999999, MeasureSpec.AT_MOST)); - textView.setText(Emoji.replaceEmoji(textView.getText(), textView.getPaint().getFontMetricsInt(), dp(14), false)); + + if (textView != null) { + textView.setText(Emoji.replaceEmoji(textView.getText(), textView.getPaint().getFontMetricsInt(), dp(14), false)); + textView.measure(MeasureSpec.makeMeasureSpec(animateWidth ? 999999 : getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(9999999, MeasureSpec.AT_MOST)); + } updateLoadingLayout(); } public int multAlpha(int color, float mult) { return (color & 0x00ffffff) | ((int) ((color >> 24 & 0xff) * mult) << 24); } - boolean scrolled = false; private ValueAnimator animator = null; public void setText(CharSequence text) { - text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), dp(14), false); textView.setText(text); textView.measure(MeasureSpec.makeMeasureSpec(animateWidth ? 999999 : getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(9999999, MeasureSpec.AT_MOST)); - updateTextLayout(); + textView.layout(getLeft() + padHorz, getTop() + padVert, getLeft() + padHorz + textView.getMeasuredWidth(), getTop() + padVert + textView.getMeasuredHeight()); if (!loaded) { loaded = true; @@ -1479,32 +1689,23 @@ public class TranslateAlert extends Dialog { animator = ValueAnimator.ofFloat(0f, 1f); animator.addUpdateListener(a -> { loadingT = (float) a.getAnimatedValue(); + onLoadAnimation(loadingT); updateHeight(); invalidate(); }); + onLoadStart(); animator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - - } - - @Override - public void onAnimationEnd(Animator animator) { + @Override public void onAnimationEnd(Animator animator) { onLoadEnd(); } - - @Override - public void onAnimationCancel(Animator animator) { + @Override public void onAnimationCancel(Animator animator) { onLoadEnd(); } - - @Override - public void onAnimationRepeat(Animator animator) { - - } + @Override public void onAnimationRepeat(Animator animator) {} + @Override public void onAnimationStart(Animator animator) {} }); - animator.setInterpolator(CubicBezierInterpolator.EASE_IN); - animator.setDuration(220); +// animator.setInterpolator(CubicBezierInterpolator.EASE_BOTH); + animator.setDuration(300); animator.start(); } else updateHeight(); @@ -1520,12 +1721,12 @@ public class TranslateAlert extends Dialog { float w = getWidth(), h = getHeight(); float cx = LocaleController.isRTL ? Math.max(w / 2f, w - 8f) : Math.min(w / 2f, 8f), - cy = Math.min(h / 2f, 8f), - R = (float) Math.sqrt(Math.max( - Math.max(cx*cx + cy*cy, (w-cx)*(w-cx) + cy*cy), - Math.max(cx*cx + (h-cy)*(h-cy), (w-cx)*(w-cx) + (h-cy)*(h-cy)) - )), - r = loadingT * R; + cy = Math.min(h / 2f, 8f), + R = (float) Math.sqrt(Math.max( + Math.max(cx*cx + cy*cy, (w-cx)*(w-cx) + cy*cy), + Math.max(cx*cx + (h-cy)*(h-cy), (w-cx)*(w-cx) + (h-cy)*(h-cy)) + )), + r = loadingT * R; inPath.reset(); inPath.addCircle(cx, cy, r, Path.Direction.CW); @@ -1542,7 +1743,7 @@ public class TranslateAlert extends Dialog { canvas.translate(-padHorz, -padVert); canvas.translate(-dx, 0); shadePath.offset(dx, 0f, tempPath); - canvas.drawPath(tempPath, loadingPaint); + canvas.drawPath(tempPath, loading ? loadingPaint : loadingIdlePaint); canvas.translate(dx, 0); canvas.restore(); @@ -1559,30 +1760,21 @@ public class TranslateAlert extends Dialog { canvas.restore(); canvas.restore(); -// canvas.save(); -// canvas.clipPath(inPath); -// canvas.translate(padHorz, padVert); -// textLayout.draw(canvas); -// canvas.restore(); - } - private Paint RED = new Paint(); - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (child == textView) { + if (textView != null) { canvas.save(); canvas.clipPath(inPath); - if (loadingT < 1f) { - rect.set(0, 0, getWidth(), getHeight()); - canvas.saveLayerAlpha(rect, (int) (255 * loadingT), Canvas.ALL_SAVE_FLAG); - } - boolean r = super.drawChild(canvas, child, drawingTime); + canvas.translate(padHorz, padVert); + canvas.saveLayerAlpha(rect, (int) (255 * loadingT), Canvas.ALL_SAVE_FLAG); + textView.draw(canvas); if (loadingT < 1f) canvas.restore(); canvas.restore(); - return r; } + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { return false; } } -} \ No newline at end of file +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index 747e0238a..19cf2db21 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -13,6 +13,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.res.Configuration; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; @@ -31,6 +32,11 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.LanguageCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -54,6 +60,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.Set; import java.util.Timer; public class LanguageSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java b/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java index 1ea79f546..66c835eda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java @@ -220,7 +220,7 @@ public class MessageSeenView extends FrameLayout { titleView.setText(ContactsController.formatName(users.get(0).first_name, users.get(0).last_name)); } else { if (peerIds.size() == 0) { - titleView.setText(LocaleController.getString(LocaleController.getString("NobodyViewed", R.string.NobodyViewed))); + titleView.setText(LocaleController.getString("NobodyViewed", R.string.NobodyViewed)); } else { titleView.setText(LocaleController.formatPluralString(isVoice ? "MessagePlayed" : "MessageSeen", peerIds.size())); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index eab4ef5bf..cdc368087 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -1131,7 +1131,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public void onAnimationEnd(Animator animation) { if (isIndicatorVisible) { if (searchItem != null) { - searchItem.setVisibility(GONE); + searchItem.setClickable(false); } if (editItemVisible) { editItem.setVisibility(GONE); @@ -1150,7 +1150,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public void onAnimationStart(Animator animation) { if (searchItem != null && !expanded) { - searchItem.setVisibility(VISIBLE); + searchItem.setClickable(true); } if (editItemVisible) { editItem.setVisibility(VISIBLE); @@ -3150,7 +3150,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_profile_actionBackground), Theme.getColor(Theme.key_profile_actionPressedBackground)), 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); - writeButton.setBackgroundDrawable(combinedDrawable); + writeButton.setBackground(combinedDrawable); if (userId != 0) { if (imageUpdater != null) { cameraDrawable = new RLottieDrawable(R.raw.camera_outline, "" + R.raw.camera_outline, AndroidUtilities.dp(56), AndroidUtilities.dp(56), false, null); @@ -3233,9 +3233,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (searchItem != null) { searchItem.setAlpha(1.0f - value); searchItem.setScaleY(1.0f - value); - searchItem.setVisibility(searchItem.getAlpha() == 0f ? View.GONE : View.VISIBLE); - if (qrItem != null && searchItem.getVisibility() == View.VISIBLE) { + searchItem.setVisibility(View.VISIBLE); + searchItem.setClickable(searchItem.getAlpha() > .5f); + if (qrItem != null) { float translation = AndroidUtilities.dp(48) * value; +// if (searchItem.getVisibility() == View.VISIBLE) +// translation += AndroidUtilities.dp(48); qrItem.setTranslationX(translation); avatarsViewPagerIndicatorView.setTranslationX(translation - AndroidUtilities.dp(48)); } @@ -4320,8 +4323,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. qrItemAnimation.start(); } else { qrItem.setAlpha(setQrVisible ? 1.0f : 0.0f); - qrItem.setTranslationX(setQrVisible ? 0f : AndroidUtilities.dp(48f)); - avatarsViewPagerIndicatorView.setTranslationX(setQrVisible ? 0f : -AndroidUtilities.dp(48f)); + float translation = AndroidUtilities.dp(48) * qrItem.getAlpha(); + qrItem.setTranslationX(translation); + avatarsViewPagerIndicatorView.setTranslationX(translation - AndroidUtilities.dp(48)); } } } @@ -6089,7 +6093,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (qrItem != null) { - qrItem.setVisibility(isQrNeedVisible() ? View.VISIBLE : View.GONE); + qrItem.setVisibility(searchTransitionProgress > 0.5f && isQrNeedVisible() ? View.VISIBLE : View.GONE); } } @@ -8242,6 +8246,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + @Override + protected void onBecomeFullyVisible() { + super.onBecomeFullyVisible(); + + try { + Drawable shadowDrawable = fragmentView.getContext().getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, + Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_profile_actionBackground), Theme.getColor(Theme.key_profile_actionPressedBackground)), + 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + writeButton.setBackground(combinedDrawable); + } catch (Exception e) {} + } + private boolean isQrNeedVisible() { return !TextUtils.isEmpty(getUserConfig().getCurrentUser().username); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java index bce485e9e..46f271f9b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java @@ -2,6 +2,8 @@ package org.telegram.ui; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.ActivityNotFoundException; @@ -23,18 +25,21 @@ import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.os.SystemClock; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -73,6 +78,7 @@ import org.telegram.ui.Cells.SettingsSearchCell; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.ChatThemeBottomSheet; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.Easings; import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.HideViewAfterAnimation; @@ -239,10 +245,15 @@ public class QrActivity extends BaseFragment { protected void onDraw(Canvas canvas) { if (prevMotionDrawable != null) { prevMotionDrawable.setBounds(0, 0, getWidth(), getHeight()); - prevMotionDrawable.draw(canvas); } currMotionDrawable.setBounds(0, 0, getWidth(), getHeight()); - currMotionDrawable.draw(canvas); + + if (prevMotionDrawable != null) + prevMotionDrawable.drawBackground(canvas); + currMotionDrawable.drawBackground(canvas); + if (prevMotionDrawable != null) + prevMotionDrawable.drawPattern(canvas); + currMotionDrawable.drawPattern(canvas); super.onDraw(canvas); } }; @@ -481,6 +492,34 @@ public class QrActivity extends BaseFragment { } } + @Override + protected AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { + if (isOpen) { + fragmentView.setAlpha(0f); + fragmentView.setTranslationX(AndroidUtilities.dp(48)); + } + + AnimatorSet animator = new AnimatorSet(); + animator.playTogether( + ObjectAnimator.ofFloat(fragmentView, View.TRANSLATION_X, isOpen ? 0 : AndroidUtilities.dp(48)), + ObjectAnimator.ofFloat(fragmentView, View.ALPHA, isOpen ? 1f : 0f) + ); + if (!isOpen) + animator.setInterpolator(new DecelerateInterpolator(1.5f)); + else + animator.setInterpolator(CubicBezierInterpolator.EASE_IN); + animator.setDuration(isOpen ? 200 : 150); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + if (callback != null) + callback.run(); + } + }); + animator.start(); + return animator; + } + private void onItemSelected(EmojiThemes newTheme, int position, boolean withAnimation) { selectedPosition = position; final EmojiThemes prevTheme = currentTheme; @@ -488,8 +527,16 @@ public class QrActivity extends BaseFragment { currentTheme = newTheme; EmojiThemes.ThemeItem themeItem = currentTheme.getThemeItem(isDarkTheme ? 1 : 0); + float duration = 1f; + if (patternAlphaAnimator != null) { +// from = (float) patternAlphaAnimator.getAnimatedValue(); + duration *= Math.max(.5f, 1f - (float) patternAlphaAnimator.getAnimatedValue()); + patternAlphaAnimator.cancel(); + } + prevMotionDrawable = currMotionDrawable; prevMotionDrawable.setIndeterminateAnimation(false); + prevMotionDrawable.setAlpha(255); currMotionDrawable = new MotionBackgroundDrawable(); currMotionDrawable.setCallback(backgroundView); @@ -497,18 +544,21 @@ public class QrActivity extends BaseFragment { currMotionDrawable.setParentView(backgroundView); currMotionDrawable.setPatternAlpha(1f); currMotionDrawable.setIndeterminateAnimation(true); - currMotionDrawable.posAnimationProgress = prevMotionDrawable.posAnimationProgress; + if (prevMotionDrawable != null) + currMotionDrawable.posAnimationProgress = prevMotionDrawable.posAnimationProgress; qrView.setPosAnimationProgress(currMotionDrawable.posAnimationProgress); TLRPC.WallPaper wallPaper = currentTheme.getWallpaper(isDarkTheme ? 1 : 0); if (wallPaper != null) { currMotionDrawable.setPatternBitmap(wallPaper.settings.intensity); + final long startedLoading = SystemClock.elapsedRealtime(); currentTheme.loadWallpaper(isDarkTheme ? 1 : 0, pair -> { if (pair != null && currentTheme.getTlTheme(isDarkTheme ? 1 : 0) != null) { final long themeId = pair.first; final Bitmap bitmap = pair.second; if (themeId == currentTheme.getTlTheme(isDarkTheme ? 1 : 0).id && bitmap != null) { - onPatternLoaded(bitmap, currMotionDrawable.getIntensity(), withAnimation); + long elapsed = SystemClock.elapsedRealtime() - startedLoading; + onPatternLoaded(bitmap, currMotionDrawable.getIntensity(), elapsed > 150); } } }); @@ -517,22 +567,20 @@ public class QrActivity extends BaseFragment { } currMotionDrawable.setPatternColorFilter(currMotionDrawable.getPatternColor()); - float from = 0; - if (patternAlphaAnimator != null) { - from = (float) patternAlphaAnimator.getAnimatedValue(); - patternAlphaAnimator.cancel(); - } - int[] newQrColors = qrColorsMap.get(newTheme.emoji + (isDarkTheme ? "n" : "d")); if (withAnimation) { - currMotionDrawable.setAlpha(0); - patternAlphaAnimator = ValueAnimator.ofFloat(from, 1f); + currMotionDrawable.setAlpha(255); + currMotionDrawable.setBackgroundAlpha(0f); + patternAlphaAnimator = ValueAnimator.ofFloat(0f, 1f); patternAlphaAnimator.addUpdateListener(animation -> { float progress = (float) animation.getAnimatedValue(); if (prevMotionDrawable != null) { + prevMotionDrawable.setBackgroundAlpha(1f); prevMotionDrawable.setPatternAlpha(1f - progress); } - currMotionDrawable.setAlpha((int) (255f * progress)); + currMotionDrawable.setBackgroundAlpha(progress); + currMotionDrawable.setPatternAlpha(progress); +// currMotionDrawable.setAlpha((int) (255f * progress)); if (newQrColors != null) { int color1 = ColorUtils.blendARGB(prevQrColors[0], newQrColors[0], progress); int color2 = ColorUtils.blendARGB(prevQrColors[1], newQrColors[1], progress); @@ -551,9 +599,25 @@ public class QrActivity extends BaseFragment { } prevMotionDrawable = null; patternAlphaAnimator = null; + currMotionDrawable.setBackgroundAlpha(1f); + currMotionDrawable.setPatternAlpha(1f); + } + + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + float progress = (float) ((ValueAnimator) animation).getAnimatedValue(); + if (newQrColors != null) { + int color1 = ColorUtils.blendARGB(prevQrColors[0], newQrColors[0], progress); + int color2 = ColorUtils.blendARGB(prevQrColors[1], newQrColors[1], progress); + int color3 = ColorUtils.blendARGB(prevQrColors[2], newQrColors[2], progress); + int color4 = ColorUtils.blendARGB(prevQrColors[3], newQrColors[3], progress); + int[] colors = new int[] { color1, color2, color3, color4 }; + System.arraycopy(colors, 0, prevQrColors, 0, 4); + } } }); - patternAlphaAnimator.setDuration(250); + patternAlphaAnimator.setDuration((int) (250 * duration)); patternAlphaAnimator.start(); } else { if (newQrColors != null) { @@ -569,7 +633,7 @@ public class QrActivity extends BaseFragment { animationSettings.applyTheme = false; animationSettings.onlyTopFragment = true; animationSettings.resourcesProvider = getResourceProvider(); - animationSettings.duration = 250; + animationSettings.duration = (int) (250 * duration); if (withAnimation) { resourcesProvider.initColors(prevTheme, isCurrentThemeDark); } else { @@ -991,8 +1055,9 @@ public class QrActivity extends BaseFragment { } setupLightDarkTheme(!forceDark); }); + darkThemeView.setAlpha(0f); darkThemeView.setVisibility(View.INVISIBLE); - rootLayout.addView(darkThemeView, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.END, 0, 0, 7, 0)); + rootLayout.addView(darkThemeView, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.END, 0, -2, 7, 0)); forceDark = !Theme.getActiveTheme().isDark(); setForceDark(Theme.getActiveTheme().isDark(), false); @@ -1068,6 +1133,8 @@ public class QrActivity extends BaseFragment { } public void onDataLoaded() { + darkThemeView.setAlpha(0f); + darkThemeView.animate().alpha(1f).setDuration(150).start(); darkThemeView.setVisibility(View.VISIBLE); progressView.animate().alpha(0f).setListener(new HideViewAfterAnimation(progressView)).setDuration(150).start(); recyclerView.setAlpha(0f); diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index d91ed0b44..c00fb44a4 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -1022,7 +1022,6 @@ Report spam Translate Automatic Translation - Translate more... Close Translation Translation failed. Try again later. Translation failed. diff --git a/build.gradle b/build.gradle index e14be25e1..7dd3a03d7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,8 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.1' - classpath 'com.google.gms:google-services:4.3.5' + classpath 'com.android.tools.build:gradle:7.0.3' + classpath 'com.google.gms:google-services:4.3.10' } } repositories {